- Separace Cache logic from DBHandleProvider.
- Change function name for readability.
- Add UID setter/getter function at AbstractRequestHandler to provide uid at CacheRequestHandler.
- Apply early-return policy to reduce indentation.
Change-Id: I1f2bc50247178a70c2268c81d2f2fc5bd2e75b2c
Signed-off-by: Junghyun Yeon <jungh.yeon@samsung.com>
LOG(DEBUG) << "No packages meets given condition for user " << uid;
return PMINFO_R_ENOENT;
}
- for (auto& pkginfo : result_list)
+ for (auto& pkginfo : result_list) {
g_hash_table_insert(packages, reinterpret_cast<gpointer>(pkginfo->package),
reinterpret_cast<gpointer>(pkginfo.get()));
+ }
return PMINFO_R_OK;
}
std::static_pointer_cast<pcp::AppInfoParcelable>(ptr));
std::vector<std::shared_ptr<application_x>> result_list = return_parcel->ExtractAppInfo();
- for (auto& app : result_list)
+ for (auto& app : result_list) {
g_hash_table_insert(packages, reinterpret_cast<gpointer>(app->appid),
reinterpret_cast<gpointer>(app.get()));
+ }
return PMINFO_R_OK;
}
+++ /dev/null
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef CACHE_FLAG_HH_
-#define CACHE_FLAG_HH_
-
-#include <mutex>
-#include <shared_mutex>
-
-namespace pkgmgr_server {
-
-#ifndef EXPORT_API
-#define EXPORT_API __attribute__((visibility("default")))
-#endif
-
-class EXPORT_API CacheFlag {
- public:
- enum class EXPORT_API Status {
- UNPREPARED,
- PREPARING,
- PREPARED
- };
-
- static bool SetPreparing() {
- bool ret = false;
- std::unique_lock<std::mutex> u(status_lock_);
- if (status_ == Status::UNPREPARED) {
- status_ = Status::PREPARING;
- ret = true;
- }
- return ret;
- }
-
- static void SetStatus(Status status) {
- std::unique_lock<std::mutex> u(status_lock_);
- status_ = status;
- }
-
- static Status GetStatus() {
- std::unique_lock<std::mutex> u(status_lock_);
- return status_;
- }
-
- static std::unique_lock<std::shared_timed_mutex> GetWriterLock() {
- return std::unique_lock<std::shared_timed_mutex>(lock_);
- }
-
- static void WriterUnLock() {
- lock_.unlock();
- }
-
- static std::shared_lock<std::shared_timed_mutex> GetReaderLock() {
- return std::shared_lock<std::shared_timed_mutex>(lock_, std::defer_lock);
- }
-
- static void ReaderUnLock() {
- lock_.unlock_shared();
- }
-
- private:
- static inline Status status_;
- static inline std::mutex status_lock_;
- static inline std::shared_timed_mutex lock_;
-};
-
-} // namespace pkgmgr_server
-
-#endif // CACHE_FLAG_HH_
#include <shared_mutex>
#include <vector>
-#include "cache_flag.hh"
+#include "cache_provider.hh"
#include "db_handle_provider.hh"
#include "utils/logging.hh"
return ret;
}
-int AppInfoDBHandler::GetHandleFromCache(
- std::vector<std::pair<sqlite3*, uid_t>>& conn_list) {
- bool is_write_op =
- GetOpType() == pkgmgr_common::DBOperationType::OPERATION_TYPE_WRITE;
- int ret = PMINFO_R_OK;
- std::string application;
-
- for (auto* it = filter_->list; it != nullptr; it = g_slist_next(it)) {
- auto node = reinterpret_cast<pkgmgrinfo_node_x*>(it->data);
- if (node->prop == E_PMINFO_APPINFO_PROP_APP_ID) {
- application = node->value;
- break;
- }
- }
-
- std::vector<std::shared_ptr<application_x>> app_list;
- for (auto& conn : conn_list) {
- app_list = DBHandleProvider::GetInst(conn.second)
- .GetApplications(
- GetPID(), is_write_op, filter_, application);
-
- handle_list_.reserve(app_list.size() + handle_list_.size());
- std::move(std::begin(app_list), std::end(app_list),
- std::back_inserter(handle_list_));
- }
-
- if (handle_list_.empty())
- ret = PMINFO_R_ENOENT;
-
- return ret;
-}
-
int AppInfoDBHandler::Execute() {
std::shared_lock<std::shared_timed_mutex> s(lock_);
SetOpType(pkgmgr_common::DBOperationType::OPERATION_TYPE_READ);
if (DBHandleProvider::GetInst(conn.second).IsWriter(GetPID()))
is_writer = true;
}
+
if (is_writer)
return GetHandleFromDB(conn_list);
- if (CacheFlag::GetStatus() == CacheFlag::Status::PREPARED) {
- auto cache_lock = CacheFlag::GetReaderLock();
- if (cache_lock.try_lock() &&
- CacheFlag::GetStatus() == CacheFlag::Status::PREPARED)
- return GetHandleFromCache(conn_list);
- }
+ CacheProvider provider(GetUID());
+ if (provider.IsPrepared() && provider.GetReadLock()) {
+ bool is_write_op =
+ GetOpType() == pkgmgr_common::DBOperationType::OPERATION_TYPE_WRITE;
+ int ret = PMINFO_R_OK;
+ std::string application;
+
+ for (auto* it = filter_->list; it != nullptr; it = g_slist_next(it)) {
+ auto node = reinterpret_cast<pkgmgrinfo_node_x*>(it->data);
+ if (node->prop == E_PMINFO_APPINFO_PROP_APP_ID) {
+ application = node->value;
+ break;
+ }
+ }
+
+ std::vector<std::shared_ptr<application_x>> app_list;
+ for (auto& conn : conn_list) {
+ app_list = CacheProvider(conn.second)
+ .GetApplications(
+ GetPID(), is_write_op, filter_, application);
+ handle_list_.reserve(app_list.size() + handle_list_.size());
+ std::move(std::begin(app_list), std::end(app_list),
+ std::back_inserter(handle_list_));
+ }
+ if (handle_list_.empty())
+ ret = PMINFO_R_ENOENT;
+
+ return ret;
+ }
return GetHandleFromDB(conn_list);
}
protected:
int GetHandleFromDB(std::vector<std::pair<sqlite3*, uid_t>>& conn_list);
- int GetHandleFromCache(std::vector<std::pair<sqlite3*, uid_t>>& conn_list);
pkgmgrinfo_filter_x* filter_;
std::vector<std::shared_ptr<application_x>> handle_list_;
uid_t uid_;
--- /dev/null
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "cache.hh"
+
+#include <memory>
+#include <mutex>
+#include <shared_mutex>
+#include <unordered_map>
+#include <vector>
+
+#include <glib.h>
+#include <sys/types.h>
+#include <sqlite3.h>
+#include <tzplatform_config.h>
+
+#include "filter_checker_provider.hh"
+#include "utils/logging.hh"
+
+#include "pkgmgrinfo_private.h"
+#include "pkgmgrinfo_internal.h"
+#include "pkgmgrinfo_internal.hh"
+
+namespace pkgmgr_server {
+namespace database {
+
+std::unordered_map<uid_t, std::unique_ptr<Cache>> Cache::cache_map_;
+
+Cache::Cache(uid_t uid) : uid_(uid), status_(Status::UNPREPARED) {}
+
+Cache& Cache::GetInst(uid_t uid) {
+ static std::mutex singleton_lock_;
+ std::unique_lock<std::mutex> u(singleton_lock_);
+
+ auto& prov = cache_map_[uid];
+ if (prov == nullptr)
+ prov.reset(new Cache(uid));
+
+ return *prov;
+}
+
+void Cache::ReleaseAll() {
+ static std::mutex singleton_lock_;
+ std::unique_lock<std::mutex> u(singleton_lock_);
+
+ for (auto& i : cache_map_)
+ i.second->ReleaseCache();
+}
+
+bool Cache::IsCachePreparationNecessary() {
+ bool result = false;
+ std::unique_lock<std::mutex> u(status_lock_);
+ if (status_ == Status::UNPREPARED) {
+ status_ = Status::PREPARING;
+ result = true;
+ }
+
+ return result;
+}
+
+void Cache::SetPrepared() {
+ std::unique_lock<std::mutex> u(status_lock_);
+ status_ = Status::PREPARED;
+}
+
+void Cache::SetUnprepared() {
+ std::unique_lock<std::mutex> u(status_lock_);
+ status_ = Status::UNPREPARED;
+}
+
+void Cache::SetPreparing() {
+ std::unique_lock<std::mutex> u(status_lock_);
+ status_ = Status::PREPARING;
+}
+
+bool Cache::IsPrepared() {
+ std::unique_lock<std::mutex> u(status_lock_);
+ return (status_ == Status::PREPARED);
+}
+
+void Cache::ReleaseCache() {
+ auto lock = GetWriterLock();
+ SetStatus(Status::PREPARING);
+
+ pkg_map_.clear();
+ app_map_.clear();
+
+ SetStatus(Status::UNPREPARED);
+}
+
+void Cache::SetStatus(Status status) {
+ std::unique_lock<std::mutex> u(status_lock_);
+ status_ = status;
+}
+
+std::unique_lock<std::shared_timed_mutex> Cache::GetWriterLock() {
+ return std::unique_lock<std::shared_timed_mutex>(lock_);
+}
+
+void Cache::WriterUnLock() {
+ lock_.unlock();
+}
+
+std::shared_lock<std::shared_timed_mutex> Cache::GetReaderLock() {
+ return std::shared_lock<std::shared_timed_mutex>(lock_, std::defer_lock);
+}
+
+void Cache::ReaderUnLock() {
+ lock_.unlock();
+}
+
+void Cache::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 Cache::AddApplication(
+ std::string app, std::shared_ptr<application_x> info) {
+ app_map_[app].push_back(info);
+ app_map_[""].push_back(std::move(info));
+}
+
+int Cache::UpdateCache(sqlite3* db, pid_t pid, uid_t uid, bool write,
+ const std::string& locale) {
+ // CacheProvider should lock first and try lock before executing this func
+ pkg_map_.clear();
+ app_map_.clear();
+
+ GHashTable* list = g_hash_table_new(g_str_hash, g_str_equal);
+ if (list == nullptr) {
+ LOG(ERROR) << "Out of memory";
+ return PMINFO_R_ERROR;
+ }
+
+ 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);
+ return PMINFO_R_ERROR;
+ }
+
+ int ret = pkginfo_internal_filter_get_list(db, tmp_filter, uid_,
+ locale.c_str(), list);
+ if (ret != PMINFO_R_OK) {
+ g_hash_table_destroy(list);
+ free(tmp_filter);
+ return ret;
+ }
+
+ 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);
+ }
+ g_hash_table_destroy(list);
+
+ std::vector<std::shared_ptr<application_x>> app_list;
+ ret = pkgmgr_server::internal::appinfo_internal_filter_get_list(db,
+ tmp_filter, uid_, uid, locale.c_str(), app_list);
+ free(tmp_filter);
+ if (ret == PMINFO_R_OK) {
+ for (auto& app : app_list) {
+ app->privileges = pkg_map_[app->package].front()->privileges;
+ std::string appid = app->appid;
+ AddApplication(std::move(appid), std::move(app));
+ }
+ }
+
+ return 0;
+}
+
+std::vector<std::shared_ptr<package_x>> Cache::GetPackages(
+ pid_t pid, bool write, 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;
+ }
+ }
+ if (pass)
+ ret.push_back(info);
+ }
+
+ return ret;
+}
+
+
+std::vector<std::shared_ptr<application_x>> Cache::GetApplications(
+ pid_t pid, bool write, pkgmgrinfo_filter_x* filter,
+ const std::string& app) {
+ /* make metadata filter map */
+ std::unordered_map<std::string, std::string> metadata_map;
+ for (auto* it = filter->list_metadata; it != nullptr; it = g_slist_next(it)) {
+ auto node = reinterpret_cast<pkgmgrinfo_metadata_node_x*>(it->data);
+ if (node->key == nullptr)
+ continue;
+
+ metadata_map[node->key] = (node->value ? node->value : "");
+ }
+
+ 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 (!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() &&
+ strstr(node->value ? node->value : "",
+ metadata->second.c_str()) != nullptr) {
+ pass = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (pass)
+ ret.push_back(info);
+ }
+
+ return ret;
+}
+
+} // namespace database
+} // namespace pkgmgr_server
--- /dev/null
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SERVER_CACHE_HH_
+#define SERVER_CACHE_HH_
+
+#include <sys/types.h>
+
+#include <memory>
+#include <mutex>
+#include <shared_mutex>
+#include <unordered_map>
+#include <vector>
+
+#include <sqlite3.h>
+
+#include "pkgmgrinfo_private.h"
+
+namespace pkgmgr_server {
+namespace database {
+
+#ifndef EXPORT_API
+#define EXPORT_API __attribute__((visibility("default")))
+#endif
+
+class EXPORT_API Cache {
+ public:
+ ~Cache() = default;
+ static Cache& GetInst(uid_t uid);
+
+ void ReleaseCache();
+ bool IsCachePreparationNecessary();
+ int UpdateCache(sqlite3* db, pid_t pid, uid_t uid, bool write,
+ const std::string& locale);
+ std::vector<std::shared_ptr<package_x>> GetPackages(
+ pid_t pid, bool write, pkgmgrinfo_filter_x* filter,
+ const std::string& package);
+ std::vector<std::shared_ptr<application_x>> GetApplications(
+ pid_t pid, bool write, pkgmgrinfo_filter_x* filter,
+ const std::string& app);
+ void SetPrepared();
+ void SetUnprepared();
+ void SetPreparing();
+ bool IsPrepared();
+
+ std::unique_lock<std::shared_timed_mutex> GetWriterLock();
+ void WriterUnLock();
+ std::shared_lock<std::shared_timed_mutex> GetReaderLock();
+ void ReaderUnLock();
+
+ static void ReleaseAll();
+
+ private:
+ explicit Cache(uid_t uid);
+ enum class EXPORT_API Status {
+ UNPREPARED,
+ PREPARING,
+ PREPARED
+ };
+
+ void SetStatus(Status status);
+
+ void AddPackage(std::string package, package_x* info);
+ void AddApplication(std::string app, std::shared_ptr<application_x> info);
+
+ std::mutex status_lock_;
+ std::shared_timed_mutex lock_;
+ uid_t uid_;
+ Status status_;
+ 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_;
+
+ static std::unordered_map<uid_t, std::unique_ptr<Cache>> cache_map_;
+};
+
+} // namespace database
+} // namespace pkgmgr_server
+
+#endif // SERVER_CACHE_HH_
#include <shared_mutex>
#include <vector>
-#include "cache_flag.hh"
+#include "cache_provider.hh"
#include "db_handle_provider.hh"
#include "utils/logging.hh"
+namespace {
+
+uid_t globaluser_uid = -1;
+
+uid_t GetGlobalUID() {
+ if (globaluser_uid == (uid_t)-1)
+ globaluser_uid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
+
+ return globaluser_uid;
+}
+
+uid_t ConvertUID(uid_t uid) {
+ if (uid < REGULAR_USER)
+ return GetGlobalUID();
+ else
+ return uid;
+}
+
+} // namespace
+
namespace pkgmgr_server {
namespace database {
std::vector<std::pair<sqlite3*, uid_t>> conn_list;
if (!Connect()) {
- CacheFlag::SetStatus(CacheFlag::Status::UNPREPARED);
+ CacheProvider(GetUID()).SetUnprepared();
return PMINFO_R_ERROR;
}
conn_list = GetConnection();
- auto lock = CacheFlag::GetWriterLock();
int ret = PMINFO_R_OK;
+
for (auto& conn : conn_list) {
- ret = DBHandleProvider::GetInst(conn.second)
- .UpdateCache(conn.first, GetPID(), uid_, false, GetLocale());
+ if (conn.second != ConvertUID(uid_))
+ continue;
+
+ CacheProvider provider(conn.second);
+ ret = provider.UpdateCache(conn.first, GetPID(), uid_, false, GetLocale());
if (ret != PMINFO_R_OK) {
- LOG(ERROR) << "Failed to update pkginfo cache : " << ret;
+ LOG(ERROR) << "Failed to update pkginfo cache for uid["
+ << uid_ << "], ret : " << ret;
break;
}
}
- CacheFlag::SetStatus(ret == PMINFO_R_OK ?
- CacheFlag::Status::PREPARED :
- CacheFlag::Status::UNPREPARED);
-
return ret;
}
--- /dev/null
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "cache_provider.hh"
+
+#include <memory>
+#include <mutex>
+#include <shared_mutex>
+#include <unordered_map>
+#include <vector>
+
+#include <glib.h>
+#include <sys/types.h>
+#include <sqlite3.h>
+#include <tzplatform_config.h>
+
+#include "cache.hh"
+#include "filter_checker_provider.hh"
+#include "utils/logging.hh"
+
+#include "pkgmgrinfo_private.h"
+#include "pkgmgrinfo_internal.h"
+#include "pkgmgrinfo_internal.hh"
+
+namespace {
+
+uid_t globaluser_uid = -1;
+
+uid_t GetGlobalUID() {
+ if (globaluser_uid == (uid_t)-1)
+ globaluser_uid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
+
+ return globaluser_uid;
+}
+
+uid_t ConvertUID(uid_t uid) {
+ if (uid < REGULAR_USER)
+ return GetGlobalUID();
+ else
+ return uid;
+}
+
+} // namespace
+
+namespace pkgmgr_server {
+namespace database {
+
+bool CacheProvider::IsCachePreparationNecessary() {
+ return Cache::GetInst(ConvertUID(uid_)).IsCachePreparationNecessary();
+}
+
+void CacheProvider::ReleaseCache() {
+ Cache::GetInst(ConvertUID(uid_)).ReleaseCache();
+}
+
+void CacheProvider::ReleaseAll() {
+ Cache::ReleaseAll();
+}
+
+bool CacheProvider::IsPrepared() {
+ return Cache::GetInst(ConvertUID(uid_)).IsPrepared();
+}
+
+bool CacheProvider::GetReadLock() {
+ reader_lock_ = Cache::GetInst(ConvertUID(uid_)).GetReaderLock();
+ if (reader_lock_.try_lock() && Cache::GetInst(ConvertUID(uid_)).IsPrepared())
+ return true;
+
+ reader_lock_.unlock();
+ return false;
+}
+
+void CacheProvider::SetUnprepared() {
+ Cache::GetInst(ConvertUID(uid_)).SetUnprepared();
+}
+
+int CacheProvider::UpdateCache(sqlite3* db, pid_t pid, uid_t uid, bool write,
+ const std::string& locale) {
+ auto lock = Cache::GetInst(ConvertUID(uid_)).GetWriterLock();
+
+ int ret = Cache::GetInst(ConvertUID(uid_)).UpdateCache(
+ db, pid, uid, write, locale);
+
+ if (ret == PMINFO_R_OK)
+ Cache::GetInst(ConvertUID(uid_)).SetPrepared();
+ else
+ Cache::GetInst(ConvertUID(uid_)).SetUnprepared();
+
+ return ret;
+}
+
+std::vector<std::shared_ptr<package_x>> CacheProvider::GetPackages(
+ pid_t pid, bool write, pkgmgrinfo_filter_x* filter,
+ const std::string& package) {
+ std::vector<std::shared_ptr<package_x>> ret;
+
+ uid_t target_uid = ConvertUID(uid_);
+ ret = Cache::GetInst(target_uid).GetPackages(pid, write, filter, package);
+
+ return ret;
+}
+
+std::vector<std::shared_ptr<application_x>> CacheProvider::GetApplications(
+ pid_t pid, bool write, pkgmgrinfo_filter_x* filter,
+ const std::string& app) {
+ std::vector<std::shared_ptr<application_x>> ret;
+ uid_t target_uid = ConvertUID(uid_);
+ ret = Cache::GetInst(target_uid).GetApplications(pid, write, filter, app);
+
+ return ret;
+}
+
+
+} // namespace database
+} // namespace pkgmgr_server
--- /dev/null
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SERVER_CACHE_PROVIDER_HH_
+#define SERVER_CACHE_PROVIDER_HH_
+
+#include <sys/types.h>
+
+#include <memory>
+#include <mutex>
+#include <shared_mutex>
+#include <unordered_map>
+#include <vector>
+
+#include <sqlite3.h>
+
+#include "pkgmgrinfo_private.h"
+
+namespace pkgmgr_server {
+namespace database {
+
+#ifndef EXPORT_API
+#define EXPORT_API __attribute__((visibility("default")))
+#endif
+
+class EXPORT_API CacheProvider {
+ public:
+ enum class EXPORT_API CacheOpResult {
+
+ PREPARED
+ };
+
+ CacheProvider(uid_t uid) : uid_(uid) {};
+ bool IsCachePreparationNecessary();
+ int UpdateCache(sqlite3* db, pid_t pid, uid_t uid,
+ bool write, const std::string& locale);
+ bool GetReadLock();
+ bool IsPrepared();
+ void ReleaseCache();
+ static void ReleaseAll();
+ void SetUnprepared();
+
+ std::vector<std::shared_ptr<package_x>> GetPackages(
+ pid_t pid, bool write, pkgmgrinfo_filter_x* filter,
+ const std::string& package);
+ std::vector<std::shared_ptr<application_x>> GetApplications(
+ pid_t pid, bool write, pkgmgrinfo_filter_x* filter,
+ const std::string& app);
+
+ private:
+ uid_t uid_;
+ std::shared_lock<std::shared_timed_mutex> reader_lock_;
+};
+
+} // namespace database
+} // namespace pkgmgr_server
+
+#endif // SERVER_CACHE_PROVIDER_HH_
#include <string>
#include <vector>
-#include "cache_flag.hh"
+#include "cache_provider.hh"
#include "utils/logging.hh"
#include "pkgmgr-info.h"
db_path_list.emplace_back(
std::make_pair(global_parser_memdb_path, GetGlobalUID()));
} else {
- if (uid_ > REGULAR_USER)
- db_path_list.emplace_back(std::make_pair(user_parser_filedb_path_, uid_));
+ if (uid_ > REGULAR_USER) {
+ db_path_list.emplace_back(
+ std::make_pair(user_parser_filedb_path_, uid_));
+ }
db_path_list.emplace_back(
std::make_pair(global_parser_filedb_path_, GetGlobalUID()));
}
sqlite3* DBHandleProvider::CreateMemoryDBHandle(const std::string& filedb_path,
- const std::string& memorydb_path) {
+ const std::string& memorydb_path) {
sqlite3* memorydb = nullptr;
sqlite3* filedb = nullptr;
int ret = sqlite3_open_v2(memorydb_path.c_str(), &memorydb,
is_user_memdb_set_ = false;
is_global_memdb_set_ = false;
- auto lock = CacheFlag::GetWriterLock();
- CacheFlag::SetStatus(CacheFlag::Status::PREPARING);
+ CacheProvider provider(uid_);
+ provider.ReleaseCache();
+
+ if (ConvertUID(uid_) != GetGlobalUID())
+ CacheProvider(GetGlobalUID()).ReleaseCache();
- pkg_map_.clear();
- app_map_.clear();
- CacheFlag::SetStatus(CacheFlag::Status::UNPREPARED);
LOG(DEBUG) << "Set Memory mode : File";
}
return true;
}
-void DBHandleProvider::TrimCache() {
- std::unique_lock<std::recursive_mutex> u(lock_);
- if (!released_)
- ReleaseCache();
-}
-
-void DBHandleProvider::ReleaseCache() {
- auto lock = CacheFlag::GetWriterLock();
- CacheFlag::SetStatus(CacheFlag::Status::PREPARING);
-
- app_map_.clear();
- pkg_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 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) {
- pkg_map_.clear();
- app_map_.clear();
-
- GHashTable* list = g_hash_table_new(g_str_hash, g_str_equal);
- if (list == nullptr) {
- LOG(ERROR) << "Out of memory";
- return PMINFO_R_ERROR;
- }
-
- 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);
- 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);
- std::string pkgid = pkg->package;
- AddPackage(std::move(pkgid), pkg);
- }
- }
-
- 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 = pkgmgr_server::internal::appinfo_internal_filter_get_list(db,
- tmp_filter, uid_, uid, locale.c_str(), app_list);
- free(tmp_filter);
- if (ret == PMINFO_R_OK) {
- for (auto& app : app_list) {
- app->privileges = pkg_map_[app->package].front()->privileges;
- std::string appid = app->appid;
- AddApplication(std::move(appid), std::move(app));
- }
- }
- released_ = false;
-
- return ret;
-}
-
-std::vector<std::shared_ptr<package_x>> DBHandleProvider::GetPackages(
- pid_t pid, bool write, 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;
- }
- }
- if (pass)
- ret.push_back(info);
- }
-
- 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));
-}
-
-std::vector<std::shared_ptr<application_x>> DBHandleProvider::GetApplications(
- pid_t pid, bool write, pkgmgrinfo_filter_x* filter,
- const std::string& app) {
- /* make metadata filter map */
- std::unordered_map<std::string, std::string> metadata_map;
- for (auto* it = filter->list_metadata; it != nullptr; it = g_slist_next(it)) {
- auto node = reinterpret_cast<pkgmgrinfo_metadata_node_x*>(it->data);
- if (node->key == nullptr)
- continue;
-
- metadata_map[node->key] = (node->value ? node->value : "");
- }
-
- 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 (!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 (pass)
- ret.push_back(info);
- }
- 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::InsertPID(pid_t pid) {
std::unique_lock<std::mutex> u(pid_list_lock_);
std::string GetCertDBPath(int pid, bool write);
void SetMemoryMode(pid_t pid);
void UnsetMemoryMode(pid_t pid);
- int UpdateCache(sqlite3* db, pid_t pid, uid_t uid, bool write,
- const std::string& locale);
- std::vector<std::shared_ptr<package_x>> GetPackages(
- pid_t pid, bool write, pkgmgrinfo_filter_x* filter,
- const std::string& package);
- std::vector<std::shared_ptr<application_x>> GetApplications(
- pid_t pid, bool write, pkgmgrinfo_filter_x* filter,
- const std::string& app);
- void TrimCache();
bool IsWriter(pid_t pid);
private:
sqlite3* CreateMemoryDBHandle(const std::string& filedb_path,
const std::string& memorydb_path);
bool IsMemoryDBActive(pid_t pid, bool write);
- void ReleaseCache();
- void AddPackage(std::string package, package_x* info);
- void AddApplication(std::string app, std::shared_ptr<application_x> info);
void InsertPID(pid_t pid);
bool ErasePID(pid_t pid);
parser_memdb_handle_;
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_;
};
} // namespace database
#include <shared_mutex>
#include <vector>
-#include "cache_flag.hh"
+#include "cache_provider.hh"
#include "db_handle_provider.hh"
#include "pkgmgrinfo_debug.h"
return ret;
}
-int PkgGetDBHandler::GetHandleFromCache(
- std::vector<std::pair<sqlite3*, uid_t>>& conn_list) {
- int ret = PMINFO_R_OK;
- std::string package;
-
- for (auto* it = filter_->list; it != nullptr; it = g_slist_next(it)) {
- auto node = reinterpret_cast<pkgmgrinfo_node_x*>(it->data);
- if (node->prop == E_PMINFO_PKGINFO_PROP_PACKAGE_ID) {
- package = node->value;
- break;
- }
- }
-
- std::vector<std::shared_ptr<package_x>> pkg_list;
- for (auto& conn : conn_list) {
- pkg_list = DBHandleProvider::GetInst(conn.second)
- .GetPackages(GetPID(), false, filter_, package);
-
- handle_list_.reserve(pkg_list.size() + handle_list_.size());
- std::move(std::begin(pkg_list), std::end(pkg_list),
- std::back_inserter(handle_list_));
- }
-
- if (handle_list_.empty())
- return PMINFO_R_ENOENT;
-
- return ret;
-}
-
int PkgGetDBHandler::Execute() {
std::shared_lock<std::shared_timed_mutex> s(lock_);
SetOpType(pkgmgr_common::DBOperationType::OPERATION_TYPE_READ);
if (is_writer)
return GetHandleFromDB(conn_list);
- if (CacheFlag::GetStatus() == CacheFlag::Status::PREPARED) {
- auto cache_lock = CacheFlag::GetReaderLock();
- if (cache_lock.try_lock() &&
- CacheFlag::GetStatus() == CacheFlag::Status::PREPARED)
- return GetHandleFromCache(conn_list);
+ CacheProvider provider(GetUID());
+ if (provider.IsPrepared() && provider.GetReadLock()) {
+ int ret = PMINFO_R_OK;
+ std::string package;
+
+ for (auto* it = filter_->list; it != nullptr; it = g_slist_next(it)) {
+ auto node = reinterpret_cast<pkgmgrinfo_node_x*>(it->data);
+ if (node->prop == E_PMINFO_PKGINFO_PROP_PACKAGE_ID) {
+ package = node->value;
+ break;
+ }
+ }
+
+ std::vector<std::shared_ptr<package_x>> pkg_list;
+ for (auto& conn : conn_list) {
+ pkg_list = CacheProvider(conn.second)
+ .GetPackages(GetPID(), false, filter_, package);
+ handle_list_.reserve(pkg_list.size() + handle_list_.size());
+ std::move(std::begin(pkg_list), std::end(pkg_list),
+ std::back_inserter(handle_list_));
+ }
+
+ if (handle_list_.empty())
+ return PMINFO_R_ENOENT;
+
+ return ret;
}
return GetHandleFromDB(conn_list);
protected:
int GetHandleFromDB(std::vector<std::pair<sqlite3*, uid_t>>& conn_list);
- int GetHandleFromCache(std::vector<std::pair<sqlite3*, uid_t>>& conn_list);
pkgmgrinfo_filter_x* filter_ = nullptr;
std::vector<std::shared_ptr<package_x>> handle_list_;
uid_t uid_;
#include "utils/logging.hh"
#include "db_handle_provider.hh"
+#include "cache_provider.hh"
#include "pkgmgrinfo_debug.h"
#include "pkgmgrinfo_internal.h"
}
}
__free_query_list(queries, args_list);
- database::DBHandleProvider::GetInst(GetUID()).TrimCache();
+ CacheProvider(GetUID()).ReleaseCache();
+
return ret;
}
return ret;
return pid_;
}
+void AbstractRequestHandler::SetUID(uid_t uid) {
+ uid_ = uid;
+}
+
+uid_t AbstractRequestHandler::GetUID() {
+ return uid_;
+}
+
} // namespace request_handler
} // namespace pkgmgr_server
virtual std::vector<uint8_t> ExtractResult() = 0;
void SetPID(pid_t pid);
+ void SetUID(uid_t uid);
protected:
pid_t GetPID();
+ uid_t GetUID();
private:
pid_t pid_;
+ uid_t uid_;
};
} // namespace request_handler
bool CreateCacheRequestHandler::HandleRequest(unsigned char* data, int size,
const std::string& locale) {
- // TODO(ilho159.kim) need to get logined user id
- psd::CacheDBHandler db(5001, GetPID());
+ psd::CacheDBHandler db(GetUID(), GetPID());
db.SetLocale(locale);
int ret = db.Execute();
#include <unordered_map>
#include <vector>
-#include "cache_flag.hh"
+#include "cache_provider.hh"
#include "create_cache_request.hh"
#include "cynara_checker.hh"
#include "pkg_request.hh"
#endif
#define LOG_TAG "PKGMGR_INFO"
+namespace {
+
+uid_t globaluser_uid = -1;
+
+uid_t GetGlobalUID() {
+ if (globaluser_uid == (uid_t)-1)
+ globaluser_uid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
+
+ return globaluser_uid;
+}
+
+uid_t ConvertUID(uid_t uid) {
+ if (uid < REGULAR_USER)
+ return GetGlobalUID();
+ else
+ return uid;
+}
+
+} // namespace
+
namespace pkgmgr_server {
namespace {
}
auto req = std::make_shared<PkgRequest>(client_fd);
- if (req->ReceiveData()) {
- pkgmgr_common::ReqType type = req->GetRequestType();
- if (CacheFlag::SetPreparing()) {
+ if (!req->ReceiveData())
+ return G_SOURCE_CONTINUE;
+
+ pkgmgr_server::database::CacheProvider provider(req->GetSenderUID());
+ if (provider.IsCachePreparationNecessary()) {
+ runner->QueueRequest(
+ std::make_shared<CreateCacheRequest>(req->GetSenderUID()));
+ }
+
+ if (ConvertUID(req->GetSenderUID()) != GetGlobalUID()) {
+ pkgmgr_server::database::CacheProvider global_provider(GetGlobalUID());
+ if (global_provider.IsCachePreparationNecessary()) {
runner->QueueRequest(
- std::make_shared<CreateCacheRequest>(req->GetSenderUID()));
+ std::make_shared<CreateCacheRequest>(GetGlobalUID()));
}
- std::vector<std::string>&& privileges = GetPrivileges(type);
- CynaraChecker::GetInst().CheckPrivilege(runner, req, privileges);
}
+ pkgmgr_common::ReqType type = req->GetRequestType();
+ std::vector<std::string>&& privileges = GetPrivileges(type);
+ CynaraChecker::GetInst().CheckPrivilege(runner, req, privileges);
+
return G_SOURCE_CONTINUE;
}
#include <malloc.h>
#include "abstract_parcelable.hh"
+#include "cache_provider.hh"
#include "command_request_handler.hh"
#include "create_cache_request_handler.hh"
#include "create_db_request_handler.hh"
try {
handler[type]->SetPID(req->GetSenderPID());
+ handler[type]->SetUID(req->GetSenderUID());
if (!handler[type]->HandleRequest(req->GetData(), req->GetSize(),
locale_.GetObject()))
LOG(ERROR) << "Failed to handle request";
database::DBHandleProvider::
GetInst(getuid()).UnsetMemoryMode(getpid());
- database::DBHandleProvider::
- GetInst(getuid()).TrimCache();
-
+ database::CacheProvider::ReleaseAll();
return false;
}