2 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
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.
21 #include "db-internal.h"
22 #include "table-statistics.h"
23 #include "table-restrictions.h"
24 #include "table-counters.h"
25 #include "table-firewall.h"
27 #define SQLITE_BUSY_TIMEOUT 500000
29 static sqlite3 *database;
32 static int __stc_db_busy(void *user, int attempts)
34 __STC_LOG_FUNC_ENTER__;
35 STC_LOGE("DB locked by another process, attempts number %d",
38 usleep(SQLITE_BUSY_TIMEOUT); /* wait for a half second*/
39 __STC_LOG_FUNC_EXIT__;
43 static gboolean __stc_db_restore(const char *src, const char *dst)
50 result = g_file_get_contents(src, &buf, &length, &error);
52 STC_LOGE("Failed to read [%s]", error->message);
57 result = g_file_set_contents(dst, buf, length, &error);
59 STC_LOGE("Failed to write [%s]", error->message);
65 STC_LOGD("Successfully restored database");
71 static gboolean __stc_db_table_init()
73 EXEC(STC_ERROR_NONE, table_statistics_prepare(database));
74 EXEC(STC_ERROR_NONE, table_restrictions_prepare(database));
75 EXEC(STC_ERROR_NONE, table_counters_prepare(database));
76 EXEC(STC_ERROR_NONE, table_firewall_prepare(database));
77 EXEC(STC_ERROR_NONE, stc_init_db_guard());
82 static int __stc_db_open(void)
86 ret = sqlite3_open(DATABASE_FULL_PATH, &database);
87 if (ret != SQLITE_OK) {
88 STC_LOGD("Failed to open database [%s]", sqlite3_errmsg(database));
89 return STC_ERROR_DB_FAILED;
92 STC_LOGD("Successfully opened database");
96 static int __stc_db_exec(char *sql, void *cb)
101 if (database == NULL)
102 return STC_ERROR_DB_FAILED;
104 ret = sqlite3_exec(database, sql, cb, 0, &error);
105 if (ret != SQLITE_OK) {
106 STC_LOGE("Failed to execute sql [%d:%s]", ret, error);
108 sqlite3_close(database);
110 __STC_LOG_FUNC_EXIT__;
111 return STC_ERROR_DB_FAILED;
114 return STC_ERROR_NONE;
117 static int __stc_db_integrity_cb(void *err, int count, char **data, char **columns)
119 STC_LOGD("%s [%s]", columns[0], data[0] ? data[0] : "null");
121 if (!g_strcmp0(columns[0], "integrity_check") && !g_strcmp0(data[0], "ok"))
127 static int __stc_db_check_integrity(void)
132 sql = sqlite3_mprintf("PRAGMA integrity_check");
133 ret = __stc_db_exec(sql, __stc_db_integrity_cb);
134 if (ret == STC_ERROR_NONE)
135 STC_LOGD("Successfully checked integrity");
142 static int __stc_db_set_locking_mode(void)
147 sql = sqlite3_mprintf("PRAGMA locking_mode = NORMAL");
148 ret = __stc_db_exec(sql, NULL);
149 if (ret == STC_ERROR_NONE)
150 STC_LOGD("Successfully set locking mode");
157 static int __stc_db_stat(void)
159 struct stat db_stat = { 0 };
161 if (stat(DATABASE_FULL_PATH, &db_stat)) {
162 STC_LOGD("Db restoration is required [no file]");
163 return STC_ERROR_DB_FAILED;
164 } else if (db_stat.st_size == 0) {
165 STC_LOGD("Db restoration is required [size is zero]");
166 return STC_ERROR_DB_FAILED;
169 return STC_ERROR_NONE;
172 static int __stc_db_verify(void)
174 ret_value_msg_if(__stc_db_check_integrity() != STC_ERROR_NONE,
175 STC_ERROR_DB_FAILED, "Failed to check integrity");
177 ret_value_msg_if(__stc_db_set_locking_mode() != STC_ERROR_NONE,
178 STC_ERROR_DB_FAILED, "Failed to set locking mode");
180 return STC_ERROR_NONE;
184 stc_error_e stc_db_initialize_once()
186 __STC_LOG_FUNC_ENTER__;
187 int retry_count = MAX_DB_RETRY_COUNT;
189 if (database != NULL) {
190 __STC_LOG_FUNC_EXIT__;
191 return STC_ERROR_NONE;
194 if (__stc_db_stat() != STC_ERROR_NONE) {
195 if (!__stc_db_restore(DATABASE_BACKUP_PATH, DATABASE_FULL_PATH)) {
196 __STC_LOG_FUNC_EXIT__;
197 return STC_ERROR_DB_FAILED;
202 if (__stc_db_open() == SQLITE_OK) {
203 if (__stc_db_verify() == STC_ERROR_NONE) {
204 STC_LOGD("Successfully verified database");
207 __stc_db_restore(DATABASE_BACKUP_PATH, DATABASE_FULL_PATH);
210 usleep(MAX_USLEEP_TIMEOUT);
211 STC_LOGD("Retry opening database [%d]", MAX_DB_RETRY_COUNT - retry_count + 1);
212 } while (retry_count--);
214 if (retry_count == 0) {
215 STC_LOGE("Failed to initialize database");
216 sqlite3_close(database);
218 __STC_LOG_FUNC_EXIT__;
219 return STC_ERROR_DB_FAILED;
222 /* Set how many times we'll repeat our attempts for sqlite_step */
223 if (sqlite3_busy_handler(database, __stc_db_busy, NULL) != SQLITE_OK)
224 STC_LOGE("Couldn't set busy handler!");
226 STC_LOGD("Successfully initialize database");
227 __STC_LOG_FUNC_EXIT__;
228 return STC_ERROR_NONE;
232 sqlite3 *stc_db_get_database(void)
234 if (database == NULL)
235 stc_db_initialize_once();
241 stc_error_e stc_db_initialize(void)
243 __STC_LOG_FUNC_ENTER__;
245 int retry_count = MAX_DB_RETRY_COUNT;
249 stc_db_initialize_once();
250 ret = __stc_db_table_init();
252 STC_LOGD("Successfully initialize database");
255 __stc_db_restore(DATABASE_BACKUP_PATH, DATABASE_FULL_PATH);
256 sqlite3_close(database);
259 STC_LOGD("Retry init database [%d]", MAX_DB_RETRY_COUNT - retry_count + 1);
260 } while (retry_count--);
262 __STC_LOG_FUNC_EXIT__;
263 return STC_ERROR_NONE;
266 gboolean stc_db_deinitialize(void)
268 __STC_LOG_FUNC_ENTER__;
269 if (database == NULL) {
270 __STC_LOG_FUNC_EXIT__;
274 table_statistics_finalize();
275 table_restrictions_finalize();
276 table_counters_finalize();
277 table_firewall_finalize();
278 sqlite3_close(database);
280 __STC_LOG_FUNC_EXIT__;