Merge "Added logic to monitor and restrict data usage per interface" into tizen
[platform/core/connectivity/stc-manager.git] / src / database / tables / table-statistics.c
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /**
18  * This file implements statistics entity handler methods.
19  *
20  * @file        table-statistics.c
21  */
22
23 #include "stc-db.h"
24 #include "table-statistics.h"
25 #include "db-internal.h"
26
27 /* DELETE statements */
28 #define DELETE_ALL "delete from statistics where time_stamp between ? and ?"
29
30 #define DELETE_APP "delete from statistics where binpath=? and " \
31         "time_stamp between ? and ? "
32
33 #define DELETE_IFACE "delete from statistics where iftype=? and " \
34         "time_stamp between ? and ?"
35
36 #define DELETE_APP_IFACE "delete from statistics where binpath=? and " \
37         "iftype=? and time_stamp between ? and ?"
38
39 #define DELETE_FIRST_BY_NUMBER "delete from statistics where time_stamp in " \
40         "(select time_stamp from statistics desc limit ?)"
41
42 /* SELECT statements */
43 #define SELECT_FOR_PERIOD "select binpath, hw_net_protocol_type, " \
44         "is_roaming, sum(received) as received, " \
45         "sum(sent) as sent, imsi, ground, iftype, ifname from statistics " \
46         "where time_stamp between ? and ? " \
47         "group by binpath, is_roaming, imsi order by received desc"
48
49 #define SELECT_FOR_PERIOD_IFACE "select binpath, hw_net_protocol_type, " \
50         "is_roaming, sum(received) as received, " \
51         "sum(sent) as sent, imsi, ground, iftype, ifname from statistics " \
52         "where time_stamp between ? and ? " \
53         "and iftype=? group by binpath, is_roaming, imsi order by received desc"
54
55 #define SELECT_CHUNKS "select binpath, hw_net_protocol_type, " \
56         "is_roaming, sum(received) as received, " \
57         "sum(sent) as sent, imsi, ground, iftype, ifname, " \
58         "time_stamp - time_stamp % ? as time_stamp " \
59         "from statistics where time_stamp between ? and ? " \
60         "group by binpath, time_stamp, imsi order by time_stamp"
61
62 #define SELECT_CHUNKS_IFACE "select binpath, hw_net_protocol_type, " \
63         "is_roaming, sum(received) as received, " \
64         "sum(sent) as sent, imsi, ground, iftype, ifname, " \
65         "time_stamp - time_stamp % ? as time_stamp " \
66         "from statistics where time_stamp between ? and ? and iftype=?" \
67         "group by binpath, time_stamp, imsi order by time_stamp"
68
69 #define SELECT_APP_DETAILS "select iftype, hw_net_protocol_type, " \
70         "is_roaming, sum(received) as received, sum(sent) as sent, " \
71         "ifname, imsi, ground from statistics " \
72         "where time_stamp between ? and ? and binpath=? " \
73         "group by binpath, iftype, ifname, imsi, hw_net_protocol_type, " \
74         "is_roaming " \
75         "order by time_stamp, binpath, iftype, ifname, imsi, " \
76         "hw_net_protocol_type, is_roaming"
77
78 #define SELECT_APP_DETAILS_IFACE "select iftype, hw_net_protocol_type, " \
79         "is_roaming, sum(received) as received, sum(sent) as sent, " \
80         "ifname, imsi, ground from statistics " \
81         "where time_stamp between ? and ? and binpath=? and iftype=?" \
82         "group by hw_net_protocol_type, is_roaming, iftype, ifname, imsi " \
83         "order by time_stamp, hw_net_protocol_type, is_roaming, iftype, " \
84         "ifname, imsi"
85
86 #define SELECT_CHUNKS_APP "select iftype, hw_net_protocol_type, " \
87         "is_roaming, sum(received) as received, sum(sent) as sent, " \
88         "ifname, imsi, ground, time_stamp - time_stamp % ? as time_stamp " \
89         "from statistics " \
90         "group by iftype, ifname, time_stamp, hw_net_protocol_type, is_roaming  " \
91         "order by time_stamp, iftype, ifname, hw_net_protocol_type, is_roaming"
92
93 #define SELECT_CHUNKS_APP_IFACE "select iftype, hw_net_protocol_type, " \
94         "is_roaming, sum(received) as received, sum(sent) as sent, " \
95         "ifname, imsi, ground, time_stamp - time_stamp % ? as time_stamp " \
96         "from statistics where time_stamp between ? and ? and binpath = ? " \
97         "and iftype = ? " \
98         "group by time_stamp, hw_net_protocol_type, is_roaming, " \
99         "iftype, ifname, imsi " \
100         "order by time_stamp, iftype, ifname, imsi, hw_net_protocol_type, " \
101         "is_roaming"
102
103 #define SELECT_TOTAL "select iftype, hw_net_protocol_type, " \
104         "is_roaming, sum(received) as received, sum(sent) as sent, " \
105         "ifname, imsi, ground from statistics " \
106         " where (time_stamp between ? and ?) and binpath != 'TOTAL_DATACALL' " \
107         "and binpath != 'TOTAL_WIFI' and binpath != 'TOTAL_BLUETOOTH' " \
108         "group by iftype, ifname, imsi, hw_net_protocol_type, is_roaming " \
109         "order by time_stamp, iftype, ifname, imsi, hw_net_protocol_type, " \
110         "is_roaming"
111
112 #define SELECT_TOTAL_IFACE "select iftype, hw_net_protocol_type, " \
113         "is_roaming, sum(received) as received, sum(sent) as sent, " \
114         "ifname, imsi, ground from statistics " \
115         " where (time_stamp between ? and ?) " \
116         "and iftype=? " \
117         "group by hw_net_protocol_type, is_roaming, " \
118         "iftype, ifname, imsi " \
119         "order by time_stamp, iftype, ifname, imsi, hw_net_protocol_type, " \
120         "is_roaming"
121
122 #define SELECT_CHUNKS_TOTAL "select iftype, hw_net_protocol_type, " \
123         "is_roaming, sum(received) as received, sum(sent) as sent, " \
124         "ifname, imsi, ground, time_stamp - time_stamp % ? as time_stamp " \
125         "from statistics where time_stamp between ? and ? " \
126         "group by time_stamp, iftype, ifname, imsi, hw_net_protocol_type, " \
127         "is_roaming " \
128         "order by time_stamp, iftype, ifname, imsi, hw_net_protocol_type, " \
129         "is_roaming"
130
131 #define SELECT_CHUNKS_TOTAL_IFACE "select iftype, hw_net_protocol_type, " \
132         "is_roaming, sum(received) as received, sum(sent) as sent, " \
133         "ifname, imsi, ground, time_stamp - time_stamp % ? as time_stamp " \
134         "from statistics where time_stamp between ? and ? " \
135         "and iftype = ? " \
136         "group by time_stamp, hw_net_protocol_type, is_roaming, iftype, ifname, imsi " \
137         "order by time_stamp, hw_net_protocol_type, is_roaming, iftype, " \
138         "ifname, imsi"
139
140 /* INSERT statement */
141 #define INSERT_VALUES "insert into statistics " \
142         "(binpath, received, sent, time_stamp, " \
143         "iftype, is_roaming, hw_net_protocol_type, " \
144         "ifname, imsi, ground) " \
145         "values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
146
147 static void __finalize_delete(void);
148
149 #define PREPARE_DELETE(stm, query) do {                         \
150         rc = sqlite3_prepare_v2(db, query, -1, &stm, NULL);     \
151         if (rc != SQLITE_OK) {                                  \
152                 stm = NULL;                                     \
153                 __finalize_delete();                            \
154                 STC_LOGE("Failed to prepare \"%s\"query"        \
155                          , query);                              \
156                 return rc;                                      \
157         }                                                       \
158 } while (0)
159
160 static void __finalize_select(void);
161
162 #define PREPARE_SELECT(stm, query) do {                         \
163         rc = sqlite3_prepare_v2(db, query, -1, &stm, NULL);     \
164         if (rc != SQLITE_OK) {                                  \
165                 stm = NULL;                                     \
166                 __finalize_select();                            \
167                 STC_LOGE("Failed to prepare \"%s\"query"        \
168                          , query);                              \
169                 return rc;                                      \
170         }                                                       \
171 } while (0)
172
173 static void __finalize_insert(void);
174
175 #define PREPARE_INSERT(stm, query) do {                         \
176         rc = sqlite3_prepare_v2(db, query, -1, &stm, NULL);     \
177         if (rc != SQLITE_OK) {                                  \
178                 stm = NULL;                                     \
179                 __finalize_insert();                            \
180                 STC_LOGE("Failed to prepare \"%s\"query"        \
181                          , query);                              \
182                 return rc;                                      \
183         }                                                       \
184 } while (0)
185
186 #define FINALIZE(stm) do {                                      \
187         if (stm) {                                              \
188                 sqlite3_finalize(stm);                          \
189                 stm = NULL;                                     \
190         }                                                       \
191 } while (0)
192
193 /* DELETE statements */
194 /* the following array is strictly ordered
195  * to find required statement the following code will be used:
196  * (app ? 1 : 0) | (iftype ? 2 : 0)
197  */
198 static sqlite3_stmt *delete_query[5];
199
200 /* SELECT statements */
201 static sqlite3_stmt *select_for_period;
202 static sqlite3_stmt *select_for_period_iface;
203 static sqlite3_stmt *select_chunks;
204 static sqlite3_stmt *select_chunks_iface;
205 static sqlite3_stmt *select_app_details;
206 static sqlite3_stmt *select_app_details_iface;
207 static sqlite3_stmt *select_chunks_app;
208 static sqlite3_stmt *select_chunks_app_iface;
209 static sqlite3_stmt *select_total;
210 static sqlite3_stmt *select_total_iface;
211 static sqlite3_stmt *select_chunks_total;
212 static sqlite3_stmt *select_chunks_total_iface;
213
214 /* INSERT statements */
215 static sqlite3_stmt *update_statistics_query;
216
217 static int __prepare_delete(sqlite3 *db)
218 {
219         __STC_LOG_FUNC_ENTER__;
220         int rc;
221         static int initialized;
222
223         if (initialized) {
224                 __STC_LOG_FUNC_EXIT__;
225                 return SQLITE_OK;
226         }
227
228         PREPARE_DELETE(delete_query[0], DELETE_ALL);
229         PREPARE_DELETE(delete_query[1], DELETE_APP);
230         PREPARE_DELETE(delete_query[2], DELETE_IFACE);
231         PREPARE_DELETE(delete_query[3], DELETE_APP_IFACE);
232         PREPARE_DELETE(delete_query[4], DELETE_FIRST_BY_NUMBER);
233
234         initialized = 1;
235         __STC_LOG_FUNC_EXIT__;
236         return rc;
237 }
238
239 static void __finalize_delete(void)
240 {
241         __STC_LOG_FUNC_ENTER__;
242
243         unsigned int i;
244         for (i = 0; i < sizeof(delete_query) / sizeof(*delete_query); i++)
245                 FINALIZE(delete_query[i]);
246
247         __STC_LOG_FUNC_EXIT__;
248 }
249
250 static int __prepare_select(sqlite3 *db)
251 {
252         __STC_LOG_FUNC_ENTER__;
253         int rc;
254         static int initialized;
255
256         if (initialized) {
257                 __STC_LOG_FUNC_EXIT__;
258                 return SQLITE_OK;
259         }
260
261         PREPARE_SELECT(select_for_period, SELECT_FOR_PERIOD);
262         PREPARE_SELECT(select_for_period_iface, SELECT_FOR_PERIOD_IFACE);
263         PREPARE_SELECT(select_chunks, SELECT_CHUNKS);
264         PREPARE_SELECT(select_chunks_iface, SELECT_CHUNKS_IFACE);
265         PREPARE_SELECT(select_app_details, SELECT_APP_DETAILS);
266         PREPARE_SELECT(select_app_details_iface, SELECT_APP_DETAILS_IFACE);
267         PREPARE_SELECT(select_chunks_app, SELECT_CHUNKS_APP);
268         PREPARE_SELECT(select_chunks_app_iface, SELECT_CHUNKS_APP_IFACE);
269         PREPARE_SELECT(select_total, SELECT_TOTAL);
270         PREPARE_SELECT(select_total_iface, SELECT_TOTAL_IFACE);
271         PREPARE_SELECT(select_chunks_total, SELECT_CHUNKS_TOTAL);
272         PREPARE_SELECT(select_chunks_total_iface, SELECT_CHUNKS_TOTAL_IFACE);
273
274         initialized = 1;
275         __STC_LOG_FUNC_EXIT__;
276         return rc;
277 }
278
279 static void __finalize_select(void)
280 {
281         __STC_LOG_FUNC_ENTER__;
282
283         FINALIZE(select_for_period);
284         FINALIZE(select_for_period_iface);
285         FINALIZE(select_chunks);
286         FINALIZE(select_chunks_iface);
287         FINALIZE(select_app_details);
288         FINALIZE(select_app_details_iface);
289         FINALIZE(select_chunks_app);
290         FINALIZE(select_chunks_app_iface);
291         FINALIZE(select_total);
292         FINALIZE(select_total_iface);
293         FINALIZE(select_chunks_total);
294         FINALIZE(select_chunks_total_iface);
295
296         __STC_LOG_FUNC_EXIT__;
297 }
298
299 static int __prepare_insert(sqlite3 *db)
300 {
301         __STC_LOG_FUNC_ENTER__;
302         int rc;
303         static int initialized;
304
305         if (initialized) {
306                 __STC_LOG_FUNC_EXIT__;
307                 return SQLITE_OK;
308         }
309
310         PREPARE_INSERT(update_statistics_query, INSERT_VALUES);
311
312         initialized = 1;
313         __STC_LOG_FUNC_EXIT__;
314         return rc;
315 }
316
317 static void __finalize_insert(void)
318 {
319         __STC_LOG_FUNC_ENTER__;
320
321         FINALIZE(update_statistics_query);
322
323         __STC_LOG_FUNC_EXIT__;
324 }
325
326 static int __is_iftype_defined(const stc_iface_type_e iftype)
327 {
328         __STC_LOG_FUNC_ENTER__;
329         __STC_LOG_FUNC_EXIT__;
330         return iftype < STC_IFACE_LAST_ELEM &&
331                 iftype > STC_IFACE_UNKNOWN &&
332                 iftype != STC_IFACE_ALL;
333 }
334
335 /* the following array is strictly ordered
336  * to find required statement the following code will be used:
337  * (iface ? 1 : 0) | (total ? 2 : 0) | (chunks ? 4 : 0)
338  */
339 static sqlite3_stmt **details_stms[] = {
340         &select_app_details,
341         &select_app_details_iface,
342         &select_total,
343         &select_total_iface,
344         &select_chunks_app,
345         &select_chunks_app_iface,
346         &select_chunks_total,
347         &select_chunks_total_iface
348 };
349
350 static sqlite3_stmt *__select_statement(const char *app_id,
351                                         const table_statistics_select_rule *rule)
352 {
353         __STC_LOG_FUNC_ENTER__;
354         const int stm_index = __is_iftype_defined(rule->iftype) |
355                 ((strlen(app_id) > 0) ? 0 : 2) | (rule->granularity ? 4 : 0);
356         STC_LOGD("stm index %d", stm_index);
357         __STC_LOG_FUNC_EXIT__;
358         return *details_stms[stm_index];
359 }
360
361 stc_error_e table_statistics_reset_first_n_entries(int num)
362 {
363         __STC_LOG_FUNC_ENTER__;
364         stc_error_e error_code = STC_ERROR_NONE;
365
366         if (!num) {
367                 STC_LOGE("Invalid number of entries");
368                 return STC_ERROR_INVALID_PARAMETER;
369         }
370
371         DB_ACTION(sqlite3_bind_int(delete_query[4], 1, num));
372
373         if (sqlite3_step(delete_query[4]) != SQLITE_DONE) {
374                 STC_LOGE("Failed to drop collected statistics.");
375                 error_code = STC_ERROR_DB_FAILED;
376                 __STC_LOG_FUNC_EXIT__;
377         }
378 handle_error:
379         sqlite3_reset(delete_query[4]);
380         return error_code;
381 }
382
383 stc_error_e table_statistics_reset(const table_statistics_reset_rule *rule)
384 {
385         __STC_LOG_FUNC_ENTER__;
386         sqlite3_stmt *stmt;
387         stc_error_e error_code = STC_ERROR_NONE;
388         int pos = 1;/* running through positions where to
389                        bind parameters in the query */
390
391         if (!rule || !rule->interval) {
392                 __STC_LOG_FUNC_EXIT__;
393                 return STC_ERROR_INVALID_PARAMETER;
394         }
395
396         /* pick a statement depending on parameters.
397            See comment for delete_query */
398         stmt = delete_query[(rule->app_id ? 1 : 0) |
399                 (rule->iftype != STC_IFACE_UNKNOWN &&
400                 rule->iftype != STC_IFACE_LAST_ELEM ? 2 : 0)];
401
402         if (rule->app_id)
403                 DB_ACTION(sqlite3_bind_text(stmt, pos++, rule->app_id, -1,
404                                             SQLITE_TRANSIENT));
405
406         if (rule->iftype != STC_IFACE_LAST_ELEM &&
407                 rule->iftype != STC_IFACE_UNKNOWN)
408                 DB_ACTION(sqlite3_bind_int(stmt, pos++, rule->iftype));
409
410         DB_ACTION(sqlite3_bind_int64(stmt, pos++, rule->interval->from));
411         DB_ACTION(sqlite3_bind_int64(stmt, pos++, rule->interval->to));
412
413         if (sqlite3_step(stmt) != SQLITE_DONE) {
414                 STC_LOGE("Failed to drop collected statistics.");
415                 error_code = STC_ERROR_DB_FAILED;
416                 __STC_LOG_FUNC_EXIT__;
417                 goto handle_error;
418         }
419
420         STC_LOGD("Entry deleted successfully.");
421 handle_error:
422         sqlite3_reset(stmt);
423         return error_code;
424 }
425
426 stc_error_e table_statistics_foreach_app(const table_statistics_select_rule *rule,
427                                          table_statistics_info_cb info_cb,
428                                          void *user_data)
429 {
430         __STC_LOG_FUNC_ENTER__;
431         table_statistics_info data;
432         sqlite3_stmt *stmt;
433         stc_error_e error_code = STC_ERROR_NONE;
434         int rc;
435         int pos = 1;/* running through positions where to
436                        bind parameters in the query */
437         stc_db_tm_interval_s interval;
438
439         memset(&data, 0, sizeof(data));
440
441         if (!rule || !info_cb) {
442                 __STC_LOG_FUNC_EXIT__;
443                 return STC_ERROR_INVALID_PARAMETER;
444         }
445
446         /* pick a statement depending on parameters */
447         if (rule->granularity) {
448                 stmt = __is_iftype_defined(rule->iftype) ?
449                         select_chunks_iface : select_chunks;
450
451                 DB_ACTION(sqlite3_bind_int64(stmt, pos++, rule->granularity));
452                 data.interval = &interval;
453         } else {
454                 stmt = __is_iftype_defined(rule->iftype)
455                         ? select_for_period_iface : select_for_period;
456         }
457
458         DB_ACTION(sqlite3_bind_int64(stmt, pos++, rule->from));
459         DB_ACTION(sqlite3_bind_int64(stmt, pos++, rule->to));
460
461         if (__is_iftype_defined(rule->iftype)) {
462                 data.iftype = rule->iftype;
463                 DB_ACTION(sqlite3_bind_int(stmt, pos++, rule->iftype));
464         }
465
466         do {
467                 rc = sqlite3_step(stmt);
468                 switch (rc) {
469                 case SQLITE_ROW:
470                         data.app_id = (char *)sqlite3_column_text(stmt, 0);
471                         data.hw_net_protocol_type = sqlite3_column_int(stmt, 1);
472                         data.roaming = sqlite3_column_int(stmt, 2);
473                         data.cnt.in_bytes = sqlite3_column_int64(stmt, 3);
474                         data.cnt.out_bytes = sqlite3_column_int64(stmt, 4);
475                         data.imsi = (char *)sqlite3_column_text(stmt, 5);
476                         data.ground = sqlite3_column_int(stmt, 6);
477                         data.iftype = sqlite3_column_int(stmt, 7);
478                         data.ifname = (char *)sqlite3_column_text(stmt, 8);
479
480                         if (rule->granularity) {
481                                 interval.from = sqlite3_column_int64(stmt, 9);
482                                 interval.to = interval.from + rule->granularity;
483                         }
484
485                         if (info_cb(&data, user_data) == STC_CANCEL)
486                                 rc = SQLITE_DONE;/* emulate end of data */
487                         __STC_LOG_FUNC_EXIT__;
488                         break;
489                 case SQLITE_DONE:
490                         __STC_LOG_FUNC_EXIT__;
491                         break;
492                 case SQLITE_ERROR:
493                 default:
494                         error_code = STC_ERROR_DB_FAILED;
495                         __STC_LOG_FUNC_EXIT__;
496                         break;
497                 }
498         } while (rc == SQLITE_ROW);
499
500 handle_error:
501         sqlite3_reset(stmt);
502         __STC_LOG_FUNC_EXIT__;
503         return error_code;
504 }
505
506 stc_error_e table_statistics_per_app(const char *app_id,
507                                      table_statistics_select_rule *rule,
508                                      table_statistics_info_cb info_cb,
509                                      void *user_data)
510 {
511         __STC_LOG_FUNC_ENTER__;
512         table_statistics_info data;
513         sqlite3_stmt *stmt;
514         stc_error_e error_code = STC_ERROR_NONE;
515         int rc;
516         int pos = 1;/* running through positions
517                        where to bind parameters in the query */
518         stc_db_tm_interval_s interval;
519
520         memset(&data, 0, sizeof(data));
521
522         if (!rule || !info_cb) {
523                 __STC_LOG_FUNC_EXIT__;
524                 return STC_ERROR_INVALID_PARAMETER;
525         }
526
527         /* pick a statement depending on parameters.
528            See comment for details_stms */
529         stmt = __select_statement(app_id, rule);
530
531         if (rule->granularity) {
532                 DB_ACTION(sqlite3_bind_int64(stmt, pos++, rule->granularity));
533                 data.interval = &interval;
534         }
535
536         DB_ACTION(sqlite3_bind_int64(stmt, pos++, rule->from));
537         DB_ACTION(sqlite3_bind_int64(stmt, pos++, rule->to));
538
539         if (strlen(app_id) > 0) {
540                 DB_ACTION(sqlite3_bind_text(stmt, pos++, app_id, -1,
541                                             SQLITE_TRANSIENT));
542                 data.app_id = (char *)app_id;
543         }
544
545         if (__is_iftype_defined(rule->iftype))
546                 DB_ACTION(sqlite3_bind_int(stmt, pos++, rule->iftype));
547
548         do {
549                 rc = sqlite3_step(stmt);
550                 switch (rc) {
551                 case SQLITE_ROW:
552                         data.iftype = sqlite3_column_int(stmt, 0);
553                         data.hw_net_protocol_type = sqlite3_column_int(stmt, 1);
554                         data.roaming = sqlite3_column_int(stmt, 2);
555                         data.cnt.in_bytes = sqlite3_column_int64(stmt, 3);
556                         data.cnt.out_bytes = sqlite3_column_int64(stmt, 4);
557                         data.ifname = (char *)sqlite3_column_text(stmt, 5);
558                         data.imsi = (char *)sqlite3_column_text(stmt, 6);
559
560                         if (rule->granularity) {
561                                 interval.from = sqlite3_column_int64(stmt, 7);
562                                 interval.to = interval.from + rule->granularity;
563                         }
564
565                         if (info_cb(&data, user_data) == STC_CANCEL)
566                                 rc = SQLITE_DONE; /* emulate end of data */
567                         __STC_LOG_FUNC_EXIT__;
568                         break;
569                 case SQLITE_DONE:
570                         __STC_LOG_FUNC_EXIT__;
571                         break;
572                 case SQLITE_ERROR:
573                 default:
574                         error_code = STC_ERROR_DB_FAILED;
575                         __STC_LOG_FUNC_EXIT__;
576                         break;
577                 }
578         } while (rc == SQLITE_ROW);
579
580 handle_error:
581         sqlite3_reset(stmt);
582         __STC_LOG_FUNC_EXIT__;
583         return error_code;
584 }
585
586 stc_error_e table_statistics_insert(stc_db_classid_iftype_key *stat_key,
587                                     stc_db_app_stats *stat,
588                                     time_t last_touch_time)
589 {
590         stc_error_e error_code = STC_ERROR_NONE;
591         sqlite3_stmt *stmt = update_statistics_query;
592         stc_hw_net_protocol_type_e hw_net_protocol_type = STC_PROTOCOL_NONE;
593
594         if (!stat->rcv_count && !stat->snd_count) {
595                 error_code = STC_ERROR_INVALID_PARAMETER;
596                 goto handle_error;
597         }
598
599         DB_ACTION(sqlite3_bind_text(stmt, 1, stat->app_id, -1,
600                                     SQLITE_STATIC));
601         DB_ACTION(sqlite3_bind_int(stmt, 2, stat->rcv_count));
602         DB_ACTION(sqlite3_bind_int(stmt, 3, stat->snd_count));
603         DB_ACTION(sqlite3_bind_int64(stmt, 4,
604                                      (sqlite3_int64)(last_touch_time)));
605         DB_ACTION(sqlite3_bind_int(stmt, 5, (int)(stat_key->iftype)));
606         DB_ACTION(sqlite3_bind_int(stmt, 6, (int)(stat->is_roaming)));
607         DB_ACTION(sqlite3_bind_int(stmt, 7, (int)hw_net_protocol_type));
608         DB_ACTION(sqlite3_bind_text(stmt, 8, stat_key->ifname, -1,
609                                     SQLITE_STATIC));
610         DB_ACTION(sqlite3_bind_text(stmt, 9,
611                                     stat_key->imsi ? stat_key->imsi : "" , -1,
612                                     SQLITE_STATIC));
613         DB_ACTION(sqlite3_bind_int(stmt, 10, (int)stat->ground));
614
615         /*we want to reuse tree*/
616         stat->rcv_count = 0;
617         stat->snd_count = 0;
618         if (sqlite3_step(stmt) != SQLITE_DONE) {
619                 STC_LOGE("Failed to record appstat. %s",
620                          sqlite3_errmsg(stc_db_get_database()));
621                 error_code = STC_ERROR_DB_FAILED;
622                 __STC_LOG_FUNC_EXIT__;
623                 goto handle_error;
624         }
625
626         STC_LOGD("App stat recorded [%s]", stat->app_id);
627
628 handle_error:
629         sqlite3_reset(stmt);
630         return error_code;
631 }
632
633 /**
634  * This function will be somewhere consumer and will not be placed in this file.
635  */
636 #if 0
637 stc_error_e table_statistics_store_result(app_stat_tree *stats)
638 {
639         time_t current_time;
640
641         pthread_rwlock_rdlock(&stats->guard);
642         WALK_TREE(stats->tree, print_appstat);
643         pthread_rwlock_unlock(&stats->guard);
644
645         time(&current_time);
646         stats->last_touch_time = current_time;
647
648         /* it's reader only, we don't modify tree, don't reduce it,
649          *              due we want to reuse it in next iteration */
650         pthread_rwlock_rdlock(&stats->guard);
651         g_tree_foreach((GTree *) stats->tree, __store_application_stat,
652                        &stats->last_touch_time);
653
654         pthread_rwlock_unlock(&stats->guard);
655         flush_quota_table();
656         change_db_entries_num_num(g_tree_nnodes((GTree *)stats->tree));
657
658         return STC_ERROR_NONE;
659 }
660 #endif
661
662 stc_error_e table_statistics_prepare(sqlite3 *db)
663 {
664         __STC_LOG_FUNC_ENTER__;
665
666         stc_error_e error_code = STC_ERROR_NONE;
667
668         if (db == NULL) {
669                 __STC_LOG_FUNC_EXIT__;
670                 return STC_ERROR_DB_FAILED;
671         }
672
673         DB_ACTION(__prepare_delete(db));
674         DB_ACTION(__prepare_select(db));
675         DB_ACTION(__prepare_insert(db));
676
677 handle_error:
678
679         __STC_LOG_FUNC_EXIT__;
680         return error_code;
681 }
682
683 void table_statistics_finalize(void)
684 {
685         __STC_LOG_FUNC_ENTER__;
686         __finalize_delete();
687         __finalize_select();
688         __finalize_insert();
689         __STC_LOG_FUNC_EXIT__;
690 }