tizen 2.3.1 release
[kernel/api/system-resource.git] / src / network / storage.c
1 /*
2  * resourced
3  *
4  * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 /*
21  * @file storage.c
22  *
23  * @desc Entity for storing applications statistics
24  *
25  * Copyright (c) 2013 Samsung Electronics Co., Ltd. All rights reserved.
26  *
27  */
28
29 #include <glib.h>
30 #include <inttypes.h>
31 #include <sqlite3.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <sys/stat.h>
36 #include <sys/types.h>
37 #include <time.h>
38 #include <unistd.h>
39
40 #include "const.h"
41 #include "iface.h"
42 #include "database.h"
43 #include "datausage-quota-processing.h"
44 #include "macro.h"
45 #include "protocol-info.h"
46 #include "storage.h"
47 #include "specific-trace.h"
48 #include "trace.h"
49
50 static sqlite3_stmt *update_statistics_query;
51 static sqlite3_stmt *update_iface_query;
52
53 enum { read_until_null = -1 };
54
55 static void handle_on_iface(const int ifindex, resourced_option_state state)
56 {
57         _D("Handling network interface %d, %d", ifindex, state);
58
59         if (!update_iface_query) {
60                 _E("Uninitialized statement");
61                 return;
62         }
63         sqlite3_bind_int(update_iface_query, 1, get_iftype(ifindex));
64         sqlite3_bind_int(update_iface_query, 2, state);
65
66         if (sqlite3_step(update_iface_query) != SQLITE_DONE)
67                 _E("Failed to record iface state. %s",
68                         sqlite3_errmsg(resourced_get_database()));
69
70         sqlite3_reset(update_iface_query);
71 }
72
73 static void handle_on_iface_up(const int ifindex)
74 {
75         handle_on_iface(ifindex, RESOURCED_OPTION_ENABLE);
76 }
77
78 static void handle_on_iface_down(const int ifindex)
79 {
80         handle_on_iface(ifindex, RESOURCED_OPTION_DISABLE);
81 }
82
83 static int init_update_statistics_query(sqlite3 *db)
84 {
85         int rc;
86
87         if (update_statistics_query)
88                 return SQLITE_OK;
89
90         rc = sqlite3_prepare_v2(db,
91                                "insert into statistics "                \
92                                "(binpath, received, sent, time_stamp, " \
93                                "iftype, is_roaming, hw_net_protocol_type, ifname) " \
94                                "values (?, ?, ?, ?, ?, ?, ?, ?)",
95                                read_until_null, &update_statistics_query, NULL);
96
97         if (rc != SQLITE_OK) {
98                 _E("Failed to prepare query %s\n", sqlite3_errmsg(db));
99                 sqlite3_finalize(update_statistics_query);
100         }
101         return rc;
102 }
103
104 static int init_update_iface_query(sqlite3 *db)
105 {
106         int rc;
107
108         if (update_iface_query)
109                 return SQLITE_OK;
110
111         rc =  sqlite3_prepare_v2(db,
112                                 "insert into iface_status " \
113                 "(update_time, iftype, ifstatus) " \
114                 "values (datetime('now'), ?, ?)", read_until_null,
115                 &update_iface_query, NULL);
116
117         if (rc != SQLITE_OK) {
118                 _E("Failed to prepare query %s\n", sqlite3_errmsg(db));
119                 sqlite3_finalize(update_iface_query);
120         }
121         return rc;
122 }
123
124 static gboolean store_application_stat(gpointer key, gpointer value,
125         gpointer __attribute((__unused__)) userdata)
126 {
127         struct application_stat *stat = (struct application_stat *)value;
128         struct classid_iftype_key *stat_key = (struct classid_iftype_key *)key;
129         time_t *last_touch_time = (time_t *)userdata;
130         resourced_hw_net_protocol_type hw_net_protocol_type =
131                 get_hw_net_protocol_type(stat_key->iftype);
132
133         if (!update_statistics_query) {
134                 _E("Uninitialized statement");
135                 return FALSE;
136         }
137
138         if (!stat->rcv_count && !stat->snd_count)
139                 return FALSE;
140
141         if (sqlite3_bind_text(update_statistics_query, 1, stat->application_id, read_until_null,
142                         SQLITE_STATIC) != SQLITE_OK) {
143                 _SE("Can not bind application_id: %s", stat->application_id);
144                 return FALSE;
145         }
146         if (sqlite3_bind_int(update_statistics_query, 2, stat->rcv_count) != SQLITE_OK) {
147                 _E("Can not bind rcv_count %d:", stat->rcv_count);
148                 return FALSE;
149         }
150         if (sqlite3_bind_int(update_statistics_query, 3, stat->snd_count) != SQLITE_OK) {
151                 _E("Can not bind snd_count: %d", stat->snd_count);
152                 return FALSE;
153         }
154         if (sqlite3_bind_int64(update_statistics_query, 4, (sqlite3_int64) (*last_touch_time)) !=
155                 SQLITE_OK) {
156                 _E("Can not bind last_touch_time: %ld", *last_touch_time);
157                 return FALSE;
158         }
159         if (sqlite3_bind_int(update_statistics_query, 5, (int)(stat_key->iftype)) != SQLITE_OK) {
160                 _E("Can not bind iftype: %d", (int)stat_key->iftype);
161                 return FALSE;
162         }
163         if (sqlite3_bind_int(update_statistics_query, 6, (int)(stat->is_roaming)) != SQLITE_OK) {
164                 _E("Can not bind is_roaming: %d", (int)(stat->is_roaming));
165                 return FALSE;
166         }
167         if (sqlite3_bind_int(update_statistics_query, 7,
168                              (int)hw_net_protocol_type) != SQLITE_OK) {
169                 _E("Can not bind protocol_type: %d", (int)hw_net_protocol_type);
170                 return FALSE;
171         }
172         if (sqlite3_bind_text(update_statistics_query, 8, stat_key->ifname, read_until_null,
173                         SQLITE_STATIC) != SQLITE_OK) {
174                 _SE("Can not bind ifname: %s", stat_key->ifname);
175                 return FALSE;
176         }
177
178         /*we want to reuse tree*/
179         stat->rcv_count = 0;
180         stat->snd_count = 0;
181         if (sqlite3_step(update_statistics_query) != SQLITE_DONE)
182                 _E("Failed to record appstat. %s", sqlite3_errmsg(resourced_get_database()));
183
184         sqlite3_reset(update_statistics_query);
185         return FALSE;
186 }
187
188 int store_result(struct application_stat_tree *stats, int flush_period)
189 {
190         time_t current_time;
191
192         time(&current_time);
193
194         if (current_time - stats->last_touch_time >= flush_period) {
195
196                 pthread_rwlock_rdlock(&stats->guard);
197                 WALK_TREE(stats->tree, print_appstat);
198                 pthread_rwlock_unlock(&stats->guard);
199
200                 if (init_update_statistics_query(resourced_get_database()) != SQLITE_OK) {
201                         _D("Failed to initialize data usage quota statements: %s\n",
202                            sqlite3_errmsg(resourced_get_database()));
203                         return 0; /* Do not iterate and free results */
204                 }
205
206                 /* it's reader only, we don't modify tree, don't reduce it,
207                  *              due we want to reuse it in next iteration */
208                 pthread_rwlock_rdlock(&stats->guard);
209                 g_tree_foreach((GTree *) stats->tree,
210                                store_application_stat,
211                                &stats->last_touch_time);
212                 pthread_rwlock_unlock(&stats->guard);
213                 flush_quota_table();
214                 time(&current_time);
215                 stats->last_touch_time = current_time;
216                 return 1;
217         }
218         return 0;
219 }
220
221 void finalize_storage_stm(void)
222 {
223         sqlite3_finalize(update_statistics_query);
224         sqlite3_finalize(update_iface_query);
225 }
226
227 iface_callback *create_iface_storage_callback(void)
228 {
229         iface_callback *ret_arg =
230                 (iface_callback *)malloc(sizeof(iface_callback));
231
232         if (init_update_iface_query(resourced_get_database())
233                 != SQLITE_OK) {
234                 _E("Initialization database failed\n");
235         }
236         ret_value_msg_if(!ret_arg, NULL, "Malloc of iface_callback failed\n");
237         ret_arg->handle_iface_up = handle_on_iface_up;
238         ret_arg->handle_iface_down = handle_on_iface_down;
239
240         return ret_arg;
241 }