Remove the possibility of incorrect memory access
[platform/core/appfw/pkgmgr-info.git] / src / server / database / db_handle_provider.cc
index 6b3579f..5576c67 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <fcntl.h>
 #include <glib.h>
+#include <sys/stat.h>
 #include <sys/types.h>
 
 #include <tzplatform_config.h>
@@ -57,11 +58,23 @@ uid_t ConvertUID(uid_t uid) {
     return uid;
 }
 
-static const std::string global_parser_memory_db_path =
-    "file:parserdb?mode=memory&cache=shared";
+bool GetModifiedTime(const char* dbpath, timespec* t) {
+  if (dbpath == nullptr || t == nullptr) {
+    LOG(ERROR) << "Invalid argument";
+    return false;
+  }
+
+  struct stat attr;
+  if (stat(dbpath, &attr)) {
+    LOG(ERROR) << "Fail to get status from file "
+        << dbpath << " errno : " << errno;
+    return false;
+  }
 
-static const std::string cert_memory_db_path =
-    "file:certdb?mode=memory&cache=shared";
+  *t = attr.st_mtim;
+
+  return true;
+}
 
 }  // namespace
 
@@ -69,103 +82,81 @@ namespace pkgmgr_server {
 namespace database {
 
 std::unordered_map<uid_t, std::unique_ptr<DBHandleProvider>>
-    DBHandleProvider::provider_;
-bool DBHandleProvider::is_memory_global_ = false;
-std::unique_ptr<sqlite3, decltype(sqlite3_close_v2)*>
-    DBHandleProvider::global_parser_memory_db_handle_(nullptr,
-                                                      sqlite3_close_v2);
-std::unique_ptr<sqlite3, decltype(sqlite3_close_v2)*>
-    DBHandleProvider::cert_memory_db_handle_(nullptr, sqlite3_close_v2);
-std::string DBHandleProvider::global_parser_file_db_path_;
-std::string DBHandleProvider::cert_file_db_path_;
-std::unordered_set<pid_t> DBHandleProvider::pid_list_;
-std::recursive_mutex DBHandleProvider::lock_;
-std::mutex DBHandleProvider::pid_list_lock_;
-
-DBHandleProvider::DBHandleProvider(uid_t uid)
-    : uid_(uid),
-      is_memory_(false),
-      parser_memory_db_handle_(nullptr, sqlite3_close_v2) {
+    DBHandleProvider::provider_map_;
+std::string DBHandleProvider::global_parser_filedb_path_;
+std::string DBHandleProvider::cert_filedb_path_;
+std::unordered_set<pid_t> DBHandleProvider::writer_pid_list_;
+std::shared_mutex DBHandleProvider::pid_list_lock_;
+
+DBHandleProvider::DBHandleProvider(uid_t uid) : uid_(uid) {
   char* tmp_path;
 
-  if (global_parser_file_db_path_.empty()) {
+  if (global_parser_filedb_path_.empty()) {
     tmp_path = getUserPkgParserDBPathUID(GetGlobalUID());
-    global_parser_file_db_path_ = tmp_path;
+    global_parser_filedb_path_ = tmp_path;
     free(tmp_path);
+  }
 
+  if (cert_filedb_path_.empty()) {
     tmp_path = getUserPkgCertDBPath();
-    cert_file_db_path_ = tmp_path;
+    cert_filedb_path_ = tmp_path;
     free(tmp_path);
   }
 
   tmp_path = getUserPkgParserDBPathUID(uid_);
-  parser_file_db_path_ = tmp_path;
+  user_parser_filedb_path_ = tmp_path;
   free(tmp_path);
-
-  parser_memory_db_path_ = "file:parserdb" +
-                           std::to_string(static_cast<int>(uid_)) +
-                           "?mode=memory&cache=shared";
 }
 
 DBHandleProvider& DBHandleProvider::GetInst(uid_t uid) {
-  static std::mutex singleton_lock_;
-  std::unique_lock<std::mutex> u(singleton_lock_);
+  static std::shared_mutex singleton_lock_;
+  std::shared_lock<std::shared_mutex> s(singleton_lock_);
 
   uid = ConvertUID(uid);
-  auto& prov = provider_[uid];
+  auto it = provider_map_.find(uid);
+  if (it != provider_map_.end())
+    return *(it->second);
+
+  s.unlock();
+  std::unique_lock<std::shared_mutex> u(singleton_lock_);
+  auto& prov = provider_map_[uid];
   if (prov == nullptr)
     prov.reset(new DBHandleProvider(uid));
 
   return *prov;
 }
 
-bool DBHandleProvider::IsCrashedWriteRequest() {
-  std::unique_lock<std::mutex> u(pid_list_lock_);
+std::unordered_set<pid_t> DBHandleProvider::CrashedWriteRequestPIDs() {
+  std::unique_lock<std::shared_mutex> u(pid_list_lock_);
 
-  if (pid_list_.empty())
-    return false;
+  if (writer_pid_list_.empty())
+    return {};
 
-  bool ret = true;
-  LOG(DEBUG) << "Check process count : " << pid_list_.size();
-  std::vector<pid_t> remove_pids;
-  for (pid_t pid : pid_list_) {
+  LOG(DEBUG) << "Check process count : " << writer_pid_list_.size();
+  std::unordered_set<pid_t> remove_pids;
+  for (pid_t pid : writer_pid_list_) {
     std::string status_path = "/proc/" + std::to_string(pid) + "/status";
 
     int fd = open(status_path.c_str(), O_RDONLY);
     if (fd < 0) {
       LOG(ERROR) << "Process is crashed : " << pid;
-      remove_pids.push_back(pid);
+      remove_pids.emplace(pid);
     } else {
-      ret = false;
       close(fd);
     }
   }
 
-  for (pid_t pid : remove_pids)
-    pid_list_.erase(pid);
-
-  return ret;
+  return remove_pids;
 }
 
-std::vector<std::pair<std::string, uid_t>> DBHandleProvider::GetParserDBPath(
-    pid_t pid, bool write) {
-  std::unique_lock<std::recursive_mutex> u(lock_);
+std::vector<std::pair<std::string, uid_t>> DBHandleProvider::GetParserDBPath() {
   std::vector<std::pair<std::string, uid_t>> db_path_list;
 
-  if (is_memory_ != is_memory_global_)
-    is_memory_global_ ? SetMemoryMode(pid) : UnsetMemoryMode(pid);
+  if (uid_ > REGULAR_USER)
+    db_path_list.emplace_back(std::make_pair(user_parser_filedb_path_, uid_));
 
-  if (IsMemoryDBActive(pid, write)) {
-    if (uid_ > REGULAR_USER)
-      db_path_list.emplace_back(std::make_pair(parser_memory_db_path_, uid_));
-    db_path_list.emplace_back(
-        std::make_pair(global_parser_memory_db_path, GetGlobalUID()));
-  } else {
-    if (uid_ > REGULAR_USER)
-      db_path_list.emplace_back(std::make_pair(parser_file_db_path_, uid_));
-    db_path_list.emplace_back(
-        std::make_pair(global_parser_file_db_path_, GetGlobalUID()));
-  }
+  db_path_list.emplace_back(
+      std::make_pair(global_parser_filedb_path_, GetGlobalUID()));
 
   if (db_path_list.size() == 1) {
     LOG(DEBUG) << "global db path : " << db_path_list[0].first;
@@ -177,109 +168,11 @@ std::vector<std::pair<std::string, uid_t>> DBHandleProvider::GetParserDBPath(
   return db_path_list;
 }
 
-std::string DBHandleProvider::GetCertDBPath(pid_t pid, bool write) {
-  std::unique_lock<std::recursive_mutex> u(lock_);
-  if (is_memory_ != is_memory_global_)
-    is_memory_global_ ? SetMemoryMode(pid) : UnsetMemoryMode(pid);
-
-  if (IsMemoryDBActive(pid, write))
-    return cert_memory_db_path;
-  else
-    return cert_file_db_path_;
-}
-
-sqlite3* DBHandleProvider::GetMemoryDBHandle(const std::string& filedb_path,
-                                             const std::string& memorydb_path) {
-  sqlite3* memorydb = nullptr;
-  sqlite3* filedb = nullptr;
-  int ret = sqlite3_open_v2(memorydb_path.c_str(), &memorydb,
-                            SQLITE_OPEN_READONLY | SQLITE_OPEN_URI, nullptr);
-  if (ret != SQLITE_OK) {
-    LOG(ERROR) << "Failed to open memory DB " << ret << ": " << memorydb_path;
-    return nullptr;
-  }
-
-  ret = sqlite3_open_v2(filedb_path.c_str(), &filedb, SQLITE_OPEN_READONLY,
-                        nullptr);
-  if (ret != SQLITE_OK) {
-    LOG(ERROR) << "Failed to open file DB " << ret << ": " << filedb_path;
-    sqlite3_close_v2(memorydb);
-    return nullptr;
-  }
-
-  sqlite3_backup* backup =
-      sqlite3_backup_init(memorydb, "main", filedb, "main");
-  if (backup == nullptr) {
-    LOG(ERROR) << "Failed to backup for memory DB";
-    sqlite3_close_v2(memorydb);
-    sqlite3_close_v2(filedb);
-    return nullptr;
-  }
-
-  sqlite3_backup_step(backup, -1);
-  sqlite3_backup_finish(backup);
-  sqlite3_close_v2(filedb);
-  return memorydb;
-}
-
-void DBHandleProvider::SetMemoryMode(pid_t pid) {
-  std::unique_lock<std::recursive_mutex> u(lock_);
-  if (is_memory_global_ && is_memory_)
-    return;
-
-  sqlite3* parser_db =
-      GetMemoryDBHandle(parser_file_db_path_, parser_memory_db_path_);
-  if (parser_db != nullptr)
-    parser_memory_db_handle_.reset(parser_db);
-
-  if (is_memory_ == is_memory_global_) {
-    sqlite3* global_parser_file_db = GetMemoryDBHandle(
-        global_parser_file_db_path_, global_parser_memory_db_path);
-    if (global_parser_file_db)
-      global_parser_memory_db_handle_.reset(global_parser_file_db);
-    sqlite3* cert_db =
-        GetMemoryDBHandle(cert_file_db_path_, cert_memory_db_path);
-    if (cert_db != nullptr)
-      cert_memory_db_handle_.reset(cert_db);
-
-    InsertPID(pid);
-  }
-
-  is_memory_ = true;
-  is_memory_global_ = true;
-  LOG(DEBUG) << "Set Memory mode : Memory";
-}
-
-void DBHandleProvider::UnsetMemoryMode(pid_t pid) {
-  std::unique_lock<std::recursive_mutex> u(lock_);
-  if (!is_memory_global_ && !is_memory_)
-    return;
-
-  auto lock = CacheFlag::GetWriterLock();
-  CacheFlag::SetStatus(CacheFlag::Status::PREPARING);
-
-  parser_memory_db_handle_.reset(nullptr);
-  cert_memory_db_handle_.reset(nullptr);
-  global_parser_memory_db_handle_.reset(nullptr);
-
-  if (!ErasePID(pid))
-    LOG(ERROR) << "Given pid is not exists in pid list : " << pid;
-
-  is_memory_ = false;
-  is_memory_global_ = false;
-  pkg_map_.clear();
-  app_map_.clear();
-  CacheFlag::SetStatus(CacheFlag::Status::UNPREPARED);
-  LOG(DEBUG) << "Set Memory mode : File";
-}
-
-bool DBHandleProvider::IsMemoryDBActive(pid_t pid, bool write) {
-  std::unique_lock<std::mutex> u(pid_list_lock_);
-  return (is_memory_ && pid_list_.find(pid) == pid_list_.end() && !write);
+std::string DBHandleProvider::GetCertDBPath() {
+  return cert_filedb_path_;
 }
 
 void DBHandleProvider::TrimCache() {
-  std::unique_lock<std::recursive_mutex> u(lock_);
   if (!released_)
     ReleaseCache();
 }
@@ -290,103 +183,204 @@ void DBHandleProvider::ReleaseCache() {
 
   app_map_.clear();
   pkg_map_.clear();
+  pending_pkg_.clear();
+  pkg_app_map_.clear();
   CacheFlag::SetStatus(CacheFlag::Status::UNPREPARED);
 
   released_ = true;
 }
 
 bool DBHandleProvider::IsWriter(pid_t pid) {
-  std::unique_lock<std::mutex> u(pid_list_lock_);
-  return pid_list_.find(pid) != pid_list_.end();
+  std::unique_lock<std::shared_mutex> s(pid_list_lock_);
+  return writer_pid_list_.find(pid) != writer_pid_list_.end();
 }
 
-int DBHandleProvider::UpdateCache(sqlite3* db, pid_t pid, uid_t uid, bool write,
-    const std::string& locale) {
+int DBHandleProvider::UpdateCache(const tizen_base::Database& 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();
 
-  GHashTable* list = g_hash_table_new(g_str_hash, g_str_equal);
-  if (list == nullptr) {
-    LOG(ERROR) << "Out of memory";
+  const char* dbpath = sqlite3_db_filename(db.GetRaw(), "main");
+
+  timespec start_time = { 0, };
+  timespec end_time = { 0, };
+  if (!GetModifiedTime(dbpath, &start_time))
     return PMINFO_R_ERROR;
+
+  pkgmgrinfo_filter_x tmp_filter = { 0, };
+  tmp_filter.cache_flag = true;
+  std::map<std::string, std::shared_ptr<package_x>> pkgs;
+  int ret = internal::GetPkgInfo(db, &tmp_filter, uid_, locale, pkgs);
+  if (ret == PMINFO_R_OK) {
+    for (auto& [key, val] : pkgs)
+      AddPackage(std::move(val));
   }
 
-  auto tmp_filter = reinterpret_cast<pkgmgrinfo_filter_x*>(
-      calloc(1, sizeof(pkgmgrinfo_filter_x)));
-  if (tmp_filter == nullptr) {
-    LOG(ERROR) << "Out of memory";
-    g_hash_table_destroy(list);
+  if (!GetModifiedTime(dbpath, &end_time))
     return PMINFO_R_ERROR;
-  }
 
-  int ret = pkginfo_internal_filter_get_list(db, tmp_filter, uid_,
-                                             locale.c_str(), list);
-  if (ret == PMINFO_R_OK) {
-    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);
-      AddPackage(pkg->package, pkg);
-    }
+  if (start_time.tv_sec != end_time.tv_sec ||
+      start_time.tv_nsec != end_time.tv_nsec) {
+    LOG(ERROR) << "Database(" << dbpath << ") modification was detected";
+    return PMINFO_R_ERROR;
   }
 
-  g_hash_table_destroy(list);
-  if (ret == PMINFO_R_ERROR) {
-    free(tmp_filter);
-    return ret;
+  std::vector<std::shared_ptr<application_x>> app_list;
+  ret = internal::GetAppInfo(db, &tmp_filter, uid_, uid, locale, app_list);
+
+  if (!GetModifiedTime(dbpath, &end_time))
+    return PMINFO_R_ERROR;
+
+  if (start_time.tv_sec != end_time.tv_sec ||
+      start_time.tv_nsec != end_time.tv_nsec) {
+    LOG(ERROR) << "Database(" << dbpath << ") modification was detected";
+    return PMINFO_R_ERROR;
   }
 
-  list = g_hash_table_new(g_str_hash, g_str_equal);
-  ret = appinfo_internal_filter_get_list(db, tmp_filter, uid_, uid,
-                                         locale.c_str(), list);
-  free(tmp_filter);
   if (ret == PMINFO_R_OK) {
-    GHashTableIter iter;
-    gpointer value;
-    g_hash_table_iter_init(&iter, list);
-    while (g_hash_table_iter_next(&iter, nullptr, &value)) {
-      auto* app = reinterpret_cast<application_x*>(value);
-      app->privileges = pkg_map_[app->package].front()->privileges;
-      AddApplication(app->appid, app);
+    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 PMINFO_R_ERROR;
+      }
+
+      app->privileges = it->second->privileges;
+      AddApplication(std::move(app));
     }
   }
-  g_hash_table_destroy(list);
+
   released_ = false;
 
   return ret;
 }
 
+inline bool CheckMetadataFilter(GList* metadata_list,
+    const std::unordered_map<std::string, std::string>& metadata_map) {
+  for (auto* it = metadata_list; 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 false;
+}
+
+inline bool CheckPkgFilters(pkgmgrinfo_filter_x* filter,
+    const std::shared_ptr<package_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().
+        GetPkgFilterChecker(node->prop);
+    if (!checker->CheckFilter(node, info.get()))
+      return false;
+  }
+
+  bool pass = true;
+  if (!metadata_map.empty())
+    pass = CheckMetadataFilter(info->metadata, metadata_map);
+
+  return pass;
+}
+
 std::vector<std::shared_ptr<package_x>> DBHandleProvider::GetPackages(
-    pid_t pid, bool write, pkgmgrinfo_filter_x* filter,
+    pid_t pid, pkgmgrinfo_filter_x* filter,
     const std::string& package) {
   std::vector<std::shared_ptr<package_x>> ret;
-  for (auto& info : pkg_map_[package]) {
-    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;
-      }
+
+  /* make metadata filter map */
+  std::unordered_map<std::string, std::string> metadata_map;
+  for (auto* it = filter->list_pkg_metadata; it != nullptr;
+      it = g_slist_next(it)) {
+    auto node = reinterpret_cast<pkgmgrinfo_metadata_node_x*>(it->data);
+    if (node->key == nullptr)
+      continue;
+    LOG(ERROR) << "add metadata filter";
+    metadata_map[node->key] = (node->value ? node->value : "");
+  }
+
+  if (internal::CheckPackageStorageStatus(filter)) {
+    if (pkgmgrinfo_pkginfo_filter_add_bool(filter,
+        PMINFO_PKGINFO_PROP_PACKAGE_CHECK_STORAGE, true) != PMINFO_R_OK) {
+      LOG(ERROR) << "Fail to add check storage value to filter";
+      return {};
     }
-    if (pass)
-      ret.push_back(info);
+  }
+  if (package.empty()) {
+    for (auto& info : pkg_map_) {
+      if (CheckPkgFilters(filter, info.second, metadata_map))
+        ret.push_back(info.second);
+    }
+  } else {
+    auto map_it = pkg_map_.find(package);
+    if (map_it != pkg_map_.end() && CheckPkgFilters(filter, map_it->second,
+        metadata_map))
+      ret.push_back(map_it->second);
   }
 
   return ret;
 }
 
-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));
+void DBHandleProvider::AddPackage(std::shared_ptr<package_x> info) {
+  pkg_map_[info->package] = std::move(info);
+}
+
+void DBHandleProvider::AddApplication(std::shared_ptr<application_x> info) {
+  std::string appid = info->appid;
+  std::string pkgid = info->package;
+  app_map_[appid] = std::move(info);
+  pkg_app_map_[pkgid].emplace(std::move(appid));
+}
+
+void DBHandleProvider::ErasePackage(const std::string& pkgid) {
+  auto it = pkg_app_map_.find(pkgid);
+  if (it != pkg_app_map_.end()) {
+    for (const auto& app : it->second)
+      app_map_.erase(app);
+    pkg_app_map_.erase(it);
+  }
+
+  pkg_map_.erase(pkgid);
+}
+
+inline bool CheckAppFilters(pkgmgrinfo_filter_x* filter,
+  const std::shared_ptr<application_x>& app_info,
+  const std::shared_ptr<package_x>& pkg_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, app_info.get(), pkg_info.get()))
+      return false;
+  }
+
+  bool pass = true;
+  if (!metadata_map.empty())
+    pass = CheckMetadataFilter(app_info->metadata, metadata_map);
+  return pass;
+}
+
+std::shared_ptr<package_x> DBHandleProvider::GetPackageByApp(
+    const char* appid) {
+  auto it = pkg_map_.find(appid);
+  if (it == pkg_map_.end())
+    return nullptr;
+
+  return it->second;
 }
 
 std::vector<std::shared_ptr<application_x>> DBHandleProvider::GetApplications(
-    pid_t pid, bool write, pkgmgrinfo_filter_x* filter,
+    pid_t pid, pkgmgrinfo_filter_x* filter,
     const std::string& app) {
   /* make metadata filter map */
   std::unordered_map<std::string, std::string> metadata_map;
@@ -399,59 +393,232 @@ std::vector<std::shared_ptr<application_x>> DBHandleProvider::GetApplications(
   }
 
   std::vector<std::shared_ptr<application_x>> ret;
-  for (auto& info : app_map_[app]) {
-    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 (internal::CheckAppStorageStatus(filter)) {
+    if (pkgmgrinfo_appinfo_filter_add_bool(filter,
+        PMINFO_APPINFO_PROP_APP_CHECK_STORAGE, true) != PMINFO_R_OK) {
+      LOG(ERROR) << "Fail to add check storage value to filter";
+      return {};
+    }
+  }
+
+  if (app.empty()) {
+    for (auto& info : app_map_) {
+      if (CheckAppFilters(filter, info.second,
+          GetPackageByApp(info.second->package), metadata_map))
+        ret.push_back(info.second);
+    }
+  } else {
+    auto map_it = app_map_.find(app);
+    if (map_it != app_map_.end() &&
+        CheckAppFilters(filter, map_it->second,
+            GetPackageByApp(map_it->second->package), metadata_map))
+      ret.push_back(map_it->second);
+  }
+
+  return ret;
+}
+
+void DBHandleProvider::InsertWriterPID(pid_t pid) {
+  std::unique_lock<std::shared_mutex> u(pid_list_lock_);
+
+  writer_pid_list_.insert(pid);
+}
+
+bool DBHandleProvider::EraseWriterPID(pid_t pid) {
+  std::unique_lock<std::shared_mutex> u(pid_list_lock_);
+
+  return writer_pid_list_.erase(pid) == 1;
+}
+
+void DBHandleProvider::RegisterPendingPackageInfo(
+    const tizen_base::Database& db, package_x* info, pid_t pid, uid_t uid,
+    const std::string& locale, pkgmgr_common::PkgWriteType write_type) {
+  if (!info || !info->package)
+    return;
+
+  InsertWriterPID(pid);
+
+  if (write_type != pkgmgr_common::PkgWriteType::Delete) {
+    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);
+    std::map<std::string, std::shared_ptr<package_x>> pkgs;
+
+    node.value = const_cast<char*>(info->package);
+    internal::GetPkgInfo(db, &tmp_filter, uid_, locale, pkgs);
+    node.prop = E_PMINFO_APPINFO_PROP_APP_PACKAGE;
+    for (auto& [pkgid, pkg_handle] : pkgs) {
+      node.value = const_cast<char*>(pkgid.c_str());
+      std::vector<std::shared_ptr<application_x>> app_list;
+      internal::GetAppInfo(db, &tmp_filter, uid_, uid, locale, app_list);
+
+      for (auto& app : app_list) {
+        app->privileges = pkg_handle->privileges;
+        pending_app_[pkgid].emplace_back(std::move(app));
       }
+
+      pending_pkg_[pkgid] = std::make_pair(pid, std::move(pkg_handle));
     }
-    if (!pass)
+
+    g_slist_free(tmp_filter.list);
+  } else {
+    pending_pkg_[info->package] = std::make_pair(pid, nullptr);
+    pending_app_.erase(info->package);
+  }
+}
+
+void DBHandleProvider::UpdatePendingPackageInfo(
+    const std::vector<std::string>& pkgids) {
+  for (const auto& pkgid : pkgids) {
+    auto pkg_it = pending_pkg_.find(pkgid);
+    if (pkg_it == pending_pkg_.end())
       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() &&
-              strstr(node->value ? node->value : "",
-                  metadata->second.c_str()) != nullptr) {
-            pass = true;
-            break;
-          }
-        }
-      }
+    ErasePackage(pkgid);
+    auto app_it = pending_app_.find(pkgid);
+    if (app_it != pending_app_.end()) {
+      for (auto& app : app_it->second)
+        AddApplication(std::move(app));
+      pending_app_.erase(app_it);
     }
 
-    if (pass)
-      ret.push_back(info);
+    if (pkg_it->second.second)
+      AddPackage(std::move(pkg_it->second.second));
+
+    EraseWriterPID(pkg_it->second.first);
+    pending_pkg_.erase(pkg_it);
+  }
+}
+
+void DBHandleProvider::UpdateCrashedWriterPackageInfo(
+    const std::unordered_set<pid_t>& pids) {
+  for (auto it = pending_pkg_.begin(); it != pending_pkg_.end();) {
+    pid_t pid = it->second.first;
+    if (pids.find(pid) == pids.end()) {
+      it++;
+      continue;
+    }
+
+    const auto& pkgid = it->first;
+    auto old_app_it = pkg_app_map_.find(pkgid);
+    if (old_app_it != pkg_app_map_.end()) {
+      for (const auto& app : old_app_it->second)
+        app_map_.erase(app);
+
+      pkg_app_map_.erase(old_app_it);
+    }
+
+    auto app_it = pending_app_.find(pkgid);
+    if (app_it != pending_app_.end()) {
+      for (auto& app : app_it->second)
+        AddApplication(std::move(app));
+      pending_app_.erase(app_it);
+    }
+
+    if (it->second.second)
+      AddPackage(std::move(it->second.second));
+
+    EraseWriterPID(it->second.first);
+    it = pending_pkg_.erase(it);
   }
-  return ret;
 }
 
-void DBHandleProvider::AddApplication(std::string app, application_x* info) {
-  auto ptr =
-      std::shared_ptr<application_x>(info, pkgmgrinfo_basic_free_application);
-  app_map_[app].push_back(ptr);
-  app_map_[""].push_back(std::move(ptr));
+bool DBHandleProvider::UpdateCachePkg(const tizen_base::Database& db, uid_t uid,
+    const std::string& pkgid, const std::string& locale) {
+  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);
+  std::map<std::string, std::shared_ptr<package_x>> pkgs;
+  internal::GetPkgInfo(db, &tmp_filter, uid_, locale, pkgs);
+  for (auto& [key, val] : pkgs) {
+    AddPackage(val);
+    for (auto& appid : pkg_app_map_[key])
+      app_map_.erase(appid);
+
+    pkg_app_map_.erase(key);
+    std::vector<std::shared_ptr<application_x>> app_list;
+    node.prop = E_PMINFO_APPINFO_PROP_APP_PACKAGE;
+    node.value = const_cast<char*>(key.c_str());
+    internal::GetAppInfo(db, &tmp_filter, uid_, uid, locale, app_list);
+    for (auto& app : app_list) {
+      app->privileges = val->privileges;
+      AddApplication(std::move(app));
+    }
+  }
+
+  return true;
 }
 
-void DBHandleProvider::InsertPID(pid_t pid) {
-  std::unique_lock<std::mutex> u(pid_list_lock_);
+bool DBHandleProvider::UpdateCacheApp(const tizen_base::Database& 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);
+  internal::GetAppInfo(db, &tmp_filter, uid_, uid, locale, 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;
+    AddApplication(std::move(app));
+  }
 
-  pid_list_.insert(pid);
+  return true;
 }
 
-bool DBHandleProvider::ErasePID(pid_t pid) {
-  std::unique_lock<std::mutex> u(pid_list_lock_);
+bool DBHandleProvider::UpdateCacheAppByPkgid(const tizen_base::Database& 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;
+  internal::GetAppInfo(db, &tmp_filter, uid_, uid, locale, 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;
+    AddApplication(std::move(app));
+  }
 
-  return pid_list_.erase(pid) == 1;
+  g_slist_free(tmp_filter.list);
+  return true;
 }
 
 }  // namespace database