Improve handling of cache 63/283163/15
authorIlho Kim <ilho159.kim@samsung.com>
Wed, 19 Oct 2022 08:18:35 +0000 (17:18 +0900)
committerChanggyu Choi <changyu.choi@samsung.com>
Tue, 25 Oct 2022 03:39:38 +0000 (12:39 +0900)
After writing the package information, entire cache is removed and created
This is an inefficient process
so change to update only cache that needs to be updated

Change-Id: I6e7eea3e23ae392765dd9cbf53cf2bc09f06f0f7
Signed-off-by: Ilho Kim <ilho159.kim@samsung.com>
src/server/database/db_handle_provider.cc
src/server/database/db_handle_provider.hh
src/server/database/pkg_set_db_handler.cc
src/server/database/query_handler.cc
src/server/database/query_handler.hh
src/server/database/remove_cache_db_handler.cc
src/server/database/remove_cache_db_handler.hh
src/server/request_handler/command_request_handler.cc

index 375c3eb..07b6105 100644 (file)
@@ -296,8 +296,6 @@ void DBHandleProvider::UnsetMemoryMode(pid_t pid) {
   is_user_memdb_set_ = false;
   is_global_memdb_set_ = false;
 
-  TrimCache();
-
   LOG(DEBUG) << "Set Memory mode : File";
 }
 
@@ -327,6 +325,8 @@ void DBHandleProvider::ReleaseCache() {
 
   app_map_.clear();
   pkg_map_.clear();
+  pending_pkg_.clear();
+  pkg_app_map_.clear();
   CacheFlag::SetStatus(CacheFlag::Status::UNPREPARED);
 
   released_ = true;
@@ -341,6 +341,8 @@ int DBHandleProvider::UpdateCache(sqlite3* db, pid_t pid, uid_t uid, bool write,
     const std::string& locale) {
   pkg_map_.clear();
   app_map_.clear();
+  pending_pkg_.clear();
+  pkg_app_map_.clear();
 
   const char* dbpath = sqlite3_db_filename(db, "main");
   bool is_inmemory_db = false;
@@ -403,12 +405,13 @@ int DBHandleProvider::UpdateCache(sqlite3* db, pid_t pid, uid_t uid, bool write,
 
   if (ret == PMINFO_R_OK) {
     for (auto& app : app_list) {
-      if (pkg_map_.find(app->package) == pkg_map_.end()) {
+      auto it = pkg_map_.find(app->package);
+      if (it == pkg_map_.end()) {
         LOG(ERROR) << "Can not find package from pkg_map";
         return PMINFO_R_ERROR;
       }
 
-      app->privileges = pkg_map_[app->package].front()->privileges;
+      app->privileges = it->second->privileges;
       std::string appid = app->appid;
       AddApplication(std::move(appid), std::move(app));
     }
@@ -419,13 +422,23 @@ int DBHandleProvider::UpdateCache(sqlite3* db, pid_t pid, uid_t uid, bool write,
   return ret;
 }
 
+inline bool CheckPkgFilters(pkgmgrinfo_filter_x* filter,
+    const std::shared_ptr<package_x>& info) {
+  for (auto* it = filter->list; it != nullptr; it = g_slist_next(it)) {
+    auto node = reinterpret_cast<pkgmgrinfo_node_x*>(it->data);
+    auto* checker = FilterCheckerProvider::GetInst().
+        GetPkgFilterChecker(node->prop);
+    if (!checker->CheckFilter(node, info.get()))
+      return false;
+  }
+
+  return true;
+}
+
 std::vector<std::shared_ptr<package_x>> DBHandleProvider::GetPackages(
     pid_t pid, pkgmgrinfo_filter_x* filter,
     const std::string& package) {
   std::vector<std::shared_ptr<package_x>> ret;
-  auto map_it = pkg_map_.find(package);
-  if (map_it == pkg_map_.end())
-    return ret;
 
   if (__check_package_storage_status(filter)) {
     if (pkgmgrinfo_pkginfo_filter_add_bool(filter,
@@ -434,20 +447,15 @@ std::vector<std::shared_ptr<package_x>> DBHandleProvider::GetPackages(
       return {};
     }
   }
-
-  for (auto& info : map_it->second) {
-    bool pass = true;
-    for (auto* it = filter->list; it != nullptr; it = g_slist_next(it)) {
-      auto node = reinterpret_cast<pkgmgrinfo_node_x*>(it->data);
-      auto* checker = FilterCheckerProvider::GetInst().
-          GetPkgFilterChecker(node->prop);
-      if (!checker->CheckFilter(node, info.get())) {
-        pass = false;
-        break;
-      }
+  if (package.empty()) {
+    for (auto& info : pkg_map_) {
+      if (CheckPkgFilters(filter, info.second))
+        ret.push_back(info.second);
     }
-    if (pass)
-      ret.push_back(info);
+  } else {
+    auto map_it = pkg_map_.find(package);
+    if (map_it != pkg_map_.end() && CheckPkgFilters(filter, map_it->second))
+      ret.push_back(map_it->second);
   }
 
   return ret;
@@ -455,8 +463,39 @@ std::vector<std::shared_ptr<package_x>> DBHandleProvider::GetPackages(
 
 void DBHandleProvider::AddPackage(std::string package, package_x* info) {
   auto ptr = std::shared_ptr<package_x>(info, pkgmgrinfo_basic_free_package);
-  pkg_map_[package].push_back(ptr);
-  pkg_map_[""].push_back(std::move(ptr));
+  pkg_map_[package] = std::move(ptr);
+}
+
+inline bool CheckAppFilters(pkgmgrinfo_filter_x* filter,
+    const std::shared_ptr<application_x>& info,
+    const std::unordered_map<std::string, std::string>& metadata_map) {
+    for (auto* it = filter->list; it != nullptr; it = g_slist_next(it)) {
+      auto node = reinterpret_cast<pkgmgrinfo_node_x*>(it->data);
+      auto* checker = FilterCheckerProvider::GetInst().
+          GetAppFilterChecker(node->prop);
+      if (!checker->CheckFilter(node, info.get()))
+        return false;
+    }
+
+    bool pass = true;
+    if (!metadata_map.empty()) {
+      pass = false;
+      for (auto* it = info->metadata; it != nullptr; it = g_list_next(it)) {
+        auto* node = reinterpret_cast<metadata_x*>(it->data);
+        if (node->key != nullptr) {
+          auto metadata = metadata_map.find(node->key);
+          if (metadata == metadata_map.end())
+            continue;
+
+          if (metadata->second.empty() ||
+              strcmp(node->value ? node->value : "",
+                  metadata->second.c_str()) == 0)
+            return true;
+        }
+      }
+    }
+
+    return pass;
 }
 
 std::vector<std::shared_ptr<application_x>> DBHandleProvider::GetApplications(
@@ -473,10 +512,6 @@ std::vector<std::shared_ptr<application_x>> DBHandleProvider::GetApplications(
   }
 
   std::vector<std::shared_ptr<application_x>> ret;
-  auto map_it = app_map_.find(app);
-  if (map_it == app_map_.end())
-    return ret;
-
   if (pkgmgr_server::internal::check_app_storage_status(filter)) {
     if (pkgmgrinfo_appinfo_filter_add_bool(filter,
         PMINFO_APPINFO_PROP_APP_CHECK_STORAGE, true) != PMINFO_R_OK) {
@@ -485,48 +520,25 @@ std::vector<std::shared_ptr<application_x>> DBHandleProvider::GetApplications(
     }
   }
 
-  for (auto& info : map_it->second) {
-    bool pass = true;
-    for (auto* it = filter->list; it != nullptr; it = g_slist_next(it)) {
-      auto node = reinterpret_cast<pkgmgrinfo_node_x*>(it->data);
-      auto* checker = FilterCheckerProvider::GetInst().
-          GetAppFilterChecker(node->prop);
-      if (!checker->CheckFilter(node, info.get())) {
-        pass = false;
-        break;
-      }
-    }
-    if (!pass)
-      continue;
-
-    if (!metadata_map.empty()) {
-      pass = false;
-      for (auto* it = info->metadata; it != nullptr; it = g_list_next(it)) {
-        auto* node = reinterpret_cast<metadata_x*>(it->data);
-        if (node->key != nullptr) {
-          auto metadata = metadata_map.find(node->key);
-          if (metadata == metadata_map.end())
-            continue;
-
-          if (metadata->second.empty() ||
-              strcmp(node->value ? node->value : "",
-                  metadata->second.c_str()) == 0) {
-            pass = true;
-            break;
-          }
-        }
-      }
+  if (app.empty()) {
+    for (auto& info : app_map_) {
+      if (CheckAppFilters(filter, info.second, metadata_map))
+        ret.push_back(info.second);
     }
-
-    if (pass)
-      ret.push_back(info);
+  } else {
+    auto map_it = app_map_.find(app);
+    if (map_it != app_map_.end() &&
+        CheckAppFilters(filter, map_it->second, metadata_map))
+      ret.push_back(map_it->second);
   }
+
   return ret;
 }
 
-void DBHandleProvider::AddApplication(std::string app, std::shared_ptr<application_x> info) {
-  app_map_[app].push_back(info);
-  app_map_[""].push_back(std::move(info));
+void DBHandleProvider::AddApplication(std::string app,
+    std::shared_ptr<application_x> info) {
+  pkg_app_map_[info->package].emplace(app);
+  app_map_[app] = std::move(info);
 }
 
 void DBHandleProvider::InsertPID(pid_t pid) {
@@ -541,5 +553,195 @@ bool DBHandleProvider::ErasePID(pid_t pid) {
   return writer_pid_list_.erase(pid) == 1;
 }
 
+void DBHandleProvider::RegisterPendingPackageInfo(
+    package_x* info, pid_t pid) {
+  if (!info || !info->package)
+    return;
+
+  pending_pkg_[pid].emplace(info->package);
+}
+
+bool DBHandleProvider::UpdatePendingPackageInfo(sqlite3* db,
+    pid_t pid, uid_t uid, const std::string& locale) {
+  auto it = pending_pkg_.find(pid);
+  if (it == pending_pkg_.end()) {
+    LOG(WARNING) << "There is no package that is pending by the pid : " << pid;
+    return true;
+  }
+
+  GHashTable* list = g_hash_table_new(g_str_hash, g_str_equal);
+  if (list == nullptr) {
+    LOG(ERROR) << "Out of memory";
+    return false;
+  }
+
+  pkgmgrinfo_filter_x tmp_filter = { 0, };
+  pkgmgrinfo_node_x node = {
+    .prop = E_PMINFO_PKGINFO_PROP_PACKAGE_ID
+  };
+  tmp_filter.cache_flag = true;
+  tmp_filter.list = g_slist_append(tmp_filter.list, (gpointer)&node);
+  for (const auto& pkg : it->second) {
+    pkg_map_.erase(pkg);
+    for (auto& appid : pkg_app_map_[pkg]) {
+      app_map_.erase(appid);
+    }
+
+    pkg_app_map_.erase(pkg);
+    node.value = const_cast<char*>(pkg.c_str());
+    pkginfo_internal_filter_get_list(db, &tmp_filter,
+        uid_, locale.c_str(), list);
+  }
+  g_slist_free(tmp_filter.list);
+
+  GHashTableIter iter;
+  gpointer value;
+  g_hash_table_iter_init(&iter, list);
+  while (g_hash_table_iter_next(&iter, nullptr, &value)) {
+    auto* pkg = reinterpret_cast<package_x*>(value);
+    std::string pkgid = pkg->package;
+    AddPackage(std::move(pkgid), pkg);
+  }
+
+  g_hash_table_iter_init(&iter, list);
+  node.prop = E_PMINFO_APPINFO_PROP_APP_PACKAGE;
+  while (g_hash_table_iter_next(&iter, nullptr, &value)) {
+    auto* pkg = reinterpret_cast<package_x*>(value);
+    node.value = pkg->package;
+    std::vector<std::shared_ptr<application_x>> app_list;
+    pkgmgr_server::internal::appinfo_internal_filter_get_list(
+        db, &tmp_filter, uid_, uid, locale.c_str(), app_list);
+
+    for (auto& app : app_list) {
+      app->privileges = pkg->privileges;
+      std::string appid = app->appid;
+      AddApplication(std::move(appid), std::move(app));
+    }
+  }
+
+  g_hash_table_destroy(list);
+  pending_pkg_.erase(pid);
+  return true;
+}
+
+bool DBHandleProvider::UpdateCachePkg(sqlite3* db, uid_t uid,
+    const std::string& pkgid, const std::string& locale) {
+  GHashTable* list = g_hash_table_new(g_str_hash, g_str_equal);
+  if (list == nullptr) {
+    LOG(ERROR) << "Out of memory";
+    return false;
+  }
+
+  pkgmgrinfo_filter_x tmp_filter = { 0, };
+  pkgmgrinfo_node_x node = {
+    .prop = E_PMINFO_PKGINFO_PROP_PACKAGE_ID,
+    .value = const_cast<char*>(pkgid.c_str())
+  };
+  tmp_filter.cache_flag = true;
+  tmp_filter.list = g_slist_append(tmp_filter.list, (gpointer)&node);
+  pkginfo_internal_filter_get_list(db, &tmp_filter,
+      uid_, locale.c_str(), list);
+
+  GHashTableIter iter;
+  gpointer value;
+  g_hash_table_iter_init(&iter, list);
+  while (g_hash_table_iter_next(&iter, nullptr, &value)) {
+    auto* pkg = reinterpret_cast<package_x*>(value);
+    std::string pkgid = pkg->package;
+    AddPackage(pkgid, pkg);
+
+    for (auto& appid : pkg_app_map_[pkgid]) {
+      app_map_.erase(appid);
+    }
+
+    pkg_app_map_.erase(pkgid);
+
+    std::vector<std::shared_ptr<application_x>> app_list;
+    node.prop = E_PMINFO_APPINFO_PROP_APP_PACKAGE;
+    node.value = const_cast<char*>(pkgid.c_str());
+
+    pkgmgr_server::internal::appinfo_internal_filter_get_list(
+        db, &tmp_filter, uid_, uid, locale.c_str(), app_list);
+
+    for (auto& app : app_list) {
+      app->privileges = pkg->privileges;
+      std::string appid = app->appid;
+      AddApplication(std::move(appid), std::move(app));
+    }
+  }
+
+  g_slist_free(tmp_filter.list);
+  return true;
+}
+
+bool DBHandleProvider::UpdateCacheApp(sqlite3* db, uid_t uid,
+    const std::string& appid, const std::string& locale) {
+  pkgmgrinfo_filter_x tmp_filter = { 0, };
+  pkgmgrinfo_node_x node = {
+    .prop = E_PMINFO_APPINFO_PROP_APP_ID,
+    .value = const_cast<char*>(appid.c_str())
+  };
+  tmp_filter.cache_flag = true;
+  tmp_filter.list = g_slist_append(tmp_filter.list, (gpointer)&node);
+
+  std::vector<std::shared_ptr<application_x>> app_list;
+  app_map_.erase(appid);
+  pkgmgr_server::internal::appinfo_internal_filter_get_list(db,
+      &tmp_filter, uid_, uid, locale.c_str(), app_list);
+  g_slist_free(tmp_filter.list);
+
+  for (auto& app : app_list) {
+    auto it = pkg_map_.find(app->package);
+    if (it == pkg_map_.end()) {
+      LOG(ERROR) << "Can not find package from pkg_map";
+      return false;
+    }
+
+    pkg_app_map_[app->package].erase(app->appid);
+    app->privileges = it->second->privileges;
+    std::string appid = app->appid;
+    AddApplication(std::move(appid), std::move(app));
+  }
+
+  return true;
+}
+
+bool DBHandleProvider::UpdateCacheAppByPkgid(sqlite3* db, uid_t uid,
+    const std::string& pkgid, const std::string& locale) {
+  auto it = pkg_map_.find(pkgid);
+  if (it == pkg_map_.end()) {
+    LOG(ERROR) << "Can not find package from pkg_map";
+    return false;
+  }
+
+  auto& pkg = it->second;
+  pkgmgrinfo_filter_x tmp_filter = { 0, };
+  pkgmgrinfo_node_x node = {
+    .prop = E_PMINFO_APPINFO_PROP_APP_PACKAGE,
+    .value = pkg->package
+  };
+
+  tmp_filter.cache_flag = true;
+  tmp_filter.list = g_slist_append(tmp_filter.list, (gpointer)&node);
+
+  std::vector<std::shared_ptr<application_x>> app_list;
+  pkgmgr_server::internal::appinfo_internal_filter_get_list(
+      db, &tmp_filter, uid_, uid, locale.c_str(), app_list);
+
+  for (auto& appid : pkg_app_map_[pkgid]) {
+    app_map_.erase(appid);
+  }
+  pkg_app_map_.erase(pkgid);
+
+  for (auto& app : app_list) {
+    app->privileges = pkg->privileges;
+    std::string appid = app->appid;
+    AddApplication(std::move(appid), std::move(app));
+  }
+
+  g_slist_free(tmp_filter.list);
+  return true;
+}
+
 }  // namespace database
 }  // namespace pkgmgr_server
index f5df1e3..6f54d0b 100644 (file)
@@ -60,6 +60,15 @@ class EXPORT_API DBHandleProvider {
       pid_t pid, pkgmgrinfo_filter_x* filter,
       const std::string& app);
   void TrimCache();
+  void RegisterPendingPackageInfo(package_x* info, pid_t pid);
+  bool UpdatePendingPackageInfo(sqlite3* db,
+      pid_t pid, uid_t uid, const std::string& locale);
+  bool UpdateCachePkg(sqlite3* db, uid_t uid, const std::string& pkgid,
+      const std::string& locale);
+  bool UpdateCacheApp(sqlite3* db, uid_t uid, const std::string& appid,
+      const std::string& locale);
+  bool UpdateCacheAppByPkgid(sqlite3* db, uid_t uid, const std::string& pkgid,
+      const std::string& locale);
 
  private:
   explicit DBHandleProvider(uid_t uid);
@@ -93,10 +102,10 @@ class EXPORT_API DBHandleProvider {
   std::string user_parser_memdb_path_;
   std::string user_parser_filedb_path_;
   bool released_ = true;
-  std::unordered_map<std::string, std::vector<std::shared_ptr<package_x>>>
-      pkg_map_;
-  std::unordered_map<std::string, std::vector<std::shared_ptr<application_x>>>
-      app_map_;
+  std::unordered_map<std::string, std::shared_ptr<package_x>> pkg_map_;
+  std::unordered_map<std::string, std::shared_ptr<application_x>> app_map_;
+  std::unordered_map<std::string, std::unordered_set<std::string>> pkg_app_map_;
+  std::unordered_map<pid_t, std::unordered_set<std::string>> pending_pkg_;
 };
 
 }  // namespace database
index 9c8d0b9..58348c0 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <vector>
 
+#include "cache_flag.hh"
 #include "db_handle_provider.hh"
 #include "utils/logging.hh"
 
@@ -72,9 +73,14 @@ int PkgSetDBHandler::Execute() {
   else
     LOG(ERROR) << "Unknown db write type";
 
-  if (ret != PM_PARSER_R_OK)
+  if (is_offline_ || ret != PMINFO_R_OK)
     return ret;
 
+  auto lock = CacheFlag::GetWriterLock();
+  if (CacheFlag::GetStatus() == CacheFlag::Status::PREPARED)
+    DBHandleProvider::GetInst(uid_)
+        .RegisterPendingPackageInfo(package_, GetPID());
+
   return ret;
 }
 
index f85dcee..b34a2dc 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 "pkgmgrinfo_debug.h"
@@ -147,38 +149,39 @@ 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];
   }
 };
@@ -262,7 +265,8 @@ int QueryHandler::ExecuteReadQuery(GList* queries, GList* args_list) {
   return ret;
 }
 
-int QueryHandler::ExecuteWriteQuery(GList* queries, GList* args_list) {
+int QueryHandler::ExecuteWriteQuery(GList* queries, GList* 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";
@@ -271,6 +275,7 @@ int QueryHandler::ExecuteWriteQuery(GList* queries, GList* args_list) {
 
   std::vector<std::pair<sqlite3*, uid_t>> conn_list = GetConnection();
   int ret = PMINFO_R_ERROR;
+  bool is_writer = DBHandleProvider::IsWriter(GetPID());
   for (auto& conn : conn_list) {
     ret = execute_write_queries(conn.first, queries, args_list);
     if (ret != PMINFO_R_OK) {
@@ -278,15 +283,58 @@ int QueryHandler::ExecuteWriteQuery(GList* queries, GList* args_list) {
       break;
     }
   }
-  database::DBHandleProvider::GetInst(GetUID()).TrimCache();
-  return ret;
+
+  if (ret != PMINFO_R_OK || is_writer || changes.size() == 0 ||
+      CacheFlag::GetStatus() != CacheFlag::Status::PREPARED)
+    return ret;
+
+  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() {
   GList* queries = nullptr;
   GList* args_list = nullptr;
-  for (auto& i : query_args_) {
-    const char* query = __query_maker.GetQuery(i.first);
+  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";
       __free_query_list(queries, args_list);
@@ -301,13 +349,33 @@ int QueryHandler::Execute() {
       __free_query_list(queries, args_list);
       return PMINFO_R_ERROR;
     }
-    arg->len = i.second.size();
-    for (auto& argument : i.second) {
+    arg->len = args.size();
+    for (auto& argument : args) {
       arg->argument = g_list_append(arg->argument,
           gpointer(argument ? (*argument).c_str() : nullptr));
     }
 
     args_list = g_list_append(args_list, arg);
+
+    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";
+      __free_query_list(queries, args_list);
+      return PMINFO_R_ERROR;
+    }
+
+    if (!args[idx])
+      continue;
+
+    changes.emplace_back(std::make_pair(flag, *args[idx]));
   }
 
   if (GetOpType() == pkgmgr_common::DBOperationType::OPERATION_TYPE_READ) {
@@ -315,7 +383,7 @@ int QueryHandler::Execute() {
     __free_query_list(queries, args_list);
     return ret;
   } else {
-    int ret = ExecuteWriteQuery(queries, args_list);
+    int ret = ExecuteWriteQuery(queries, args_list, changes);
     __free_query_list(queries, args_list);
     return ret;
   }
index b060508..9ba3738 100644 (file)
@@ -35,6 +35,13 @@ namespace database {
 #define EXPORT_API __attribute__((visibility("default")))
 #endif
 
+enum class CacheChangeFlag {
+  NONE,
+  PKG,
+  APP,
+  APPBYPKG
+};
+
 class EXPORT_API QueryHandler : public AbstractDBHandler {
  public:
   QueryHandler(uid_t uid, int pid);
@@ -50,7 +57,8 @@ class EXPORT_API QueryHandler : public AbstractDBHandler {
 
  private:
   int ExecuteReadQuery(GList* queries, GList* args_list);
-  int ExecuteWriteQuery(GList* queries, GList* args_list);
+  int ExecuteWriteQuery(GList* queries, GList* args_list,
+      const std::vector<std::pair<CacheChangeFlag, std::string>>& changes);
 
   uid_t uid_;
   std::vector<std::string> query_;
index d4ca31a..f12cb48 100644 (file)
 
 #include "remove_cache_db_handler.hh"
 
+#include "cache_flag.hh"
 #include "db_handle_provider.hh"
 
 namespace pkgmgr_server {
 namespace database {
 
 RemoveCacheDBHandler::RemoveCacheDBHandler(uid_t uid, int pid)
-    : AbstractDBHandler(uid, pid) {}
+    : AbstractDBHandler(uid, pid), uid_(uid) {}
 
 int RemoveCacheDBHandler::Execute() {
   std::unique_lock<std::shared_mutex> u(lock_);
+  SetOpType(pkgmgr_common::DBOperationType::OPERATION_TYPE_READ);
+  SetDBType(pkgmgr_common::DBType::DB_TYPE_FILE_PKGDB);
 
   database::DBHandleProvider::GetInst(GetUID()).UnsetMemoryMode(GetPID());
-  database::DBHandleProvider::GetInst(GetUID()).TrimCache();
+
+  if (!Connect()) {
+    database::DBHandleProvider::GetInst(GetUID()).TrimCache();
+    return PMINFO_R_ERROR;
+  }
+
+  std::vector<std::pair<sqlite3*, uid_t>> conn_list = GetConnection();
+  auto lock = CacheFlag::GetWriterLock();
+  if (CacheFlag::GetStatus() != CacheFlag::Status::PREPARED)
+    return PMINFO_R_OK;
+  CacheFlag::SetStatus(CacheFlag::Status::PREPARING);
+  bool success = true;
+  for (auto& conn : conn_list) {
+    auto& provider = database::DBHandleProvider::GetInst(conn.second);
+    success = provider.UpdatePendingPackageInfo(conn.first,
+        GetPID(), uid_, GetLocale());
+    if (!success) {
+      provider.TrimCache();
+      break;
+    }
+  }
+  CacheFlag::SetStatus(success ?
+      CacheFlag::Status::PREPARED : CacheFlag::Status::UNPREPARED);
 
   return PMINFO_R_OK;
 }
index 65f56cf..b33dcea 100644 (file)
@@ -32,6 +32,9 @@ class EXPORT_API RemoveCacheDBHandler : public AbstractDBHandler {
  public:
   RemoveCacheDBHandler(uid_t uid, int pid);
   int Execute() override;
+
+ private:
+  uid_t uid_;
 };
 
 }  // namespace database
index d98e4a4..458b3a8 100644 (file)
@@ -43,6 +43,7 @@ bool CommandRequestHandler::HandleRequest(unsigned char* data, size_t size,
 
   if (parcel->GetCmd() == CommandType::RemoveCache) {
     database::RemoveCacheDBHandler db(parcel->GetUid(), GetPID());
+    db.SetLocale(locale);
     int ret = db.Execute();
     result_ = std::make_shared<pcp::ResultParcelable>(
         ret, std::vector<pcp::StrArgs>{});