4 * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd. All rights reserved.
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 * @desc Implementation of the datausage foreach function.
31 #include "data_usage.h"
32 #include "datausage-foreach.h"
36 #define DATA_USAGE_FOR_PERIOD "select binpath, hw_net_protocol_type, " \
37 "is_roaming, sum(received) as received, " \
38 "sum(sent) as sent from statistics where time_stamp between ? and ? " \
39 "group by binpath, is_roaming order by received desc"
41 #define DATA_USAGE_FOR_PERIOD_IFACE "select binpath, hw_net_protocol_type, " \
42 "is_roaming, sum(received) as received, " \
43 "sum(sent) as sent from statistics where time_stamp between ? and ? " \
44 "and iftype=? group by binpath, is_roaming order by received desc"
46 #define DATA_USAGE_CHUNKS "select binpath, hw_net_protocol_type, " \
47 "is_roaming, sum(received) as received, " \
48 "sum(sent) as sent, time_stamp - time_stamp % ? as time_stamp " \
49 "from statistics where time_stamp between ? and ? " \
50 "group by binpath, time_stamp order by time_stamp"
52 #define DATA_USAGE_CHUNKS_IFACE "select binpath, hw_net_protocol_type, " \
53 "is_roaming, sum(received) as received, " \
54 "sum(sent) as sent, time_stamp as start_time, " \
55 "time_stamp - time_stamp % ? as time_stamp " \
56 "from statistics where time_stamp between ? and ? and iftype=?" \
57 "group by binpath, time_stamp order by time_stamp"
59 #define DATA_USAGE_APP_DETAILS "select iftype, hw_net_protocol_type, " \
60 "is_roaming, sum(received) as received, sum(sent) as sent, " \
61 "ifname from statistics where time_stamp between ? and ? " \
62 "and binpath=? group by binpath, iftype, is_roaming order by iftype"
64 #define DATA_USAGE_APP_DETAILS_IFACE "select iftype, hw_net_protocol_type, " \
65 "is_roaming, sum(received) as received, sum(sent) as sent, " \
66 "ifname from statistics where time_stamp between ? and ? " \
67 "and binpath=? and iftype=?"
69 #define DATA_USAGE_CHUNKS_APP "select iftype, hw_net_protocol_type, " \
70 "is_roaming, sum(received) as received, sum(sent) as sent, " \
71 "ifname, time_stamp - time_stamp % ? as time_stamp " \
72 "from statistics where time_stamp between ? and ? and binpath = ? " \
73 "group by iftype, time_stamp order by time_stamp, iftype"
75 #define DATA_USAGE_CHUNKS_APP_IFACE "select iftype, hw_net_protocol_type, " \
76 "is_roaming, sum(received) as received, sum(sent) as sent, " \
77 "ifname, time_stamp - time_stamp % ? as time_stamp " \
78 "from statistics where time_stamp between ? and ? and binpath = ? " \
79 "and iftype = ? group by time_stamp order by time_stamp"
81 #define DATA_USAGE_TOTAL "select iftype, hw_net_protocol_type, " \
82 "is_roaming, sum(received) as received, sum(sent) as sent, " \
83 "ifname from statistics where time_stamp between ? and ? " \
84 "group by iftype order by iftype, is_roaming"
86 #define DATA_USAGE_TOTAL_IFACE "select iftype, hw_net_protocol_type, " \
87 "is_roaming, sum(received) as received, sum(sent) as sent, " \
88 "ifname from statistics where time_stamp between ? and ? " \
91 #define DATA_USAGE_CHUNKS_TOTAL "select iftype, hw_net_protocol_type, " \
92 "is_roaming, sum(received) as received, sum(sent) as sent, " \
93 "ifname, time_stamp - time_stamp % ? as time_stamp " \
94 "from statistics where time_stamp between ? and ? " \
95 "group by iftype, time_stamp order by time_stamp, iftype"
97 #define DATA_USAGE_CHUNKS_TOTAL_IFACE "select iftype, hw_net_protocol_type, " \
98 "is_roaming, sum(received) as received, sum(sent) as sent, " \
99 "ifname, time_stamp - time_stamp % ? as time_stamp " \
100 "from statistics where time_stamp between ? and ? " \
101 "and iftype = ? group by time_stamp order by time_stamp"
103 static sqlite3_stmt *data_usage_for_period;
104 static sqlite3_stmt *data_usage_for_period_iface;
105 static sqlite3_stmt *data_usage_chunks;
106 static sqlite3_stmt *data_usage_chunks_iface;
107 static sqlite3_stmt *data_usage_app_details;
108 static sqlite3_stmt *data_usage_app_details_iface;
109 static sqlite3_stmt *data_usage_chunks_app;
110 static sqlite3_stmt *data_usage_chunks_app_iface;
111 static sqlite3_stmt *data_usage_total;
112 static sqlite3_stmt *data_usage_total_iface;
113 static sqlite3_stmt *data_usage_chunks_total;
114 static sqlite3_stmt *data_usage_chunks_total_iface;
116 #define PREPARE(stm, query) do { \
117 rc = sqlite3_prepare_v2(db, query, -1, &stm, NULL); \
118 if (rc != SQLITE_OK) { \
120 finalize_datausage_foreach(); \
121 _E("Failed to prepare %s\n", query); \
126 int init_datausage_foreach(sqlite3 *db)
129 static int initialized;
134 PREPARE(data_usage_for_period, DATA_USAGE_FOR_PERIOD);
135 PREPARE(data_usage_for_period_iface, DATA_USAGE_FOR_PERIOD_IFACE);
136 PREPARE(data_usage_chunks, DATA_USAGE_CHUNKS);
137 PREPARE(data_usage_chunks_iface, DATA_USAGE_CHUNKS_IFACE);
138 PREPARE(data_usage_app_details, DATA_USAGE_APP_DETAILS);
139 PREPARE(data_usage_app_details_iface, DATA_USAGE_APP_DETAILS_IFACE);
140 PREPARE(data_usage_chunks_app, DATA_USAGE_CHUNKS_APP);
141 PREPARE(data_usage_chunks_app_iface, DATA_USAGE_CHUNKS_APP_IFACE);
142 PREPARE(data_usage_total, DATA_USAGE_TOTAL);
143 PREPARE(data_usage_total_iface, DATA_USAGE_TOTAL_IFACE);
144 PREPARE(data_usage_chunks_total, DATA_USAGE_CHUNKS_TOTAL);
145 PREPARE(data_usage_chunks_total_iface, DATA_USAGE_CHUNKS_TOTAL_IFACE);
151 #define FINALIZE(stm) do { \
153 sqlite3_finalize(stm); \
158 void finalize_datausage_foreach(void)
160 FINALIZE(data_usage_for_period);
161 FINALIZE(data_usage_for_period_iface);
162 FINALIZE(data_usage_chunks);
163 FINALIZE(data_usage_chunks_iface);
164 FINALIZE(data_usage_app_details);
165 FINALIZE(data_usage_app_details_iface);
166 FINALIZE(data_usage_chunks_app);
167 FINALIZE(data_usage_chunks_app_iface);
168 FINALIZE(data_usage_total);
169 FINALIZE(data_usage_total_iface);
170 FINALIZE(data_usage_chunks_total);
171 FINALIZE(data_usage_chunks_total_iface);
174 static int is_iftype_defined(const resourced_iface_type iftype)
176 return iftype < RESOURCED_IFACE_LAST_ELEM &&
177 iftype > RESOURCED_IFACE_UNKNOWN &&
178 iftype != RESOURCED_IFACE_ALL;
181 API resourced_ret_c data_usage_foreach(const data_usage_selection_rule *rule,
182 data_usage_info_cb info_cb,
185 data_usage_info data;
187 resourced_ret_c result = RESOURCED_ERROR_NONE;
188 resourced_counters *cnt = &data.foreground.cnt;
190 int pos = 1;/* running through positions where to
191 bind parameters in the query */
192 resourced_tm_interval interval;
194 libresourced_db_initialize_once();
195 if (init_datausage_foreach(resourced_get_database())!= SQLITE_OK) {
196 _D("Failed to initialize data usage statements: %s\n",
197 sqlite3_errmsg(resourced_get_database()));
198 return RESOURCED_ERROR_DB_FAILED;
202 memset(&data, 0, sizeof(data));
204 if (!rule || !info_cb)
205 return RESOURCED_ERROR_INVALID_PARAMETER;
207 /* pick a statement depending on parameters */
208 if (rule->granularity) {
209 stm = is_iftype_defined(rule->iftype) ?
210 data_usage_chunks_iface : data_usage_chunks;
212 if (sqlite3_bind_int64(stm, pos++, rule->granularity) !=
214 result = RESOURCED_ERROR_DB_FAILED;
217 data.interval = &interval;
219 stm = is_iftype_defined(rule->iftype)
220 ? data_usage_for_period_iface : data_usage_for_period;
223 if (sqlite3_bind_int64(stm, pos++, rule->from) != SQLITE_OK) {
224 result = RESOURCED_ERROR_DB_FAILED;
227 if (sqlite3_bind_int64(stm, pos++, rule->to) != SQLITE_OK) {
228 result = RESOURCED_ERROR_DB_FAILED;
232 if (is_iftype_defined(rule->iftype)) {
233 data.iftype = rule->iftype;
235 (stm, pos++, rule->iftype) != SQLITE_OK) {
236 result = RESOURCED_ERROR_DB_FAILED;
242 rc = sqlite3_step(stm);
245 data.app_id = (char *)sqlite3_column_text(stm, 0);
246 data.hw_net_protocol_type = sqlite3_column_int(stm, 1);
247 data.roaming = sqlite3_column_int(stm, 2);
248 cnt->incoming_bytes = sqlite3_column_int64(stm, 3);
249 cnt->outgoing_bytes = sqlite3_column_int64(stm, 4);
250 if (rule->granularity) {
251 interval.from = sqlite3_column_int64(stm, 5);
252 interval.to = interval.from + rule->granularity;
255 if (info_cb(&data, user_data) == RESOURCED_CANCEL)
256 rc = SQLITE_DONE;/* emulate end of data */
262 result = RESOURCED_ERROR_DB_FAILED;
265 } while (rc == SQLITE_ROW);
271 /* the following array is strictly ordered
272 * to find required statement the following code will be used:
273 * (iface ? 1 : 0) | (total ? 2 : 0) | (chunks ? 4 : 0)
275 static sqlite3_stmt **details_stms[] = {
276 &data_usage_app_details,
277 &data_usage_app_details_iface,
279 &data_usage_total_iface,
280 &data_usage_chunks_app,
281 &data_usage_chunks_app_iface,
282 &data_usage_chunks_total,
283 &data_usage_chunks_total_iface
286 static sqlite3_stmt *select_statement(const char *app_id,
287 const data_usage_selection_rule *rule)
289 return *details_stms[is_iftype_defined(rule->iftype) |
290 (app_id ? 0 : 2) | (rule->granularity ? 4 : 0)];
293 API resourced_ret_c data_usage_details_foreach(const char *app_id,
294 data_usage_selection_rule *rule,
295 data_usage_info_cb info_cb, void *user_data)
297 data_usage_info data;
299 resourced_ret_c result = RESOURCED_ERROR_NONE;
300 resourced_counters *cnt = &data.foreground.cnt;
302 int pos = 1;/* running through positions
303 where to bind parameters in the query */
304 resourced_tm_interval interval;
306 libresourced_db_initialize_once();
307 if (init_datausage_foreach(resourced_get_database())!= SQLITE_OK) {
308 _D("Failed to initialize data usage statements: %s\n",
309 sqlite3_errmsg(resourced_get_database()));
310 return RESOURCED_ERROR_DB_FAILED;
312 memset(&data, 0, sizeof(data));
314 if (!rule || !info_cb)
315 return RESOURCED_ERROR_INVALID_PARAMETER;
317 /* pick a statement depending on parameters.
318 See comment for details_stms */
319 stm = select_statement(app_id, rule);
321 if (rule->granularity) {
322 if (sqlite3_bind_int64(stm, pos++, rule->granularity) !=
324 result = RESOURCED_ERROR_DB_FAILED;
327 data.interval = &interval;
330 if (sqlite3_bind_int64(stm, pos++, rule->from) != SQLITE_OK) {
331 result = RESOURCED_ERROR_DB_FAILED;
334 if (sqlite3_bind_int64(stm, pos++, rule->to) != SQLITE_OK) {
335 result = RESOURCED_ERROR_DB_FAILED;
340 if (sqlite3_bind_text(stm, pos++, app_id, -1, SQLITE_TRANSIENT)
342 result = RESOURCED_ERROR_DB_FAILED;
345 data.app_id = app_id;
348 if (is_iftype_defined(rule->iftype)) {
350 (stm, pos++, rule->iftype) != SQLITE_OK) {
351 result = RESOURCED_ERROR_DB_FAILED;
357 rc = sqlite3_step(stm);
360 data.iftype = sqlite3_column_int(stm, 0);
361 data.hw_net_protocol_type = sqlite3_column_int(stm, 1);
362 data.roaming = sqlite3_column_int(stm, 2);
363 cnt->incoming_bytes = sqlite3_column_int64(stm, 3);
364 cnt->outgoing_bytes = sqlite3_column_int64(stm, 4);
365 data.ifname = (char *)sqlite3_column_text(stm, 5);
367 if (rule->granularity) {
368 interval.from = sqlite3_column_int64(stm, 6);
369 interval.to = interval.from + rule->granularity;
371 data.app_id = (char *)sqlite3_column_text(stm, 0);
374 if (info_cb(&data, user_data) == RESOURCED_CANCEL)
375 rc = SQLITE_DONE; /* emulate end of data */
381 result = RESOURCED_ERROR_DB_FAILED;
384 } while (rc == SQLITE_ROW);