#include "pkginfo_client.hh"
+#include <cpu-boosting.h>
+#include <dlfcn.h>
+
#include <parcel.hh>
#include <vconf.h>
+#include <mutex>
#include <string>
#include "parcelable_factory.hh"
-#include "get_appinfo_request_handler.hh"
-#include "get_cert_request_handler.hh"
-#include "get_depinfo_request_handler.hh"
-#include "get_pkginfo_request_handler.hh"
-#include "query_request_handler.hh"
-#include "set_cert_request_handler.hh"
-#include "set_pkginfo_request_handler.hh"
+#include "system_locale.hh"
+#include "ready_checker.hh"
+#include "utils/logging.hh"
#include "pkgmgrinfo_debug.h"
+#include "pkgmgrinfo_private.h"
+#define LIBPKGMGR_INFO LIB_PATH "/libpkgmgr-info-server.so.0"
+#define DIRECT_ACCESS_FUNC "_request_handler_direct_access"
namespace pkgmgr_client {
constexpr const char SOCK_PATH[] = "/run/pkgmgr-info-server";
+constexpr const char SERVER_READY[] = "/run/.pkginfo_server_ready";
+constexpr const char DEST_PROCESS_NAME[] = "pkgmgr-info";
+
+PkgInfoClient::CPUInheritanceInvoker::CPUInheritanceInvoker()
+ : set_complete_(false) {}
+
+PkgInfoClient::CPUInheritanceInvoker::~CPUInheritanceInvoker() {
+ ClearCPUInheritance();
+}
+
+void PkgInfoClient::CPUInheritanceInvoker::SetCPUInheritance() {
+ int ret = resource_set_cpu_inheritance(gettid(), DEST_PROCESS_NAME, -1);
+ if (ret != 0) {
+ LOG(ERROR) << "set cpu inheritance fail ret : " << ret;
+ return;
+ }
+
+ set_complete_ = true;
+}
+
+void PkgInfoClient::CPUInheritanceInvoker::ClearCPUInheritance() {
+ if (!set_complete_)
+ return;
+
+ int ret = resource_clear_cpu_inheritance(gettid(), DEST_PROCESS_NAME);
+ if (ret != 0) {
+ LOG(ERROR) << "clear cpu inheritance fail ret : " << ret;
+ return;
+ }
+
+ set_complete_ = false;
+}
PkgInfoClient::PkgInfoClient(
std::shared_ptr<pkgmgr_common::parcel::AbstractParcelable> parcel,
}
bool PkgInfoClient::SendRequest() {
+ static pkgmgr_common::ReadyChecker check_server(SERVER_READY);
if (socket_ == nullptr) {
- LOGE("Socket is not ready");
+ LOG(ERROR) << "Socket is not ready";
return false;
}
- if (!socket_->Connect()) {
- LOGE("Failed to connect client socket, try to direct access");
+
+ tizen_base::Parcel p;
+ p.WriteParcelable(*parcel_.get());
+
+ // CREATE_DB request type need to be executed directly by the caller
+ if (req_type_ == pkgmgr_common::ReqType::CREATE_DB) {
+ is_offline_ = true;
+ return RequestHandlerDirectAccess(&p);
+ }
+
+ if (!check_server.IsReady()) {
+ LOG(WARNING) << "Server is not ready, try to direct access"
+ ", Request type: " << pkgmgr_common::ReqTypeToString(req_type_);
is_offline_ = true;
- return RequestHandlerDirectAccess();
+ return RequestHandlerDirectAccess(&p);
+ }
+
+ LOG(WARNING) << "Try to send request, Request type: "
+ << pkgmgr_common::ReqTypeToString(req_type_);
+
+ cpu_inheritance_invoker_.SetCPUInheritance();
+ if (!socket_->Connect(req_type_)) {
+ LOG(ERROR) << "Failed to connect client socket, try to direct access"
+ ", Request type: " << pkgmgr_common::ReqTypeToString(req_type_);
+ is_offline_ = true;
+ return RequestHandlerDirectAccess(&p);
}
if (socket_->SendData(&req_type_, sizeof(req_type_)) != 0) {
- LOGE("fail to send data");
+ LOG(ERROR) << "fail to send data";
return false;
}
- tizen_base::Parcel p;
- p.WriteParcelable(*parcel_.get());
- const auto& raw = p.GetRaw();
- int len = raw.size();
+ pid_t tid = gettid();
+ if (socket_->SendData(&tid, sizeof(tid)) != 0) {
+ LOG(ERROR) << "fail to send data";
+ return false;
+ }
+ size_t len = p.GetDataSize();
if (socket_->SendData(&len, sizeof(len)) != 0) {
- LOGE("fail to send data");
+ LOG(ERROR) << "fail to send data";
return false;
}
- if (socket_->SendData(&raw[0], len) != 0) {
- LOGE("Fail to send data");
+ if (socket_->SendData(p.GetData(), len) != 0) {
+ LOG(ERROR) << "Fail to send data";
return false;
}
return result_parcel_;
if (socket_ == nullptr) {
- LOGE("Socket is not ready");
+ LOG(ERROR) << "Socket is not ready";
return nullptr;
}
- int len = 0;
+
+ size_t len = 0;
if (socket_->ReceiveData(&len, sizeof(len)) != 0 || len <= 0) {
- LOGE("Fail to receive data");
+ LOG(ERROR) << "Fail to receive data";
return nullptr;
}
- unsigned char* raw = new (std::nothrow) unsigned char[len];
+ unsigned char* raw = static_cast<unsigned char*>(malloc(len));
if (raw == nullptr) {
- LOGE("Out of memory");
+ LOG(ERROR) << "Out of memory";
return nullptr;
}
if (socket_->ReceiveData(raw, len) != 0) {
- LOGE("Fail to receive data");
- delete[] raw;
+ LOG(ERROR) << "Fail to receive data";
+ free(raw);
return nullptr;
}
- auto res = pkgmgr_common::parcel::ParcelableFactory::GetInst().CreateParcel(
- raw, len);
- delete[] raw;
+ LOG(WARNING) << "Success to receive result from server";
- return res;
-}
+ cpu_inheritance_invoker_.ClearCPUInheritance();
-bool PkgInfoClient::RequestHandlerDirectAccess() {
- std::unique_ptr<pkgmgr_server::request_handler::AbstractRequestHandler>
- handler;
- switch (req_type_) {
- case pkgmgr_common::ReqType::GET_PKG_INFO:
- handler.reset(
- new pkgmgr_server::request_handler::GetPkginfoRequestHandler());
- break;
- case pkgmgr_common::ReqType::GET_APP_INFO:
- handler.reset(
- new pkgmgr_server::request_handler::GetAppinfoRequestHandler());
- break;
- case pkgmgr_common::ReqType::SET_PKG_INFO:
- handler.reset(
- new pkgmgr_server::request_handler::SetPkginfoRequestHandler());
- break;
- case pkgmgr_common::ReqType::SET_CERT_INFO:
- handler.reset(
- new pkgmgr_server::request_handler::SetCertRequestHandler());
- break;
- case pkgmgr_common::ReqType::GET_CERT_INFO:
- handler.reset(
- new pkgmgr_server::request_handler::GetCertRequestHandler());
- break;
- case pkgmgr_common::ReqType::GET_PKG_DEP_INFO:
- handler.reset(
- new pkgmgr_server::request_handler::GetDepinfoRequestHandler());
- break;
- case pkgmgr_common::ReqType::QUERY:
- handler.reset(new pkgmgr_server::request_handler::QueryRequestHandler());
- break;
- default:
- handler.reset(nullptr);
- break;
- }
+ return pkgmgr_common::parcel::ParcelableFactory::GetInst().CreateParcel(
+ raw, len);
+}
- if (handler == nullptr) {
- LOGE("Can't reset handler with type[%d]", req_type_);
- return false;
+bool PkgInfoClient::RequestHandlerDirectAccess(tizen_base::Parcel* parcel) {
+ static std::mutex lock;
+ static void* handle = nullptr;
+ static void* (*dl_func)(int, unsigned char*, int, const char*);
+
+ std::unique_lock<std::mutex> u(lock);
+ if (handle == nullptr) {
+ handle = dlopen(LIBPKGMGR_INFO, RTLD_GLOBAL | RTLD_LAZY);
+ if (!handle) {
+ LOG(ERROR) << "Failed to open library: " << LIBPKGMGR_INFO
+ << ", : " << dlerror();
+ return false;
+ }
+ dl_func = reinterpret_cast<void* (*)(
+ int, unsigned char*, int, const char*)>(
+ dlsym(handle, DIRECT_ACCESS_FUNC));
+ if (dl_func == nullptr) {
+ LOG(ERROR) << "cannot find " << DIRECT_ACCESS_FUNC << " symbol in "
+ << LIBPKGMGR_INFO;
+ dlclose(handle);
+ handle = nullptr;
+ return false;
+ }
}
+ u.unlock();
- tizen_base::Parcel p;
- p.WriteParcelable(*parcel_.get());
- std::vector<uint8_t> raw = p.GetRaw();
- std::unique_ptr<char, decltype(std::free)*> locale(
- _get_system_locale(), std::free);
- if (locale.get() == nullptr)
- return false;
-
- handler->HandleRequest(&raw[0], raw.size(), locale.get());
- auto result = handler->ExtractResult();
- if (result.size() == 0)
- return true;
+ size_t len = 0;
+ uint8_t* raw = parcel->Detach(&len);
+ result_parcel_.reset(
+ reinterpret_cast<pkgmgr_common::parcel::AbstractParcelable*>(
+ dl_func(req_type_, raw, len,
+ pkgmgr_common::SystemLocale::GetInst(false).Get().c_str())));
- result_parcel_.reset(pkgmgr_common::parcel::ParcelableFactory::GetInst()
- .CreateParcel(&result[0], result.size())
- .release());
+ LOG(WARNING) << "Success to receive result";
return true;
}