From 67e7fa8b9f890246b3ef0b1c06291ae470b7c010 Mon Sep 17 00:00:00 2001 From: Ilho Kim Date: Sun, 28 Feb 2021 12:57:34 +0900 Subject: [PATCH] Implement pkgmgrinfo_pkginfo_set_installed_storage Signed-off-by: Ilho Kim --- src/common/database/abstract_db_handler.cc | 2 + src/common/database/abstract_db_handler.hh | 1 + src/common/database/query_handler.cc | 50 +++++++++----- src/common/database/query_handler.hh | 4 +- src/common/parcel/query_parcelable.cc | 25 +++++-- src/common/parcel/query_parcelable.hh | 5 +- .../request_handler/query_request_handler.cc | 2 +- src/manager/pkginfo_manager.cc | 61 +++++++++++++++++ src/manager/pkginfo_manager.h | 4 ++ src/pkginfo_internal.c | 76 ++++++++++++++++++++++ src/pkgmgrinfo_db.c | 66 +------------------ src/pkgmgrinfo_internal.h | 1 + test/unit_tests/test_parcel.cc | 5 +- 13 files changed, 209 insertions(+), 93 deletions(-) diff --git a/src/common/database/abstract_db_handler.cc b/src/common/database/abstract_db_handler.cc index 70d7bd2..872c53e 100644 --- a/src/common/database/abstract_db_handler.cc +++ b/src/common/database/abstract_db_handler.cc @@ -286,5 +286,7 @@ void AbstractDBHandler::SetLocale(const std::string& locale) { void AbstractDBHandler::SetDBType(DBType type) { db_type_ = type; } +AbstractDBHandler::OperationType AbstractDBHandler::GetOpType() { return op_type_; } + } // namespace database } // namespace pkgmgr_common diff --git a/src/common/database/abstract_db_handler.hh b/src/common/database/abstract_db_handler.hh index 0c7099a..16a4e50 100644 --- a/src/common/database/abstract_db_handler.hh +++ b/src/common/database/abstract_db_handler.hh @@ -49,6 +49,7 @@ class EXPORT_API AbstractDBHandler { void SetLocale(const std::string& locale); void SetDBType(DBType type); void SetOpType(OperationType type); + OperationType GetOpType(); protected: bool Connect(); diff --git a/src/common/database/query_handler.cc b/src/common/database/query_handler.cc index e260c70..7764412 100644 --- a/src/common/database/query_handler.cc +++ b/src/common/database/query_handler.cc @@ -25,7 +25,7 @@ QueryHandler::QueryHandler(uid_t uid) : AbstractDBHandler(uid), uid_(uid) {} QueryHandler::~QueryHandler() {} -void QueryHandler::SetQuery(std::string query) { +void QueryHandler::SetQuery(std::vector query) { query_ = query; } @@ -44,24 +44,44 @@ bool QueryHandler::Execute() { GList* list =nullptr; int row = 0; int col = 0; - int ret = get_query_result(GetConnection(), query_.c_str(), &list, &row, &col); - if (ret != PMINFO_R_OK) { - // TODO: error log + if (query_.size() == 0) return false; - } - result_.clear(); - result_.resize(row); - GList* tmp = list; - for (int i = 0; i < row; ++i) { - for (int j = 0; j < col; ++j) { - result_[i].emplace_back(reinterpret_cast(tmp->data)); - tmp = tmp->next; + if (GetOpType() == OPERATION_TYPE_READ) { + int ret = get_query_result(GetConnection(), query_[0].c_str(), &list, &row, &col); + if (ret != PMINFO_R_OK) { + // TODO: error log + return false; } - } - g_list_free(list); - return true; + result_.clear(); + result_.resize(row); + GList* tmp = list; + for (int i = 0; i < row; ++i) { + for (int j = 0; j < col; ++j) { + result_[i].emplace_back(reinterpret_cast(tmp->data)); + tmp = tmp->next; + } + } + + g_list_free(list); + return true; + } else { + result_.clear(); + result_.resize(1); + const char **queries = (const char **)calloc(query_.size(), sizeof(char *)); + int i = 0; + for (const auto& query : query_) + queries[i++] = query.c_str(); + + int ret = execute_write_queries(GetConnection(), queries, query_.size()); + if (ret != 0) + result_[0].emplace_back("FAIL"); + else + result_[0].emplace_back("SUCCESS"); + free(queries); + return true; + } } } // namespace database diff --git a/src/common/database/query_handler.hh b/src/common/database/query_handler.hh index a1df5b4..93eba5c 100644 --- a/src/common/database/query_handler.hh +++ b/src/common/database/query_handler.hh @@ -37,7 +37,7 @@ class EXPORT_API QueryHandler : public AbstractDBHandler{ public: QueryHandler(uid_t uid); ~QueryHandler(); - void SetQuery(std::string query); + void SetQuery(std::vector query); bool BindString(std::string value); bool BindInt(int value); std::string GetString(); @@ -48,7 +48,7 @@ class EXPORT_API QueryHandler : public AbstractDBHandler{ private: uid_t uid_; - std::string query_; + std::vector query_; std::vector> result_; }; diff --git a/src/common/parcel/query_parcelable.cc b/src/common/parcel/query_parcelable.cc index 0d66367..1d6d12f 100644 --- a/src/common/parcel/query_parcelable.cc +++ b/src/common/parcel/query_parcelable.cc @@ -25,32 +25,43 @@ namespace pkgmgr_common { namespace parcel { QueryParcelable::QueryParcelable() - : AbstractParcelable(0, ParcelableType::Query), query_(""), db_type_(AbstractDBHandler::DBType::DB_TYPE_NONE), op_type_(AbstractDBHandler::OperationType::OPERATION_TYPE_NONE) {} + : AbstractParcelable(0, ParcelableType::Query), db_type_(AbstractDBHandler::DBType::DB_TYPE_NONE), op_type_(AbstractDBHandler::OperationType::OPERATION_TYPE_NONE) {} -QueryParcelable::QueryParcelable(uid_t uid, std::string query, AbstractDBHandler::DBType db_type, AbstractDBHandler::OperationType op_type) - : AbstractParcelable(uid, ParcelableType::Query), query_(query), db_type_(db_type), op_type_(op_type) {} + +QueryParcelable::QueryParcelable(uid_t uid, std::string query, + AbstractDBHandler::DBType db_type, AbstractDBHandler::OperationType op_type) + : AbstractParcelable(0, ParcelableType::Query), queries_(std::vector{query}), db_type_(db_type), op_type_(op_type) {} + +QueryParcelable::QueryParcelable(uid_t uid, std::vector queries, AbstractDBHandler::DBType db_type, AbstractDBHandler::OperationType op_type) + : AbstractParcelable(uid, ParcelableType::Query), queries_(queries), db_type_(db_type), op_type_(op_type) {} void QueryParcelable::WriteToParcel(tizen_base::Parcel* parcel) const { AbstractParcelable::WriteToParcel(parcel); - parcel->WriteString(query_); + WriteInt(parcel, queries_.size()); + for (const auto& query : queries_) + parcel->WriteString(query); WriteInt(parcel, db_type_); WriteInt(parcel, op_type_); } void QueryParcelable::ReadFromParcel(tizen_base::Parcel* parcel) { + int query_size = 0; int op_type = 0; int db_type = 0; AbstractParcelable::ReadFromParcel(parcel); - query_ = parcel->ReadString(); + ReadInt(parcel, &query_size); + for (int i = 0; i < query_size; ++i) { + queries_.emplace_back(parcel->ReadString()); + } ReadInt(parcel, &db_type); db_type_ = static_cast(db_type); ReadInt(parcel, &op_type); op_type_ = static_cast(op_type); } -const std::string& QueryParcelable::GetQuery() { - return query_; +const std::vector& QueryParcelable::GetQueries() { + return queries_; } AbstractDBHandler::DBType QueryParcelable::GetDBType() { diff --git a/src/common/parcel/query_parcelable.hh b/src/common/parcel/query_parcelable.hh index 7b2e260..63b52c0 100644 --- a/src/common/parcel/query_parcelable.hh +++ b/src/common/parcel/query_parcelable.hh @@ -26,7 +26,8 @@ class EXPORT_API QueryParcelable : public AbstractParcelable { QueryParcelable(); QueryParcelable(uid_t uid, std::string query, AbstractDBHandler::DBType db_type, AbstractDBHandler::OperationType op_type); - const std::string& GetQuery(); + QueryParcelable(uid_t uid, std::vector query, AbstractDBHandler::DBType db_type, AbstractDBHandler::OperationType op_type); + const std::vector& GetQueries(); AbstractDBHandler::DBType GetDBType(); AbstractDBHandler::OperationType GetOpType(); @@ -34,7 +35,7 @@ class EXPORT_API QueryParcelable : public AbstractParcelable { void ReadFromParcel(tizen_base::Parcel* parcel) override; private: - std::string query_; + std::vector queries_; AbstractDBHandler::DBType db_type_; AbstractDBHandler::OperationType op_type_; }; diff --git a/src/common/request_handler/query_request_handler.cc b/src/common/request_handler/query_request_handler.cc index d1fca70..a1a90b0 100644 --- a/src/common/request_handler/query_request_handler.cc +++ b/src/common/request_handler/query_request_handler.cc @@ -28,7 +28,7 @@ bool QueryRequestHandler::HandleRequest(unsigned char* data, int size, QueryHandler db(parcel->GetUid()); db.SetLocale(locale); - db.SetQuery(parcel->GetQuery()); + db.SetQuery(parcel->GetQueries()); db.SetDBType(parcel->GetDBType()); db.SetOpType(parcel->GetOpType()); if (db.Execute() == false) return false; diff --git a/src/manager/pkginfo_manager.cc b/src/manager/pkginfo_manager.cc index af51152..630a2b4 100644 --- a/src/manager/pkginfo_manager.cc +++ b/src/manager/pkginfo_manager.cc @@ -567,3 +567,64 @@ extern "C" EXPORT_API int _get_pkg_updateinfo(const char *pkgid, return PMINFO_R_OK; } + +extern "C" EXPORT_API int _pkginfo_set_usr_installed_storage(const char *pkgid, + INSTALL_LOCATION location, const char *external_pkg_path, + uid_t uid) +{ + char *query = NULL; + const char *location_str; + std::vector queries; + + if (location == INSTALL_INTERNAL) + location_str = "installed_internal"; + else if (location == INSTALL_EXTERNAL) + location_str = "installed_external"; + else + location_str = "installed_extended"; + /* pkgcakge_info table */ + query = sqlite3_mprintf( + "update package_info set installed_storage=%Q, external_path=%Q where package=%Q", + location_str, external_pkg_path, pkgid); + queries.emplace_back(query); + sqlite3_free(query); + + /* package_app_info table */ + query = sqlite3_mprintf( + "update package_app_info set app_installed_storage=%Q, app_external_path=%Q where package=%Q", + location_str, external_pkg_path, pkgid); + queries.emplace_back(query); + sqlite3_free(query); + + std::shared_ptr parcelable( + new pkgmgr_common::parcel::QueryParcelable(uid, queries, + pkgmgr_common::database::AbstractDBHandler::DBType::DB_TYPE_FILE_PKGDB, + pkgmgr_common::database::AbstractDBHandler::OperationType::OPERATION_TYPE_WRITE)); + + pkgmgr_client::PkgInfoClient client(parcelable, uid, + pkgmgr_common::ReqType::QUERY); + if (!client.SendRequest()) { + return PMINFO_R_ERROR; + } + + std::shared_ptr return_parcel( + std::static_pointer_cast( + client.GetResultParcel())); + + auto result_list = return_parcel->GetResult(); + if (result_list.size() != 1) { + LOG(ERROR) << "Invalid result"; + return PMINFO_R_ERROR; + } + + if (result_list[0].size() != 1) { + LOG(ERROR) << "Invalid result"; + return PMINFO_R_ERROR; + } + + LOG(ERROR) << "result : " << result_list[0][0]; + if (result_list[0][0] != "SUCCESS") + return PMINFO_R_ERROR; + + return PMINFO_R_OK; +} diff --git a/src/manager/pkginfo_manager.h b/src/manager/pkginfo_manager.h index a2cabc1..1e63a5e 100644 --- a/src/manager/pkginfo_manager.h +++ b/src/manager/pkginfo_manager.h @@ -59,6 +59,10 @@ int _plugininfo_get_appids( int _get_pkg_updateinfo(const char *pkgid, GSList **update_info_list, uid_t uid); +int _pkginfo_set_usr_installed_storage(const char *pkgid, + INSTALL_LOCATION location, const char *external_pkg_path, + uid_t uid); + #ifdef __cplusplus } #endif diff --git a/src/pkginfo_internal.c b/src/pkginfo_internal.c index de84f5f..0e1e085 100644 --- a/src/pkginfo_internal.c +++ b/src/pkginfo_internal.c @@ -20,6 +20,40 @@ #include "pkgmgrinfo_debug.h" #include "pkgmgr-info.h" +#define __BEGIN_TRANSACTION(db) \ +do { \ + if (sqlite3_exec(db, "BEGIN DEFERRED", NULL, NULL, NULL) != \ + SQLITE_OK) { \ + _LOGE("begin transaction failed: %s", sqlite3_errmsg(db)); \ + return -1; \ + } \ +} while (0) \ + +#define __DO_TRANSACTION(db, func) \ +do { \ + if (func) { \ + _LOGE("transaction failed: %s, rollback", sqlite3_errmsg(db)); \ + if (sqlite3_exec(db, "ROLLBACK", NULL, NULL, NULL) != \ + SQLITE_OK) \ + _LOGE("roll back transaction failed: %s", \ + sqlite3_errmsg(db)); \ + return -1; \ + } \ +} while (0) \ + +#define __END_TRANSACTION(db) \ +do { \ + if (sqlite3_exec(db, "COMMIT", NULL, NULL, NULL) != \ + SQLITE_OK) { \ + _LOGE("commit failed: %s, rollback", sqlite3_errmsg(db)); \ + if (sqlite3_exec(db, "ROLLBACK", NULL, NULL, NULL) != \ + SQLITE_OK) \ + _LOGE("roll back transaction failed: %s", \ + sqlite3_errmsg(db)); \ + return -1; \ + } \ +} while (0) \ + static int __free_packages(gpointer key, gpointer value, gpointer user_data) { @@ -621,3 +655,45 @@ API int get_query_result(sqlite3 *db, const char *query, return PMINFO_R_OK; } + +static int __execute_query(sqlite3 *db, const char *query) { + int ret = 0; + sqlite3_stmt *stmt = NULL; + + ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL); + if (ret != SQLITE_OK) { + LOGE("prepare failed: %s", sqlite3_errmsg(db)); + return -1; + } + + ret = sqlite3_step(stmt); + if (ret != SQLITE_DONE) { + LOGE("step failed: %s", sqlite3_errmsg(db)); + sqlite3_finalize(stmt); + return -1; + } + + sqlite3_finalize(stmt); + + return 0; +} + +API int execute_write_queries(sqlite3 *db, const char **queries, int len) { + int ret = 0; + int col_cnt = 0; + int row_cnt = 0; + int i = 0; + sqlite3_stmt *stmt = NULL; + char *result = NULL; + + __BEGIN_TRANSACTION(db); + for (i = 0; i < len; ++i) { + __DO_TRANSACTION(db, __execute_query(db, queries[i])); + } + __END_TRANSACTION(db); + + // Is db handel freed by AbstractDBHandler? + // sqlite3_close_v2(db); + + return 0; +} diff --git a/src/pkgmgrinfo_db.c b/src/pkgmgrinfo_db.c index e313037..c9ee010 100644 --- a/src/pkgmgrinfo_db.c +++ b/src/pkgmgrinfo_db.c @@ -20,6 +20,7 @@ #include "pkgmgrinfo_private.h" #include "pkgmgr_parser.h" #include "pkgmgr_parser_db.h" +#include "manager/pkginfo_manager.h" typedef int (*sqlite_query_callback)(void *data, int ncols, char **coltxt, char **colname); @@ -242,70 +243,7 @@ inline void _save_column_str(sqlite3_stmt *stmt, int idx, char **str) API int pkgmgrinfo_pkginfo_set_usr_installed_storage(const char *pkgid, INSTALL_LOCATION location, const char *external_pkg_path, uid_t uid) { retvm_if(pkgid == NULL, PMINFO_R_EINVAL, "pkgid is NULL\n"); - int ret = -1; - sqlite3 *pkgmgr_parser_db = NULL; - char *query = NULL; - char *db_path; - const char *location_str; - - db_path = getUserPkgParserDBPathUID(uid); - if (db_path == NULL) { - _LOGE("Failed to get pkg parser db path - %d", uid); - return PMINFO_R_ERROR; - } - - //ret = __open_db(db_path, &pkgmgr_parser_db, SQLITE_OPEN_READWRITE); - ret = 0; - if (ret != SQLITE_OK) { - _LOGE("connect db failed!"); - free(db_path); - return PMINFO_R_ERROR; - } - free(db_path); - - /*Begin transaction*/ - /* Setting Manifest DB */ - ret = sqlite3_exec(pkgmgr_parser_db, "BEGIN DEFERRED", NULL, NULL, NULL); - tryvm_if(ret != SQLITE_OK, ret = PMINFO_R_ERROR, "Failed to begin transaction\n"); - _LOGD("Transaction Begin\n"); - - if (location == INSTALL_INTERNAL) - location_str = "installed_internal"; - else if (location == INSTALL_EXTERNAL) - location_str = "installed_external"; - else - location_str = "installed_extended"; - /* pkgcakge_info table */ - query = sqlite3_mprintf( - "update package_info set installed_storage=%Q, external_path=%Q where package=%Q", - location_str, external_pkg_path, pkgid); - - ret = sqlite3_exec(pkgmgr_parser_db, query, NULL, NULL, NULL); - tryvm_if(ret != SQLITE_OK, ret = PMINFO_R_ERROR, "Don't execute query = %s\n", query); - sqlite3_free(query); - - /* package_app_info table */ - query = sqlite3_mprintf( - "update package_app_info set app_installed_storage=%Q, app_external_path=%Q where package=%Q", - location_str, external_pkg_path, pkgid); - - ret = sqlite3_exec(pkgmgr_parser_db, query, NULL, NULL, NULL); - tryvm_if(ret != SQLITE_OK, ret = PMINFO_R_ERROR, "Don't execute query = %s\n", query); - - /*Commit transaction*/ - ret = sqlite3_exec(pkgmgr_parser_db, "COMMIT", NULL, NULL, NULL); - if (ret != SQLITE_OK) { - _LOGE("Failed to commit transaction. Rollback now\n"); - ret = sqlite3_exec(pkgmgr_parser_db, "ROLLBACK", NULL, NULL, NULL); - tryvm_if(ret != SQLITE_OK, ret = PMINFO_R_ERROR, "Don't execute query = %s\n", query); - } - _LOGD("Transaction Commit and End\n"); - - ret = PMINFO_R_OK; -catch: - sqlite3_close_v2(pkgmgr_parser_db); - sqlite3_free(query); - return ret; + return _pkginfo_set_usr_installed_storage(pkgid, location, external_pkg_path, uid); } API int pkgmgrinfo_pkginfo_set_installed_storage(const char *pkgid, INSTALL_LOCATION location, const char *external_pkg_path) diff --git a/src/pkgmgrinfo_internal.h b/src/pkgmgrinfo_internal.h index 8697af7..52d8178 100644 --- a/src/pkgmgrinfo_internal.h +++ b/src/pkgmgrinfo_internal.h @@ -21,6 +21,7 @@ int certinfo_internal_get(sqlite3 *db, const char *pkgid, uid_t uid, pkgmgrinfo_ int certinfo_internal_set(sqlite3 *db, const char *pkgid, pkgmgrinfo_instcertinfo_h handle, uid_t uid); int certinfo_internal_delete(sqlite3 *db, const char *pkgid); int get_query_result(sqlite3 *db, const char *query, GList **list, int *row, int *col); +int execute_write_queries(sqlite3 *db, const char **queries, int len); /** @} */ #ifdef __cplusplus } diff --git a/test/unit_tests/test_parcel.cc b/test/unit_tests/test_parcel.cc index f5bbe5e..fd76bc7 100644 --- a/test/unit_tests/test_parcel.cc +++ b/test/unit_tests/test_parcel.cc @@ -175,7 +175,8 @@ TEST_F(ParcelTest, ResultParcelable) { TEST_F(ParcelTest, QueryParcelable) { tizen_base::Parcel parcel; - std::string query = "select * from package_info"; + std::vector query; + query.emplace_back("select * from package_info"); pp::QueryParcelable origin_parcelable(0, query, pkgmgr_common::database::AbstractDBHandler::DBType::DB_TYPE_FILE_PKGDB, @@ -184,7 +185,7 @@ TEST_F(ParcelTest, QueryParcelable) { parcel.WriteParcelable(origin_parcelable); parcel.ReadParcelable(&new_parcelable); - EXPECT_EQ(origin_parcelable.GetQuery(), new_parcelable.GetQuery()); + EXPECT_EQ(origin_parcelable.GetQueries(), new_parcelable.GetQueries()); EXPECT_EQ(origin_parcelable.GetDBType(), new_parcelable.GetDBType()); EXPECT_EQ(origin_parcelable.GetOpType(), new_parcelable.GetOpType()); } -- 2.7.4