Add alarm-manager database version control 34/216434/6
authorInkyun Kil <inkyun.kil@samsung.com>
Wed, 28 Aug 2019 08:20:17 +0000 (17:20 +0900)
committerInkyun Kil <inkyun.kil@samsung.com>
Thu, 26 Dec 2019 23:21:00 +0000 (23:21 +0000)
Change-Id: I0ebbb8bb013e13e0e847c9910fb2f4ef5e4ae19a
Signed-off-by: Inkyun Kil <inkyun.kil@samsung.com>
Signed-off-by: Jusung Son <jusung07.son@samsung.com>
server/alarm-manager-db-migration.c [new file with mode: 0644]
server/alarm-manager-db.c
server/alarm-manager-db.h
server/alarm-manager.c [changed mode: 0755->0644]

diff --git a/server/alarm-manager-db-migration.c b/server/alarm-manager-db-migration.c
new file mode 100644 (file)
index 0000000..14bcc3f
--- /dev/null
@@ -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 <stdio.h>
+#include <sqlite3.h>
+
+#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;
+}
index 12cdea2..0fdd4bf 100644 (file)
 #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;
 }
index 59f6902..b454ba2 100644 (file)
@@ -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
old mode 100755 (executable)
new mode 100644 (file)
index 8babbfa..57506e8
@@ -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);