Fix logic to recover corrupted db 53/161953/5
authorSeungha Son <seungha.son@samsung.com>
Tue, 28 Nov 2017 09:49:07 +0000 (18:49 +0900)
committerSeungha Son <seungha.son@samsung.com>
Thu, 30 Nov 2017 04:24:32 +0000 (04:24 +0000)
Signed-off-by: Seungha Son <seungha.son@samsung.com>
Change-Id: I32acf596972e146751ddcbb39fb981a4daa7e317

src/notification_db.c
src/notification_db_query.h

index ff37d90afa86d03d5b77f2ffdb2f6c8b1949b056..267db26fb6958d2f58ed25fd9c18c460c5bf145c 100755 (executable)
 #include <notification_db.h>
 #include "notification_db_query.h"
 
+static bool is_db_corrupted = false;
+
+static int __check_integrity_cb(void *pid, int argc, char **argv, char **notUsed)
+{
+       if (!strcmp(argv[0], "ok")) {
+               NOTIFICATION_ERR("db integrity result : %s" , argv[0]);
+               is_db_corrupted = true;
+               return -1;
+       }
+
+       NOTIFICATION_INFO("db integrity result : %s" , argv[0]);
+       return 0;
+}
+
+static int __recover_corrupted_db(sqlite3 *db)
+{
+       int ret = NOTIFICATION_ERROR_NONE;
+       int sql_ret;
+       char *errmsg = NULL;
+
+       NOTIFICATION_INFO("DB is corrupted, start to recover corrupted db");
+       if (db)
+               sqlite3_close(db);
+       unlink(DBPATH);
+
+       sql_ret = sqlite3_open_v2(DBPATH, &db,
+                               SQLITE_OPEN_CREATE |SQLITE_OPEN_READWRITE,
+                               NULL);
+       if (sql_ret != SQLITE_OK) {
+               NOTIFICATION_ERR("Failed to open db[%d]", sql_ret);
+               unlink(DBPATH);
+               ret = NOTIFICATION_ERROR_FROM_DB;
+               goto out;
+       }
+
+       sql_ret = sqlite3_exec(db, CREATE_NOTIFICATION_TABLE, NULL, NULL, &errmsg);
+       if (sql_ret != SQLITE_OK) {
+               NOTIFICATION_ERR("Failed to exec query[%d][%s]", sql_ret, errmsg);
+               ret = NOTIFICATION_ERROR_FROM_DB;
+       }
+
+out:
+       if (errmsg)
+               sqlite3_free(errmsg);
+
+       return ret;
+}
+
 EXPORT_API int notification_db_init()
 {
-       int ret;
+       int ret = NOTIFICATION_ERROR_NONE;
+       int sql_ret;
        sqlite3 *db = NULL;
        char *errmsg = NULL;
 
-       ret = sqlite3_open_v2(DBPATH, &db,
+       sql_ret = sqlite3_open_v2(DBPATH, &db,
                        SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, NULL);
-       if (ret != SQLITE_OK) {
+       if (sql_ret != SQLITE_OK) {
                /* LCOV_EXCL_START */
                NOTIFICATION_ERR("Failed to open db[%d]", ret);
-
-               if (sqlite3_errcode(db) == SQLITE_CORRUPT) {
-                       if (db)
-                               sqlite3_close(db);
-                       unlink(DBPATH);
-
-                       ret = sqlite3_open_v2(DBPATH, &db, SQLITE_OPEN_CREATE |
-                                       SQLITE_OPEN_READWRITE, NULL);
-                       if (ret != SQLITE_OK) {
-                               NOTIFICATION_ERR("Failed to open db[%d]", ret);
-                               unlink(DBPATH);
-                               ret = NOTIFICATION_ERROR_FROM_DB;
-                               goto out;
-                       }
-               } else {
-                       ret = NOTIFICATION_ERROR_FROM_DB;
-                       goto out;
-               }
+               ret = NOTIFICATION_ERROR_FROM_DB;
+               goto out;
                /* LCOV_EXCL_STOP */
        }
 
-       ret = sqlite3_exec(db, CREATE_NOTIFICATION_TABLE, NULL, NULL, &errmsg);
-       if (ret != SQLITE_OK) {
+       sql_ret = sqlite3_exec(db, CREATE_NOTIFICATION_TABLE, NULL, NULL, &errmsg);
+       if (sql_ret != SQLITE_OK) {
                /* LCOV_EXCL_START */
                NOTIFICATION_ERR("Failed to exec sqlite[%d][%s]", ret, errmsg);
-
-               if (ret == SQLITE_CORRUPT || ret == SQLITE_NOTADB) {
-                       sqlite3_close(db);
-                       unlink(DBPATH);
-                       ret = sqlite3_open_v2(DBPATH, &db, SQLITE_OPEN_CREATE |
-                                       SQLITE_OPEN_READWRITE, NULL);
-                       if (ret != SQLITE_OK) {
-                               NOTIFICATION_ERR("Failed to open db[%d]", ret);
-                               unlink(DBPATH);
-                               ret = NOTIFICATION_ERROR_FROM_DB;
-                               goto out;
-                       }
-
-                       sqlite3_free(errmsg);
-                       ret = sqlite3_exec(db, CREATE_NOTIFICATION_TABLE, NULL,
-                                               NULL, &errmsg);
-                       if (ret != SQLITE_OK) {
-                               NOTIFICATION_ERR("Failed to exec sqlite, \
-                                               again[%d][%s]", ret, errmsg);
-                               unlink(DBPATH);
-                               ret = NOTIFICATION_ERROR_FROM_DB;
-                               goto out;
-                       }
-               } else {
-                       ret = NOTIFICATION_ERROR_FROM_DB;
-                       goto out;
-               }
+               ret = NOTIFICATION_ERROR_FROM_DB;
+               goto out;
                /* LCOV_EXCL_STOP */
        }
 
-       ret = NOTIFICATION_ERROR_NONE;
+       sql_ret = sqlite3_exec(db, "PRAGMA integrity_check",
+                              __check_integrity_cb, NULL, &errmsg);
+       if (sql_ret != SQLITE_OK || is_db_corrupted) {
+               NOTIFICATION_ERR("Failed to exec query[%d][%s]", sql_ret, errmsg);
+               ret = NOTIFICATION_ERROR_FROM_DB;
+       }
 
 out:
+       if (sql_ret == SQLITE_CORRUPT || sql_ret == SQLITE_NOTADB || is_db_corrupted)
+               ret = __recover_corrupted_db(db);
        if (errmsg)
                sqlite3_free(errmsg);
-
        if (db)
                sqlite3_close(db);
 
index 6a22573b3424692bc67196ecaddd51638ddf602f..ef11a451fff14be063935ec91efa4b2f48d17743 100755 (executable)
@@ -22,7 +22,6 @@
 #define CREATE_NOTIFICATION_TABLE \
        "PRAGMA journal_mode = PERSIST;\n" \
        "PRAGMA synchronous = FULL;\n" \
-       "PRAGMA integrity_check;\n" \
        "CREATE TABLE IF NOT EXISTS noti_list (\n" \
        "  type INTEGER NOT NULL,\n" \
        "  layout INTEGER NOT NULL DEFAULT 0,\n" \