4 * Copyright (c) 2012 - 2013 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.
24 #include "cal_internal.h"
25 #include "cal_typedef.h"
28 #include "cal_db_util.h"
30 static TLS sqlite3 *calendar_db_handle;
31 static TLS int transaction_cnt = 0;
32 static TLS int transaction_ver = 0;
33 static TLS bool version_up = false;
35 static TLS bool event_change=false;
36 static TLS bool todo_change=false;
37 static TLS bool calendar_change=false;
39 static inline void __cal_db_util_notify_event_change(void)
41 int fd = open(CAL_NOTI_EVENT_CHANGED, O_TRUNC | O_RDWR);
48 static inline void __cal_db_util_notify_todo_change(void)
50 int fd = open(CAL_NOTI_TODO_CHANGED, O_TRUNC | O_RDWR);
57 static inline void __cal_db_util_notify_calendar_change(void)
59 int fd = open(CAL_NOTI_CALENDAR_CHANGED, O_TRUNC | O_RDWR);
62 calendar_change = false;
66 static inline void __cal_db_util_cancel_changes(void)
69 calendar_change = false;
73 int _cal_db_util_notify(cal_noti_type_e type)
75 if (0 < transaction_cnt) {
77 case CAL_NOTI_TYPE_EVENT:
80 case CAL_NOTI_TYPE_TODO:
83 case CAL_NOTI_TYPE_CALENDAR:
84 calendar_change = true;
87 ERR("The type(%d) is not supported", type);
88 return CALENDAR_ERROR_INVALID_PARAMETER;
90 return CALENDAR_ERROR_NONE;
94 case CAL_NOTI_TYPE_EVENT:
95 __cal_db_util_notify_event_change();
97 case CAL_NOTI_TYPE_TODO:
98 __cal_db_util_notify_todo_change();
100 case CAL_NOTI_TYPE_CALENDAR:
101 __cal_db_util_notify_calendar_change();
104 ERR("The type(%d) is not supported", type);
105 return CALENDAR_ERROR_INVALID_PARAMETER;
108 return CALENDAR_ERROR_NONE;
111 int _cal_db_util_open(void)
115 if (!calendar_db_handle) {
116 ret = db_util_open(CAL_DB_PATH, &calendar_db_handle, 0);
117 retvm_if(SQLITE_OK != ret, CALENDAR_ERROR_DB_FAILED,
118 "db_util_open() Failed(%d).", ret);
120 return CALENDAR_ERROR_NONE;
123 int _cal_db_util_close(void)
127 if (calendar_db_handle) {
128 ret = db_util_close(calendar_db_handle);
129 warn_if(SQLITE_OK != ret, "db_util_close() Failed(%d)", ret);
130 calendar_db_handle = NULL;
131 CAL_DBG("The database disconnected really.");
134 return CALENDAR_ERROR_NONE;
137 int _cal_db_util_last_insert_id(void)
139 return sqlite3_last_insert_rowid(calendar_db_handle);
142 int _cal_db_util_query_get_first_int_result(const char *query, GSList *bind_text, int *result)
147 sqlite3_stmt *stmt = NULL;
148 retvm_if(NULL == calendar_db_handle, CALENDAR_ERROR_DB_FAILED, "Database is not opended");
150 ret = sqlite3_prepare_v2(calendar_db_handle, query, strlen(query), &stmt, NULL);
151 retvm_if(SQLITE_OK != ret, CALENDAR_ERROR_DB_FAILED,
152 "sqlite3_prepare_v2(%s) failed(%s).", query, sqlite3_errmsg(calendar_db_handle));
156 for (index = 0; g_slist_nth(bind_text, index); index++)
158 text = (char *)g_slist_nth_data(bind_text, index);
161 _cal_db_util_stmt_bind_text(stmt, index + 1, text);
166 ret = sqlite3_step(stmt);
167 if (SQLITE_ROW != ret)
169 ERR("sqlite3_step() failed(%d, %s).", ret, sqlite3_errmsg(calendar_db_handle));
170 sqlite3_finalize(stmt);
171 if (SQLITE_DONE == ret) return CALENDAR_ERROR_DB_FAILED;
172 return CALENDAR_ERROR_DB_FAILED;
175 if (result) *result = sqlite3_column_int(stmt, 0);
176 sqlite3_finalize(stmt);
178 return CALENDAR_ERROR_NONE;
181 cal_db_util_error_e _cal_db_util_query_exec(char *query)
184 char *err_msg = NULL;
186 retvm_if(NULL == calendar_db_handle, CALENDAR_ERROR_DB_FAILED, "Database is not opended");
187 //CALS_DBG("query : %s", query);
189 ret = sqlite3_exec(calendar_db_handle, query, NULL, NULL, &err_msg);
190 if (SQLITE_OK != ret) {
191 ERR("sqlite3_exec(%s) failed(%d, %s).", query, ret, err_msg);
192 sqlite3_free(err_msg);
196 return CAL_DB_ERROR_LOCKED;
198 return CAL_DB_ERROR_IOERR;
200 return CAL_DB_ERROR_NO_SPACE;
202 return CAL_DB_ERROR_FAIL;
207 sqlite3_free(err_msg);
213 sqlite3_stmt* _cal_db_util_query_prepare(char *query)
216 sqlite3_stmt *stmt = NULL;
218 retvm_if(NULL == query, NULL, "Invalid query");
219 retvm_if(NULL == calendar_db_handle, NULL, "Database is not opended");
220 //CALS_DBG("prepare query : %s", query);
222 ret = sqlite3_prepare_v2(calendar_db_handle, query, strlen(query), &stmt, NULL);
223 retvm_if(SQLITE_OK != ret, NULL,
224 "sqlite3_prepare_v2(%s) Failed(%s).", query, sqlite3_errmsg(calendar_db_handle));
229 cal_db_util_error_e _cal_db_util_stmt_step(sqlite3_stmt *stmt)
232 ret = sqlite3_step(stmt);
236 ret = CAL_DB_ERROR_LOCKED;
239 ret = CAL_DB_ERROR_IOERR;
242 ret = CAL_DB_ERROR_NO_SPACE;
244 case SQLITE_CONSTRAINT:
245 ret = CAL_DB_ERROR_ALREADY_EXIST;
254 ERR("sqlite3_step() Failed(%d)", ret);
255 ret = CAL_DB_ERROR_FAIL;
261 #define CAL_COMMIT_TRY_MAX 500000
262 int _cal_db_util_begin_trans(void)
264 if(transaction_cnt <= 0)
269 ret = _cal_db_util_query_exec("BEGIN IMMEDIATE TRANSACTION");
270 // !! check error code
271 while(CAL_DB_OK != ret && progress < CAL_COMMIT_TRY_MAX) {
273 ret = _cal_db_util_query_exec("BEGIN IMMEDIATE TRANSACTION");
276 retvm_if(CAL_DB_OK != ret, ret, "cal_query_exec() Failed(%d)", ret);
279 const char *query = "SELECT ver FROM "CAL_TABLE_VERSION;
280 ret = _cal_db_util_query_get_first_int_result(query, NULL, &transaction_ver);
281 if (CALENDAR_ERROR_NONE != ret)
283 ERR("_cal_db_util_query_get_first_int_result() failed");
289 CAL_DBG("transaction_cnt : %d", transaction_cnt);
291 return CALENDAR_ERROR_NONE;
294 int _cal_db_util_end_trans(bool is_success)
298 char query[CAL_DB_SQL_MIN_LEN];
302 if (0 != transaction_cnt) {
303 CAL_DBG("transaction_cnt : %d", transaction_cnt);
304 return CALENDAR_ERROR_NONE;
307 if (false == is_success) {
308 __cal_db_util_cancel_changes();
309 ret = _cal_db_util_query_exec("ROLLBACK TRANSACTION");
310 return CALENDAR_ERROR_NONE;
315 snprintf(query, sizeof(query), "UPDATE %s SET ver = %d",
316 CAL_TABLE_VERSION, transaction_ver);
317 ret = _cal_db_util_query_exec(query);
318 warn_if(CAL_DB_OK != ret, "cal_query_exec(version up) Failed(%d).", ret);
322 ret = _cal_db_util_query_exec("COMMIT TRANSACTION");
323 // !! check error code
324 while (CAL_DB_OK != ret && progress < CAL_COMMIT_TRY_MAX) {
326 ret = _cal_db_util_query_exec("COMMIT TRANSACTION");
329 if (CAL_DB_OK != ret) {
331 ERR("cal_query_exec() Failed(%d)", ret);
332 __cal_db_util_cancel_changes();
333 tmp_ret = _cal_db_util_query_exec("ROLLBACK TRANSACTION");
334 warn_if(CAL_DB_OK != tmp_ret, "cal_query_exec(ROLLBACK) Failed(%d).", tmp_ret);
335 return CALENDAR_ERROR_DB_FAILED;
337 if (event_change) __cal_db_util_notify_event_change();
338 if (todo_change) __cal_db_util_notify_todo_change();
339 if (calendar_change) __cal_db_util_notify_calendar_change();
341 CAL_DBG("transaction_ver = %d",transaction_ver);
342 return CALENDAR_ERROR_NONE;
345 int _cal_db_util_get_next_ver(void)
351 if (0 < transaction_cnt) {
353 return transaction_ver + 1;
356 query = "SELECT ver FROM "CAL_TABLE_VERSION;
358 ret = _cal_db_util_query_get_first_int_result(query, NULL, &count);
359 if (CALENDAR_ERROR_NONE != ret)
361 ERR("_cal_db_util_query_get_first_int_result() failed");
367 int _cal_db_util_get_transaction_ver(void)
369 return transaction_ver;