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