4 * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: DongHoo Park <donghoo.park@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
36 #ifndef PLUGIN_VERSION
37 #define PLUGIN_VERSION 1
40 #define BUSY_WAITING_USEC 50000 /* 0.05 sec */
41 #define BUSY_WAITING_MAX 20 /* wait for max 1 sec */
44 static gboolean __update_query_database(Storage *strg, void *handle, const char *query, GHashTable *in_param)
47 sqlite3_stmt *stmt = NULL;
48 char szQuery[1000+1]; /* +1 is for NULL Termination Character '\0' */
55 memset(szQuery, '\0', 1001);
56 strncpy(szQuery, query, 1000);
58 rv = sqlite3_prepare_v2(handle, szQuery, strlen(szQuery), &stmt, NULL);
59 if (rv != SQLITE_OK) {
60 err("fail to connect to table (%d)", rv);
65 g_hash_table_iter_init(&iter, in_param);
66 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
67 dbg("key(%s), value(%s)", (const char *)key, (const char *)value);
69 if (!value || g_strcmp0((const char *)value, "") == 0) {
71 rv = sqlite3_bind_null(stmt, atoi((const char *)key));
74 rv = sqlite3_bind_text(stmt, atoi((const char *)key), (const char *)value, strlen((const char *)value),
78 if (rv != SQLITE_OK) {
79 dbg("fail to bind data (%d)", rv);
85 if (rv != SQLITE_OK) {
86 sqlite3_finalize(stmt);
90 rv = sqlite3_step(stmt);
91 dbg("update query executed (%d)", rv);
92 sqlite3_finalize(stmt);
94 if (rv != SQLITE_DONE)
100 static int _busy_handler(void *pData, int count)
102 if (count < BUSY_WAITING_MAX) {
103 usleep(BUSY_WAITING_USEC);
107 dbg("Busy Handler will be returned SQLITE_BUSY error\n");
111 static void *create_handle(Storage *strg, const char *path)
114 sqlite3 *handle = NULL;
117 err("Invalid input param error");
121 rv = sqlite3_open(path, &handle);
122 if (rv != SQLITE_OK) {
123 err("fail to connect database err(%d), errmsg(%s)", rv, sqlite3_errmsg(handle));
127 rv = sqlite3_busy_handler(handle, _busy_handler, NULL);
128 if (rv != SQLITE_OK) {
129 err("fail to register busy handler err(%d), errmsg(%s)", rv, sqlite3_errmsg(handle));
130 sqlite3_close(handle);
134 dbg("connected to %s", path);
138 static gboolean remove_handle(Storage *strg, void *handle)
145 rv = sqlite3_close(handle);
146 if (rv != SQLITE_OK) {
147 err("fail to close database err(%d)", rv);
152 dbg("disconnected from database");
156 static gboolean update_query_database(Storage *strg, void *handle, const char *query, GHashTable *in_param)
162 ret = __update_query_database(strg, handle, query, in_param);
167 static gboolean _read_query_database_internal(Storage *strg, void *handle, const char *query, GHashTable *in_param,
168 gpointer out_param, int out_param_cnt, gboolean in_order)
170 int rv = 0, local_index = 0, outter_index = 0;
171 sqlite3_stmt *stmt = NULL;
172 char szQuery[5000+1]; /* +1 is for NULL Termination Character '\0' */
179 memset(szQuery, '\0', 5001);
180 strncpy(szQuery, query, 5000);
182 rv = sqlite3_prepare_v2(handle, szQuery, strlen(szQuery), &stmt, NULL);
183 if (rv != SQLITE_OK) {
184 err("fail to connect to table (%d)", rv);
189 g_hash_table_iter_init(&iter, in_param);
190 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
191 dbg("key(%s), value(%s)", (const char *)key, (const char *)value);
193 if (!value || g_strcmp0((const char *)value, "") == 0) {
195 rv = sqlite3_bind_null(stmt, atoi((const char *)key));
198 rv = sqlite3_bind_text(stmt, atoi((const char *)key), (const char *)value, strlen((const char *)value),
202 if (rv != SQLITE_OK) {
203 dbg("fail to bind data (%d)", rv);
209 if (rv != SQLITE_OK) {
210 sqlite3_finalize(stmt);
214 rv = sqlite3_step(stmt);
215 dbg("read query executed (%d), in_order (%d)", rv, in_order);
217 while (rv == SQLITE_ROW) {
218 GHashTable *out_param_data;
220 out_param_data = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
222 for (local_index = 0; local_index < out_param_cnt; local_index++) {
224 const unsigned char *tmp;
225 tmp = sqlite3_column_text(stmt, local_index);
226 snprintf(tmp_key, sizeof(tmp_key), "%d", local_index);
227 g_hash_table_insert(out_param_data, g_strdup(tmp_key), g_strdup((const char *)tmp));
231 GSList **temp = out_param;
232 *temp = g_slist_append(*temp, out_param_data);
234 char tmp_key_outter[32];
235 snprintf(tmp_key_outter, sizeof(tmp_key_outter), "%d", outter_index);
236 g_hash_table_insert((GHashTable*)out_param, g_strdup(tmp_key_outter), out_param_data);
239 rv = sqlite3_step(stmt);
242 sqlite3_finalize(stmt);
246 static gboolean read_query_database(Storage *strg, void *handle, const char *query, GHashTable *in_param,
247 GHashTable **out_param, int out_param_cnt)
249 GHashTable *out_hash_table;
251 if (out_param == NULL)
254 out_hash_table = g_hash_table_new_full(g_str_hash, g_str_equal,
255 g_free, (GDestroyNotify)g_hash_table_destroy);
257 if (_read_query_database_internal(strg,
258 handle, query, in_param, out_hash_table, out_param_cnt, FALSE) == FALSE) {
259 g_hash_table_destroy(out_hash_table);
263 *out_param = out_hash_table;
268 static gboolean read_query_database_in_order(Storage *strg, void *handle, const char *query, GHashTable *in_param,
269 GSList **out_param, int out_param_cnt)
271 if (_read_query_database_internal(strg,
272 handle, query, in_param, out_param, out_param_cnt, TRUE) == FALSE)
278 static gboolean insert_query_database(Storage *strg, void *handle, const char *query, GHashTable *in_param)
281 sqlite3_stmt *stmt = NULL;
282 char szQuery[5000+1]; /* +1 is for NULL Termination Character '\0' */
288 memset(szQuery, '\0', 5001);
289 strncpy(szQuery, query, 5000);
291 rv = sqlite3_prepare_v2(handle, szQuery, strlen(szQuery), &stmt, NULL);
292 if (rv != SQLITE_OK) {
293 err("fail to connect to table (%d)", rv);
298 g_hash_table_iter_init(&iter, in_param);
299 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
300 dbg("key(%s), value(%s)", (const char *)key, (const char *)value);
302 if (!value || g_strcmp0((const char *)value, "") == 0) {
304 rv = sqlite3_bind_null(stmt, atoi((const char *)key));
307 rv = sqlite3_bind_text(stmt, atoi((const char *)key), (const char *)value, strlen((const char *)value),
311 if (rv != SQLITE_OK) {
312 dbg("fail to bind data (%d)", rv);
318 if (rv != SQLITE_OK) {
319 sqlite3_finalize(stmt);
323 rv = sqlite3_step(stmt);
324 dbg("insert query executed (%d)", rv);
325 sqlite3_finalize(stmt);
327 if (rv != SQLITE_DONE)
333 static gboolean remove_query_database(Storage *strg, void *handle, const char *query, GHashTable *in_param)
339 ret = __update_query_database(strg, handle, query, in_param);
344 static struct storage_operations ops = {
345 .create_handle = create_handle,
346 .remove_handle = remove_handle,
347 .update_query_database = update_query_database,
348 .read_query_database = read_query_database,
349 .read_query_database_in_order = read_query_database_in_order,
350 .insert_query_database = insert_query_database,
351 .remove_query_database = remove_query_database,
354 static gboolean on_load()
360 static gboolean on_init(TcorePlugin *p)
365 tcore_storage_new(p, "database", &ops);
367 dbg("finish to initialize database plug-in");
371 static void on_unload(TcorePlugin *p)
380 strg = tcore_server_find_storage(tcore_plugin_ref_server(p), "database");
384 tcore_storage_free(strg);
389 EXPORT_API struct tcore_plugin_define_desc plugin_define_desc = {
391 .priority = TCORE_PLUGIN_PRIORITY_HIGH - 1,
392 .version = PLUGIN_VERSION,