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