tizen 2.3 release
[framework/system/deviced.git] / src / logd / src / liblogd-db / events.c
1 #define _GNU_SOURCE
2 #include <errno.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6
7 #include "db.h"
8 #include "events.h"
9 #include "macro.h"
10
11 #define LOAD_APPS_SQL "SELECT * FROM applications;"
12 #define STORE_APP_SQL "INSERT INTO applications (name) VALUES (?);"
13 #define STORE_EVENT_SQL "INSERT INTO events\
14         (object, action, time_stamp, app_id, info) VALUES (?, ?, ?, ?, ?);"
15 #define LOAD_EVENTS_SQL "SELECT E.object, E.action, E.time_stamp, A.name, E.info\
16         FROM applications A, events E                                   \
17         WHERE E.app_id=A.id"
18 #define DEL_OLD_EVENTS_SQL "DELETE FROM events WHERE time_stamp < ?"
19
20
21 #define LOAD_EVENTS_ALL "SELECT E.object, E.action, E.time_stamp, A.name, E.info\
22         FROM applications A, events E\
23         WHERE E.app_id=A.id"
24 #define AND " AND"
25 #define OR " OR"
26 #define TIMESTAMP_LT " (time_stamp < %lld)"
27 #define TIMESTAMP_GT " (time_stamp > %lld)"
28 #define BY_OBJECT " (object = %d)"
29 #define BY_ACTION " (action = %d)"
30 #define EXTRA (32)
31
32 #define QUERY_BASE_STR_LEN sizeof(LOAD_EVENTS_ALL)
33 #define QUERY_ADD_STR_TIME_LEN sizeof(TIMESTAMP_LT) + sizeof(AND) \
34         + sizeof(TIMESTAMP_GT) + EXTRA
35 #define QUERY_ADD_STR_LEN_MAX sizeof(BY_OBJECT) + sizeof(AND) + EXTRA
36
37 static sqlite3 *db;
38
39 static sqlite3_stmt *load_apps_stmt;
40 static sqlite3_stmt *store_app_stmt;
41 static sqlite3_stmt *store_event_stmt;
42 static sqlite3_stmt *load_events_stmt;
43 static sqlite3_stmt *del_old_events_stmt;
44
45 int events_init(void)
46 {
47         db = logd_get_db();
48
49         PREPARE_STMT(load_apps_stmt, LOAD_APPS_SQL);
50         PREPARE_STMT(store_app_stmt, STORE_APP_SQL);
51         PREPARE_STMT(store_event_stmt, STORE_EVENT_SQL);
52         PREPARE_STMT(load_events_stmt, LOAD_EVENTS_SQL);
53         PREPARE_STMT(del_old_events_stmt, DEL_OLD_EVENTS_SQL);
54
55         return 0;
56 }
57
58 int events_finalize(void)
59 {
60         FINALIZE_STMT(load_apps_stmt);
61         FINALIZE_STMT(store_app_stmt);
62         FINALIZE_STMT(store_event_stmt);
63         FINALIZE_STMT(load_events_stmt);
64         FINALIZE_STMT(del_old_events_stmt);
65
66         return 0;
67 }
68
69 API int logd_store_app(const char *app)
70 {
71         DB_CHECK(sqlite3_reset(store_app_stmt));
72         DB_CHECK(sqlite3_bind_text(store_app_stmt, 1, app, -1, SQLITE_STATIC));
73         if (sqlite3_step(store_app_stmt) != SQLITE_DONE) {
74                 _E("Failed to record to applications table: %s",
75                    sqlite3_errmsg(db));
76                 return -1;
77         }
78
79         return 0;
80 }
81
82 API int logd_load_apps(enum logd_db_query (*cb) (int, const char *, void *),
83                 void *user_data)
84 {
85         const char *app = NULL;
86         int id;
87
88         while (sqlite3_step(load_apps_stmt) == SQLITE_ROW) {
89                 app = (const char *)sqlite3_column_text(load_apps_stmt, 0);
90                 id = sqlite3_column_int(load_apps_stmt, 1);
91                 if (!cb(id, app, user_data))
92                         break;
93         }
94
95         return 0;
96 }
97
98 API int logd_store_event(int event_type, uint64_t _time, int app_id,
99                    const char *message)
100 {
101         DB_CHECK(sqlite3_reset(store_event_stmt));
102         DB_CHECK(sqlite3_bind_int(store_event_stmt, 1, event_type & 0xffff));
103         DB_CHECK(sqlite3_bind_int(store_event_stmt, 2, event_type >> 16));
104         DB_CHECK(sqlite3_bind_int64(store_event_stmt, 3, _time));
105         DB_CHECK(sqlite3_bind_int(store_event_stmt, 4, app_id));
106         DB_CHECK(sqlite3_bind_text(store_event_stmt, 5, message, -1,
107                  SQLITE_STATIC));
108
109         if (sqlite3_step(store_event_stmt) != SQLITE_DONE) {
110                 _E("Failed to record to events table: %s", sqlite3_errmsg(db));
111                 return -1;
112         }
113
114         return 0;
115 }
116
117 API int logd_load_events(enum logd_db_query (*cb)(const struct logd_event_info *, void *),
118         sqlite3_stmt *stmt, void *user_data)
119 {
120         struct logd_event_info event;
121         int ret = 0;
122
123         stmt = stmt ? stmt : load_events_stmt;
124
125         while (sqlite3_step(stmt) == SQLITE_ROW) {
126                 event.object = sqlite3_column_int(stmt, 0);
127                 event.action = sqlite3_column_int(stmt, 1);
128                 event.time = sqlite3_column_int64(stmt, 2);
129
130                 event.application =
131                         strdup((char *)sqlite3_column_text(stmt, 3));
132                 event.message =
133                         strdup((char *)sqlite3_column_text(stmt, 4));
134
135                 ret = cb(&event, user_data);
136                 free(event.message);
137                 free(event.application);
138                 if (ret != LOGD_DB_QUERY_CONTINUE)
139                         break;
140         }
141
142         return 0;
143 }
144
145
146 API int delete_old_events(uint64_t min_time)
147 {
148         DB_CHECK(sqlite3_reset(del_old_events_stmt));
149         DB_CHECK(sqlite3_bind_int64(del_old_events_stmt, 1, min_time));
150
151         if (sqlite3_step(del_old_events_stmt) != SQLITE_DONE) {
152                 _E("Failed to remove old events: %s", sqlite3_errmsg(db));
153                 return -1;
154         }
155
156         return 0;
157 }
158
159 API int logd_foreach_events(const struct logd_events_filter *filter,
160         enum logd_db_query (*cb)(const struct logd_event_info *, void *),
161         void *user_data)
162 {
163         char *buf, *qbuf;
164         int idx, omidx, amidx, ret, len, firstskip;
165         sqlite3_stmt *stmt;
166
167         if (filter == NULL) {
168                 len = QUERY_BASE_STR_LEN;
169
170                 buf = (char *)malloc(len);
171                 if (!buf) {
172                         ret = -ENOMEM;
173                         goto out_finish;
174                 }
175                 len -= snprintf(buf, len, LOAD_EVENTS_ALL);
176                 if (len < 0) {
177                         ret = len;
178                         goto out_free;
179                 }
180
181         } else {
182                 omidx = 0;
183                 for (idx = 0; idx < LOGD_OBJECT_MAX; idx++) {
184                         if (filter->objects_mask[idx] == 1)
185                                 omidx++;
186                 }
187                 amidx = 0;
188                 for (idx = 0; idx < LOGD_ACTION_MAX; idx++) {
189                         if (filter->actions_mask[idx] == 1)
190                                 amidx++;
191                 }
192
193                 len = QUERY_BASE_STR_LEN + sizeof(AND) +
194                         QUERY_ADD_STR_TIME_LEN +
195                         (omidx * QUERY_ADD_STR_LEN_MAX) +
196                         (amidx * QUERY_ADD_STR_LEN_MAX);
197
198                 buf = (char *)malloc(len);
199                 if (!buf) {
200                         ret = -ENOMEM;
201                         goto out_finish;
202                 }
203                 len -= snprintf(buf, len, LOAD_EVENTS_ALL);
204                 if (len < 0) {
205                         ret = len;
206                         goto out_free;
207                 }
208
209                 if (filter->from) {
210                         strcat(buf, AND);
211                         ret = asprintf(&qbuf, TIMESTAMP_GT, filter->from);
212                         if (ret <=0)
213                                 goto out_free;
214                         strcat(buf, qbuf);
215                         free(qbuf);
216                 }
217
218                 if (filter->to) {
219                         strcat(buf, AND);
220                         ret = asprintf(&qbuf, TIMESTAMP_LT, filter->to);
221                         if (ret <=0)
222                                 goto out_free;
223                         strcat(buf, qbuf);
224                         free(qbuf);
225                 }
226
227                 if (omidx) {
228                         strcat(buf, AND);
229                         strcat(buf, " (");
230                         firstskip = 0;
231                         for (idx = 0; idx < LOGD_OBJECT_MAX; idx++) {
232                                 if (filter->objects_mask[idx] == 1) {
233                                         if (firstskip != 0)
234                                                 strcat(buf, OR);
235                                         else
236                                                 firstskip = 1;
237                                         ret = asprintf(&qbuf, BY_OBJECT, idx);
238                                         if (ret <= 0)
239                                                 goto out_free;
240                                         strncat(buf, qbuf, ret);
241                                         free(qbuf);
242                                 }
243                         }
244                         strcat(buf, ")");
245                 }
246                 if (amidx) {
247                         strcat(buf, AND);
248                         strcat(buf, " (");
249                         firstskip = 0;
250                         for (idx = 0; idx < LOGD_ACTION_MAX; idx++) {
251                                 if (filter->actions_mask[idx] == 1) {
252                                         if (firstskip != 0)
253                                                 strcat(buf, OR);
254                                         else
255                                                 firstskip = 1;
256                                         ret = asprintf(&qbuf, BY_ACTION, idx);
257                                         if (ret <= 0)
258                                                 goto out_free;
259                                         strncat(buf, qbuf, ret);
260                                         free(qbuf);
261                                 }
262                         }
263                         strcat(buf, ")");
264                 }
265         }
266
267         PREPARE_STMT(stmt, buf);
268         free(buf);
269         ret = logd_load_events(cb, stmt, user_data);
270         FINALIZE_STMT(stmt);
271
272         return ret;
273
274 out_free:
275         free(buf);
276 out_finish:
277         return ret;
278 }