Update DB tolerance logic 71/214371/3 accepted/tizen/unified/20190923.011228 submit/tizen/20190920.150357
authorwn.jang <wn.jang@samsung.com>
Fri, 20 Sep 2019 14:30:08 +0000 (23:30 +0900)
committerWonnam Jang <wn.jang@samsung.com>
Fri, 20 Sep 2019 15:03:43 +0000 (15:03 +0000)
Change-Id: I7ba1e8870cc763a218cf2dea38592ae1f6435b46

common/vc_cmd_db.c
common/vc_cmd_db.h
server/vcd_server.c

index 74087db..37726a9 100644 (file)
@@ -61,7 +61,7 @@ static sqlite3* g_db_backup_handle = NULL;
 static char* g_path = NULL;
 static char* g_backup_path = NULL;
 static int g_ref_cnt = 0;
-static bool is_db_corrupted = false;
+
 int g_fpid = -1;
 int g_db_cnt = 0;
 int g_backup_db_cnt = 0;
@@ -1443,7 +1443,7 @@ static int __vc_db_create_table(sqlite3* db_handle, const char* table)
        return VC_DB_ERROR_NONE;
 }
 
-int __vc_db_open_db(char** path, sqlite3** db_handle)
+int __vc_db_open_db_for_daemon(char** path, sqlite3** db_handle)
 {
        struct stat stat;
        int ret = db_util_open(*path, db_handle, DB_UTIL_REGISTER_HOOK_METHOD);
@@ -1508,53 +1508,97 @@ int __vc_db_open_db(char** path, sqlite3** db_handle)
                int ret = sqlite3_exec(*db_handle, sql, NULL, NULL, &err_msg);
                if (ret != SQLITE_OK) {
                        SLOG(LOG_ERROR, vc_db_tag(), "sqlite3_exec returned %d: %s", ret, err_msg);
+                       return VC_DB_ERROR_OPERATION_FAILED;
                }
        }
        return VC_DB_ERROR_NONE;
 }
 
-static int __vc_db_integrity_check_cb(void *NotUsed, int argc, char **argv, char **azColName)
+static int __vc_db_restore_table(sqlite3* db_handle, const char* table)
 {
-       SLOG(LOG_INFO, vc_db_tag(), "integrity check cb is called");
-
-       char *check_str = "ok";
-       if (0 != strncmp(argv[0], check_str, strlen(check_str))) {
-               SLOG(LOG_ERROR, vc_db_tag(), "db integrity result : %s", argv[0]);
-               is_db_corrupted = true;
-               return -1;
+       /* check whether there is a vc_info table or not */
+       bool is_exist = false;
+       int ret = __vc_db_check_table(db_handle, table, &is_exist);
+       if (VC_DB_ERROR_NONE != ret || false == is_exist) {
+               SLOG(LOG_WARN, vc_db_tag(), "[WARNING] There is no table (%s) (%d). Make a table", table, ret);
+               if (VC_DB_ERROR_NONE != __vc_db_create_table(db_handle, table)) {
+                       SLOG(LOG_ERROR, vc_db_tag(), "[ERROR] Fail to create table(%s), %d", table, ret);
+                       return VC_DB_ERROR_OPERATION_FAILED;
+               }
+       } else {
+               SLOG(LOG_INFO, vc_db_tag(), "[INFO] There is the table (%s)", table);
        }
-
-       SLOG(LOG_INFO, vc_db_tag(), "db integrity result : %s", argv[0]);
-       return 0;
+       return VC_DB_ERROR_NONE;
 }
 
-bool __vc_db_connect_db(char** path, sqlite3** db_handle)
+bool __vc_db_connect_db_for_daemon(char** path, sqlite3** db_handle)
 {
        bool is_connect = false;
-       int ret = __vc_db_open_db(path, db_handle);
+       int ret = __vc_db_open_db_for_daemon(path, db_handle);
        if (0 != ret) {
                int cnt = 0;
                while (cnt <= 5) {
-                       SLOG(LOG_ERROR, vc_db_tag(), "[ERROR] Fail to open DB");
+                       SLOG(LOG_ERROR, vc_db_tag(), "[ERROR] Fail to open DB for daemon");
 
                        usleep(100000);
-                       if (0 == __vc_db_open_db(path, db_handle)) {
-                               SLOG(LOG_ERROR, vc_db_tag(), "[INFO] Success to open DB");
+                       if (0 == __vc_db_open_db_for_daemon(path, db_handle)) {
+                               SLOG(LOG_ERROR, vc_db_tag(), "[INFO] Success to open DB for daemon");
                                is_connect = true;
                                break;
                        }
                        cnt++;
                }
        } else {
-               SLOG(LOG_ERROR, vc_db_tag(), "[INFO] Success to open DB");
+               SLOG(LOG_ERROR, vc_db_tag(), "[INFO] Success to open DB for daemon");
                is_connect = true;
        }
        return is_connect;
 }
 
-int vc_db_initialize(void)
+static int __vc_db_integrity_check_cb(void *NotUsed, int argc, char **argv, char **azColName)
+{
+       SLOG(LOG_INFO, vc_db_tag(), "integrity check cb is called");
+
+       int ret;
+       char *check_str = "ok";
+       if (0 != strncmp(argv[0], check_str, strlen(check_str))) {
+               SLOG(LOG_ERROR, vc_db_tag(), "[ERROR] Doesn't have integrity(%s), retry to connect after removing", argv[0]);
+               if (0 != remove(g_path)) {
+                       SLOG(LOG_ERROR, vc_db_tag(), "[Error] remove file(%s) is failed for daemon", g_path);
+                       g_db_cnt = (g_db_cnt + 1) % 1000;
+                       snprintf(g_path, 256, "%s/.vc_info_%d.db", VC_RUNTIME_INFO_ROOT, g_db_cnt);
+               }
+               bool is_connect = __vc_db_connect_db_for_daemon(&g_path, &g_db_handle);
+               if (true == is_connect) {
+                       SLOG(LOG_ERROR, vc_db_tag(), "[INFO] Success to connect main DB for daemon");
+                       ret = __vc_db_restore_table(g_db_handle, VC_INFO_TABLE);
+                       if (0 != ret) {
+                               SLOG(LOG_ERROR, vc_db_tag(), "[ERROR] Fail to create table (%s)", VC_INFO_TABLE);
+                       }
+                       ret = __vc_db_restore_table(g_db_handle, VC_RESULT_TABLE);
+                       if (0 != ret) {
+                               SLOG(LOG_ERROR, vc_db_tag(), "[ERROR] Fail to create table (%s)", VC_RESULT_TABLE);
+                       }
+                       is_connect = __vc_db_connect_db_for_daemon(&g_backup_path, &g_db_backup_handle);
+                       if (true == is_connect) {
+                               SLOG(LOG_ERROR, vc_db_tag(), "[INFO] Success to connect backup DB for daemon");
+                               if (0 != vc_db_restore_command()) {
+                                       SLOG(LOG_ERROR, vc_db_tag(), "[ERROR] Fail to restore command");
+                               }
+                       }
+               } else {
+                       SLOG(LOG_ERROR, vc_db_tag(), "[ERROR] Fail to connect main DB for daemon");
+                       return VC_DB_ERROR_OPERATION_FAILED;
+               }
+       }
+
+       SLOG(LOG_INFO, vc_db_tag(), "db integrity result : %s", argv[0]);
+       return VC_DB_ERROR_NONE;
+}
+
+int vc_db_initialize_for_daemon(void)
 {
-       SLOG(LOG_INFO, vc_db_tag(), "DB initialization");
+       SLOG(LOG_INFO, vc_db_tag(), "DB on initialization for daemon");
 
        if (0 < g_ref_cnt) {
                g_ref_cnt++;
@@ -1578,41 +1622,159 @@ int vc_db_initialize(void)
        }
        snprintf(g_backup_path, 256, "%s/.vc_backup.db", VC_RUNTIME_INFO_ROOT);
 
-       bool is_connect = __vc_db_connect_db(&g_path, &g_db_handle);
+       bool is_connect = __vc_db_connect_db_for_daemon(&g_path, &g_db_handle);
        if (false == is_connect) {
-               SLOG(LOG_ERROR, vc_db_tag(), "[ERROR] Fail to connect main DB, retry to connect after removing file");
+               SLOG(LOG_ERROR, vc_db_tag(), "[ERROR] Fail to connect main DB, retry to connect after removing");
                if (0 != remove(g_path)) {
-                       SLOG(LOG_ERROR, vc_db_tag(), "[Error] remove file(%s) is failed", g_path);
+                       SLOG(LOG_ERROR, vc_db_tag(), "[Error] remove file(%s) is failed for daemon", g_path);
                        g_db_cnt = (g_db_cnt + 1) % 1000;
                        snprintf(g_path, 256, "%s/.vc_info_%d.db", VC_RUNTIME_INFO_ROOT, g_db_cnt);
                }
-               is_connect = __vc_db_connect_db(&g_path, &g_db_handle);
+               is_connect = __vc_db_connect_db_for_daemon(&g_path, &g_db_handle);
                if (true == is_connect) {
-                       SLOG(LOG_ERROR, vc_db_tag(), "[INFO] Success to connect main DB");
-                       is_connect = __vc_db_connect_db(&g_backup_path, &g_db_backup_handle);
+                       SLOG(LOG_ERROR, vc_db_tag(), "[INFO] Success to connect main DB for daemon");
+                       is_connect = __vc_db_connect_db_for_daemon(&g_backup_path, &g_db_backup_handle);
                        if (true == is_connect) {
-                               SLOG(LOG_ERROR, vc_db_tag(), "[INFO] Success to connect backup DB");
+                               SLOG(LOG_ERROR, vc_db_tag(), "[INFO] Success to connect backup DB for daemon");
                                if (0 != vc_db_restore_command()) {
                                        SLOG(LOG_ERROR, vc_db_tag(), "[ERROR] Fail to restore command");
                                }
                        }
                } else {
-                       SLOG(LOG_ERROR, vc_db_tag(), "[ERROR] Fail to connect main DB");
+                       SLOG(LOG_ERROR, vc_db_tag(), "[ERROR] Fail to connect main DB for daemon");
                        return VC_DB_ERROR_OPERATION_FAILED;
                }
        }
 
        int ret = sqlite3_exec(g_db_handle, "pragma integrity_check", __vc_db_integrity_check_cb, NULL, NULL);
-       if (true == is_db_corrupted || SQLITE_CORRUPT == ret) {
-               SLOG(LOG_ERROR, vc_db_tag(), "[ERROR] Fail to open DB");
+       if (SQLITE_CORRUPT == ret) {
+               SLOG(LOG_ERROR, vc_db_tag(), "[ERROR] Fail to open DB for daemon");
 
                ret = db_util_close(g_db_handle);
                if (ret != SQLITE_OK) {
-                       SLOG(LOG_ERROR, vc_db_tag(), "[ERROR] Fail to close db, ret %d: %s", ret, sqlite3_errmsg(g_db_handle));
+                       SLOG(LOG_ERROR, vc_db_tag(), "[ERROR] Fail to close db, ret %d: %s for daemon", ret, sqlite3_errmsg(g_db_handle));
                }
                g_db_handle = NULL;
 
                if (0 != remove(g_path)) {
+                       SLOG(LOG_ERROR, vc_db_tag(), "[Error] remove file(%s) is failed for daemon", g_path);
+                       g_db_cnt = (g_db_cnt + 1) % 1000;
+                       snprintf(g_path, 256, "%s/.vc_info_%d.db", VC_RUNTIME_INFO_ROOT, g_db_cnt);
+               }
+               is_connect = __vc_db_connect_db_for_daemon(&g_path, &g_db_handle);
+               if (true == is_connect) {
+                       SLOG(LOG_ERROR, vc_db_tag(), "[INFO] Success to connect main DB for daemon");
+                       is_connect = __vc_db_connect_db_for_daemon(&g_backup_path, &g_db_backup_handle);
+                       if (true == is_connect) {
+                               SLOG(LOG_ERROR, vc_db_tag(), "[INFO] Success to connect backup DB for daemon");
+                               if (0 != vc_db_restore_command()) {
+                                       SLOG(LOG_ERROR, vc_db_tag(), "[ERROR] Fail to restore command for daemon");
+                               }
+                       }
+               } else {
+                       SLOG(LOG_ERROR, vc_db_tag(), "[ERROR] Fail to connect main DB for daemon");
+                       return VC_DB_ERROR_OPERATION_FAILED;
+               }
+
+               g_ref_cnt++;
+               SLOG(LOG_INFO, vc_db_tag(), "[SUCCESS] DB initialization after restore for daemon");
+               return 0;
+       }
+
+       is_connect = __vc_db_connect_db_for_daemon(&g_backup_path, &g_db_backup_handle);
+       if (false == is_connect) {
+               SLOG(LOG_ERROR, vc_db_tag(), "[ERROR] Fail to open backup DB, retry to connect after removing file for daemon");
+               if (0 != remove(g_backup_path)) {
+                       g_backup_db_cnt = (g_backup_db_cnt + 1) % 1000;
+                       SLOG(LOG_ERROR, vc_db_tag(), "[Error] remove file(%s) is failed", g_backup_path);
+                       snprintf(g_backup_path, 256, "%s/.vc_backup_%d.db", VC_RUNTIME_INFO_ROOT, g_backup_db_cnt);
+               }
+               is_connect = __vc_db_connect_db_for_daemon(&g_path, &g_db_backup_handle);
+               if (true == is_connect) {
+                       SLOG(LOG_ERROR, vc_db_tag(), "[INFO] Success to connect backup DB for daemon");
+                       if (0 != vc_db_restore_command()) {
+                               SLOG(LOG_ERROR, vc_db_tag(), "[ERROR] Fail to restore command for daemon");
+                       }
+               }
+       }
+
+       g_ref_cnt++;
+
+       SLOG(LOG_INFO, vc_db_tag(), "[SUCCESS] DB initialization for daemon");
+       return VC_DB_ERROR_NONE;
+}
+
+int __vc_db_open_db(char** path, sqlite3** db_handle)
+{
+       int ret = db_util_open(*path, db_handle, DB_UTIL_REGISTER_HOOK_METHOD);
+       if (ret != SQLITE_OK) {
+               SLOG(LOG_ERROR, vc_db_tag(), "[ERROR] Fail to open db for daemon, path = %s, ret %d: %s", *path, ret, sqlite3_errmsg(*db_handle));
+               if (*db_handle) {
+                       db_util_close(*db_handle);
+                       *db_handle = NULL;
+               }
+
+               free(*path);
+               *path = NULL;
+               return VC_DB_ERROR_OPERATION_FAILED;
+       }
+       return VC_DB_ERROR_NONE;
+}
+
+bool __vc_db_connect_db(char** path, sqlite3** db_handle)
+{
+       bool is_connect = false;
+       int ret = __vc_db_open_db(path, db_handle);
+       if (0 != ret) {
+               int cnt = 0;
+               while (cnt <= 5) {
+                       SLOG(LOG_ERROR, vc_db_tag(), "[ERROR] Fail to open DB");
+
+                       usleep(100000);
+                       if (0 == __vc_db_open_db(path, db_handle)) {
+                               SLOG(LOG_ERROR, vc_db_tag(), "[INFO] Success to open DB");
+                               is_connect = true;
+                               break;
+                       }
+                       cnt++;
+               }
+       } else {
+               SLOG(LOG_ERROR, vc_db_tag(), "[INFO] Success to open DB");
+               is_connect = true;
+       }
+       return is_connect;
+}
+
+int vc_db_initialize(void)
+{
+       SLOG(LOG_INFO, vc_db_tag(), "DB on initialization");
+
+       if (0 < g_ref_cnt) {
+               g_ref_cnt++;
+               return VC_DB_ERROR_NONE;
+       }
+
+       /* For voice control DB */
+       g_path = (char*)calloc(256, sizeof(char));
+       if (NULL == g_path) {
+               SLOG(LOG_ERROR, vc_db_tag(), "[ERROR] Fail to allocate memory");
+               return VC_DB_ERROR_OUT_OF_MEMORY;
+       }
+       /* This should be changed to general DB space - TZ_USER_DB */
+       snprintf(g_path, 256, "%s/.vc_info.db", VC_RUNTIME_INFO_ROOT);
+
+       /* For Backup DB */
+       g_backup_path = (char*)calloc(256, sizeof(char));
+       if (NULL == g_backup_path) {
+               SLOG(LOG_ERROR, vc_db_tag(), "[ERROR] Fail to allocate memory");
+               return VC_DB_ERROR_OUT_OF_MEMORY;
+       }
+       snprintf(g_backup_path, 256, "%s/.vc_backup.db", VC_RUNTIME_INFO_ROOT);
+
+       bool is_connect = __vc_db_connect_db(&g_path, &g_db_handle);
+       if (false == is_connect) {
+               SLOG(LOG_ERROR, vc_db_tag(), "[ERROR] Fail to connect main DB, retry to connect after removing");
+               if (0 != remove(g_path)) {
                        SLOG(LOG_ERROR, vc_db_tag(), "[Error] remove file(%s) is failed", g_path);
                        g_db_cnt = (g_db_cnt + 1) % 1000;
                        snprintf(g_path, 256, "%s/.vc_info_%d.db", VC_RUNTIME_INFO_ROOT, g_db_cnt);
@@ -1631,10 +1793,6 @@ int vc_db_initialize(void)
                        SLOG(LOG_ERROR, vc_db_tag(), "[ERROR] Fail to connect main DB");
                        return VC_DB_ERROR_OPERATION_FAILED;
                }
-
-               g_ref_cnt++;
-               SLOG(LOG_INFO, vc_db_tag(), "[SUCCESS] DB initialization after restore");
-               return 0;
        }
 
        is_connect = __vc_db_connect_db(&g_backup_path, &g_db_backup_handle);
@@ -1647,7 +1805,7 @@ int vc_db_initialize(void)
                }
                is_connect = __vc_db_connect_db(&g_path, &g_db_backup_handle);
                if (true == is_connect) {
-                       SLOG(LOG_ERROR, vc_db_tag(), "[INFO] Success to connect backup DB");
+                       SLOG(LOG_ERROR, vc_db_tag(), "[INFO] Success to connect backup");
                        if (0 != vc_db_restore_command()) {
                                SLOG(LOG_ERROR, vc_db_tag(), "[ERROR] Fail to restore command");
                        }
@@ -2044,9 +2202,12 @@ static int __vc_db_insert_command(sqlite3* db_handle, int pid, vc_cmd_type_e typ
 
 int vc_db_insert_command(int pid, vc_cmd_type_e type, vc_cmd_s* cmd, bool skip_invocation)
 {
-       int ret = __vc_db_insert_command(g_db_handle, pid, type, cmd, skip_invocation);
-       if (0 != ret) {
-               SLOG(LOG_DEBUG, vc_db_tag(), "[ERROR] Fail to insert command, %d", ret);
+       int cnt = 0;
+       int ret = -1;
+       while (cnt < 5 && (ret = __vc_db_insert_command(g_db_handle, pid, type, cmd, skip_invocation))) {
+               usleep(100000);
+               SLOG(LOG_DEBUG, vc_db_tag(), "[ERROR] Fail to insert command(%d), retry cnt(%d)", ret, cnt);
+               cnt++;
        }
        return ret;
 }
index 0a4f76a..87376e5 100644 (file)
@@ -50,6 +50,8 @@ typedef struct _deactivated_app_s {
        char*   appid;
 } vc_deactivated_app_s;
 
+int vc_db_initialize_for_daemon(void);
+
 int vc_db_initialize(void);
 
 int vc_db_finalize(void);
index c640d82..c4425d0 100644 (file)
@@ -1222,7 +1222,7 @@ int vcd_initialize(vce_request_callback_s *callback)
                SLOG(LOG_ERROR, TAG_VCD, "[Server WARNING] Fail to initialize config.");
        }
 
-       ret = vc_db_initialize();
+       ret = vc_db_initialize_for_daemon();
        if (0 != ret) {
                SLOG(LOG_ERROR, TAG_VCD, "[ERROR] Fail to initialize DB : %d", ret);
                return ret;