2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
26 #include <app_common.h>
27 #include <app_internal.h>
28 #include <app_preference.h>
29 #include <app_preference_internal.h>
35 #define LOG_TAG "CAPI_APPFW_PREFERENCE"
38 static sqlite3 *pref_db = NULL;
39 static bool is_update_hook_registered = false;
40 static pref_changed_cb_node_t *head = NULL;
42 static void _finish(void *data)
46 sqlite3_close(pref_db);
51 static int _busy_handler(void *pData, int count)
54 LOGD("Busy Handler Called! : PID(%d) / CNT(%d)\n", getpid(), count+1);
55 usleep((count+1)*100000);
58 LOGD("Busy Handler will be returned SQLITE_BUSY error : PID(%d) \n", getpid());
63 static int _initialize(void)
65 char *data_path = NULL;
66 char db_path[TIZEN_PATH_MAX] = {0, };
70 if ((data_path = app_get_data_path()) == NULL)
72 LOGE("IO_ERROR(0x%08x) : fail to get data directory", PREFERENCE_ERROR_IO_ERROR);
73 return PREFERENCE_ERROR_IO_ERROR;
75 snprintf(db_path, sizeof(db_path), "%s/%s", data_path, PREF_DB_NAME);
78 ret = sqlite3_open(db_path, &pref_db);
81 LOGE("IO_ERROR(0x%08x) : fail to open db(%s)", PREFERENCE_ERROR_IO_ERROR, sqlite3_errmsg(pref_db));
83 return PREFERENCE_ERROR_IO_ERROR;
86 ret = sqlite3_busy_handler(pref_db, _busy_handler, NULL);
87 if (ret != SQLITE_OK) {
88 LOGW("IO_ERROR(0x%08x) : fail to register busy handler(%s)\n", PREFERENCE_ERROR_IO_ERROR, sqlite3_errmsg(pref_db));
91 ret = sqlite3_exec(pref_db, "CREATE TABLE IF NOT EXISTS pref ( pref_key TEXT PRIMARY KEY, pref_type TEXT, pref_data TEXT)",
95 LOGE("IO_ERROR(0x%08x) : fail to create db table(%s)", PREFERENCE_ERROR_IO_ERROR, errmsg);
97 sqlite3_close(pref_db);
99 return PREFERENCE_ERROR_IO_ERROR;
102 app_finalizer_add(_finish, NULL);
104 return PREFERENCE_ERROR_NONE;
107 static int _write_data(const char *key, const char *type, const char *data)
114 if (key == NULL || key[0] == '\0' || data == NULL)
116 LOGE("INVALID_PARAMETER(0x%08x)", PREFERENCE_ERROR_INVALID_PARAMETER);
117 return PREFERENCE_ERROR_INVALID_PARAMETER;
120 /* insert data or update data if data already exist */
121 ret = preference_is_existing(key, &exist);
122 if (ret != PREFERENCE_ERROR_NONE)
127 // to use sqlite3_update_hook, we have to use INSERT/UPDATE operation instead of REPLACE operation
130 buf = sqlite3_mprintf("UPDATE %s SET %s=?, %s=? WHERE %s=?;",
131 PREF_TBL_NAME, PREF_F_TYPE_NAME, PREF_F_DATA_NAME, PREF_F_KEY_NAME);
135 buf = sqlite3_mprintf("INSERT INTO %s (%s, %s, %s) values (?, ?, ?);",
136 PREF_TBL_NAME, PREF_F_KEY_NAME, PREF_F_TYPE_NAME, PREF_F_DATA_NAME);
141 LOGE("IO_ERROR(0x%08x) : fail to create query string", PREFERENCE_ERROR_IO_ERROR);
142 return PREFERENCE_ERROR_IO_ERROR;
145 ret = sqlite3_prepare(pref_db, buf, strlen(buf), &stmt, NULL);
146 if (ret != SQLITE_OK) {
147 LOGE("IO_ERROR(0x%08x) : fail to prepare query (%d/%s)",
148 PREFERENCE_ERROR_IO_ERROR,
149 sqlite3_extended_errcode(pref_db),
150 sqlite3_errmsg(pref_db));
151 return PREFERENCE_ERROR_IO_ERROR;
156 ret = sqlite3_bind_text(stmt, 1, type, strlen(type), SQLITE_STATIC);
157 if(ret != SQLITE_OK) {
158 LOGE("IO_ERROR(0x%08x) : fail to bind(1) query (%d/%s)",
159 PREFERENCE_ERROR_IO_ERROR,
160 sqlite3_extended_errcode(pref_db),
161 sqlite3_errmsg(pref_db));
162 sqlite3_finalize(stmt);
163 return PREFERENCE_ERROR_IO_ERROR;
165 ret = sqlite3_bind_text(stmt, 2, data, strlen(data), SQLITE_STATIC);
166 if(ret != SQLITE_OK) {
167 LOGE("IO_ERROR(0x%08x) : fail to bind(2) query (%d/%s)",
168 PREFERENCE_ERROR_IO_ERROR,
169 sqlite3_extended_errcode(pref_db),
170 sqlite3_errmsg(pref_db));
171 sqlite3_finalize(stmt);
172 return PREFERENCE_ERROR_IO_ERROR;
174 ret = sqlite3_bind_text(stmt, 3, key, strlen(key), SQLITE_STATIC);
175 if(ret != SQLITE_OK) {
176 LOGE("IO_ERROR(0x%08x) : fail to bind(3) query (%d/%s)",
177 PREFERENCE_ERROR_IO_ERROR,
178 sqlite3_extended_errcode(pref_db),
179 sqlite3_errmsg(pref_db));
180 sqlite3_finalize(stmt);
181 return PREFERENCE_ERROR_IO_ERROR;
186 ret = sqlite3_bind_text(stmt, 1, key, strlen(key), SQLITE_STATIC);
187 if(ret != SQLITE_OK) {
188 LOGE("IO_ERROR(0x%08x) : fail to bind(1) query (%d/%s)",
189 PREFERENCE_ERROR_IO_ERROR,
190 sqlite3_extended_errcode(pref_db),
191 sqlite3_errmsg(pref_db));
192 sqlite3_finalize(stmt);
193 return PREFERENCE_ERROR_IO_ERROR;
195 ret = sqlite3_bind_text(stmt, 2, type, strlen(type), SQLITE_STATIC);
196 if(ret != SQLITE_OK) {
197 LOGE("IO_ERROR(0x%08x) : fail to bind(2) query (%d/%s)",
198 PREFERENCE_ERROR_IO_ERROR,
199 sqlite3_extended_errcode(pref_db),
200 sqlite3_errmsg(pref_db));
201 sqlite3_finalize(stmt);
202 return PREFERENCE_ERROR_IO_ERROR;
204 ret = sqlite3_bind_text(stmt, 3, data, strlen(data), SQLITE_STATIC);
205 if(ret != SQLITE_OK) {
206 LOGE("IO_ERROR(0x%08x) : fail to bind(3) query (%d/%s)",
207 PREFERENCE_ERROR_IO_ERROR,
208 sqlite3_extended_errcode(pref_db),
209 sqlite3_errmsg(pref_db));
210 sqlite3_finalize(stmt);
211 return PREFERENCE_ERROR_IO_ERROR;
215 ret = sqlite3_step(stmt);
216 if (ret != SQLITE_DONE) {
217 LOGE("IO_ERROR(0x%08x): fail to write data(%d/%s)",
218 PREFERENCE_ERROR_IO_ERROR,
219 sqlite3_extended_errcode(pref_db),
220 sqlite3_errmsg(pref_db));
221 sqlite3_finalize(stmt);
222 return PREFERENCE_ERROR_IO_ERROR;
225 sqlite3_finalize(stmt);
231 return PREFERENCE_ERROR_NONE;
234 //static int _read_data(const char *key, preference_type_e *type, char *data)
235 static int _read_data(const char *key, char *type, char *data)
244 if (key == NULL || key[0] == '\0' || data == NULL)
246 LOGE("INVALID_PARAMETER(0x%08x)", PREFERENCE_ERROR_INVALID_PARAMETER);
247 return PREFERENCE_ERROR_INVALID_PARAMETER;
252 if (_initialize() != PREFERENCE_ERROR_NONE)
254 LOGE("IO_ERROR(0x%08x) : fail to initialize db", PREFERENCE_ERROR_IO_ERROR);
255 return PREFERENCE_ERROR_IO_ERROR;
259 buf = sqlite3_mprintf("SELECT %s, %s, %s FROM %s WHERE %s=%Q;",
260 PREF_F_KEY_NAME, PREF_F_TYPE_NAME, PREF_F_DATA_NAME, PREF_TBL_NAME, PREF_F_KEY_NAME, key);
264 LOGE("IO_ERROR(0x%08x) : fail to create query string", PREFERENCE_ERROR_IO_ERROR);
265 return PREFERENCE_ERROR_IO_ERROR;
268 ret = sqlite3_get_table(pref_db, buf, &result, &rows, &columns, &errmsg);
270 if (ret != SQLITE_OK)
272 LOGE("IO_ERROR(0x%08x) : fail to read data (%s)", PREFERENCE_ERROR_IO_ERROR, errmsg);
273 sqlite3_free(errmsg);
274 return PREFERENCE_ERROR_IO_ERROR;
279 LOGE("NO_KEY(0x%08x) : fail to find given key(%s)", PREFERENCE_ERROR_NO_KEY, key);
280 sqlite3_free_table(result);
281 return PREFERENCE_ERROR_NO_KEY;
284 snprintf(type, 2, "%s", result[4]); // get type value
285 snprintf(data, BUF_LEN, "%s", result[5]); // get data value
287 sqlite3_free_table(result);
289 return PREFERENCE_ERROR_NONE;
293 int preference_set_int(const char *key, int value)
297 snprintf(type, 2, "%d", PREFERENCE_TYPE_INT);
298 snprintf(data, BUF_LEN, "%d", value);
299 return _write_data(key, type, data);
302 int preference_get_int(const char *key, int *value)
309 LOGE("INVALID_PARAMETER(0x%08x)", PREFERENCE_ERROR_INVALID_PARAMETER);
310 return PREFERENCE_ERROR_INVALID_PARAMETER;
313 ret = _read_data(key, type, data);
314 if (ret == PREFERENCE_ERROR_NONE)
316 if (atoi(type) == PREFERENCE_TYPE_INT)
322 LOGE("INVALID_PARAMETER(0x%08x) : param type(%d)", PREFERENCE_ERROR_INVALID_PARAMETER, atoi(type));
323 return PREFERENCE_ERROR_INVALID_PARAMETER;
330 int preference_set_double(const char *key, double value)
334 snprintf(type, 2, "%d", PREFERENCE_TYPE_DOUBLE);
335 snprintf(data, BUF_LEN, "%f", value);
336 return _write_data(key, type, data);
339 int preference_get_double(const char *key, double *value)
347 LOGE("INVALID_PARAMETER(0x%08x)", PREFERENCE_ERROR_INVALID_PARAMETER);
348 return PREFERENCE_ERROR_INVALID_PARAMETER;
351 ret = _read_data(key, type, data);
352 if (ret == PREFERENCE_ERROR_NONE)
354 if (atoi(type) == PREFERENCE_TYPE_DOUBLE)
360 LOGE("INVALID_PARAMETER(0x%08x) : param type(%d)", PREFERENCE_ERROR_INVALID_PARAMETER, atoi(type));
361 return PREFERENCE_ERROR_INVALID_PARAMETER;
368 int preference_set_string(const char *key, const char *value)
372 snprintf(type, 2, "%d", PREFERENCE_TYPE_STRING);
373 if (strlen(value) > (BUF_LEN-1))
375 LOGE("INVALID_PARAMETER(0x%08x) : param type(%d)", PREFERENCE_ERROR_INVALID_PARAMETER, atoi(type));
376 return PREFERENCE_ERROR_INVALID_PARAMETER;
378 return _write_data(key, type, value);
381 int preference_get_string(const char *key, char **value)
390 LOGE("INVALID_PARAMETER(0x%08x)", PREFERENCE_ERROR_INVALID_PARAMETER);
391 return PREFERENCE_ERROR_INVALID_PARAMETER;
394 ret = _read_data(key, type, data);
395 if (ret == PREFERENCE_ERROR_NONE)
397 if (atoi(type) == PREFERENCE_TYPE_STRING)
399 *value = strdup(data);
402 LOGE("OUT_OF_MEMORY(0x%08x)", PREFERENCE_ERROR_OUT_OF_MEMORY);
403 return PREFERENCE_ERROR_OUT_OF_MEMORY;
408 LOGE("INVALID_PARAMETER(0x%08x) : param type(%d)", PREFERENCE_ERROR_INVALID_PARAMETER, atoi(type));
409 return PREFERENCE_ERROR_INVALID_PARAMETER;
416 int preference_set_boolean(const char *key, bool value)
420 snprintf(type, 2, "%d", PREFERENCE_TYPE_BOOLEAN);
421 snprintf(data, BUF_LEN, "%d", value);
422 return _write_data(key, type, data);
425 int preference_get_boolean(const char *key, bool *value)
433 LOGE("INVALID_PARAMETER(0x%08x)", PREFERENCE_ERROR_INVALID_PARAMETER);
434 return PREFERENCE_ERROR_INVALID_PARAMETER;
437 ret = _read_data(key, type, data);
438 if (ret == PREFERENCE_ERROR_NONE)
440 if (atoi(type) == PREFERENCE_TYPE_BOOLEAN)
442 *value = (bool)atoi(data);
446 LOGE("INVALID_PARAMETER(0x%08x) : param type(%d)", PREFERENCE_ERROR_INVALID_PARAMETER, atoi(type));
447 return PREFERENCE_ERROR_INVALID_PARAMETER;
455 // TODO: below operation is too heavy, let's find the light way to check.
456 int preference_is_existing(const char *key, bool *exist)
465 if (key == NULL || key[0] == '\0' || exist == NULL)
467 LOGE("INVALID_PARAMETER(0x%08x)", PREFERENCE_ERROR_INVALID_PARAMETER);
468 return PREFERENCE_ERROR_INVALID_PARAMETER;
473 if (_initialize() != PREFERENCE_ERROR_NONE)
475 LOGE("IO_ERROR(0x%08x) : fail to initialize db", PREFERENCE_ERROR_IO_ERROR);
476 return PREFERENCE_ERROR_IO_ERROR;
480 /* check data is exist */
481 buf = sqlite3_mprintf("SELECT %s FROM %s WHERE %s=%Q;", PREF_F_KEY_NAME, PREF_TBL_NAME, PREF_F_KEY_NAME, key);
485 LOGE("IO_ERROR(0x%08x) : fail to create query string", PREFERENCE_ERROR_IO_ERROR);
486 return PREFERENCE_ERROR_IO_ERROR;
489 ret = sqlite3_get_table(pref_db, buf, &result, &rows, &columns, &errmsg);
491 if (ret != SQLITE_OK)
493 LOGE("IO_ERROR(0x%08x) : fail to read data(%s)", PREFERENCE_ERROR_IO_ERROR, errmsg);
494 sqlite3_free(errmsg);
495 return PREFERENCE_ERROR_IO_ERROR;
507 sqlite3_free_table(result);
508 return PREFERENCE_ERROR_NONE;
511 static pref_changed_cb_node_t* _find_node(const char *key)
513 pref_changed_cb_node_t *tmp_node;
515 if (key == NULL || key[0] == '\0' )
524 if (strcmp(tmp_node->key, key) == 0)
528 tmp_node = tmp_node->next;
535 static int _add_node(const char *key, preference_changed_cb cb, void *user_data)
537 pref_changed_cb_node_t *tmp_node;
539 if (key == NULL || key[0] == '\0' || cb == NULL)
541 LOGE("INVALID_PARAMETER(0x%08x)", PREFERENCE_ERROR_INVALID_PARAMETER);
542 return PREFERENCE_ERROR_INVALID_PARAMETER;
545 tmp_node = _find_node(key);
547 if (tmp_node != NULL)
550 tmp_node->user_data = user_data;
554 tmp_node = (pref_changed_cb_node_t*)malloc(sizeof(pref_changed_cb_node_t));
555 if (tmp_node == NULL)
557 LOGE("OUT_OF_MEMORY(0x%08x)", PREFERENCE_ERROR_OUT_OF_MEMORY);
558 return PREFERENCE_ERROR_OUT_OF_MEMORY;
561 tmp_node->key = strdup(key);
562 if (tmp_node->key == NULL)
565 LOGE("OUT_OF_MEMORY(0x%08x)", PREFERENCE_ERROR_OUT_OF_MEMORY);
566 return PREFERENCE_ERROR_OUT_OF_MEMORY;
570 head->prev = tmp_node;
572 tmp_node->user_data = user_data;
573 tmp_node->prev = NULL;
574 tmp_node->next = head;
578 return PREFERENCE_ERROR_NONE;
581 static int _remove_node(const char *key)
583 pref_changed_cb_node_t *tmp_node;
585 if (key == NULL || key[0] == '\0' )
587 LOGE("INVALID_PARAMETER(0x%08x)", PREFERENCE_ERROR_INVALID_PARAMETER);
588 return PREFERENCE_ERROR_INVALID_PARAMETER;
591 tmp_node = _find_node(key);
593 if (tmp_node == NULL)
595 return PREFERENCE_ERROR_NONE;
598 if (tmp_node->prev != NULL)
600 tmp_node->prev->next = tmp_node->next;
604 head = tmp_node->next;
607 if (tmp_node->next != NULL)
609 tmp_node->next->prev = tmp_node->prev;
619 return PREFERENCE_ERROR_NONE;
623 static void _remove_all_node(void)
625 pref_changed_cb_node_t *tmp_node;
630 head = tmp_node->next;
642 static void _update_cb(void *data, int action, char const *db_name, char const *table_name, sqlite_int64 rowid)
650 pref_changed_cb_node_t *tmp_node;
652 // skip INSERT/DELETE event
653 if (action != SQLITE_UPDATE)
658 if (strcmp(table_name, PREF_TBL_NAME) != 0)
660 SECURE_LOGE("given table name (%s) is not same", table_name);
664 buf = sqlite3_mprintf("SELECT %s FROM %s WHERE rowid='%lld';", PREF_F_KEY_NAME, PREF_TBL_NAME, rowid);
669 ret = sqlite3_get_table(pref_db, buf, &result, &rows, &columns, &errmsg);
671 if (ret != SQLITE_OK)
673 LOGI("fail to read data(%s)", errmsg);
674 sqlite3_free(errmsg);
680 sqlite3_free_table(result);
684 tmp_node = _find_node(result[1]);
686 if (tmp_node != NULL && tmp_node->cb != NULL)
688 tmp_node->cb(result[1], tmp_node->user_data);
691 sqlite3_free_table(result);
695 int preference_remove(const char *key)
702 ret = preference_is_existing(key, &exist);
703 if (ret != PREFERENCE_ERROR_NONE)
710 return PREFERENCE_ERROR_NO_KEY;
713 /* insert data or update data if data already exist */
714 buf = sqlite3_mprintf("DELETE FROM %s WHERE %s = ?",
715 PREF_TBL_NAME, PREF_F_KEY_NAME, key);
718 LOGE("IO_ERROR(0x%08x) : fail to create query string", PREFERENCE_ERROR_IO_ERROR);
719 return PREFERENCE_ERROR_IO_ERROR;
722 ret = sqlite3_prepare(pref_db, buf, strlen(buf), &stmt, NULL);
723 if (ret != SQLITE_OK) {
724 LOGE("IO_ERROR(0x%08x) : fail to prepare query (%d/%s)",
725 PREFERENCE_ERROR_IO_ERROR,
726 sqlite3_extended_errcode(pref_db),
727 sqlite3_errmsg(pref_db));
728 return PREFERENCE_ERROR_IO_ERROR;
731 ret = sqlite3_bind_text(stmt, 1, key, strlen(key), SQLITE_STATIC);
732 if(ret != SQLITE_OK) {
733 LOGE("IO_ERROR(0x%08x) : fail to bind(1) query (%d/%s)",
734 PREFERENCE_ERROR_IO_ERROR,
735 sqlite3_extended_errcode(pref_db),
736 sqlite3_errmsg(pref_db));
737 sqlite3_finalize(stmt);
738 return PREFERENCE_ERROR_IO_ERROR;
741 ret = sqlite3_step(stmt);
742 if (ret != SQLITE_DONE) {
743 LOGE("IO_ERROR(0x%08x): fail to delete data(%d/%s)",
744 PREFERENCE_ERROR_IO_ERROR,
745 sqlite3_extended_errcode(pref_db),
746 sqlite3_errmsg(pref_db));
747 sqlite3_finalize(stmt);
748 return PREFERENCE_ERROR_IO_ERROR;
751 sqlite3_finalize(stmt);
757 // if exist, remove changed cb
760 return PREFERENCE_ERROR_NONE;
764 int preference_remove_all(void)
772 if (_initialize() != PREFERENCE_ERROR_NONE)
774 LOGE("IO_ERROR(0x%08x) : fail to initialize db", PREFERENCE_ERROR_IO_ERROR);
775 return PREFERENCE_ERROR_IO_ERROR;
779 /* insert data or update data if data already exist */
780 buf = sqlite3_mprintf("DELETE FROM %s;", PREF_TBL_NAME);
783 LOGE("IO_ERROR(0x%08x) : fail to create query string", PREFERENCE_ERROR_IO_ERROR);
784 return PREFERENCE_ERROR_IO_ERROR;
787 ret = sqlite3_exec(pref_db, buf, NULL, NULL, &errmsg);
789 if (ret != SQLITE_OK)
791 LOGE("IO_ERROR(0x%08x) : fail to delete data (%s)", PREFERENCE_ERROR_IO_ERROR, errmsg);
792 sqlite3_free(errmsg);
793 return PREFERENCE_ERROR_IO_ERROR;
796 // if exist, remove changed cb
799 return PREFERENCE_ERROR_NONE;
803 int preference_set_changed_cb(const char *key, preference_changed_cb callback, void *user_data)
808 ret = preference_is_existing(key, &exist);
809 if (ret != PREFERENCE_ERROR_NONE)
816 LOGE("NO_KEY(0x%08x) : fail to find given key(%s)", PREFERENCE_ERROR_NO_KEY, key);
817 return PREFERENCE_ERROR_NO_KEY;
820 if (!is_update_hook_registered)
822 sqlite3_update_hook(pref_db, _update_cb, NULL);
823 is_update_hook_registered = true;
826 return _add_node(key, callback, user_data);
829 int preference_unset_changed_cb(const char *key)
834 ret = preference_is_existing(key, &exist);
835 if (ret != PREFERENCE_ERROR_NONE)
842 LOGE("NO_KEY(0x%08x) : fail to find given key(%s)", PREFERENCE_ERROR_NO_KEY, key);
843 return PREFERENCE_ERROR_NO_KEY;
846 return _remove_node(key);
849 int preference_foreach_item(preference_item_cb callback, void *user_data)
859 if (callback == NULL)
861 LOGE("INVALID_PARAMETER(0x%08x)", PREFERENCE_ERROR_INVALID_PARAMETER);
862 return PREFERENCE_ERROR_INVALID_PARAMETER;
867 if (_initialize() != PREFERENCE_ERROR_NONE)
869 LOGE("IO_ERROR(0x%08x) : fail to initialize db", PREFERENCE_ERROR_IO_ERROR);
870 return PREFERENCE_ERROR_IO_ERROR;
874 buf = sqlite3_mprintf("SELECT %s FROM %s;", PREF_F_KEY_NAME, PREF_TBL_NAME);
877 LOGE("IO_ERROR(0x%08x) : fail to create query string", PREFERENCE_ERROR_IO_ERROR);
878 return PREFERENCE_ERROR_IO_ERROR;
881 ret = sqlite3_get_table(pref_db, buf, &result, &rows, &columns, &errmsg);
883 if (ret != SQLITE_OK)
885 LOGE("IO_ERROR(0x%08x) : fail to read data (%s)", PREFERENCE_ERROR_IO_ERROR, errmsg);
886 sqlite3_free(errmsg);
887 return PREFERENCE_ERROR_IO_ERROR;
890 for (i = 1; i <= rows; i++)
892 if (callback(result[i], user_data) != true)
898 sqlite3_free_table(result);
900 return PREFERENCE_ERROR_NONE;