Add db integrity check 94/226894/6 submit/tizen/20200309.062544
authorjk.koo <jk.koo@samsung.com>
Fri, 6 Mar 2020 06:49:56 +0000 (15:49 +0900)
committerjk.koo <jk.koo@samsung.com>
Mon, 9 Mar 2020 05:03:21 +0000 (14:03 +0900)
Change-Id: Ie46ee7fe48510d9034455e652a40adb1e84037cf
Signed-off-by: jk.koo <jk.koo@samsung.com>
packaging/contacts-service.spec
server/ctsvc_schema_recovery.c
server/ctsvc_server_group.c
server/ctsvc_server_sqlite.c
server/ctsvc_server_sqlite.h
server/db/ctsvc_db_schema.h

index e5ca4d7..67a3a00 100644 (file)
@@ -1,6 +1,6 @@
 Name:       contacts-service
 Summary:    Contacts Service
-Version:    0.13.75
+Version:    0.13.76
 Release:    0
 Group:      Social & Content/Service
 License:    Apache-2.0
index 17aa3d8..adeb6ac 100644 (file)
@@ -51,7 +51,7 @@ static inline int __ctsvc_server_remake_db_file()
        char *errmsg = NULL;
        sqlite3 *db = NULL;
 
-       ret = ctsvc_server_db_open(&db);
+       ret = ctsvc_server_db_open(&db, NULL);
        RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "ctsvc_server_db_open() Fail(%d)", ret);
 
        ret = sqlite3_exec(db, schema_query, NULL, 0, &errmsg);
@@ -67,49 +67,114 @@ static inline int __ctsvc_server_remake_db_file()
        return CONTACTS_ERROR_NONE;
 }
 
-static int __ctsvc_server_check_table()
+static bool need_to_remove = false;
+static int __integrity_callback(void *pid, int argc, char **argv, char **notUsed2)
 {
-       int ret;
+       CTS_FN_CALL;
+
+       if (NULL == argv || NULL == argv[0]) {
+               ERR("Invalid parameter");
+               need_to_remove = true;
+               return -1;
+       }
+
+       if (0 != strcmp(argv[0], "ok")) {
+               ERR("integrity_check() Fail(argv[%s])", argv[0]);
+               need_to_remove = true;
+               return -1;
+       }
+
+       DBG("integrity_check done");
+       return 0;
+}
+
+static int __ctsvc_server_check_db_integrity(void)
+{
+       CTS_FN_CALL;
+       int ret = 0;
        sqlite3 *db = NULL;
-       char query[CTS_SQL_MAX_LEN] = {0};
        cts_stmt stmt = NULL;
+       int sqlite_error = SQLITE_OK;
 
-       ret = ctsvc_server_db_open(&db);
-       RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "ctsvc_server_db_open() Fail(%d)", ret);
+       ret = ctsvc_server_db_open(&db, &sqlite_error);
+       if (CONTACTS_ERROR_NONE != ret) {
+               /* LCOV_EXCL_START */
+               ERR("ctsvc_server_db_open() Fail(%d), sqlite_error(%d)", ret, sqlite_error);
+               if (SQLITE_ERROR == sqlite_error ||SQLITE_CORRUPT == sqlite_error ||SQLITE_NOTADB == sqlite_error)
+                       return -1;
+               else
+                       return 0;
+               /* LCOV_EXCL_STOP */
+       }
+
+       ret = sqlite3_exec(db, "pragma integrity_check", __integrity_callback, NULL, NULL);
+       if (true == need_to_remove || SQLITE_ERROR == ret || SQLITE_CORRUPT == ret || SQLITE_NOTADB == ret) {
+               /* LCOV_EXCL_START */
+               ERR("need_to_remove [%s], ret [%d]", need_to_remove ? "true" : "false", ret);
+               need_to_remove = false;
+               return -1;
+               /* LCOV_EXCL_STOP */
+       }
 
-       snprintf(query, sizeof(query),
-                       "SELECT name FROM sqlite_master WHERE type='table' AND name='%s'",
-                       CTS_TABLE_CONTACTS);
+       /* check if table is missing */
+       const char *query = "SELECT count(*) FROM sqlite_master WHERE type='table'"
+               " AND name IN ('persons','addressbooks','contacts','contact_deleteds','cts_version' ,"
+               "'sdn','data','groups','group_deleteds','group_relations','speeddials','favorites','sim_info',"
+               "'phonelogs','phonelog_stat','contact_stat','activities','activity_photos','search_index','name_lookup','phone_lookup','my_profiles')";
        ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
        if (SQLITE_OK != ret) {
                /* LCOV_EXCL_START */
-               ERR("sqlite3_prepare_v2(%s) Fail(%s)", query, sqlite3_errmsg(db));
-               ctsvc_server_db_close();
-               return CONTACTS_ERROR_DB;
+               ERR("sqlite3_qlite3_prepare_v2() Fail(%d)", ret);
+               if (SQLITE_ERROR == ret ||SQLITE_CORRUPT == ret ||SQLITE_NOTADB == ret)
+                       return -1;
+               else
+                       return 0;
                /* LCOV_EXCL_STOP */
        }
 
        ret = sqlite3_step(stmt);
        if (SQLITE_ROW != ret) {
                /* LCOV_EXCL_START */
-               ERR("contacts table does not exist in contacts DB file : %s", sqlite3_errmsg(db));
+               ERR("sqlite3_step() Fail(%d)", ret);
                sqlite3_finalize(stmt);
-               ctsvc_server_db_close();
-               return CTSVC_ERR_NO_TABLE;
+               if (SQLITE_ERROR == ret ||SQLITE_CORRUPT == ret ||SQLITE_NOTADB == ret)
+                       return -1;
+               else
+                       return 0;
                /* LCOV_EXCL_STOP */
        }
 
+       int get_count = sqlite3_column_int(stmt, 0);
        sqlite3_finalize(stmt);
-       ctsvc_server_db_close();
-       return CONTACTS_ERROR_NONE;
+
+       if (get_count != CTS_SCHEMA_TABLE_TOTAL) {
+               /* LCOV_EXCL_START */
+               ERR("Table is missing(expected(%d) but result(%d)", CTS_SCHEMA_TABLE_TOTAL, get_count);
+               return -1;
+               /* LCOV_EXCL_STOP */
+       }
+
+       return 0;
 }
 
 int ctsvc_server_check_schema(void)
 {
-       if (CTSVC_ERR_NO_DB_FILE == __ctsvc_server_check_db_file())
-               __ctsvc_server_remake_db_file();
-       else if (CTSVC_ERR_NO_TABLE == __ctsvc_server_check_table())
+       if (CONTACTS_ERROR_NONE != __ctsvc_server_check_db_file()
+               || 0 != __ctsvc_server_check_db_integrity())
+       {
+               ERR("Need to remove and remake db files");
+
+               ctsvc_server_db_close();
+
+               if (remove(CTSVC_DB_SHM_FILE) != 0)
+                       ERR("Failed to remove CTSVC_DB_SHM_FILE");
+               if (remove(CTSVC_DB_WAL_FILE) != 0)
+                       ERR("Failed to remove CTSVC_DB_WAL_FILE");
+               if (remove(CTSVC_DB_PATH) !=0)
+                       ERR("Failed to remove CTSVC_DB_PATH");
+
                __ctsvc_server_remake_db_file();
+       }
 
        return CONTACTS_ERROR_NONE;
 }
index 9c228d3..e7eb4b4 100644 (file)
@@ -44,7 +44,7 @@ int ctsvc_group_add_contact_in_transaction(int group_id, int contact_id)
 
        ret = ctsvc_query_get_first_int_result(query, &exist);
        if (CONTACTS_ERROR_NONE != ret) {
-               DBG("ctsvc_query_get_first_int_result fail(%d)");
+               DBG("ctsvc_query_get_first_int_result fail(%d)", ret);
                return ret;
        }
        if (1 == exist) {
index 73bcecf..8b21c73 100644 (file)
 
 static sqlite3 *server_db;
 
-int ctsvc_server_db_open(sqlite3 **db)
+int ctsvc_server_db_open(sqlite3 **db, int *sqlite_error)
 {
        CTS_FN_CALL;
        int ret;
 
        if (NULL == server_db) {
-               ret = db_util_open(CTSVC_DB_PATH, &server_db, 0);
-               RETVM_IF(ret != SQLITE_OK || NULL == server_db, CONTACTS_ERROR_DB,
-                               "db_util_open() Fail(%d), server_db(%s)", ret, sqlite3_errmsg(server_db));
-
-               ret = sqlite3_create_function(server_db, "_DATA_DELETE_", 2, SQLITE_UTF8, NULL,
-                               ctsvc_db_data_delete_callback, NULL, NULL);
-               RETVM_IF(SQLITE_OK != ret, CONTACTS_ERROR_DB,
-                               "sqlite3_create_function() Fail(%d)", ret);
-               ret = sqlite3_create_function(server_db, "_DATA_IMAGE_DELETE_", 1, SQLITE_UTF8, NULL,
-                               ctsvc_db_image_delete_callback, NULL, NULL);
-               RETVM_IF(SQLITE_OK != ret, CONTACTS_ERROR_DB,
-                               "sqlite3_create_function() Fail(%d)", ret);
-               ret = sqlite3_create_function(server_db, "_DATA_COMPANY_DELETE_", 1, SQLITE_UTF8, NULL,
-                               ctsvc_db_company_delete_callback, NULL, NULL);
-               RETVM_IF(SQLITE_OK != ret, CONTACTS_ERROR_DB,
-                               "sqlite3_create_function() Fail(%d)", ret);
+               do {
+                       ret = db_util_open(CTSVC_DB_PATH, &server_db, 0);
+                       if (ret != SQLITE_OK || NULL == server_db) {
+                               ERR("db_util_open() Fail(%d), server_db(%s)", ret, sqlite3_errmsg(server_db));
+                               break;
+                       }
+
+                       ret = sqlite3_create_function(server_db, "_DATA_DELETE_", 2, SQLITE_UTF8, NULL,
+                                       ctsvc_db_data_delete_callback, NULL, NULL);
+                       if (SQLITE_OK != ret) {
+                               ERR("sqlite3_create_function() Fail(%d)", ret);
+                               break;
+                       }
+
+                       ret = sqlite3_create_function(server_db, "_DATA_IMAGE_DELETE_", 1, SQLITE_UTF8, NULL,
+                                       ctsvc_db_image_delete_callback, NULL, NULL);
+                       if (SQLITE_OK != ret) {
+                               ERR("sqlite3_create_function() Fail(%d)", ret);
+                               break;
+                       }
+
+                       ret = sqlite3_create_function(server_db, "_DATA_COMPANY_DELETE_", 1, SQLITE_UTF8, NULL,
+                                       ctsvc_db_company_delete_callback, NULL, NULL);
+                       if (SQLITE_OK != ret) {
+                               ERR("sqlite3_create_function() Fail(%d)", ret);
+                               break;
+                       }
+
 #ifdef ENABLE_LOG_FEATURE
-               ret = sqlite3_create_function(server_db, "_PHONE_LOG_DELETE_", 1, SQLITE_UTF8, NULL,
-                               ctsvc_db_phone_log_delete_callback, NULL, NULL);
-               RETVM_IF(SQLITE_OK != ret, CONTACTS_ERROR_DB,
-                               "sqlite3_create_function() Fail(%d)", ret);
+                       ret = sqlite3_create_function(server_db, "_PHONE_LOG_DELETE_", 1, SQLITE_UTF8, NULL,
+                                       ctsvc_db_phone_log_delete_callback, NULL, NULL);
+                       if (SQLITE_OK != ret) {
+                               ERR("sqlite3_create_function() Fail(%d)", ret);
+                               break;
+                       }
 #endif /* ENABLE_LOG_FEATURE */
-               ret = sqlite3_create_function(server_db, "_PERSON_DELETE_", 1, SQLITE_UTF8, NULL,
-                               ctsvc_db_person_delete_callback, NULL, NULL);
-               RETVM_IF(SQLITE_OK != ret, CONTACTS_ERROR_DB,
-                               "sqlite3_create_function() Fail(%d)", ret);
-               ret = sqlite3_create_function(server_db, "_GROUP_DELETE_", 1, SQLITE_UTF8, NULL,
-                               ctsvc_db_group_delete_callback, NULL, NULL);
-               RETVM_IF(SQLITE_OK != ret, CONTACTS_ERROR_DB,
-                               "sqlite3_create_function() Fail(%d)", ret);
-               ret = sqlite3_create_function(server_db, "_NUMBER_COMPARE_", 4, SQLITE_UTF8, NULL,
-                               ctsvc_db_phone_number_equal_callback, NULL, NULL);
-               RETVM_IF(SQLITE_OK != ret, CONTACTS_ERROR_DB,
-                               "sqlite3_create_function() Fail(%d)", ret);
-               ret = sqlite3_create_collation(server_db, "_NAME_SORT_", SQLITE_UTF8, (void *)SQLITE_UTF8,
-                               ctsvc_db_group_name_sort_callback);
-               RETVM_IF(SQLITE_OK != ret, CONTACTS_ERROR_DB,
-                               "sqlite3_create_collation() Fail(%d)", ret);
+
+                       ret = sqlite3_create_function(server_db, "_PERSON_DELETE_", 1, SQLITE_UTF8, NULL,
+                                       ctsvc_db_person_delete_callback, NULL, NULL);
+                       if (SQLITE_OK != ret) {
+                               ERR("sqlite3_create_function() Fail(%d)", ret);
+                               break;
+                       }
+
+                       ret = sqlite3_create_function(server_db, "_GROUP_DELETE_", 1, SQLITE_UTF8, NULL,
+                                       ctsvc_db_group_delete_callback, NULL, NULL);
+                       if (SQLITE_OK != ret) {
+                               ERR("sqlite3_create_function() Fail(%d)", ret);
+                               break;
+                       }
+
+                       ret = sqlite3_create_function(server_db, "_NUMBER_COMPARE_", 4, SQLITE_UTF8, NULL,
+                                       ctsvc_db_phone_number_equal_callback, NULL, NULL);
+                       if (SQLITE_OK != ret) {
+                               ERR("sqlite3_create_function() Fail(%d)", ret);
+                               break;
+                       }
+
+                       ret = sqlite3_create_collation(server_db, "_NAME_SORT_", SQLITE_UTF8, (void *)SQLITE_UTF8,
+                                       ctsvc_db_group_name_sort_callback);
+                       if (SQLITE_OK != ret) {
+                               ERR("sqlite3_create_collation() Fail(%d)", ret);
+                               break;
+                       }
+               } while (0);
+
+               if (ret != SQLITE_OK || NULL == server_db) {
+                       if (sqlite_error)
+                               *sqlite_error = ret;
+                       return CONTACTS_ERROR_DB;
+               }
        }
+
        if (db)
                *db = server_db;
        return CONTACTS_ERROR_NONE;
@@ -190,7 +224,7 @@ int ctsvc_server_update_sort(int prev_sort_primary, int prev_sort_secondary, int
        char *errmsg = NULL;
        char query[CTS_SQL_MIN_LEN] = {0};
 
-       ret = ctsvc_server_db_open(&db);
+       ret = ctsvc_server_db_open(&db, NULL);
        RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "ctsvc_server_db_open() Fail(%d)", ret);
 
        ret = ctsvc_server_begin_trans();
@@ -329,7 +363,7 @@ int ctsvc_server_insert_sdn_contact(const char *name, const char *number,
        sqlite3_stmt *stmt = NULL;
        char query[CTS_SQL_MIN_LEN] = {0};
 
-       ret = ctsvc_server_db_open(&db);
+       ret = ctsvc_server_db_open(&db, NULL);
        RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "ctsvc_server_db_open() Fail(%d)", ret);
 
        snprintf(query, sizeof(query), "INSERT INTO %s(name, number, sim_slot_no) VALUES(?, ?, ?)",
@@ -370,7 +404,7 @@ int ctsvc_server_delete_sdn_contact(int sim_slot_no)
        sqlite3_stmt *stmt = NULL;
        char query[CTS_SQL_MAX_LEN] = {0};
 
-       ret = ctsvc_server_db_open(&db);
+       ret = ctsvc_server_db_open(&db, NULL);
        RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "helper_db_open() Fail(%d)", ret);
 
        if (sim_slot_no < 0)
@@ -411,7 +445,7 @@ int ctsvc_server_update_collation()
 
        ctsvc_db_set_status(CONTACTS_DB_STATUS_CHANGING_COLLATION);
 
-       ret = ctsvc_server_db_open(&db);
+       ret = ctsvc_server_db_open(&db, NULL);
        if (CONTACTS_ERROR_NONE != ret) {
                /* LCOV_EXCL_START */
                ERR("ctsvc_server_db_open() Fail(%d)", ret);
@@ -699,7 +733,7 @@ int ctsvc_server_update_sort_name()
 
        ctsvc_db_set_status(CONTACTS_DB_STATUS_CHANGING_COLLATION);
 
-       ret = ctsvc_server_db_open(&db);
+       ret = ctsvc_server_db_open(&db, NULL);
        if (CONTACTS_ERROR_NONE != ret) {
                /* LCOV_EXCL_START */
                ERR("ctsvc_server_db_open() Fail(%d)", ret);
index d8faaa3..d5c4d1c 100644 (file)
@@ -21,7 +21,7 @@
 
 #include <sqlite3.h>
 
-int ctsvc_server_db_open(sqlite3 **db);
+int ctsvc_server_db_open(sqlite3 **db, int *sqlite_error);
 int ctsvc_server_db_close(void);
 int ctsvc_server_update_sort(int prev_sort_primary, int prev_sort_secondary, int new_sort_primary, int new_sort_secondary);
 int ctsvc_server_insert_sdn_contact(const char *name, const char *number, int sim_slot_no);
index 00d14e6..8439a2c 100644 (file)
 #include <tzplatform_config.h>
 
 #define CTSVC_DB_PATH tzplatform_mkpath(TZ_USER_DB, "privacy/.contacts-svc.db")
+#define CTSVC_DB_SHM_FILE tzplatform_mkpath(TZ_USER_DB, "privacy/.contacts-svc.db-shm")
+#define CTSVC_DB_WAL_FILE tzplatform_mkpath(TZ_USER_DB, "privacy/.contacts-svc.db-wal")
 
 /* For Security */
 #define CTS_SECURITY_FILE_GROUP 5000
 #define CTS_SECURITY_DEFAULT_PERMISSION 0666
 #define CTS_SECURITY_DIR_DEFAULT_PERMISSION 0770
 
-#define CTS_SCHEMA_TABLE_TOTAL 10
+/* MUST MACTH table count */
+#define CTS_SCHEMA_TABLE_TOTAL 22
 
 /* DB Tables */
 #define CTS_TABLE_PERSONS "persons"