#include "pkginfo_client.hh"
-#include "../common/parcel/abstract_parcel.hh"
+#include <cpu-boosting.h>
+#include <dlfcn.h>
+#include <parcel.hh>
+#include <vconf.h>
+
+#include <mutex>
#include <string>
+#include "parcelable_factory.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::AbstractParcel> parcel, uid_t uid,
- std::shared_ptr<pkgmgr_common::parcel::AbstractParcel::IFactory> factory)
- : parcel_(parcel), uid_(uid), factory_(factory) {}
+ std::shared_ptr<pkgmgr_common::parcel::AbstractParcelable> parcel,
+ uid_t uid, pkgmgr_common::ReqType req_type)
+ : parcel_(parcel),
+ result_parcel_(nullptr),
+ uid_(uid),
+ req_type_(req_type),
+ is_offline_(false) {
+ socket_ = std::make_unique<pkgmgr_common::socket::ClientSocket>(SOCK_PATH);
+}
+
+bool PkgInfoClient::SendRequest() {
+ static pkgmgr_common::ReadyChecker check_server(SERVER_READY);
+ if (socket_ == nullptr) {
+ LOG(ERROR) << "Socket is not ready";
+ return false;
+ }
+
+ 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(&p);
+ }
-bool PkgInfoClient::SendRequest() { return true; }
+ LOG(WARNING) << "Try to send request, Request type: "
+ << pkgmgr_common::ReqTypeToString(req_type_);
-std::shared_ptr<pkgmgr_common::parcel::AbstractParcel>
+ 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) {
+ LOG(ERROR) << "fail to send data";
+ return false;
+ }
+
+ 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) {
+ LOG(ERROR) << "fail to send data";
+ return false;
+ }
+
+ if (socket_->SendData(p.GetData(), len) != 0) {
+ LOG(ERROR) << "Fail to send data";
+ return false;
+ }
+
+ return true;
+}
+
+std::shared_ptr<pkgmgr_common::parcel::AbstractParcelable>
PkgInfoClient::GetResultParcel() {
- return nullptr;
+ if (is_offline_)
+ return result_parcel_;
+
+ if (socket_ == nullptr) {
+ LOG(ERROR) << "Socket is not ready";
+ return nullptr;
+ }
+
+ size_t len = 0;
+ if (socket_->ReceiveData(&len, sizeof(len)) != 0 || len <= 0) {
+ LOG(ERROR) << "Fail to receive data";
+ return nullptr;
+ }
+
+ unsigned char* raw = static_cast<unsigned char*>(malloc(len));
+ if (raw == nullptr) {
+ LOG(ERROR) << "Out of memory";
+ return nullptr;
+ }
+
+ if (socket_->ReceiveData(raw, len) != 0) {
+ LOG(ERROR) << "Fail to receive data";
+ free(raw);
+ return nullptr;
+ }
+
+ LOG(WARNING) << "Success to receive result from server";
+
+ cpu_inheritance_invoker_.ClearCPUInheritance();
+
+ return pkgmgr_common::parcel::ParcelableFactory::GetInst().CreateParcel(
+ raw, len);
+}
+
+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();
+
+ 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())));
+
+ LOG(WARNING) << "Success to receive result";
+
+ return true;
}
} // namespace pkgmgr_client