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