Add some logs for debugging
[platform/core/appfw/pkgmgr-info.git] / src / server / database / db_handle_provider.cc
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "db_handle_provider.hh"
18
19 #include <fcntl.h>
20 #include <glib.h>
21 #include <sys/stat.h>
22 #include <sys/types.h>
23
24 #include <tzplatform_config.h>
25
26 #include <algorithm>
27 #include <string>
28 #include <vector>
29
30 #include "cache_flag.hh"
31 #include "utils/logging.hh"
32
33 #include "pkgmgr-info.h"
34 #include "pkgmgrinfo_debug.h"
35 #include "pkgmgrinfo_internal.h"
36 #include "pkgmgrinfo_private.h"
37
38 #ifdef LOG_TAG
39 #undef LOG_TAG
40 #endif
41 #define LOG_TAG "PKGMGR_INFO"
42
43 namespace {
44
45 uid_t globaluser_uid = -1;
46
47 uid_t GetGlobalUID() {
48   if (globaluser_uid == (uid_t)-1)
49     globaluser_uid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
50
51   return globaluser_uid;
52 }
53
54 uid_t ConvertUID(uid_t uid) {
55   if (uid < REGULAR_USER)
56     return GetGlobalUID();
57   else
58     return uid;
59 }
60
61 bool GetModifiedTime(const char* dbpath, timespec* t) {
62   if (dbpath == nullptr || t == nullptr) {
63     LOG(ERROR) << "Invalid argument";
64     return false;
65   }
66
67   struct stat attr;
68   if (stat(dbpath, &attr)) {
69     LOG(ERROR) << "Fail to get status from file "
70         << dbpath << " errno : " << errno;
71     return false;
72   }
73
74   *t = attr.st_mtim;
75
76   return true;
77 }
78
79 static const std::string global_parser_memdb_path =
80     "file:parserdb?mode=memory&cache=shared";
81
82 static const std::string cert_memdb_path =
83     "file:certdb?mode=memory&cache=shared";
84
85 }  // namespace
86
87 namespace pkgmgr_server {
88 namespace database {
89
90 std::unordered_map<uid_t, std::unique_ptr<DBHandleProvider>>
91     DBHandleProvider::provider_map_;
92 bool DBHandleProvider::is_global_memdb_set_ = false;
93 std::unique_ptr<sqlite3, decltype(sqlite3_close_v2)*>
94     DBHandleProvider::global_parser_memdb_handle_(nullptr,
95                                                   sqlite3_close_v2);
96 std::unique_ptr<sqlite3, decltype(sqlite3_close_v2)*>
97     DBHandleProvider::cert_memdb_handle_(nullptr, sqlite3_close_v2);
98 std::string DBHandleProvider::global_parser_filedb_path_;
99 std::string DBHandleProvider::cert_filedb_path_;
100 std::unordered_set<pid_t> DBHandleProvider::writer_pid_list_;
101 std::recursive_mutex DBHandleProvider::lock_;
102 std::shared_mutex DBHandleProvider::pid_list_lock_;
103
104 DBHandleProvider::DBHandleProvider(uid_t uid)
105     : uid_(uid),
106       is_user_memdb_set_(false),
107       parser_memdb_handle_(nullptr, sqlite3_close_v2) {
108   char* tmp_path;
109
110   if (global_parser_filedb_path_.empty()) {
111     tmp_path = getUserPkgParserDBPathUID(GetGlobalUID());
112     global_parser_filedb_path_ = tmp_path;
113     free(tmp_path);
114   }
115
116   if (cert_filedb_path_.empty()) {
117     tmp_path = getUserPkgCertDBPath();
118     cert_filedb_path_ = tmp_path;
119     free(tmp_path);
120   }
121
122   tmp_path = getUserPkgParserDBPathUID(uid_);
123   user_parser_filedb_path_ = tmp_path;
124   free(tmp_path);
125
126   user_parser_memdb_path_ = "file:parserdb" +
127                             std::to_string(static_cast<int>(uid_)) +
128                             "?mode=memory&cache=shared";
129 }
130
131 DBHandleProvider& DBHandleProvider::GetInst(uid_t uid) {
132   static std::shared_mutex singleton_lock_;
133   std::shared_lock<std::shared_mutex> s(singleton_lock_);
134
135   uid = ConvertUID(uid);
136   auto it = provider_map_.find(uid);
137   if (it != provider_map_.end())
138     return *(it->second);
139
140   s.unlock();
141   std::unique_lock<std::shared_mutex> u(singleton_lock_);
142   auto& prov = provider_map_[uid];
143   if (prov == nullptr)
144     prov.reset(new DBHandleProvider(uid));
145
146   return *prov;
147 }
148
149 bool DBHandleProvider::IsCrashedWriteRequest() {
150   std::unique_lock<std::shared_mutex> u(pid_list_lock_);
151
152   if (writer_pid_list_.empty())
153     return false;
154
155   bool ret = true;
156   LOG(DEBUG) << "Check process count : " << writer_pid_list_.size();
157   std::vector<pid_t> remove_pids;
158   for (pid_t pid : writer_pid_list_) {
159     std::string status_path = "/proc/" + std::to_string(pid) + "/status";
160
161     int fd = open(status_path.c_str(), O_RDONLY);
162     if (fd < 0) {
163       LOG(ERROR) << "Process is crashed : " << pid;
164       remove_pids.push_back(pid);
165     } else {
166       ret = false;
167       close(fd);
168     }
169   }
170
171   for (pid_t pid : remove_pids)
172     writer_pid_list_.erase(pid);
173
174   return ret;
175 }
176
177 std::vector<std::pair<std::string, uid_t>> DBHandleProvider::GetParserDBPath(
178     pid_t pid, bool write) {
179   std::unique_lock<std::recursive_mutex> u(lock_);
180   std::vector<std::pair<std::string, uid_t>> db_path_list;
181
182   if (is_user_memdb_set_ != is_global_memdb_set_)
183     is_global_memdb_set_ ? SetMemoryMode(pid) : UnsetMemoryMode(pid);
184
185   if (IsMemoryDBActive(pid, write)) {
186     if (uid_ > REGULAR_USER)
187       db_path_list.emplace_back(std::make_pair(user_parser_memdb_path_, uid_));
188
189     db_path_list.emplace_back(
190         std::make_pair(global_parser_memdb_path, GetGlobalUID()));
191   } else {
192     if (uid_ > REGULAR_USER)
193       db_path_list.emplace_back(std::make_pair(user_parser_filedb_path_, uid_));
194
195     db_path_list.emplace_back(
196         std::make_pair(global_parser_filedb_path_, GetGlobalUID()));
197   }
198
199   if (db_path_list.size() == 1) {
200     LOG(DEBUG) << "global db path : " << db_path_list[0].first;
201   } else {
202     LOG(DEBUG) << "local db path : " << db_path_list[0].first;
203     LOG(DEBUG) << "global db path : " << db_path_list[1].first;
204   }
205
206   return db_path_list;
207 }
208
209 std::string DBHandleProvider::GetCertDBPath(pid_t pid, bool write) {
210   std::unique_lock<std::recursive_mutex> u(lock_);
211   if (is_user_memdb_set_ != is_global_memdb_set_)
212     is_global_memdb_set_ ? SetMemoryMode(pid) : UnsetMemoryMode(pid);
213
214   if (IsMemoryDBActive(pid, write))
215     return cert_memdb_path;
216   else
217     return cert_filedb_path_;
218 }
219
220 sqlite3* DBHandleProvider::CreateMemoryDBHandle(const std::string& filedb_path,
221                                              const std::string& memorydb_path) {
222   sqlite3* memorydb = nullptr;
223   sqlite3* filedb = nullptr;
224   LOG(INFO) << "Create memory db handle : " << memorydb_path;
225   int ret = sqlite3_open_v2(memorydb_path.c_str(), &memorydb,
226                             SQLITE_OPEN_READONLY | SQLITE_OPEN_URI, nullptr);
227   if (ret != SQLITE_OK) {
228     LOG(ERROR) << "Failed to open memory DB " << ret << ": " << memorydb_path;
229     return nullptr;
230   }
231
232   ret = sqlite3_open_v2(filedb_path.c_str(), &filedb, SQLITE_OPEN_READONLY,
233                         nullptr);
234   if (ret != SQLITE_OK) {
235     LOG(ERROR) << "Failed to open file DB " << ret << ": " << filedb_path;
236     sqlite3_close_v2(memorydb);
237     return nullptr;
238   }
239
240   sqlite3_backup* backup =
241       sqlite3_backup_init(memorydb, "main", filedb, "main");
242   if (backup == nullptr) {
243     LOG(ERROR) << "Failed to backup for memory DB";
244     sqlite3_close_v2(memorydb);
245     sqlite3_close_v2(filedb);
246     return nullptr;
247   }
248
249   sqlite3_backup_step(backup, -1);
250   sqlite3_backup_finish(backup);
251   sqlite3_close_v2(filedb);
252   LOG(INFO) << "Create memory db handle done";
253   return memorydb;
254 }
255
256 void DBHandleProvider::SetMemoryMode(pid_t pid) {
257   std::unique_lock<std::recursive_mutex> u(lock_);
258   if (is_global_memdb_set_ && is_user_memdb_set_)
259     return;
260
261   sqlite3* parser_db =
262       CreateMemoryDBHandle(user_parser_filedb_path_, user_parser_memdb_path_);
263   if (parser_db != nullptr)
264     parser_memdb_handle_.reset(parser_db);
265
266   if (is_user_memdb_set_ == is_global_memdb_set_) {
267     sqlite3* global_parser_file_db = CreateMemoryDBHandle(
268         global_parser_filedb_path_, global_parser_memdb_path);
269     if (global_parser_file_db)
270       global_parser_memdb_handle_.reset(global_parser_file_db);
271
272     sqlite3* cert_db =
273         CreateMemoryDBHandle(cert_filedb_path_, cert_memdb_path);
274     if (cert_db != nullptr)
275       cert_memdb_handle_.reset(cert_db);
276
277     InsertPID(pid);
278   }
279
280   is_user_memdb_set_ = true;
281   is_global_memdb_set_ = true;
282   LOG(INFO) << "Set Memory mode : Memory";
283 }
284
285 void DBHandleProvider::UnsetMemoryMode(pid_t pid) {
286   std::unique_lock<std::recursive_mutex> u(lock_);
287   if (!is_global_memdb_set_ && !is_user_memdb_set_)
288     return;
289
290   parser_memdb_handle_.reset(nullptr);
291   cert_memdb_handle_.reset(nullptr);
292   global_parser_memdb_handle_.reset(nullptr);
293
294   if (!ErasePID(pid))
295     LOG(ERROR) << "Given pid is not exists in pid list : " << pid;
296
297   is_user_memdb_set_ = false;
298   is_global_memdb_set_ = false;
299
300   LOG(DEBUG) << "Set Memory mode : File";
301 }
302
303 bool DBHandleProvider::IsMemoryDBActive(pid_t pid, bool write) {
304   std::unique_lock<std::shared_mutex> u(pid_list_lock_);
305   if (!is_user_memdb_set_)
306     return false;
307
308   if (write)
309     return false;
310
311   if (writer_pid_list_.find(pid) != writer_pid_list_.end())
312     return false;
313
314   return true;
315 }
316
317 void DBHandleProvider::TrimCache() {
318   std::unique_lock<std::recursive_mutex> u(lock_);
319   if (!released_)
320     ReleaseCache();
321 }
322
323 void DBHandleProvider::ReleaseCache() {
324   auto lock = CacheFlag::GetWriterLock();
325   CacheFlag::SetStatus(CacheFlag::Status::PREPARING);
326
327   app_map_.clear();
328   pkg_map_.clear();
329   pending_pkg_.clear();
330   pkg_app_map_.clear();
331   CacheFlag::SetStatus(CacheFlag::Status::UNPREPARED);
332
333   released_ = true;
334 }
335
336 bool DBHandleProvider::IsWriter(pid_t pid) {
337   std::unique_lock<std::shared_mutex> s(pid_list_lock_);
338   return writer_pid_list_.find(pid) != writer_pid_list_.end();
339 }
340
341 int DBHandleProvider::UpdateCache(const tizen_base::Database& db, pid_t pid,
342     uid_t uid, bool write, const std::string& locale) {
343   pkg_map_.clear();
344   app_map_.clear();
345   pending_pkg_.clear();
346   pkg_app_map_.clear();
347
348   const char* dbpath = sqlite3_db_filename(db.GetRaw(), "main");
349   bool is_inmemory_db = false;
350   if (dbpath == nullptr || strlen(dbpath) == 0) {
351     LOG(INFO) << "database is inmemory db";
352     is_inmemory_db = true;
353   }
354
355   timespec start_time = { 0, };
356   timespec end_time = { 0, };
357   if (!is_inmemory_db && !GetModifiedTime(dbpath, &start_time))
358     return PMINFO_R_ERROR;
359
360   pkgmgrinfo_filter_x tmp_filter = { 0, };
361   tmp_filter.cache_flag = true;
362   std::map<std::string, std::shared_ptr<package_x>> pkgs;
363   int ret = internal::GetPkgInfo(db, &tmp_filter, uid_, locale, pkgs);
364   if (ret == PMINFO_R_OK) {
365     for (auto& [key, val] : pkgs)
366       AddPackage(std::move(key), std::move(val));
367   }
368
369   if (!is_inmemory_db && !GetModifiedTime(dbpath, &end_time))
370     return PMINFO_R_ERROR;
371
372   if (start_time.tv_sec != end_time.tv_sec ||
373       start_time.tv_nsec != end_time.tv_nsec) {
374     LOG(ERROR) << "Database(" << dbpath << ") modification was detected";
375     return PMINFO_R_ERROR;
376   }
377
378   std::vector<std::shared_ptr<application_x>> app_list;
379   ret = internal::GetAppInfo(db, &tmp_filter, uid_, uid, locale, app_list);
380
381   if (!is_inmemory_db && !GetModifiedTime(dbpath, &end_time))
382     return PMINFO_R_ERROR;
383
384   if (start_time.tv_sec != end_time.tv_sec ||
385       start_time.tv_nsec != end_time.tv_nsec) {
386     LOG(ERROR) << "Database(" << dbpath << ") modification was detected";
387     return PMINFO_R_ERROR;
388   }
389
390   if (ret == PMINFO_R_OK) {
391     for (auto& app : app_list) {
392       auto it = pkg_map_.find(app->package);
393       if (it == pkg_map_.end()) {
394         LOG(ERROR) << "Can not find package from pkg_map";
395         return PMINFO_R_ERROR;
396       }
397
398       app->privileges = it->second->privileges;
399       std::string appid = app->appid;
400       AddApplication(std::move(appid), std::move(app));
401     }
402   }
403
404   released_ = false;
405
406   return ret;
407 }
408
409 inline bool CheckMetadataFilter(GList* metadata_list,
410     const std::unordered_map<std::string, std::string>& metadata_map) {
411   for (auto* it = metadata_list; it != nullptr; it = g_list_next(it)) {
412     auto* node = reinterpret_cast<metadata_x*>(it->data);
413     if (node->key != nullptr) {
414       auto metadata = metadata_map.find(node->key);
415       if (metadata == metadata_map.end())
416         continue;
417
418       if (metadata->second.empty() ||
419           strcmp(node->value ? node->value : "", metadata->second.c_str()) == 0)
420         return true;
421     }
422   }
423   return false;
424 }
425
426 inline bool CheckPkgFilters(pkgmgrinfo_filter_x* filter,
427     const std::shared_ptr<package_x>& info,
428     const std::unordered_map<std::string, std::string>& metadata_map) {
429   for (auto* it = filter->list; it != nullptr; it = g_slist_next(it)) {
430     auto node = reinterpret_cast<pkgmgrinfo_node_x*>(it->data);
431     auto* checker = FilterCheckerProvider::GetInst().
432         GetPkgFilterChecker(node->prop);
433     if (!checker->CheckFilter(node, info.get()))
434       return false;
435   }
436
437   bool pass = true;
438   if (!metadata_map.empty())
439     pass = CheckMetadataFilter(info->metadata, metadata_map);
440
441   return pass;
442 }
443
444 std::vector<std::shared_ptr<package_x>> DBHandleProvider::GetPackages(
445     pid_t pid, pkgmgrinfo_filter_x* filter,
446     const std::string& package) {
447   std::vector<std::shared_ptr<package_x>> ret;
448
449   /* make metadata filter map */
450   std::unordered_map<std::string, std::string> metadata_map;
451   for (auto* it = filter->list_pkg_metadata; it != nullptr;
452       it = g_slist_next(it)) {
453     auto node = reinterpret_cast<pkgmgrinfo_metadata_node_x*>(it->data);
454     if (node->key == nullptr)
455       continue;
456     LOG(ERROR) << "add metadata filter";
457     metadata_map[node->key] = (node->value ? node->value : "");
458   }
459
460   if (internal::CheckPackageStorageStatus(filter)) {
461     if (pkgmgrinfo_pkginfo_filter_add_bool(filter,
462         PMINFO_PKGINFO_PROP_PACKAGE_CHECK_STORAGE, true) != PMINFO_R_OK) {
463       LOG(ERROR) << "Fail to add check storage value to filter";
464       return {};
465     }
466   }
467   if (package.empty()) {
468     for (auto& info : pkg_map_) {
469       if (CheckPkgFilters(filter, info.second, metadata_map))
470         ret.push_back(info.second);
471     }
472   } else {
473     auto map_it = pkg_map_.find(package);
474     if (map_it != pkg_map_.end() && CheckPkgFilters(filter, map_it->second,
475         metadata_map))
476       ret.push_back(map_it->second);
477   }
478
479   return ret;
480 }
481
482 void DBHandleProvider::AddPackage(std::string package,
483     std::shared_ptr<package_x> info) {
484   pkg_map_[package] = std::move(info);
485 }
486
487 inline bool CheckAppFilters(pkgmgrinfo_filter_x* filter,
488   const std::shared_ptr<application_x>& app_info,
489   const std::shared_ptr<package_x>& pkg_info,
490   const std::unordered_map<std::string, std::string>& metadata_map) {
491   for (auto* it = filter->list; it != nullptr; it = g_slist_next(it)) {
492     auto node = reinterpret_cast<pkgmgrinfo_node_x*>(it->data);
493     auto* checker = FilterCheckerProvider::GetInst().
494         GetAppFilterChecker(node->prop);
495     if (!checker->CheckFilter(node, app_info.get(), pkg_info.get()))
496       return false;
497   }
498
499   bool pass = true;
500   if (!metadata_map.empty())
501     pass = CheckMetadataFilter(app_info->metadata, metadata_map);
502   return pass;
503 }
504
505 std::shared_ptr<package_x> DBHandleProvider::GetPackageByApp(
506     const char* appid) {
507   auto it = pkg_map_.find(appid);
508   if (it == pkg_map_.end())
509     return nullptr;
510
511   return it->second;
512 }
513
514 std::vector<std::shared_ptr<application_x>> DBHandleProvider::GetApplications(
515     pid_t pid, pkgmgrinfo_filter_x* filter,
516     const std::string& app) {
517   /* make metadata filter map */
518   std::unordered_map<std::string, std::string> metadata_map;
519   for (auto* it = filter->list_metadata; it != nullptr; it = g_slist_next(it)) {
520     auto node = reinterpret_cast<pkgmgrinfo_metadata_node_x*>(it->data);
521     if (node->key == nullptr)
522       continue;
523
524     metadata_map[node->key] = (node->value ? node->value : "");
525   }
526
527   std::vector<std::shared_ptr<application_x>> ret;
528   if (internal::CheckAppStorageStatus(filter)) {
529     if (pkgmgrinfo_appinfo_filter_add_bool(filter,
530         PMINFO_APPINFO_PROP_APP_CHECK_STORAGE, true) != PMINFO_R_OK) {
531       LOG(ERROR) << "Fail to add check storage value to filter";
532       return {};
533     }
534   }
535
536   if (app.empty()) {
537     for (auto& info : app_map_) {
538       if (CheckAppFilters(filter, info.second,
539           GetPackageByApp(info.second->package), metadata_map))
540         ret.push_back(info.second);
541     }
542   } else {
543     auto map_it = app_map_.find(app);
544     if (map_it != app_map_.end() &&
545         CheckAppFilters(filter, map_it->second,
546             GetPackageByApp(map_it->second->package), metadata_map))
547       ret.push_back(map_it->second);
548   }
549
550   return ret;
551 }
552
553 void DBHandleProvider::AddApplication(std::string app,
554     std::shared_ptr<application_x> info) {
555   pkg_app_map_[info->package].emplace(app);
556   app_map_[app] = std::move(info);
557 }
558
559 void DBHandleProvider::InsertPID(pid_t pid) {
560   std::unique_lock<std::shared_mutex> u(pid_list_lock_);
561
562   writer_pid_list_.insert(pid);
563 }
564
565 bool DBHandleProvider::ErasePID(pid_t pid) {
566   std::unique_lock<std::shared_mutex> u(pid_list_lock_);
567
568   return writer_pid_list_.erase(pid) == 1;
569 }
570
571 void DBHandleProvider::RegisterPendingPackageInfo(package_x* info) {
572   if (!info || !info->package)
573     return;
574
575   pending_pkg_.emplace(info->package);
576 }
577
578 void DBHandleProvider::UpdatePendingPackageInfo(const tizen_base::Database& db,
579     pid_t pid, uid_t uid, const std::string& locale) {
580   pkgmgrinfo_filter_x tmp_filter = { 0, };
581   pkgmgrinfo_node_x node = {
582     .prop = E_PMINFO_PKGINFO_PROP_PACKAGE_ID
583   };
584   tmp_filter.cache_flag = true;
585   tmp_filter.list = g_slist_append(tmp_filter.list, (gpointer)&node);
586   std::map<std::string, std::shared_ptr<package_x>> pkgs;
587   for (const auto& pkg : pending_pkg_) {
588     pkg_map_.erase(pkg);
589     for (auto& appid : pkg_app_map_[pkg]) {
590       app_map_.erase(appid);
591     }
592
593     pkg_app_map_.erase(pkg);
594     node.value = const_cast<char*>(pkg.c_str());
595     internal::GetPkgInfo(db, &tmp_filter, uid_, locale, pkgs);
596   }
597
598   for (auto& [key, val] : pkgs)
599     AddPackage(key, val);
600
601   node.prop = E_PMINFO_APPINFO_PROP_APP_PACKAGE;
602   for (auto& [key, val] : pkgs) {
603     node.value = val->package;
604     std::vector<std::shared_ptr<application_x>> app_list;
605     internal::GetAppInfo(db, &tmp_filter, uid_, uid, locale, app_list);
606
607     for (auto& app : app_list) {
608       app->privileges = val->privileges;
609       std::string appid = app->appid;
610       AddApplication(std::move(appid), std::move(app));
611     }
612   }
613
614   g_slist_free(tmp_filter.list);
615   pending_pkg_.clear();
616 }
617
618 bool DBHandleProvider::UpdateCachePkg(const tizen_base::Database& db, uid_t uid,
619     const std::string& pkgid, const std::string& locale) {
620   pkgmgrinfo_filter_x tmp_filter = { 0, };
621   pkgmgrinfo_node_x node = {
622     .prop = E_PMINFO_PKGINFO_PROP_PACKAGE_ID,
623     .value = const_cast<char*>(pkgid.c_str())
624   };
625   tmp_filter.cache_flag = true;
626   tmp_filter.list = g_slist_append(tmp_filter.list, (gpointer)&node);
627   std::map<std::string, std::shared_ptr<package_x>> pkgs;
628   internal::GetPkgInfo(db, &tmp_filter, uid_, locale, pkgs);
629   for (auto& [key, val] : pkgs) {
630     AddPackage(key, val);
631     for (auto& appid : pkg_app_map_[key]) {
632       app_map_.erase(appid);
633     }
634
635     pkg_app_map_.erase(key);
636     std::vector<std::shared_ptr<application_x>> app_list;
637     node.prop = E_PMINFO_APPINFO_PROP_APP_PACKAGE;
638     node.value = const_cast<char*>(key.c_str());
639     internal::GetAppInfo(db, &tmp_filter, uid_, uid, locale, app_list);
640     for (auto& app : app_list) {
641       app->privileges = val->privileges;
642       std::string appid = app->appid;
643       AddApplication(std::move(appid), std::move(app));
644     }
645   }
646
647   return true;
648 }
649
650 bool DBHandleProvider::UpdateCacheApp(const tizen_base::Database& db, uid_t uid,
651     const std::string& appid, const std::string& locale) {
652   pkgmgrinfo_filter_x tmp_filter = { 0, };
653   pkgmgrinfo_node_x node = {
654     .prop = E_PMINFO_APPINFO_PROP_APP_ID,
655     .value = const_cast<char*>(appid.c_str())
656   };
657   tmp_filter.cache_flag = true;
658   tmp_filter.list = g_slist_append(tmp_filter.list, (gpointer)&node);
659
660   std::vector<std::shared_ptr<application_x>> app_list;
661   app_map_.erase(appid);
662   internal::GetAppInfo(db, &tmp_filter, uid_, uid, locale, app_list);
663   g_slist_free(tmp_filter.list);
664
665   for (auto& app : app_list) {
666     auto it = pkg_map_.find(app->package);
667     if (it == pkg_map_.end()) {
668       LOG(ERROR) << "Can not find package from pkg_map";
669       return false;
670     }
671
672     pkg_app_map_[app->package].erase(app->appid);
673     app->privileges = it->second->privileges;
674     std::string appid = app->appid;
675     AddApplication(std::move(appid), std::move(app));
676   }
677
678   return true;
679 }
680
681 bool DBHandleProvider::UpdateCacheAppByPkgid(const tizen_base::Database& db,
682     uid_t uid, const std::string& pkgid, const std::string& locale) {
683   auto it = pkg_map_.find(pkgid);
684   if (it == pkg_map_.end()) {
685     LOG(ERROR) << "Can not find package from pkg_map";
686     return false;
687   }
688
689   auto& pkg = it->second;
690   pkgmgrinfo_filter_x tmp_filter = { 0, };
691   pkgmgrinfo_node_x node = {
692     .prop = E_PMINFO_APPINFO_PROP_APP_PACKAGE,
693     .value = pkg->package
694   };
695
696   tmp_filter.cache_flag = true;
697   tmp_filter.list = g_slist_append(tmp_filter.list, (gpointer)&node);
698
699   std::vector<std::shared_ptr<application_x>> app_list;
700   internal::GetAppInfo(db, &tmp_filter, uid_, uid, locale, app_list);
701
702   for (auto& appid : pkg_app_map_[pkgid]) {
703     app_map_.erase(appid);
704   }
705   pkg_app_map_.erase(pkgid);
706
707   for (auto& app : app_list) {
708     app->privileges = pkg->privileges;
709     std::string appid = app->appid;
710     AddApplication(std::move(appid), std::move(app));
711   }
712
713   g_slist_free(tmp_filter.list);
714   return true;
715 }
716
717 }  // namespace database
718 }  // namespace pkgmgr_server