Fix inconsistency between cache and database
[platform/core/appfw/pkgmgr-info.git] / src / server / runner.cc
index 6bcfd87..2d29a93 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <cpu-boosting.h>
 #include <fcntl.h>
 #include <glib-unix.h>
 #include <stdlib.h>
 
 #include <algorithm>
 #include <string>
-#include <unordered_map>
-#include <vector>
 
+#include "cache_flag.hh"
+#include "create_cache_request.hh"
 #include "cynara_checker.hh"
 #include "pkg_request.hh"
+#include "remove_all_cache_request.hh"
 #include "runner.hh"
+#include "utils/logging.hh"
+
 #include "pkgmgrinfo_debug.h"
 #include "pkgmgrinfo_private.h"
 
@@ -39,18 +43,9 @@ namespace pkgmgr_server {
 namespace {
 
 static const std::string SOCK_PATH = "/run/pkgmgr-info-server";
-const char PRIVILEGE_PACKAGE_MANAGER_ADMIN[] = "http://tizen.org/privilege/packagemanager.admin";
-
-std::vector<std::string> GetPrivileges(pkgmgr_common::ReqType type) {
-  std::vector<std::string> ret;
-  if (type == pkgmgr_common::SET_CERT_INFO) {
-    ret.emplace_back(PRIVILEGE_PACKAGE_MANAGER_ADMIN);
-  } else if (type == pkgmgr_common::SET_PKG_INFO) {
-    ret.emplace_back(PRIVILEGE_PACKAGE_MANAGER_ADMIN);
-  }
-
-  return ret;
-}
+constexpr const char PRIVILEGE_PACKAGE_MANAGER_ADMIN[] =
+    "http://tizen.org/privilege/packagemanager.admin";
+constexpr const char DEST_PROCESS_NAME[] = "pkgmgr-info";
 
 }  // namespace
 
@@ -60,57 +55,57 @@ Runner::Runner(unsigned int thread_num) {
   CynaraChecker::GetInst().Init();
   server_ = std::make_unique<pkgmgr_common::socket::ServerSocket>(SOCK_PATH);
   thread_pool_ = std::make_unique<WorkerThread>(thread_num_);
-  auto condition = static_cast<GIOCondition>(
-      G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL);
+  SetCPUInheritance();
+  auto condition = static_cast<GIOCondition>(G_IO_IN);
   sid_ = g_unix_fd_add(server_->GetFd(), condition, OnReceiveRequest, this);
-  vconf_notify_key_changed(VCONFKEY_LANGSET, OnLanguageChange, this);
-  std::unique_ptr<char, decltype(std::free)*> locale(
-      _get_system_locale(), std::free);
-  if (locale.get() == nullptr)
-    return;
+  default_uid_ = tzplatform_getuid(TZ_SYS_DEFAULT_USER);
+  pkgmgr_common::SystemLocale::GetInst().RegisterEvent(this);
+  pkgmgr_common::DbChangeObserver::GetInst().Listen();
+  pkgmgr_common::DbChangeObserver::GetInst().RegisterEvent(this);
+  thread_pool_->SetLocale(pkgmgr_common::SystemLocale::GetInst().Get());
+
+  if (CacheFlag::SetPreparing())
+    QueueRequest(std::make_shared<CreateCacheRequest>(default_uid_, this));
 
-  thread_pool_->SetLocale(locale.get());
   LOGI("Start Runner");
 }
 
 Runner::~Runner() {
   g_source_remove(sid_);
-  vconf_ignore_key_changed(VCONFKEY_LANGSET, OnLanguageChange);
+  if (timer_ > 0)
+    g_source_remove(timer_);
   CynaraChecker::GetInst().Fini();
+  pkgmgr_common::SystemLocale::GetInst().UnRegisterEvent();
+  pkgmgr_common::DbChangeObserver::GetInst().UnRegisterEvent();
 }
 
 int Runner::OnReceiveRequest(int fd, GIOCondition cond, void* user_data) {
-  if (static_cast<int>(cond) & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) {
-    LOGE("Invalid condition fd(%d) condition(%d)", fd, static_cast<int>(cond));
-    abort();
-    return G_SOURCE_REMOVE;
-  }
-
   auto runner = static_cast<Runner*>(user_data);
   int client_fd = runner->server_->Accept();
   if (client_fd < 0) {
-    LOGE("Failed to Accept. errno(%d)", errno);
+    LOG(ERROR) << "Failed to Accept. errno:" << errno;
     return G_SOURCE_CONTINUE;
   }
 
   auto req = std::make_shared<PkgRequest>(client_fd);
-  if (req->ReceiveData()) {
-    pkgmgr_common::ReqType type = req->GetRequestType();
-    std::vector<std::string>&& privileges = GetPrivileges(type);
-    CynaraChecker::GetInst().CheckPrivilege(runner, req, privileges);
+
+  if (CacheFlag::SetPreparing()) {
+    runner->QueueRequest(
+        std::make_shared<CreateCacheRequest>(runner->default_uid_, runner));
   }
+  runner->QueueRequest(std::move(req));
 
   return G_SOURCE_CONTINUE;
 }
 
-void Runner::OnLanguageChange(keynode_t* key, void* user_data) {
-  auto runner = static_cast<Runner*>(user_data);
-  std::unique_ptr<char, decltype(std::free)*> locale(
-      _get_system_locale(), std::free);
-  if (locale.get() == nullptr)
-    return;
+void Runner::OnChanged(const std::string& locale) {
+  thread_pool_->SetLocale(locale);
+  QueueRequest(std::make_shared<RemoveAllCacheRequest>(default_uid_));
+}
 
-  runner->thread_pool_->SetLocale(locale.get());
+void Runner::OnDbChanged() {
+  QueueRequest(std::make_shared<RemoveAllCacheRequest>(default_uid_));
+  SetCreateCacheTimer();
 }
 
 bool Runner::QueueRequest(std::shared_ptr<PkgRequest> req) {
@@ -118,4 +113,62 @@ bool Runner::QueueRequest(std::shared_ptr<PkgRequest> req) {
   return true;
 }
 
+void Runner::OnCreateCacheDone(bool success) {
+  static bool ready = false;
+  if (ready)
+    return;
+
+  if (success) {
+    ready = true;
+    LOG(WARNING) << "pkginfo-server is ready";
+    g_idle_add(
+        [](gpointer data) -> gboolean {
+          int fd = creat("/run/.pkginfo_server_ready",
+                         S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+          if (fd != -1)
+            close(fd);
+
+          return G_SOURCE_REMOVE;
+        },
+        nullptr);
+  } else {
+    LOG(WARNING) << "Fail to create cache";
+    SetCreateCacheTimer();
+  }
+}
+
+void Runner::SetCPUInheritance() {
+  int ret;
+  resource_pid_t resource_st = { 0, };
+  resource_st.pid = getpid();
+
+  ret = resource_register_cpu_inheritance_destination(
+      DEST_PROCESS_NAME, resource_st);
+  if (ret != 0)
+    LOG(ERROR) << "Fail to register cpu inheritance destination ret : " << ret;
+}
+
+void Runner::SetCreateCacheTimer() {
+  if (timer_ > 0)
+    g_source_remove(timer_);
+
+  timer_ = g_timeout_add_seconds_full(G_PRIORITY_LOW, 10,
+      RetryCreateCache, this, NULL);
+}
+
+gboolean Runner::RetryCreateCache(void* data) {
+  LOG(WARNING) << "Retry to create cache";
+  auto* runner = static_cast<Runner*>(data);
+  runner->timer_ = 0;
+
+  pkgmgr_common::DbChangeObserver::GetInst().SetChanged(false);
+  pkgmgr_common::DbChangeObserver::GetInst().Listen();
+
+  if (CacheFlag::SetPreparing()) {
+    runner->QueueRequest(
+        std::make_shared<CreateCacheRequest>(runner->default_uid_, runner));
+  }
+  return G_SOURCE_REMOVE;
+}
+
 }  // namespace pkgmgr_server