Change how to check pkginfo server ready flag
[platform/core/appfw/pkgmgr-info.git] / src / client / pkginfo_client.cc
index b314e77..d2ca8d5 100644 (file)
@@ -4,26 +4,61 @@
 
 #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,
@@ -36,43 +71,59 @@ PkgInfoClient::PkgInfoClient(
   socket_ = std::make_unique<pkgmgr_common::socket::ClientSocket>(SOCK_PATH);
 }
 
-PkgInfoClient::~PkgInfoClient() {
-  if (socket_ != nullptr)
-    socket_->Disconnect();
-}
-
 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");
-    socket_->Disconnect();
+
+  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();
+    return RequestHandlerDirectAccess(&p);
+  }
+
+  if (!check_server.IsReady() && !check_server.Check()) {
+    LOG(WARNING) << "Server is not ready, try to direct access"
+        ", Request type: " << pkgmgr_common::ReqTypeToString(req_type_);
+    is_offline_ = true;
+    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");
-    socket_->Disconnect();
+    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");
-    socket_->Disconnect();
+    LOG(ERROR) << "fail to send data";
     return false;
   }
 
-  if (socket_->SendData(&raw[0], len) != 0) {
-    LOGE("Fail to send data");
-    socket_->Disconnect();
+  if (socket_->SendData(p.GetData(), len) != 0) {
+    LOG(ERROR) << "Fail to send data";
     return false;
   }
 
@@ -85,95 +136,70 @@ PkgInfoClient::GetResultParcel() {
     return result_parcel_;
 
   if (socket_ == nullptr) {
-    LOGE("Socket is not ready");
+    LOG(ERROR) << "Socket is not ready";
     return nullptr;
   }
-  int len = 0;
-  if (socket_->ReceiveData(&len, sizeof(len)) != 0) {
-    LOGE("Fail to receive data");
-    socket_->Disconnect();
+
+  size_t len = 0;
+  if (socket_->ReceiveData(&len, sizeof(len)) != 0 || len <= 0) {
+    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");
-    socket_->Disconnect();
+    LOG(ERROR) << "Out of memory";
     return nullptr;
   }
 
   if (socket_->ReceiveData(raw, len) != 0) {
-    LOGE("Fail to receive data");
-    socket_->Disconnect();
-    delete[] raw;
+    LOG(ERROR) << "Fail to receive data";
+    free(raw);
     return nullptr;
   }
-  socket_->Disconnect();
 
-  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;
 }