Encapsulate write operations in a transaction when creating a db file 96/160896/4
authorJi-hoon Lee <dalton.lee@samsung.com>
Mon, 20 Nov 2017 04:45:30 +0000 (13:45 +0900)
committerJihoon Kim <jihoon48.kim@samsung.com>
Tue, 21 Nov 2017 02:03:23 +0000 (02:03 +0000)
If isf-panel-efl crashes or terminates abnormally while
creating a ime_info db file, the db file would contain
only the partial information of installed IMEs but
it may look normal when trying to read it later.
For this reason, it is better to encapsulate all write
operations in a transaction.
And, since individual insert/delete operation could fail
also, we check the number of installed IMEs too.

Change-Id: If0c5cf1120f3ac2dd7e9f25f360eeb443622de2b

ism/extras/efl_panel/isf_panel_efl.cpp
ism/src/isf_pkg.cpp
ism/src/isf_query_utility.cpp
ism/src/isf_query_utility.h

index 3593559..f403cec 100644 (file)
@@ -2016,9 +2016,35 @@ static bool set_active_ise (const String &uuid, bool launch_ise)
 
     bool ise_changed = false, valid = false;
 
+    int ime_num = -1; /* If we failed retrieving the number of IMEs installed, assume we need to clear IME related settings */
+    pkgmgrinfo_appinfo_filter_h handle;
+    int ret = pkgmgrinfo_appinfo_filter_create(&handle);
+    if (ret == PMINFO_R_OK) {
+        ret = pkgmgrinfo_appinfo_filter_add_string(handle, PMINFO_APPINFO_PROP_APP_CATEGORY, "http://tizen.org/category/ime");
+        if (ret == PMINFO_R_OK) {
+            ret = pkgmgrinfo_appinfo_filter_count(handle, &ime_num);
+            if (ret != PMINFO_R_OK) {
+                LOGW("pkgmgrinfo_appinfo_filter_count failed(%d)\n", ret);
+            }
+        }
+        pkgmgrinfo_appinfo_filter_destroy (handle);
+    }
+    else {
+        LOGE ("pkgmgrinfo_appinfo_filter_create failed(%d)", ret);
+    }
+
+    /* If the ime_num and _ime_info.size() are different, it is likely that the isf-panel-efl was
+       terminated abnormally while processing package manager's install / uninstall events */
+    LOGD("Checking whether db file needs to be re-created : %d %d", ime_num, _ime_info.size());
+    if (ime_num != (int)_ime_info.size()) {
+        _ime_info.clear();
+        isf_db_delete_ime_info();
+        isf_pkg_reload_ime_info_db();
+        isf_pkg_select_all_ime_info_db(_ime_info);
+    }
+
     if (_ime_info.size () == 0) {
 #ifdef HAVE_PKGMGR_INFO
-        pkgmgrinfo_appinfo_filter_h handle;
         int ret = pkgmgrinfo_appinfo_filter_create (&handle);
         if (ret == PMINFO_R_OK) {
             ret = pkgmgrinfo_appinfo_filter_add_string (handle, PMINFO_APPINFO_PROP_APP_CATEGORY, "http://tizen.org/category/ime");
index 7aca3a8..5a1832d 100644 (file)
@@ -233,10 +233,13 @@ int isf_pkg_ime_app_list_cb (const pkgmgrinfo_appinfo_h handle, void *user_data)
         }
     }
 
-    ret = isf_db_insert_ime_info (&ime_db);
+    bool in_transaction = false;
+    if (isf_db_is_in_transaction ()) in_transaction = true;
+
+    ret = isf_db_insert_ime_info (&ime_db, in_transaction);
     if (ret < 1) {
         if (result) {
-            ret = isf_db_update_ime_info (&ime_db);
+            ret = isf_db_update_ime_info (&ime_db, in_transaction);
             if (ret) {
                 *result = 2;    // Updated
             }
@@ -269,9 +272,13 @@ void isf_pkg_reload_ime_info_db(void)
     if (ret == PMINFO_R_OK) {
         ret = pkgmgrinfo_appinfo_filter_add_string (handle, PMINFO_APPINFO_PROP_APP_CATEGORY, "http://tizen.org/category/ime");
         if (ret == PMINFO_R_OK) {
+            isf_db_begin_transaction();
             ret = pkgmgrinfo_appinfo_filter_foreach_appinfo (handle, isf_pkg_ime_app_list_cb, NULL);
             if (ret != PMINFO_R_OK) {
                 LOGW ("pkgmgrinfo_appinfo_filter_foreach_appinfo failed(%d)\n", ret);
+                isf_db_rollback_transaction();
+            } else {
+                isf_db_commit_transaction();
             }
         }
         else {
@@ -295,7 +302,7 @@ void isf_pkg_reload_ime_info_db(void)
 int isf_pkg_select_all_ime_info_db(std::vector<ImeInfoDB> &ime_info)
 {
     int result = isf_db_select_all_ime_info(ime_info);
-    if (result == 0) {   // Probably ime_info DB's already added by scim process. But isf_db_delete_ime_info() can delete it, so try to make one here.
+    if (result == 0) {
         isf_pkg_reload_ime_info_db();
 
         return isf_db_select_all_ime_info(ime_info);
index aca3eef..c1c37b7 100644 (file)
@@ -79,16 +79,28 @@ static struct {
     const char* pPath;
     sqlite3* pHandle;
     bool need_reset;
+    bool in_transaction;
 } databaseInfo = {
-    DB_PATH, NULL, false
+    DB_PATH, NULL, false, false
 };
 
 static inline int _db_disconnect(void);
 
+static inline bool _is_in_transaction(void)
+{
+    return databaseInfo.in_transaction;
+}
+
 static inline int _begin_transaction(void)
 {
     sqlite3_stmt* pStmt = NULL;
 
+    if (databaseInfo.in_transaction != false)
+    {
+        LOGE("Transaction already started\n");
+        return EXIT_FAILURE;
+    }
+
     int ret = sqlite3_prepare_v2(databaseInfo.pHandle, "BEGIN TRANSACTION", -1, &pStmt, NULL);
     if (ret != SQLITE_OK)
     {
@@ -103,6 +115,8 @@ static inline int _begin_transaction(void)
         return EXIT_FAILURE;
     }
 
+    databaseInfo.in_transaction = true;
+
     sqlite3_finalize(pStmt);
     return EXIT_SUCCESS;
 }
@@ -111,6 +125,12 @@ static inline int _rollback_transaction(void)
 {
     sqlite3_stmt* pStmt = NULL;
 
+    if (databaseInfo.in_transaction != true)
+    {
+        LOGE("Transaction not started\n");
+        return EXIT_FAILURE;
+    }
+
     int ret = sqlite3_prepare_v2(databaseInfo.pHandle, "ROLLBACK TRANSACTION", -1, &pStmt, NULL);
     if (ret != SQLITE_OK)
     {
@@ -125,6 +145,8 @@ static inline int _rollback_transaction(void)
         return EXIT_FAILURE;
     }
 
+    databaseInfo.in_transaction = false;
+
     sqlite3_finalize(pStmt);
     return EXIT_SUCCESS;
 }
@@ -133,6 +155,12 @@ static inline int _commit_transaction(void)
 {
     sqlite3_stmt* pStmt = NULL;
 
+    if (databaseInfo.in_transaction != true)
+    {
+        LOGE("Transaction not started\n");
+        return EXIT_FAILURE;
+    }
+
     int ret = sqlite3_prepare_v2(databaseInfo.pHandle, "COMMIT TRANSACTION", -1, &pStmt, NULL);
     if (ret != SQLITE_OK)
     {
@@ -147,6 +175,8 @@ static inline int _commit_transaction(void)
         return EXIT_FAILURE;
     }
 
+    databaseInfo.in_transaction = false;
+
     sqlite3_finalize(pStmt);
     return EXIT_SUCCESS;
 }
@@ -270,6 +300,15 @@ static inline int _db_connect(void)
     return 0;
 }
 
+static inline int _db_is_connected(void)
+{
+    if (databaseInfo.pHandle) {
+        return 1;
+    }
+
+    return 0;
+}
+
 static inline int _db_disconnect(void)
 {
     if (!databaseInfo.pHandle)
@@ -1555,7 +1594,7 @@ EXAPI int isf_db_update_has_option_by_appid(const char *appid, bool has_option)
  *
  * @return the number of updated data.
  */
-EXAPI int isf_db_update_ime_info(ImeInfoDB *ime_db)
+EXAPI int isf_db_update_ime_info(ImeInfoDB *ime_db, bool in_transaction)
 {
     int ret = 0;
 
@@ -1564,9 +1603,9 @@ EXAPI int isf_db_update_ime_info(ImeInfoDB *ime_db)
         return ret;
     }
 
-    if (_db_connect() == 0) {
+    if (in_transaction || _db_connect() == 0) {
         ret = _db_update_ime_info(ime_db);
-        _db_disconnect();
+        if (!in_transaction) _db_disconnect();
     }
     else
         LOGW ("failed\n");
@@ -1581,7 +1620,7 @@ EXAPI int isf_db_update_ime_info(ImeInfoDB *ime_db)
  *
  * @return the number of inserted data.
  */
-EXAPI int isf_db_insert_ime_info(ImeInfoDB *ime_db)
+EXAPI int isf_db_insert_ime_info(ImeInfoDB *ime_db, bool in_transaction)
 {
     int ret = 0;
 
@@ -1589,9 +1628,9 @@ EXAPI int isf_db_insert_ime_info(ImeInfoDB *ime_db)
         return ret;
     }
 
-    if (_db_connect() == 0) {
+    if (in_transaction || _db_connect() == 0) {
         ret = _db_insert_ime_info(ime_db);
-        _db_disconnect();
+        if (!in_transaction) _db_disconnect();
     }
     else {
         LOGE ("_db_connect() failed\n");
@@ -1672,6 +1711,79 @@ EXAPI int isf_db_delete_ime_info(void)
     return ret;
 }
 
+/**
+* @brief Begin transaction
+*
+* @return 1 if there is an ongoing transaction, otherwise return 0.
+*/
+EXAPI int isf_db_is_in_transaction(void)
+{
+    int ret = 0;
+
+    if (_db_is_connected() == 1) {
+        if (_is_in_transaction()) {
+            ret = 1;
+        }
+    }
+
+    return ret;
+}
+
+/**
+ * @brief Begin transaction
+ *
+ * @return 1 if it is successful, otherwise return 0.
+ */
+EXAPI int isf_db_begin_transaction(void)
+{
+    int ret = EXIT_FAILURE;
+
+    if (_db_is_connected() == 0) {
+        if (_db_connect() == 0) {
+            ret = _begin_transaction();
+        }
+    } else
+        LOGW("failed\n");
+
+    return (ret == EXIT_SUCCESS);
+}
+
+/**
+ * @brief Commit current transaction
+ *
+ * @return 1 if it is successful, otherwise return 0.
+ */
+EXAPI int isf_db_commit_transaction(void)
+{
+    int ret = EXIT_FAILURE;
+
+    if (_db_is_connected() == 1) {
+        ret = _commit_transaction();
+        _db_disconnect();
+    } else
+        LOGW("failed\n");
+
+    return (ret == EXIT_SUCCESS);
+}
+
+/**
+ * @brief Rollback current transaction
+ *
+ * @return 1 if it is successful, otherwise return 0.
+ */
+EXAPI int isf_db_rollback_transaction(void)
+{
+    int ret = EXIT_FAILURE;
+
+    if (_db_is_connected() == 1) {
+        ret = _rollback_transaction();
+        _db_disconnect();
+    } else
+        LOGW("failed\n");
+
+    return (ret == EXIT_SUCCESS);
+}
+
 /*
 vi:ts=4:nowrap:ai:expandtab
 */
index f200bbf..04f1ffb 100644 (file)
@@ -75,11 +75,15 @@ EXAPI int isf_db_update_label_by_appid(const char *appid, const char *label);
 EXAPI int isf_db_update_disp_lang(const char *disp_lang);
 EXAPI int isf_db_update_is_enabled_by_appid(const char *appid, bool is_enabled);
 EXAPI int isf_db_update_has_option_by_appid(const char *appid, bool has_option);
-EXAPI int isf_db_update_ime_info(ImeInfoDB *ime_db);
-EXAPI int isf_db_insert_ime_info(ImeInfoDB *ime_db);
+EXAPI int isf_db_update_ime_info(ImeInfoDB *ime_db, bool in_transaction);
+EXAPI int isf_db_insert_ime_info(ImeInfoDB *ime_db, bool in_transaction);
 EXAPI int isf_db_delete_ime_info_by_pkgid(const char *pkgid);
 EXAPI int isf_db_delete_ime_info_by_appid(const char *appid);
 EXAPI int isf_db_delete_ime_info(void);
+EXAPI int isf_db_is_in_transaction(void);
+EXAPI int isf_db_begin_transaction(void);
+EXAPI int isf_db_commit_transaction(void);
+EXAPI int isf_db_rollback_transaction(void);
 
 #endif /* __ISF_QUERY_UTILITY_H__ */