Refactor pkgmgr-info
[platform/core/appfw/pkgmgr-info.git] / src / server / database / query_handler.cc
index 78d9c8c..1d481e3 100644 (file)
 #include "query_handler.hh"
 
 #include <shared_mutex>
+#include <tuple>
 #include <vector>
 
 #include "utils/logging.hh"
+#include "cache_flag.hh"
 #include "db_handle_provider.hh"
-#include "cache_provider.hh"
 
 #include "pkgmgrinfo_debug.h"
 #include "pkgmgrinfo_internal.h"
@@ -148,55 +149,45 @@ constexpr const char query_unregister_all_pkg_update_info[] =
 
 class QueryMaker {
  public:
-  std::vector<const char*> query_raw_ = {
-    query_appinfo_get_localed_label,
-    query_appinfo_get_datacontrol_info,
-    query_appinfo_get_datacontrol_appid,
-    query_appinfo_get_datacontrol_trusted_info,
-    query_appinfo_get_datacontrol_privileges,
-    query_appinfo_get_appcontrol_privileges,
-    query_plugininfo_get_appids,
-    query_get_pkg_updateinfo_1,
-    query_get_pkg_updateinfo_2,
-    query_pkginfo_set_usr_installed_storage_1,
-    query_pkginfo_set_usr_installed_storage_2,
-    query_certinfo_compare_pkg_certinfo,
-    query_certinfo_compare_app_certinfo,
-    query_pkginfo_delete_certinfo,
-
-    query_insert_package_plugin_execution_info,
-    query_delete_package_plugin_execution_info,
-    query_update_global_app_disable,
-    query_update_app_disable_info,
-    query_update_pkg_disable_info,
-    query_update_global_app_splash_screen_display_info,
-    query_update_app_splash_screen_display_info,
-    query_update_app_label_info,
-    query_update_app_icon_info,
-    query_update_tep_info,
-    query_register_pkg_update_info,
-    query_unregister_pkg_update_info,
-    query_unregister_all_pkg_update_info,
+  using CacheChangeFlag = pkgmgr_server::database::CacheChangeFlag;
+  std::vector<std::tuple<const char*, CacheChangeFlag, int>> query_raw_ = {
+    { query_appinfo_get_localed_label, CacheChangeFlag::NONE, 0 },
+    { query_appinfo_get_datacontrol_info, CacheChangeFlag::NONE, 0 },
+    { query_appinfo_get_datacontrol_appid, CacheChangeFlag::NONE, 0 },
+    { query_appinfo_get_datacontrol_trusted_info, CacheChangeFlag::NONE, 0 },
+    { query_appinfo_get_datacontrol_privileges, CacheChangeFlag::NONE, 0 },
+    { query_appinfo_get_appcontrol_privileges, CacheChangeFlag::NONE, 0 },
+    { query_plugininfo_get_appids, CacheChangeFlag::NONE, 0 },
+    { query_get_pkg_updateinfo_1, CacheChangeFlag::NONE, 0 },
+    { query_get_pkg_updateinfo_2, CacheChangeFlag::NONE, 0 },
+    { query_pkginfo_set_usr_installed_storage_1, CacheChangeFlag::PKG, 2 },
+    { query_pkginfo_set_usr_installed_storage_2, CacheChangeFlag::APPBYPKG, 2 },
+    { query_certinfo_compare_pkg_certinfo, CacheChangeFlag::NONE, 0 },
+    { query_certinfo_compare_app_certinfo, CacheChangeFlag::NONE, 0 },
+    { query_pkginfo_delete_certinfo, CacheChangeFlag::NONE, 0 },
+
+    { query_insert_package_plugin_execution_info, CacheChangeFlag::PKG, 0 },
+    { query_delete_package_plugin_execution_info, CacheChangeFlag::PKG, 0 },
+    { query_update_global_app_disable, CacheChangeFlag::APP, 0 },
+    { query_update_app_disable_info, CacheChangeFlag::APP, 1 },
+    { query_update_pkg_disable_info, CacheChangeFlag::PKG, 1 },
+    { query_update_global_app_splash_screen_display_info, CacheChangeFlag::APP, 0 },
+    { query_update_app_splash_screen_display_info, CacheChangeFlag::APP, 1 },
+    { query_update_app_label_info, CacheChangeFlag::APP, 1 },
+    { query_update_app_icon_info, CacheChangeFlag::APP, 1 },
+    { query_update_tep_info, CacheChangeFlag::PKG, 1 },
+    { query_register_pkg_update_info, CacheChangeFlag::NONE, 0 },
+    { query_unregister_pkg_update_info, CacheChangeFlag::NONE, 0 },
+    { query_unregister_all_pkg_update_info, CacheChangeFlag::NONE, 0 },
   };
 
-  const char* GetQuery(int index) {
+  const std::tuple<const char*, CacheChangeFlag, int>& GetQueryInfo(int index) {
     return query_raw_[index];
   }
 };
 
 QueryMaker __query_maker;
 
-void __free_argument(gpointer data) {
-  query_args* args = reinterpret_cast<query_args*>(data);
-  g_list_free(args->argument);
-  free(args);
-}
-
-void __free_query_list(GList* queries, GList* args_list) {
-  g_list_free(queries);
-  g_list_free_full(args_list, __free_argument);
-}
-
 }  // namespace
 
 namespace pkgmgr_server {
@@ -220,91 +211,141 @@ std::vector<pkgmgr_common::parcel::StrArgs> QueryHandler::GetResult() {
   return std::move(result_);
 }
 
-int QueryHandler::Execute() {
-  std::shared_lock<std::shared_timed_mutex> s(lock_);
+int QueryHandler::ExecuteReadQuery(const std::vector<std::string>& queries,
+    const std::vector<std::vector<std::optional<std::string>>>& args_list) {
+  std::shared_lock<std::shared_mutex> s(lock_);
   if (!Connect()) {
     LOG(ERROR) << "Failed to connect database";
     return PMINFO_R_ERROR;
   }
 
-  GList* queries = nullptr;
-  GList* args_list = nullptr;
-  for (auto& i : query_args_) {
-    const char* query = __query_maker.GetQuery(i.first);
-    if (query == nullptr) {
-      LOG(ERROR) << "Failed to get query";
-      __free_query_list(queries, args_list);
-      return PMINFO_R_ERROR;
-    }
+  const auto& conn_list = GetConnection();
+  int ret = PMINFO_R_ERROR;
+  for (const auto& conn : conn_list) {
+    int i = 0;
+    for (auto& q : queries) {
+      std::vector<std::vector<std::optional<std::string>>> result;
+      ret = internal::GetQueryResult(conn.first, q, args_list[i++], result);
+      if (ret == PMINFO_R_ERROR) {
+        LOG(ERROR) << "Failed to execute query";
+        return ret;
+      }
 
-    queries = g_list_append(queries, (gpointer)query);
-    query_args* arg = reinterpret_cast<query_args*>(
-        calloc(1, sizeof(query_args)));
-    if (arg == nullptr) {
-      LOG(ERROR) << "Out of memory";
-      __free_query_list(queries, args_list);
-      return PMINFO_R_ERROR;
-    }
-    arg->len = i.second.size();
-    for (auto& argument : i.second) {
-      arg->argument = g_list_append(arg->argument,
-          gpointer(argument ? (*argument).c_str() : nullptr));
+      for (auto& r : result) {
+        result_.push_back(std::move(r));
+      }
     }
+  }
 
-    args_list = g_list_append(args_list, arg);
+  return ret;
+}
+
+int QueryHandler::ExecuteWriteQuery(const std::vector<std::string>& queries,
+    const std::vector<std::vector<std::optional<std::string>>>& args_list,
+    const std::vector<std::pair<CacheChangeFlag, std::string>>& changes) {
+  std::unique_lock<std::shared_mutex> u(lock_);
+  if (!Connect()) {
+    LOG(ERROR) << "Failed to connect database";
+    return PMINFO_R_ERROR;
   }
 
-  std::vector<std::pair<sqlite3*, uid_t>> conn_list = GetConnection();
+  const auto& conn_list = GetConnection();
   int ret = PMINFO_R_ERROR;
-  if (GetOpType() == pkgmgr_common::DBOperationType::OPERATION_TYPE_READ) {
-    for (auto& conn : conn_list) {
-      for (GList* it = args_list; it; it = it->next) {
-        GList* list = nullptr;
-        int row = 0;
-        int col = 0;
-
-        query_args* params = reinterpret_cast<query_args*>(it->data);
-        ret = get_query_result(conn.first, (const char *)queries->data,
-            params->argument, &list, &row, &col);
-        if (ret == PMINFO_R_ERROR) {
-          LOG(ERROR) << "Failed to execute query";
-          __free_query_list(queries, args_list);
-          return ret;
-        }
-
-        GList* tmp = list;
-        for (int i = 0; i < row; ++i) {
-          pkgmgr_common::parcel::StrArgs vt;
-          for (int j = 0; j < col; ++j) {
-            if (!tmp->data)
-              vt.emplace_back(std::nullopt);
-            else
-              vt.emplace_back(reinterpret_cast<char *>(tmp->data));
-            tmp = tmp->next;
-          }
-          result_.emplace_back(std::move(vt));
-        }
-
-        g_list_free_full(list, free);
-      }
+  bool is_writer = DBHandleProvider::IsWriter(GetPID());
+  for (const auto& conn : conn_list) {
+    ret = internal::ExecuteWriteQueries(conn.first, queries, args_list);
+    if (ret != PMINFO_R_OK) {
+      LOG(ERROR) << "Failed to execute";
+      break;
     }
-    __free_query_list(queries, args_list);
+  }
 
+  if (ret != PMINFO_R_OK || is_writer || changes.size() == 0 ||
+      CacheFlag::GetStatus() != CacheFlag::Status::PREPARED)
     return ret;
-  } else {
-    for (auto& conn : conn_list) {
-      ret = execute_write_queries(conn.first, queries, args_list);
-      if (ret != PMINFO_R_OK) {
-        LOG(ERROR) << "Failed to execute";
+
+  bool success = true;
+  CacheFlag::SetStatus(CacheFlag::Status::PREPARING);
+  auto lock = CacheFlag::GetWriterLock();
+  for (auto& conn : conn_list) {
+    auto& provider = database::DBHandleProvider::GetInst(conn.second);
+    for (const auto& [flag, name] : changes) {
+      switch (flag) {
+      case CacheChangeFlag::PKG:
+        success = provider.UpdateCachePkg(conn.first, uid_, name, GetLocale());
+        break;
+      case CacheChangeFlag::APP:
+        success = provider.UpdateCacheApp(conn.first, uid_, name, GetLocale());
+        break;
+      case CacheChangeFlag::APPBYPKG:
+        success =
+            provider.UpdateCacheAppByPkgid(conn.first, uid_, name, GetLocale());
+        break;
+      default:
         break;
       }
+
+      if (!success) {
+        LOG(ERROR) << "Write query failed. " << static_cast<int>(flag) << ' '
+                   << name;
+        break;
+      }
+    }
+
+    if (!success) {
+      provider.TrimCache();
+      break;
+    }
+  }
+
+  CacheFlag::SetStatus(success ?
+      CacheFlag::Status::PREPARED : CacheFlag::Status::UNPREPARED);
+
+  return PMINFO_R_OK;
+}
+
+int QueryHandler::Execute() {
+  std::vector<std::string> queries;
+  std::vector<std::vector<std::optional<std::string>>> args_list;
+  std::vector<std::pair<CacheChangeFlag, std::string>> changes;
+  for (auto& [queryIndex, args] : query_args_) {
+    const auto& query_info = __query_maker.GetQueryInfo(queryIndex);
+    const char* query = std::get<0>(query_info);
+    if (query == nullptr) {
+      LOG(ERROR) << "Failed to get query";
+      return PMINFO_R_ERROR;
+    }
+
+    queries.push_back(query);
+    args_list.push_back(args);
+
+    if (GetOpType() == pkgmgr_common::DBOperationType::OPERATION_TYPE_READ)
+      continue;
+
+    CacheChangeFlag flag = std::get<1>(query_info);
+    if (flag == CacheChangeFlag::NONE)
+      continue;
+
+    /* Cache changed query steps */
+    unsigned int idx = std::get<2>(query_info);
+    if (args.size() <= idx) {
+      LOG(ERROR) << "Invalid query argument";
+      return PMINFO_R_ERROR;
     }
-    __free_query_list(queries, args_list);
-    CacheProvider(GetUID()).ReleaseCache();
 
+    if (!args[idx])
+      continue;
+
+    changes.emplace_back(std::make_pair(flag, *args[idx]));
+  }
+
+  if (GetOpType() == pkgmgr_common::DBOperationType::OPERATION_TYPE_READ) {
+    int ret = ExecuteReadQuery(queries, args_list);
+    return ret;
+  } else {
+    int ret = ExecuteWriteQuery(queries, args_list, changes);
     return ret;
   }
-  return ret;
 }
 
 }  // namespace database