#include "query_handler.hh"
#include <shared_mutex>
+#include <tuple>
#include <vector>
#include "utils/logging.hh"
+#include "cache_flag.hh"
#include "db_handle_provider.hh"
-#include "cache_provider.hh"
#include "pkgmgrinfo_debug.h"
#include "pkgmgrinfo_internal.h"
class QueryMaker {
public:
- std::vector<const char*> query_raw_ = {
- query_appinfo_get_localed_label,
- query_appinfo_get_datacontrol_info,
- query_appinfo_get_datacontrol_appid,
- query_appinfo_get_datacontrol_trusted_info,
- query_appinfo_get_datacontrol_privileges,
- query_appinfo_get_appcontrol_privileges,
- query_plugininfo_get_appids,
- query_get_pkg_updateinfo_1,
- query_get_pkg_updateinfo_2,
- query_pkginfo_set_usr_installed_storage_1,
- query_pkginfo_set_usr_installed_storage_2,
- query_certinfo_compare_pkg_certinfo,
- query_certinfo_compare_app_certinfo,
- query_pkginfo_delete_certinfo,
-
- query_insert_package_plugin_execution_info,
- query_delete_package_plugin_execution_info,
- query_update_global_app_disable,
- query_update_app_disable_info,
- query_update_pkg_disable_info,
- query_update_global_app_splash_screen_display_info,
- query_update_app_splash_screen_display_info,
- query_update_app_label_info,
- query_update_app_icon_info,
- query_update_tep_info,
- query_register_pkg_update_info,
- query_unregister_pkg_update_info,
- query_unregister_all_pkg_update_info,
+ using CacheChangeFlag = pkgmgr_server::database::CacheChangeFlag;
+ std::vector<std::tuple<const char*, CacheChangeFlag, int>> query_raw_ = {
+ { query_appinfo_get_localed_label, CacheChangeFlag::NONE, 0 },
+ { query_appinfo_get_datacontrol_info, CacheChangeFlag::NONE, 0 },
+ { query_appinfo_get_datacontrol_appid, CacheChangeFlag::NONE, 0 },
+ { query_appinfo_get_datacontrol_trusted_info, CacheChangeFlag::NONE, 0 },
+ { query_appinfo_get_datacontrol_privileges, CacheChangeFlag::NONE, 0 },
+ { query_appinfo_get_appcontrol_privileges, CacheChangeFlag::NONE, 0 },
+ { query_plugininfo_get_appids, CacheChangeFlag::NONE, 0 },
+ { query_get_pkg_updateinfo_1, CacheChangeFlag::NONE, 0 },
+ { query_get_pkg_updateinfo_2, CacheChangeFlag::NONE, 0 },
+ { query_pkginfo_set_usr_installed_storage_1, CacheChangeFlag::PKG, 2 },
+ { query_pkginfo_set_usr_installed_storage_2, CacheChangeFlag::APPBYPKG, 2 },
+ { query_certinfo_compare_pkg_certinfo, CacheChangeFlag::NONE, 0 },
+ { query_certinfo_compare_app_certinfo, CacheChangeFlag::NONE, 0 },
+ { query_pkginfo_delete_certinfo, CacheChangeFlag::NONE, 0 },
+
+ { query_insert_package_plugin_execution_info, CacheChangeFlag::PKG, 0 },
+ { query_delete_package_plugin_execution_info, CacheChangeFlag::PKG, 0 },
+ { query_update_global_app_disable, CacheChangeFlag::APP, 0 },
+ { query_update_app_disable_info, CacheChangeFlag::APP, 1 },
+ { query_update_pkg_disable_info, CacheChangeFlag::PKG, 1 },
+ { query_update_global_app_splash_screen_display_info, CacheChangeFlag::APP, 0 },
+ { query_update_app_splash_screen_display_info, CacheChangeFlag::APP, 1 },
+ { query_update_app_label_info, CacheChangeFlag::APP, 1 },
+ { query_update_app_icon_info, CacheChangeFlag::APP, 1 },
+ { query_update_tep_info, CacheChangeFlag::PKG, 1 },
+ { query_register_pkg_update_info, CacheChangeFlag::NONE, 0 },
+ { query_unregister_pkg_update_info, CacheChangeFlag::NONE, 0 },
+ { query_unregister_all_pkg_update_info, CacheChangeFlag::NONE, 0 },
};
- const char* GetQuery(int index) {
+ const std::tuple<const char*, CacheChangeFlag, int>& GetQueryInfo(int index) {
return query_raw_[index];
}
};
QueryMaker __query_maker;
-void __free_argument(gpointer data) {
- query_args* args = reinterpret_cast<query_args*>(data);
- g_list_free(args->argument);
- free(args);
-}
-
-void __free_query_list(GList* queries, GList* args_list) {
- g_list_free(queries);
- g_list_free_full(args_list, __free_argument);
-}
-
} // namespace
namespace pkgmgr_server {
return std::move(result_);
}
-int QueryHandler::Execute() {
- std::shared_lock<std::shared_timed_mutex> s(lock_);
+int QueryHandler::ExecuteReadQuery(const std::vector<std::string>& queries,
+ const std::vector<std::vector<std::optional<std::string>>>& args_list) {
+ std::shared_lock<std::shared_mutex> s(lock_);
if (!Connect()) {
LOG(ERROR) << "Failed to connect database";
return PMINFO_R_ERROR;
}
- GList* queries = nullptr;
- GList* args_list = nullptr;
- for (auto& i : query_args_) {
- const char* query = __query_maker.GetQuery(i.first);
- if (query == nullptr) {
- LOG(ERROR) << "Failed to get query";
- __free_query_list(queries, args_list);
- return PMINFO_R_ERROR;
- }
+ const auto& conn_list = GetConnection();
+ int ret = PMINFO_R_ERROR;
+ for (const auto& conn : conn_list) {
+ int i = 0;
+ for (auto& q : queries) {
+ std::vector<std::vector<std::optional<std::string>>> result;
+ ret = internal::GetQueryResult(conn.first, q, args_list[i++], result);
+ if (ret == PMINFO_R_ERROR) {
+ LOG(ERROR) << "Failed to execute query";
+ return ret;
+ }
- queries = g_list_append(queries, (gpointer)query);
- query_args* arg = reinterpret_cast<query_args*>(
- calloc(1, sizeof(query_args)));
- if (arg == nullptr) {
- LOG(ERROR) << "Out of memory";
- __free_query_list(queries, args_list);
- return PMINFO_R_ERROR;
- }
- arg->len = i.second.size();
- for (auto& argument : i.second) {
- arg->argument = g_list_append(arg->argument,
- gpointer(argument ? (*argument).c_str() : nullptr));
+ for (auto& r : result) {
+ result_.push_back(std::move(r));
+ }
}
+ }
- args_list = g_list_append(args_list, arg);
+ return ret;
+}
+
+int QueryHandler::ExecuteWriteQuery(const std::vector<std::string>& queries,
+ const std::vector<std::vector<std::optional<std::string>>>& args_list,
+ const std::vector<std::pair<CacheChangeFlag, std::string>>& changes) {
+ std::unique_lock<std::shared_mutex> u(lock_);
+ if (!Connect()) {
+ LOG(ERROR) << "Failed to connect database";
+ return PMINFO_R_ERROR;
}
- std::vector<std::pair<sqlite3*, uid_t>> conn_list = GetConnection();
+ const auto& conn_list = GetConnection();
int ret = PMINFO_R_ERROR;
- if (GetOpType() == pkgmgr_common::DBOperationType::OPERATION_TYPE_READ) {
- for (auto& conn : conn_list) {
- for (GList* it = args_list; it; it = it->next) {
- GList* list = nullptr;
- int row = 0;
- int col = 0;
-
- query_args* params = reinterpret_cast<query_args*>(it->data);
- ret = get_query_result(conn.first, (const char *)queries->data,
- params->argument, &list, &row, &col);
- if (ret == PMINFO_R_ERROR) {
- LOG(ERROR) << "Failed to execute query";
- __free_query_list(queries, args_list);
- return ret;
- }
-
- GList* tmp = list;
- for (int i = 0; i < row; ++i) {
- pkgmgr_common::parcel::StrArgs vt;
- for (int j = 0; j < col; ++j) {
- if (!tmp->data)
- vt.emplace_back(std::nullopt);
- else
- vt.emplace_back(reinterpret_cast<char *>(tmp->data));
- tmp = tmp->next;
- }
- result_.emplace_back(std::move(vt));
- }
-
- g_list_free_full(list, free);
- }
+ bool is_writer = DBHandleProvider::IsWriter(GetPID());
+ for (const auto& conn : conn_list) {
+ ret = internal::ExecuteWriteQueries(conn.first, queries, args_list);
+ if (ret != PMINFO_R_OK) {
+ LOG(ERROR) << "Failed to execute";
+ break;
}
- __free_query_list(queries, args_list);
+ }
+ if (ret != PMINFO_R_OK || is_writer || changes.size() == 0 ||
+ CacheFlag::GetStatus() != CacheFlag::Status::PREPARED)
return ret;
- } else {
- for (auto& conn : conn_list) {
- ret = execute_write_queries(conn.first, queries, args_list);
- if (ret != PMINFO_R_OK) {
- LOG(ERROR) << "Failed to execute";
+
+ bool success = true;
+ CacheFlag::SetStatus(CacheFlag::Status::PREPARING);
+ auto lock = CacheFlag::GetWriterLock();
+ for (auto& conn : conn_list) {
+ auto& provider = database::DBHandleProvider::GetInst(conn.second);
+ for (const auto& [flag, name] : changes) {
+ switch (flag) {
+ case CacheChangeFlag::PKG:
+ success = provider.UpdateCachePkg(conn.first, uid_, name, GetLocale());
+ break;
+ case CacheChangeFlag::APP:
+ success = provider.UpdateCacheApp(conn.first, uid_, name, GetLocale());
+ break;
+ case CacheChangeFlag::APPBYPKG:
+ success =
+ provider.UpdateCacheAppByPkgid(conn.first, uid_, name, GetLocale());
+ break;
+ default:
break;
}
+
+ if (!success) {
+ LOG(ERROR) << "Write query failed. " << static_cast<int>(flag) << ' '
+ << name;
+ break;
+ }
+ }
+
+ if (!success) {
+ provider.TrimCache();
+ break;
+ }
+ }
+
+ CacheFlag::SetStatus(success ?
+ CacheFlag::Status::PREPARED : CacheFlag::Status::UNPREPARED);
+
+ return PMINFO_R_OK;
+}
+
+int QueryHandler::Execute() {
+ std::vector<std::string> queries;
+ std::vector<std::vector<std::optional<std::string>>> args_list;
+ std::vector<std::pair<CacheChangeFlag, std::string>> changes;
+ for (auto& [queryIndex, args] : query_args_) {
+ const auto& query_info = __query_maker.GetQueryInfo(queryIndex);
+ const char* query = std::get<0>(query_info);
+ if (query == nullptr) {
+ LOG(ERROR) << "Failed to get query";
+ return PMINFO_R_ERROR;
+ }
+
+ queries.push_back(query);
+ args_list.push_back(args);
+
+ if (GetOpType() == pkgmgr_common::DBOperationType::OPERATION_TYPE_READ)
+ continue;
+
+ CacheChangeFlag flag = std::get<1>(query_info);
+ if (flag == CacheChangeFlag::NONE)
+ continue;
+
+ /* Cache changed query steps */
+ unsigned int idx = std::get<2>(query_info);
+ if (args.size() <= idx) {
+ LOG(ERROR) << "Invalid query argument";
+ return PMINFO_R_ERROR;
}
- __free_query_list(queries, args_list);
- CacheProvider(GetUID()).ReleaseCache();
+ if (!args[idx])
+ continue;
+
+ changes.emplace_back(std::make_pair(flag, *args[idx]));
+ }
+
+ if (GetOpType() == pkgmgr_common::DBOperationType::OPERATION_TYPE_READ) {
+ int ret = ExecuteReadQuery(queries, args_list);
+ return ret;
+ } else {
+ int ret = ExecuteWriteQuery(queries, args_list, changes);
return ret;
}
- return ret;
}
} // namespace database