From: Inkyun Kil Date: Wed, 28 Aug 2019 08:20:17 +0000 (+0900) Subject: Add alarm-manager database version control X-Git-Tag: accepted/tizen/unified/20200110.123526~2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=8b1f28c25cbcf5fdacad6d0be62652087c835a69;p=platform%2Fcore%2Fappfw%2Falarm-manager.git Add alarm-manager database version control Change-Id: I0ebbb8bb013e13e0e847c9910fb2f4ef5e4ae19a Signed-off-by: Inkyun Kil Signed-off-by: Jusung Son --- diff --git a/server/alarm-manager-db-migration.c b/server/alarm-manager-db-migration.c new file mode 100644 index 0000000..14bcc3f --- /dev/null +++ b/server/alarm-manager-db-migration.c @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "alarm-manager-db.h" + +extern sqlite3 *alarmmgr_db; + +int migration_func_version_1(void) +{ + static const char *query = "CREATE TABLE IF NOT EXISTS alarmmgr_temp (\n" \ + " alarm_id INTEGER PRIMARY KEY, \n" \ + " start INTEGER, \n" \ + " end INTEGER, \n" \ + " uid INTEGER, \n" \ + " global INTEGER, \n" \ + " is_disabled INTEGER, \n" \ + " caller_pkgid TEXT, \n" \ + " callee_pkgid TEXT, \n" \ + " app_unique_name TEXT, \n" \ + " app_service_name TEXT, \n" \ + " app_service_name_mod TEXT, \n" \ + " bundle TEXT, \n" \ + " noti_len INTEGER, \n" \ + " noti TEXT, \n" \ + " year INTEGER, \n" \ + " month INTEGER, \n" \ + " day INTEGER, \n" \ + " hour INTEGER, \n" \ + " min INTEGER, \n" \ + " sec INTEGER, \n" \ + " msec INTEGER, \n" \ + " day_of_week INTEGER, \n" \ + " repeat INTEGER, \n" \ + " alarm_type INTEGER, \n" \ + " reserved_info INTEGER, \n" \ + " dst_service_name TEXT, \n" \ + " dst_service_name_mod TEXT \n" \ + ")"; + + static const char *insert_query = "INSERT INTO alarmmgr_temp (alarm_id, start, \ + end, uid, global, is_disabled, caller_pkgid, callee_pkgid, \ + app_unique_name, app_service_name, app_service_name_mod, \ + bundle, noti_len, noti, year, month, day, hour, min, sec, msec,\ + day_of_week, repeat, alarm_type, reserved_info, \ + dst_service_name, dst_service_name_mod) \ + SELECT alarm_id, start, end, uid, global, is_disabled, \ + caller_pkgid, callee_pkgid, app_unique_name, app_service_name, \ + app_service_name_mod, bundle, noti_len, noti, year, month, \ + day, hour, min, sec, msec, day_of_week, repeat, alarm_type, \ + reserved_info, dst_service_name, dst_service_name_mod \ + FROM alarmmgr"; + + char *error_message = NULL; + int ret; + + LOGD("DB migration init version start"); + + ret = sqlite3_exec(alarmmgr_db, "DROP TABLE IF EXISTS alarmmgr_temp", NULL, + NULL, &error_message); + if (ret != SQLITE_OK) { + LOGE("Don't execute drop, error message = %s", error_message); + sqlite3_free(error_message); + return ret; + } + + ret = sqlite3_exec(alarmmgr_db, query, NULL, NULL, &error_message); + if (ret != SQLITE_OK) { + LOGE("Don't execute query = %s, error message = %s", query, error_message); + sqlite3_free(error_message); + return ret; + } + + ret = sqlite3_exec(alarmmgr_db, insert_query, NULL, NULL, &error_message); + if (ret != SQLITE_OK) { + LOGE("Don't execute query = %s, error message = %s", insert_query, error_message); + sqlite3_free(error_message); + return ret; + } + + ret = sqlite3_exec(alarmmgr_db, "DROP TABLE alarmmgr", NULL, NULL, &error_message); + if (ret != SQLITE_OK) { + LOGE("Don't execute drop alarmmgr, error message = %s", error_message); + sqlite3_free(error_message); + return ret; + } + + ret = sqlite3_exec(alarmmgr_db, "ALTER TABLE alarmmgr_temp RENAME TO alarmmgr", + NULL, NULL, &error_message); + if (ret != SQLITE_OK) { + LOGE("Don't execute alter, error message = %s", error_message); + sqlite3_free(error_message); + return ret; + } + + return ALARMMGR_RESULT_SUCCESS; +} diff --git a/server/alarm-manager-db.c b/server/alarm-manager-db.c index 12cdea2..0fdd4bf 100644 --- a/server/alarm-manager-db.c +++ b/server/alarm-manager-db.c @@ -30,35 +30,49 @@ #include "alarm-manager-db.h" #define ALARMMGR_DB_FILE tzplatform_mkpath(TZ_SYS_DB, ".alarmmgr.db") -#define QUERY_CREATE_TABLE_ALARMMGR "create table if not exists alarmmgr \ - (alarm_id integer primary key,\ - start integer,\ - end integer,\ - uid integer,\ - global integer,\ - is_disabled integer,\ - caller_pkgid text,\ - callee_pkgid text,\ - app_unique_name text,\ - app_service_name text,\ - app_service_name_mod text,\ - bundle text, \ - noti_len integer,\ - noti text, \ - year integer,\ - month integer,\ - day integer,\ - hour integer,\ - min integer,\ - sec integer,\ - msec integer,\ - day_of_week integer,\ - repeat integer,\ - alarm_type integer,\ - reserved_info integer,\ - dst_service_name text, \ - dst_service_name_mod text \ - )" +#define QUERY_CREATE_TABLE_ALARMMGR \ + " CREATE TABLE IF NOT EXISTS alarmmgr (\n" \ + " alarm_id INTEGER PRIMARY KEY, \n" \ + " start INTEGER, \n" \ + " end INTEGER, \n" \ + " uid INTEGER, \n" \ + " global INTEGER, \n" \ + " is_disabled INTEGER, \n" \ + " caller_pkgid TEXT, \n" \ + " callee_pkgid TEXT, \n" \ + " app_unique_name TEXT, \n" \ + " app_service_name TEXT, \n" \ + " app_service_name_mod TEXT, \n" \ + " bundle TEXT, \n" \ + " noti_len INTEGER, \n" \ + " noti TEXT, \n" \ + " year INTEGER, \n" \ + " month INTEGER, \n" \ + " day INTEGER, \n" \ + " hour INTEGER, \n" \ + " min INTEGER, \n" \ + " sec INTEGER, \n" \ + " msec INTEGER, \n" \ + " day_of_week INTEGER, \n" \ + " repeat INTEGER, \n" \ + " alarm_type INTEGER, \n" \ + " reserved_info INTEGER, \n" \ + " dst_service_name TEXT, \n" \ + " dst_service_name_mod TEXT \n" \ + ")" + +enum schema_version +{ + SCHEMA_VERSION_0 = 0, + SCHEMA_VERSION_1 = 1, + SCHEMA_VERSION_LATEST = SCHEMA_VERSION_1 +} schema_version_e; + +typedef struct +{ + const char *change_log; + int (*func)(void); +} migration_func; extern GSList *g_disabled_alarm_list; extern __alarm_server_context_t alarm_context; @@ -66,6 +80,116 @@ extern __alarm_server_context_t alarm_context; sqlite3 *alarmmgr_db; static bool is_db_corrupted = false; +static const migration_func m_func[] = +{ + {"SCHEMA_VERSION_0", NULL}, + {"SCHEMA_VERSION_1", migration_func_version_1} +}; + +static int __create_db_version(void) +{ + static const char *query = "CREATE TABLE IF NOT EXISTS schema_version (version INTEGER)"; + + if (sqlite3_exec(alarmmgr_db, query, NULL, NULL, NULL) != SQLITE_OK) { + LOGE("Failed to execute the query (%s)\n", sqlite3_errmsg(alarmmgr_db)); + return -1; + } + + return 0; +} + +static int __update_db_version(int ver) +{ + char *query; + + if (sqlite3_exec(alarmmgr_db, "DELETE FROM schema_version", NULL, NULL, NULL) + != SQLITE_OK) { + LOGE("Failed to execute the query (%s)\n", sqlite3_errmsg(alarmmgr_db)); + return -1; + } + + query = sqlite3_mprintf("INSERT INTO schema_version (version) VALUES (%d)", ver); + if (query == NULL) { + LOGE("Failed to alloc query"); + return -1; + } + + if (sqlite3_exec(alarmmgr_db, query, NULL, NULL, NULL) != SQLITE_OK) { + LOGE("Failed to execute the query (%s)\n", sqlite3_errmsg(alarmmgr_db)); + sqlite3_free(query); + return -1; + } + + sqlite3_free(query); + + return 0; +} + +static int __get_db_version(void) +{ + static const char *dml = "SELECT version FROM schema_version"; + sqlite3_stmt *stmt; + int ret; + + ret = sqlite3_prepare_v2(alarmmgr_db, dml, -1, &stmt, NULL); + if (ret != SQLITE_OK) { + LOGE("sqlite3_prepare_v2 error : %d", ret); + return -1; + } + + if (sqlite3_step(stmt) != SQLITE_ROW) + ret = -1; + else + ret = sqlite3_column_int(stmt, 0); + + sqlite3_reset(stmt); + sqlite3_clear_bindings(stmt); + sqlite3_finalize(stmt); + return ret; +} + +static int __db_upgrade(void) +{ + int ver, ret, i; + + ver = __get_db_version(); + if (ver >= SCHEMA_VERSION_LATEST) + return 0; + + if (sqlite3_exec(alarmmgr_db, "BEGIN TRANSACTION", NULL, NULL, NULL)) { + LOGE("begin transaction error : %s", sqlite3_errmsg(alarmmgr_db)); + return -1; + } + + if (ver == -1) { + LOGD("Schema version not exists : %d", ver); + ret = __create_db_version(); + if (ret != 0) + goto out; + + ver = SCHEMA_VERSION_0; + } + + for (i = ver + 1 ; i <= SCHEMA_VERSION_LATEST; i++) { + if (m_func[i].func() != ALARMMGR_RESULT_SUCCESS) { + ret = -1; + goto out; + } + + } + ret = __update_db_version(SCHEMA_VERSION_LATEST); + +out: + if (ret == 0) { + if (sqlite3_exec(alarmmgr_db, "END TRANSACTION", NULL, NULL, NULL)) + LOGE("end transaction error : %s", sqlite3_errmsg(alarmmgr_db)); + } else { + if (sqlite3_exec(alarmmgr_db, "ROLLBACK TRANSACTION", NULL, NULL, NULL)) + LOGE("rollback transaction error : %s", sqlite3_errmsg(alarmmgr_db)); + } + return ret; +} + static int __db_busyhandler(void *pData, int count) { if (5 - count > 0) { @@ -502,10 +626,45 @@ int __check_callback(void *pid, int argc, char **argv, char **notUsed2) return 0; } +int __check_alarmmgr_table(sqlite3 *alarmmgr_db, bool *is_exist) +{ + sqlite3_stmt *stmt = NULL; + int count, sqlret; + + sqlret = sqlite3_prepare_v2(alarmmgr_db, + "SELECT COUNT(*) FROM sqlite_master WHERE name='alarmmgr'", + -1, &stmt, NULL); + if (sqlret != SQLITE_OK) { + /* LCOV_EXCL_START */ + LOGE("sqlite3_prepare_v2 failed [%d][%s]", sqlret, + sqlite3_errmsg(alarmmgr_db)); + return sqlret; + /* LCOV_EXCL_STOP */ + } + + sqlret = sqlite3_step(stmt); + if (sqlret == SQLITE_ROW) + count = sqlite3_column_int(stmt, 0); + else + count = 0; + + LOGD("DB search result[%d]", count); + + if (count > 0) + *is_exist = true; + else + *is_exist = false; + + sqlite3_finalize(stmt); + + return SQLITE_OK; + +} bool _initialize_db() { char *error_message = NULL; int ret; + bool is_exist; /* Create or Open the DB file */ ret = sqlite3_open(ALARMMGR_DB_FILE, &alarmmgr_db); @@ -527,6 +686,17 @@ bool _initialize_db() return false; } } + + ret = __check_alarmmgr_table(alarmmgr_db, &is_exist); + if (ret != SQLITE_OK) { + if (ret == SQLITE_CORRUPT) { + goto recover; + } else { + sqlite3_close(alarmmgr_db); + return false; + } + } + /* Create alarmmgr table */ ret = sqlite3_exec(alarmmgr_db, QUERY_CREATE_TABLE_ALARMMGR, NULL, NULL, &error_message); if (ret != SQLITE_OK) { @@ -540,6 +710,25 @@ bool _initialize_db() } } + if (is_exist == false) { + if (__create_db_version() != 0) { + sqlite3_close(alarmmgr_db); + return false; + } + + if (__update_db_version(SCHEMA_VERSION_LATEST) != 0) { + sqlite3_close(alarmmgr_db); + return false; + } + } else { + ret = __db_upgrade(); + if (ret) { + LOGE("Failed db's migration"); + sqlite3_close(alarmmgr_db); + return false; + } + } + /* Check integrity of DB */ ret = sqlite3_exec(alarmmgr_db, "PRAGMA integrity_check", __check_callback, NULL, 0); if (ret != SQLITE_OK || is_db_corrupted) { @@ -577,5 +766,15 @@ recover: return false; } + if (__create_db_version() != 0) { + sqlite3_close(alarmmgr_db); + return false; + } + + if (__update_db_version(SCHEMA_VERSION_LATEST) != 0) { + sqlite3_close(alarmmgr_db); + return false; + } + return true; } diff --git a/server/alarm-manager-db.h b/server/alarm-manager-db.h index 59f6902..b454ba2 100644 --- a/server/alarm-manager-db.h +++ b/server/alarm-manager-db.h @@ -34,6 +34,8 @@ bool _update_alarms(__alarm_info_t *__alarm_info); gboolean _update_relative_alarms(gpointer user_data); void _update_db_for_disabled_alarm(alarm_id_t alarm_id, bool disabled_by_ups); +int migration_func_version_1(void); + #ifdef __cplusplus } #endif diff --git a/server/alarm-manager.c b/server/alarm-manager.c old mode 100755 new mode 100644 index 8babbfa..57506e8 --- a/server/alarm-manager.c +++ b/server/alarm-manager.c @@ -1956,6 +1956,7 @@ static int __check_modifiable(uid_t uid, pid_t pid, int alarm_id) for (gs_iter = alarm_context.alarms; gs_iter != NULL; gs_iter = g_slist_next(gs_iter)) { entry = (__alarm_info_t *)gs_iter->data; if (entry->uid == uid && entry->alarm_id == alarm_id && + entry->caller_pkgid && strcmp(caller_pkgid, entry->caller_pkgid) == 0) { LOGD("Found alarm of app (uid:%d, pid:%d, caller_pkgid:%s) ", uid, pid, caller_pkgid);