From: jk.koo Date: Tue, 10 Mar 2020 02:01:09 +0000 (+0900) Subject: modify DB checking logic X-Git-Tag: accepted/tizen/unified/20200312.131127^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=92e1e3dd3dadb4f077d7d864beea7aa0e8d168e6;p=platform%2Fcore%2Fpim%2Fcontacts-service.git modify DB checking logic Change-Id: Icb2a6de1eb004bfeb98917251f0bc21b0f3ed203 Signed-off-by: jk.koo --- diff --git a/server/ctsvc_schema_recovery.c b/server/ctsvc_schema_recovery.c index adeb6ac..40faf6f 100644 --- a/server/ctsvc_schema_recovery.c +++ b/server/ctsvc_schema_recovery.c @@ -30,19 +30,13 @@ #include "ctsvc_schema_recovery.h" #include "ctsvc_db_schema.h" -/* Additional Error */ -enum { - CTSVC_ERR_NO_DB_FILE = -10000, - CTSVC_ERR_NO_TABLE, -}; - -static inline int __ctsvc_server_check_db_file(void) +static inline bool __ctsvc_server_db_file_exist(void) { int fd = open(CTSVC_DB_PATH, O_RDONLY); - RETVM_IF(-1 == fd, CTSVC_ERR_NO_DB_FILE, "DB file is not exist"); + RETVM_IF(-1 == fd, false, "DB file does not exist"); close(fd); - return CONTACTS_ERROR_NONE; + return true; } static inline int __ctsvc_server_remake_db_file() @@ -67,112 +61,165 @@ static inline int __ctsvc_server_remake_db_file() return CONTACTS_ERROR_NONE; } -static bool need_to_remove = false; -static int __integrity_callback(void *pid, int argc, char **argv, char **notUsed2) +static int __integrity_callback(void *user_data, int ncol, char **cols, char **name) { CTS_FN_CALL; - if (NULL == argv || NULL == argv[0]) { - ERR("Invalid parameter"); - need_to_remove = true; - return -1; - } + RETV_IF(0 == ncol, CONTACTS_ERROR_DB); + RETV_IF(NULL == cols, CONTACTS_ERROR_DB); - if (0 != strcmp(argv[0], "ok")) { - ERR("integrity_check() Fail(argv[%s])", argv[0]); - need_to_remove = true; - return -1; + if (0 != strcmp(cols[0], "ok")) { + ERR("integrity_check Fail(%s)", cols[0]); + return CONTACTS_ERROR_DB; } - DBG("integrity_check done"); return 0; } -static int __ctsvc_server_check_db_integrity(void) +static bool __ctsvc_server_check_db_table(sqlite3 *db) { CTS_FN_CALL; - int ret = 0; - sqlite3 *db = NULL; + int ret; cts_stmt stmt = NULL; - int sqlite_error = SQLITE_OK; - ret = ctsvc_server_db_open(&db, &sqlite_error); - if (CONTACTS_ERROR_NONE != ret) { + do { + /* check if table is missing */ + const char *query = "SELECT count(*) FROM sqlite_master WHERE type='table'" + " AND name IN ('"CTS_TABLE_PERSONS"','"CTS_TABLE_ADDRESSBOOKS"','"CTS_TABLE_CONTACTS"'," + "'"CTS_TABLE_DELETEDS"','"CTS_TABLE_VERSION"','"CTS_TABLE_SDN"','"CTS_TABLE_DATA"'," + "'"CTS_TABLE_GROUPS"','"CTS_TABLE_GROUP_DELETEDS"','"CTS_TABLE_GROUP_RELATIONS"'," + "'"CTS_TABLE_SPEEDDIALS"','"CTS_TABLE_FAVORITES"','"CTS_TABLE_SIM_INFO"'," + "'"CTS_TABLE_PHONELOGS"','"CTS_TABLE_PHONELOG_STAT"','"CTS_TABLE_CONTACT_STAT"'," + "'"CTS_TABLE_ACTIVITIES"','"CTS_TABLE_ACTIVITY_PHOTOS"','"CTS_TABLE_SEARCH_INDEX"'," + "'"CTS_TABLE_NAME_LOOKUP"','"CTS_TABLE_PHONE_LOOKUP"','"CTS_TABLE_MY_PROFILES"')"; + ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL); + if (SQLITE_OK != ret) { + /* LCOV_EXCL_START */ + ERR("sqlite3_prepare_v2() Fail(%s)", sqlite3_errstr(ret)); + break; + /* LCOV_EXCL_STOP */ + } + + ret = sqlite3_step(stmt); + if (SQLITE_ROW != ret) { + /* LCOV_EXCL_START */ + ERR("sqlite3_step() Fail(%s)", sqlite3_errstr(ret)); + sqlite3_finalize(stmt); + break; + /* LCOV_EXCL_STOP */ + } + }while (0); + + switch (ret) { + case SQLITE_ROW: + break; + case SQLITE_DONE: + case SQLITE_BUSY: + case SQLITE_LOCKED: + case SQLITE_FULL: + case SQLITE_CONSTRAINT: + case SQLITE_NOMEM: /* 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; + // It's not critical. It can be ignored + INFO("False Positive(err = [%d]%s)", ret, sqlite3_errstr(ret)); + return true; /* 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) { + case SQLITE_IOERR: + case SQLITE_CORRUPT: + default: /* LCOV_EXCL_START */ - ERR("need_to_remove [%s], ret [%d]", need_to_remove ? "true" : "false", ret); - need_to_remove = false; - return -1; + ERR("Critical Error(%d:%s)", ret, sqlite3_errstr(ret)); + ctsvc_server_db_close(); + return false; /* LCOV_EXCL_STOP */ } - /* 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) { + int get_count = sqlite3_column_int(stmt, 0); + sqlite3_finalize(stmt); + + if (get_count != CTS_SCHEMA_TABLE_TOTAL) { /* LCOV_EXCL_START */ - ERR("sqlite3_qlite3_prepare_v2() Fail(%d)", ret); - if (SQLITE_ERROR == ret ||SQLITE_CORRUPT == ret ||SQLITE_NOTADB == ret) - return -1; - else - return 0; + ERR("Table is missing(expected(%d) but result(%d)", CTS_SCHEMA_TABLE_TOTAL, get_count); + ctsvc_server_db_close(); + return false; /* LCOV_EXCL_STOP */ } - ret = sqlite3_step(stmt); - if (SQLITE_ROW != ret) { + return true; +} + +static bool __ctsvc_server_check_db() +{ + CTS_FN_CALL; + int ret; + sqlite3 *db = NULL; + int sqlite_error = SQLITE_OK; + + ret = ctsvc_server_db_open(&db, &sqlite_error); + if (CONTACTS_ERROR_NONE != ret) { /* LCOV_EXCL_START */ - ERR("sqlite3_step() Fail(%d)", ret); - sqlite3_finalize(stmt); - if (SQLITE_ERROR == ret ||SQLITE_CORRUPT == ret ||SQLITE_NOTADB == ret) - return -1; - else - return 0; + INFO("ctsvc_server_db_open() Fail(%d), sqlite_error(%s)", ret, sqlite3_errstr(sqlite_error)); + + if (SQLITE_BUSY == sqlite_error || SQLITE_NOMEM == sqlite_error) { + INFO("it's not critical enough to clear the db."); + return true; + } + ctsvc_server_db_close(); + return false; /* LCOV_EXCL_STOP */ } - int get_count = sqlite3_column_int(stmt, 0); - sqlite3_finalize(stmt); - - if (get_count != CTS_SCHEMA_TABLE_TOTAL) { + ret = sqlite3_exec(db, "pragma integrity_check", __integrity_callback, NULL, NULL); + if (SQLITE_ABORT == ret) { /* LCOV_EXCL_START */ - ERR("Table is missing(expected(%d) but result(%d)", CTS_SCHEMA_TABLE_TOTAL, get_count); - return -1; + ERR("integrity_check Fail()"); + ctsvc_server_db_close(); + return false; /* LCOV_EXCL_STOP */ } - return 0; + return __ctsvc_server_check_db_table(db); } -int ctsvc_server_check_schema(void) +static void __ctsvc_server_backup_file() { - 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(); + int i; + const int MAX_BACKUP = 4; + char new_path[CTSVC_PATH_MAX_LEN]; + for (i = 0; i < MAX_BACKUP; i++) { + snprintf(new_path, sizeof(new_path), "%s%d", CTSVC_DB_PATH, i); + if (-1 == access(new_path, F_OK)) + break; + } - 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"); + if (rename(CTSVC_DB_PATH, new_path)) + ERR("rename(%s) Fail(%d)", new_path, errno); + snprintf(new_path, sizeof(new_path), "%s%d", CTSVC_DB_SHM_PATH, i); + if (rename(CTSVC_DB_SHM_PATH, new_path)) + ERR("rename(%s) Fail(%d)", new_path, errno); + snprintf(new_path, sizeof(new_path), "%s%d", CTSVC_DB_WAL_PATH, i); + if (rename(CTSVC_DB_WAL_PATH, new_path)) + ERR("rename(%s) Fail(%d)", new_path, errno); + + i = (i + 1) % MAX_BACKUP; + snprintf(new_path, sizeof(new_path), "%s%d", CTSVC_DB_PATH, i); + if (0 == access(new_path, F_OK)) { + remove(new_path); + snprintf(new_path, sizeof(new_path), "%s%d", CTSVC_DB_SHM_PATH, i); + remove(new_path); + snprintf(new_path, sizeof(new_path), "%s%d", CTSVC_DB_WAL_PATH, i); + remove(new_path); + } +} +int ctsvc_server_check_schema(void) +{ + if (false == __ctsvc_server_db_file_exist()) { + ERR("Need to remake db files"); + __ctsvc_server_remake_db_file(); + } else if (false == __ctsvc_server_check_db()) { + ERR("Need to backup and remake db files"); + __ctsvc_server_backup_file(); __ctsvc_server_remake_db_file(); } diff --git a/server/db/ctsvc_db_schema.h b/server/db/ctsvc_db_schema.h index 8439a2c..6af8b6a 100644 --- a/server/db/ctsvc_db_schema.h +++ b/server/db/ctsvc_db_schema.h @@ -22,8 +22,8 @@ #include #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") +#define CTSVC_DB_SHM_PATH tzplatform_mkpath(TZ_USER_DB, "privacy/.contacts-svc.db-shm") +#define CTSVC_DB_WAL_PATH tzplatform_mkpath(TZ_USER_DB, "privacy/.contacts-svc.db-wal") /* For Security */ #define CTS_SECURITY_FILE_GROUP 5000