Keep the mmap shared memory area 71/323471/11
authorIlho Kim <ilho159.kim@samsung.com>
Thu, 24 Apr 2025 03:17:59 +0000 (12:17 +0900)
committerIlho Kim <ilho159.kim@samsung.com>
Wed, 14 May 2025 08:27:09 +0000 (17:27 +0900)
In the case of a writer, the size of the shared memory
is maintained as a multiple of 2
and the size of the shared memory is increased only
when the size needs to be increased

In the case of reader, if the size of the shared memory doesn't change,
maintain the mmap shared memory area

Change-Id: Ia735561c820cd26ec849cff999027347f8e70c9c
Signed-off-by: Ilho Kim <ilho159.kim@samsung.com>
15 files changed:
src/common/shared_memory/shm_app_reader.cc
src/common/shared_memory/shm_app_reader.hh
src/common/shared_memory/shm_config.cc
src/common/shared_memory/shm_config.hh
src/common/shared_memory/shm_pkg_reader.cc
src/common/shared_memory/shm_pkg_reader.hh
src/common/shared_memory/shm_reader.cc
src/common/shared_memory/shm_reader.hh
src/pkgmgrinfo_appinfo.cc
src/pkgmgrinfo_pkginfo.cc
src/server/appinfo_internal.cc
src/server/pkginfo_internal.cc
src/server/shared_memory/shm_manager.cc
src/server/shared_memory/shm_writer.cc
src/server/shared_memory/shm_writer.hh

index 52830cb71dd96125b27826b195160c3e19621beb..045bdbe9604a73be7a012e84d87637fa34a3965e 100644 (file)
@@ -22,6 +22,8 @@
 #include <fcntl.h>
 #include <unistd.h>
 
+#include <mutex>
+#include <shared_mutex>
 #include <unordered_set>
 
 #include "utils/logging.hh"
 #undef LOG_TAG
 #define LOG_TAG "PKGMGR_INFO"
 
+namespace {
+
+uid_t globaluser_uid = -1;
+
+uid_t GetGlobalUID() {
+  if (globaluser_uid == (uid_t)-1)
+    globaluser_uid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
+
+  return globaluser_uid;
+}
+
+uid_t ConvertUID(uid_t uid) {
+  if (uid < REGULAR_USER)
+    return GetGlobalUID();
+  else
+    return uid;
+}
+
+}  // namespace
+
 namespace pkgmgr_common {
 namespace shared_memory {
 
+static const std::string APP_SHM_PREFIX = ".pkgmgr_info_app_";
+
 inline bool CheckPrivilegeFilters(const char* pkgid, uid_t uid,
     const std::unordered_set<std::string>& privilege_filters) {
   ShmPkgReader pkg_reader(uid);
@@ -81,12 +105,12 @@ int ShmAppReader::GetHandles(pkgmgrinfo_filter_x* filter,
 
   if (filter_checker.AppIdFilterValue()) {
     for (auto& reader : readers_) {
-      int result;
-      auto handle = reader.GetHandle(filter_checker.AppIdFilterValue(), &result);
+      ShmError result;
+      auto handle = reader->GetHandle(filter_checker.AppIdFilterValue(), &result);
       if (!handle) {
-        if (result == TIZEN_ERROR_NO_DATA)
+        if (result == ShmError::NO_DATA)
           continue;
-        else if (result != TIZEN_ERROR_NONE)
+        else if (result != ShmError::NONE)
           return PMINFO_R_ERROR;
       } else {
         if (filter_checker.Check(*handle))
@@ -96,9 +120,9 @@ int ShmAppReader::GetHandles(pkgmgrinfo_filter_x* filter,
     }
   } else {
     for (auto& reader : readers_) {
-      int result;
-      auto handles = reader.GetHandles(&result);
-      if (!handles && result != TIZEN_ERROR_NONE)
+      ShmError result;
+      auto handles = reader->GetHandles(&result);
+      if (!handles && result != ShmError::NONE)
         return PMINFO_R_ERROR;
 
       if (!handles)
@@ -115,32 +139,10 @@ int ShmAppReader::GetHandles(pkgmgrinfo_filter_x* filter,
 
 ShmAppReader::ShmAppReader(uid_t uid) : uid_(uid) {
   readers_.emplace_back(
-      ShmNameProvider::AppConfig(uid),
-      ShmNameProvider::AppHandle(uid),
-      ShmNameProvider::AppIndexs(uid),
-      ShmNameProvider::AppKeys(uid));
+      ShmAppReader::ShmAppReaderProvider::GetReader(uid));
   if (uid > REGULAR_USER)
     readers_.emplace_back(
-        ShmNameProvider::AppConfig(GLOBAL_USER),
-        ShmNameProvider::AppHandle(GLOBAL_USER),
-        ShmNameProvider::AppIndexs(GLOBAL_USER),
-        ShmNameProvider::AppKeys(GLOBAL_USER));
-}
-
-bool ShmAppReader::Init() {
-  if (_is_writer()) {
-    LOGD("process(%d) is writer", getpid());
-    return false;
-  }
-
-  for (auto& reader : readers_) {
-    if (!reader.Init()) {
-      LOGE("Init reader fail");
-      return false;
-    }
-  }
-
-  return true;
+        ShmAppReader::ShmAppReaderProvider::GetReader(GLOBAL_USER));
 }
 
 ShmAppReader::FilterChecker::FilterChecker(uid_t uid)
@@ -177,6 +179,9 @@ bool ShmAppReader::FilterChecker::Init(pkgmgrinfo_filter_x* filter) {
 
   for (auto* it = filter->list; it != nullptr; it = g_slist_next(it)) {
     auto node = reinterpret_cast<pkgmgrinfo_node_x*>(it->data);
+    if (node->prop == E_PMINFO_APPINFO_PROP_PRIVILEGE)
+      continue;
+
     filter_checker_.emplace_back(std::make_pair(FilterCheckerProvider::GetInst().
         GetAppFilterChecker(node->prop), node->value));
   }
@@ -203,5 +208,25 @@ const char* ShmAppReader::FilterChecker::AppIdFilterValue() {
   return appid_filter_;
 }
 
+ShmReader<AppInfoHandle>*
+    ShmAppReader::ShmAppReaderProvider::GetReader(uid_t uid) {
+  static std::shared_mutex lock_;
+  std::shared_lock<std::shared_mutex> s(lock_);
+
+  uid = ConvertUID(uid);
+  auto it = readers_map_.find(uid);
+  if (it != readers_map_.end())
+    return it->second;
+
+  s.unlock();
+  std::unique_lock<std::shared_mutex> u(lock_);
+  auto* prov = readers_map_[uid];
+  if (prov == nullptr)
+    readers_map_[uid] =
+        new ShmReader<AppInfoHandle>(APP_SHM_PREFIX + std::to_string(uid));
+
+  return readers_map_[uid];
+}
+
 }  // namespace shared_memory
 }  // namespace pkgmgr_common
index 98eae850970aee6b703a0ca36d4222837a079f22..58d023a21464dab1a50e6fdfb88a73437f1388ac 100644 (file)
@@ -23,7 +23,6 @@ class EXPORT_API ShmAppReader {
  public:
   ShmAppReader(uid_t uid);
 
-  bool Init();
   int GetHandles(pkgmgrinfo_filter_x* filter,
       std::map<std::string, AppInfoHandle>& list);
 
@@ -43,8 +42,20 @@ class EXPORT_API ShmAppReader {
     std::vector<std::pair<IAppFilterChecker*, const char*>> filter_checker_;
   };
 
+  class EXPORT_API ShmAppReaderProvider {
+   public:
+    ShmAppReaderProvider() = delete;
+
+    static ShmReader<AppInfoHandle>* GetReader(uid_t uid);
+
+   private:
+    static inline std::unordered_map<uid_t,
+        ShmReader<AppInfoHandle>*> readers_map_;
+  };
+
+ private:
+  std::vector<ShmReader<AppInfoHandle>*> readers_;
   uid_t uid_;
-  std::vector<ShmReader<AppInfoHandle>> readers_;
 };
 
 }  // namespace shared_memory
index d18ed33b4b0b765486ea753b211677fe39303383..e973e676622e271d2fd328c60f4ee78f4ab901ca 100644 (file)
 #undef LOG_TAG
 #define LOG_TAG "PKGMGR_INFO"
 
-namespace {
-
-uid_t globaluser_uid = -1;
+namespace pkgmgr_common {
+namespace shared_memory {
 
-uid_t GetGlobalUID() {
-  if (globaluser_uid == (uid_t)-1)
-    globaluser_uid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
+ShmMapper::ShmMapper(std::string shm_name)
+    : shm_name_(std::move(shm_name)), fd_(-1), mapping_ptr_(nullptr) {}
 
-  return globaluser_uid;
-}
+ShmMapper::~ShmMapper() {
+  if (mapping_ptr_) {
+    size_t target_size = GetPowerOfTwoSizeWithData(mapping_ptr_->mem_size);
+    LOGD("try to munmap (%p, %zu)", mapping_ptr_, target_size);
+    if (munmap(mapping_ptr_, target_size) != 0)
+      LOGE("Failed to munmap %s", shm_name_.c_str());
+  }
 
-uid_t ConvertUID(uid_t uid) {
-  if (uid < REGULAR_USER)
-    return GetGlobalUID();
-  else
-    return uid;
+  if (fd_ != -1) {
+    LOGW("close fd(%d)", fd_);
+    close(fd_);
+  }
 }
 
-}  // namespace
+uint8_t* ShmMapper::GetPtr() const {
+  if (!mapping_ptr_)
+    return nullptr;
 
-namespace pkgmgr_common {
-namespace shared_memory {
+  if (mapping_ptr_->mem_size == 0)
+    return nullptr;
 
-static constexpr const char PKG_CONFIG[] = ".pkgmgr_pkg_config";
-static constexpr const char PKG_HANDLE_SHM_NAME[] = ".pkgmgr_info_pkg_handle";
-static constexpr const char PKG_INDEXS_SHM_NAME[] = ".pkgmgr_info_pkg_indexs";
-static constexpr const char PKG_KEYS_SHM_NAME[] = ".pkgmgr_info_pkg_keys";
-static constexpr const char APP_CONFIG[] = ".pkgmgr_app_config";
-static constexpr const char APP_HANDLE_SHM_NAME[] = ".pkgmgr_info_app_handle";
-static constexpr const char APP_INDEXS_SHM_NAME[] = ".pkgmgr_info_app_indexs";
-static constexpr const char APP_KEYS_SHM_NAME[] = ".pkgmgr_info_app_keys";
-
-static std::string GetName(const char* prefix, uid_t uid) {
-  return std::string(prefix) + "_" + std::to_string(uid);
+  return (uint8_t*)(mapping_ptr_ + 1);
 }
 
-const char* ShmNameProvider::PkgConfig(uid_t uid) {
-  uid = ConvertUID(uid);
-  auto it = pkg_config_names_.find(uid);
-  if (it != pkg_config_names_.end())
-    return it->second.c_str();
+size_t ShmMapper::GetMemSize() const {
+  if (!mapping_ptr_)
+    return 0;
 
-  return pkg_config_names_.emplace(uid, GetName(PKG_CONFIG, uid))
-      .first->second.c_str();
+  return mapping_ptr_->mem_size;
 }
 
-const char* ShmNameProvider::PkgHandle(uid_t uid) {
-  uid = ConvertUID(uid);
-  auto it = pkg_handle_names_.find(uid);
-  if (it != pkg_handle_names_.end())
-    return it->second.c_str();
-
-  return pkg_handle_names_.emplace(uid, GetName(PKG_HANDLE_SHM_NAME, uid))
-      .first->second.c_str();
+size_t ShmMapper::GetMemSizeWithData(size_t mem_size) {
+  return mem_size + sizeof(ShmData);
 }
 
-const char* ShmNameProvider::PkgIndexs(uid_t uid) {
-  uid = ConvertUID(uid);
-  auto it = pkg_indexs_names_.find(uid);
-  if (it != pkg_indexs_names_.end())
-    return it->second.c_str();
-
-  return pkg_indexs_names_.emplace(uid, GetName(PKG_INDEXS_SHM_NAME, uid))
-      .first->second.c_str();
-}
+size_t ShmMapper::GetPowerOfTwoSizeWithData(size_t mem_size) {
+  mem_size += sizeof(ShmData);
+  size_t result = 1;
+  for (size_t i = 0; i < sizeof(mem_size) * 8 - 1; ++i) {
+    if (result >= mem_size)
+      break;
 
-const char* ShmNameProvider::PkgKeys(uid_t uid) {
-  uid = ConvertUID(uid);
-  auto it = pkg_keys_names_.find(uid);
-  if (it != pkg_keys_names_.end())
-    return it->second.c_str();
+    result <<= 1;
+  }
 
-  return pkg_keys_names_.emplace(uid, GetName(PKG_KEYS_SHM_NAME, uid))
-      .first->second.c_str();
+  return result;
 }
 
-const char* ShmNameProvider::AppConfig(uid_t uid) {
-  uid = ConvertUID(uid);
-  auto it = app_config_names_.find(uid);
-  if (it != app_config_names_.end())
-    return it->second.c_str();
+ShmWriteMapper::ShmWriteMapper(std::string shm_name) :
+    ShmMapper(std::move(shm_name)), version_(1) {}
 
-  return app_config_names_.emplace(uid, GetName(APP_CONFIG, uid))
-      .first->second.c_str();
-}
+ShmWriteMapper::~ShmWriteMapper() {}
 
-const char* ShmNameProvider::AppHandle(uid_t uid) {
-  uid = ConvertUID(uid);
-  auto it = app_handle_names_.find(uid);
-  if (it != app_handle_names_.end())
-    return it->second.c_str();
+ShmError ShmWriteMapper::Init(size_t mem_size) {
+  LOGD("shm_unlink (%s)", shm_name_.c_str());
+  if (shm_unlink(shm_name_.c_str()) != 0)
+    LOGD("failed to unlink(%s) %d", shm_name_.c_str(), errno);
 
-  return app_handle_names_.emplace(uid, GetName(APP_HANDLE_SHM_NAME, uid))
-      .first->second.c_str();
-}
+  int fd = shm_open(shm_name_.c_str(), O_CREAT|O_RDWR, 0664);
+  if (fd == -1) {
+    LOGE("failed to open(%s). errno(%d)", shm_name_.c_str(), errno);
+    return ShmError::SYSTEM;
+  }
+  LOGD("shm_open success fd(%d)", fd);
 
-const char* ShmNameProvider::AppIndexs(uid_t uid) {
-  uid = ConvertUID(uid);
-  auto it = app_indexs_names_.find(uid);
-  if (it != app_indexs_names_.end())
-    return it->second.c_str();
+  size_t target_size = GetPowerOfTwoSizeWithData(mem_size);
+  if (ftruncate(fd, target_size) != 0) {
+    LOGE("failed to ftruncate (%zu), close fd(%d)", target_size, fd);
+    close(fd);
+    return ShmError::SYSTEM;
+  }
+  LOGD("ftruncate success fd(%d), size(%zu), name(%s)",
+      fd, target_size, shm_name_.c_str());
 
-  return app_indexs_names_.emplace(uid, GetName(APP_INDEXS_SHM_NAME, uid))
-      .first->second.c_str();
-}
+  uint8_t* mem_ptr =
+      (uint8_t*)mmap(NULL, target_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+  if(mem_ptr == MAP_FAILED) {
+    LOGE("failed to mmap(%s), size(%zu). errno(%d)", shm_name_.c_str(), target_size, errno);
+    if(ftruncate(fd, 0) != 0)
+      LOGE("failed to truncate (%d:0)", fd);
 
-const char* ShmNameProvider::AppKeys(uid_t uid) {
-  uid = ConvertUID(uid);
-  auto it = app_keys_names_.find(uid);
-  if (it != app_keys_names_.end())
-    return it->second.c_str();
+    LOGD("shm_unlink (%s)", shm_name_.c_str());
+    shm_unlink(shm_name_.c_str());
+    LOGW("close fd(%d)", fd);
+    close(fd);
+    return ShmError::SYSTEM;
+  }
+  LOGD("mmap success (%p, %zu)", mem_ptr, target_size);
 
-  return app_keys_names_.emplace(uid, GetName(APP_KEYS_SHM_NAME, uid))
-      .first->second.c_str();
-}
+  fd_ = fd;
+  mapping_ptr_ = (ShmData*)mem_ptr;
+  mapping_ptr_->mem_size = mem_size;
+  mapping_ptr_->version = version_++;
 
-ShmMapper::ShmMapper(const char* shm_name)
-    : shm_name_(shm_name), mem_size_(0), mem_ptr_(nullptr) {}
+  LOGD("[%s], memsize : %zu, version : %zu", shm_name_.c_str(), mapping_ptr_->mem_size, mapping_ptr_->version);
 
-ShmMapper::~ShmMapper() {
-  if (mem_ptr_ && munmap(mem_ptr_, mem_size_) != 0)
-    LOGE("Failed to munmap %s", shm_name_);
+  return ShmError::NONE;
 }
 
-uint8_t* ShmMapper::GetPtr() const {
-  return mem_ptr_;
-}
+ShmError ShmWriteMapper::Resize(size_t mem_size) {
+  if (!mapping_ptr_) {
+    LOGE("Invalid operation");
+    return ShmError::SYSTEM;
+  }
 
-size_t ShmMapper::GetSize() const {
-  return mem_size_;
-}
+  size_t origin_size = GetPowerOfTwoSizeWithData(mapping_ptr_->mem_size);
+  size_t new_size = GetPowerOfTwoSizeWithData(mem_size);
 
-ShmWriteMapper::ShmWriteMapper(const char* shm_name) :
-    ShmMapper(shm_name), fd_(-1) {}
+  if (origin_size == new_size) {
+    mapping_ptr_->mem_size = mem_size;
+    return ShmError::NONE;
+  }
 
-ShmWriteMapper::~ShmWriteMapper() {
-  if (fd_ != -1)
-    close(fd_);
-  fd_ = -1;
-}
+  LOGD("try resize %zu(%zu) to %zu(%zu)",
+      mapping_ptr_->mem_size, origin_size,
+      mem_size, new_size);
 
-bool ShmWriteMapper::Init(size_t mem_size) {
-  if(shm_unlink(shm_name_) != 0) {
-    LOGD("failed to unlink(%s) %d", shm_name_, errno);
-  } else {
-    LOGD("success to unlink(%s)", shm_name_);
+  LOGD("try to munmap (%p, %zu)", mapping_ptr_, origin_size);
+  if (munmap(mapping_ptr_, origin_size) != 0) {
+    LOGE("Failed to munmap %s", shm_name_.c_str());
+    return ShmError::SYSTEM;
   }
 
-  int fd = shm_open(shm_name_, O_CREAT|O_RDWR, 0664);
-  if(fd == -1) {
-    LOGE("failed to open(%s). errno(%d)", shm_name_, errno);
-    return false;
+  if (ftruncate(fd_, new_size) != 0) {
+    LOGE("failed to truncate (%d:%zu), %s", fd_, new_size, shm_name_.c_str());
+    return ShmError::SYSTEM;
   }
+  LOGD("ftruncate success fd(%d), size(%zu), name(%s)",
+      fd_, new_size, shm_name_.c_str());
 
-  if(ftruncate(fd, mem_size) != 0) {
-    LOGE("failed to truncate (%d:%zu)", fd, mem_size);
-    close(fd);
-    return false;
+  uint8_t* mem_ptr = (uint8_t*)mmap(NULL, new_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd_, 0);
+  if(mem_ptr == MAP_FAILED) {
+    LOGE("failed to mmap(%s). errno(%d)", shm_name_.c_str(), errno);
+    if(ftruncate(fd_, 0) != 0)
+      LOGE("failed to truncate (%d:0)", fd_);
+
+    LOGD("shm_unlink (%s)", shm_name_.c_str());
+    shm_unlink(shm_name_.c_str());
+    LOGW("close fd(%d)", fd_);
+    close(fd_);
+    fd_ = -1;
+    mapping_ptr_ = nullptr;
+    version_ = 0;
+    return ShmError::SYSTEM;
   }
+  LOGD("mmap success (%p, %zu)", mem_ptr, new_size);
+
+  mapping_ptr_ = (ShmData*)mem_ptr;
+  mapping_ptr_->mem_size = mem_size;
+  mapping_ptr_->version = version_++;
+
+  return ShmError::NONE;
+}
+
+ShmError ShmWriteMapper::Clear() {
+  version_ = 1;
 
-  uint8_t* mem_ptr = nullptr;
-  if (mem_size != 0) {
-    mem_ptr = (uint8_t*)mmap(NULL, mem_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
-    if(mem_ptr == MAP_FAILED) {
-      LOGE("failed to mmap(%s), size(%zu). errno(%d)", shm_name_, mem_size, errno);
-      if(ftruncate(fd, 0) != 0)
-        LOGE("failed to truncate (%d:0)", fd);
+  if (fd_ != -1) {
+    LOGW("close shm(%s), fd(%d)", shm_name_.c_str(), fd_);
+    close(fd_);
+    fd_ = -1;
+  }
 
-      shm_unlink(shm_name_);
-      close(fd);
-      return false;
+  if (mapping_ptr_) {
+    size_t target_size = GetPowerOfTwoSizeWithData(mapping_ptr_->mem_size);
+    LOGD("try to munmap (%p, %zu)", mapping_ptr_, target_size);
+    if (munmap(mapping_ptr_, target_size) != 0) {
+      LOGE("Failed to munmap %s", shm_name_.c_str());
+      return ShmError::SYSTEM;
     }
+
+    mapping_ptr_ = nullptr;
   }
 
-  fd_ = fd;
-  mem_size_ = mem_size;
-  mem_ptr_ = mem_ptr;
+  return ShmError::NONE;
+}
 
-  return true;
+size_t ShmWriteMapper::GetVersion() const {
+  return version_;
 }
 
-bool ShmWriteMapper::Resize(size_t mem_size) {
-  LOGD("try resize %zu to %zu", mem_size_, mem_size);
+ShmReadMapper::ShmReadMapper(std::string shm_name) :
+    ShmMapper(std::move(shm_name)), last_version_(0), last_mem_size_(0) {}
 
-  if (munmap(mem_ptr_, mem_size_) != 0) {
-    LOGE("Failed to munmap %s", shm_name_);
-    return false;
-  }
+ShmReadMapper::~ShmReadMapper() {}
 
-  if (ftruncate(fd_, mem_size) != 0) {
-    LOGE("failed to truncate (%d:%zu), %s", fd_, mem_size, shm_name_);
-    return false;
+ShmError ShmReadMapper::Init() {
+  if(fd_ > 0) return ShmError::NONE;
+
+  fd_ = shm_open(shm_name_.c_str(), O_RDONLY, 0664);
+  if (fd_ == -1) {
+    LOGE("failed to open(%s). errno(%d)", shm_name_.c_str(), errno);
+    fd_ = -1;
+    return (errno == ENOENT) ? ShmError::SHM_NOT_EXIST : ShmError::SYSTEM;
   }
+  LOGD("shm_open success fd(%d)", fd_);
 
-  uint8_t* mem_ptr = (uint8_t*)mmap(NULL, mem_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd_, 0);
-  if(mem_ptr == MAP_FAILED) {
-    LOGE("failed to mmap(%s). errno(%d)", shm_name_, errno);
-    if(ftruncate(fd_, 0) != 0)
-      LOGE("failed to truncate (%d:0)", fd_);
+  ShmData data;
+  ssize_t bytes_read = read(fd_, &data, sizeof(data));
+  if (bytes_read == -1) {
+    LOGE("failed to read shm data, error(%d)", errno);
+    return ShmError::SYSTEM;
+  }
 
-    shm_unlink(shm_name_);
+  if (MappingShm(data.mem_size, data.version) != ShmError::NONE) {
+    LOGE("failed to load shared memroy, close fd(%d)", fd_);
     close(fd_);
     fd_ = -1;
-    return false;
+    return ShmError::SYSTEM;
+  }
+
+  return ShmError::NONE;
+}
+
+ShmError ShmReadMapper::MappingShm(size_t mem_size, size_t version) {
+  if (mapping_ptr_) {
+    size_t mapping_size = GetPowerOfTwoSizeWithData(last_mem_size_);
+    LOGD("try to munmap (%p, %zu)", mapping_ptr_, mapping_size);
+    if (munmap(mapping_ptr_, mapping_size) != 0) {
+      LOGE("Failed to munmap %s", shm_name_.c_str());
+      mapping_ptr_ = nullptr;
+      return ShmError::SYSTEM;
+    }
+  }
+
+  size_t target_size = GetPowerOfTwoSizeWithData(mem_size);
+  uint8_t* shm = (uint8_t*)mmap(NULL, target_size, PROT_READ, MAP_SHARED, fd_, 0);
+  if (shm == MAP_FAILED) {
+    LOGE("failed to mmap(%s). fd(%d), errno(%d)", shm_name_.c_str(), fd_, errno);
+    mapping_ptr_ = nullptr;
+    return ShmError::SYSTEM;
   }
+  LOGD("mmap (%p, %zu) success", shm, target_size);
 
-  mem_size_ = mem_size;
-  mem_ptr_ = mem_ptr;
+  mapping_ptr_ = (ShmData*)shm;
+  last_version_ = mapping_ptr_->version;
+  last_mem_size_ = mapping_ptr_->mem_size;
 
-  return true;
+  return ShmError::NONE;
 }
 
-ShmReadMapper::ShmReadMapper(const char* shm_name) :
-    ShmMapper(shm_name), fd_(-1) {}
+ShmError ShmReadMapper::LoadAll() {
+  std::shared_lock<std::shared_mutex> s(lock_);
+  if (fd_ == -1) {
+    s.unlock();
+    std::unique_lock<std::shared_mutex> u(lock_);
 
-ShmReadMapper::~ShmReadMapper() {
-  if (fd_ != -1)
-    close(fd_);
-  fd_ = -1;
+    if (fd_ != -1)
+      return ShmError::NONE;
+
+    return Init();
+  }
+
+  if (mapping_ptr_) {
+    if (last_version_ == mapping_ptr_->version)
+      return ShmError::NONE;
+
+    LOGD("last_version_ : %zu, new_version : %zu",
+        last_version_, mapping_ptr_->version);
+    s.unlock();
+    std::unique_lock<std::shared_mutex> u(lock_);
+    if (last_version_ == mapping_ptr_->version)
+      return ShmError::NONE;
+
+    return MappingShm(mapping_ptr_->mem_size, mapping_ptr_->version);
+  } else {
+    s.unlock();
+    std::unique_lock<std::shared_mutex> u(lock_);
+    if (mapping_ptr_)
+      return ShmError::NONE;
+
+    return Init();
+  }
 }
 
-bool ShmReadMapper::Init() {
-  if(fd_ > 0) return true;
+ShmError ShmReadMapper::Reload() {
+  std::unique_lock<std::shared_mutex> u(lock_);
+  size_t mapping_size = GetPowerOfTwoSizeWithData(last_mem_size_);
 
-  int fd = shm_open(shm_name_, O_RDONLY, 0664);
-  if(fd == -1) {
-    LOGE("failed to open(%s). errno(%d)", shm_name_, errno);
-    return false;
+  if (mapping_ptr_) {
+    LOGD("try to munmap (%p, %zu)", mapping_ptr_, mapping_size);
+    if (munmap(mapping_ptr_, mapping_size) != 0)
+      LOGE("Failed to munmap %s", shm_name_.c_str());
   }
+  mapping_ptr_ = nullptr;
+  fd_ = -1;
 
-  fd_ = fd;
-  return true;
+  return Init();
 }
 
-bool ShmReadMapper::LoadAll(size_t mem_size) {
-  if(mem_ptr_){
-    if (mem_size == mem_size_) {
-      return true;
-    } else {
-      if (munmap(mem_ptr_, mem_size_) != 0) {
-        LOGE("Failed to munmap %s", shm_name_);
-        return false;
-      }
-      mem_ptr_ = nullptr;
-      mem_size_ = 0;
+ShmError ShmReadMapper::Unload() {
+  std::unique_lock<std::shared_mutex> u(lock_);
+  if (!mapping_ptr_ && fd_ == -1)
+    return ShmError::NONE;
+
+  ShmError result = ShmError::NONE;
+  if (mapping_ptr_) {
+    size_t mapping_size = GetPowerOfTwoSizeWithData(last_mem_size_);
+    LOGD("try to munmap (%p, %zu)", mapping_ptr_, mapping_size);
+    if (munmap(mapping_ptr_, mapping_size) != 0) {
+      LOGE("Failed to munmap %s", shm_name_.c_str());
+      result = ShmError::SYSTEM;
     }
+
+    mapping_ptr_ = nullptr;
   }
 
-  uint8_t* shm = (uint8_t*)mmap(NULL, mem_size, PROT_READ, MAP_SHARED, fd_, 0);
-  if (shm == MAP_FAILED) {
-    LOGE("failed to mmap(%s). errno(%d)", shm_name_, errno);
+  if (fd_) {
+    LOGW("close fd(%d)", fd_);
     close(fd_);
     fd_ = -1;
-    mem_ptr_ = nullptr;
-    mem_size_ = 0;
-    return false;
   }
 
-  mem_ptr_ = shm;
-  mem_size_ = mem_size;
+  return result;
+}
+
+ShmLockGuard::ShmLockGuard(pthread_rwlock_t* lock) : lock_(lock) {}
 
-  return true;
+ShmLockGuard::~ShmLockGuard() {
+  if (!lock_)
+    return;
+
+  Unlock();
 }
 
-uint8_t* ShmReadMapper::CopyPartial(size_t offset, size_t size) {
-  uint8_t* ptr = reinterpret_cast<uint8_t*>(malloc(size));
-  if (ptr == nullptr) {
-    LOGE("Out of memory, len(%zu)", size);
-    close(fd_);
-    fd_ = -1;
-    return nullptr;
+ShmLockGuard::ShmLockGuard(ShmLockGuard&& guard) noexcept {
+  lock_ = guard.lock_;
+  guard.lock_ = nullptr;
+}
+
+ShmLockGuard& ShmLockGuard::operator=(ShmLockGuard&& guard) noexcept {
+  if (this != &guard) {
+    lock_ = guard.lock_;
+    guard.lock_ = nullptr;
   }
+  return *this;
+}
 
-  if (mem_ptr_ && ((offset + size) < mem_size_)) {// case in-mmap, read mem
-    memcpy(ptr, mem_ptr_, size);
-  } else { // case out-mmap, read file
-    if (lseek(fd_, offset, SEEK_SET) == -1) {
-      LOGE("lseek fail fd(%d), index(%zd)", fd_, offset);
-      free(ptr);
-      close(fd_);
-      fd_ = -1;
-      return nullptr;
-    }
+void ShmLockGuard::Unlock() {
+  if (!lock_)
+    return;
 
-    ssize_t read_num = read(fd_, ptr, size);
-    LOGD("read_num: %zd, len: %zu", read_num, size);
-    if (read_num == -1) {
-      LOGE("Failed to read %zu bytes, read_num(%zd)", size, read_num);
-      free(ptr);
-      close(fd_);
-      fd_ = -1;
-      return nullptr;
-    }
+  LOGD("try unlock (%p)", lock_);
+  int ret = pthread_rwlock_unlock(lock_);
+  if (ret != 0) {
+    LOGE("Failed to unlock, %d", ret);
+    return;
   }
-  return ptr;
+
+  lock_ = nullptr;
 }
 
 ShmConfigHandler::~ShmConfigHandler() {
-  if (has_lock_) {
-    Unlock();
+  if (config_data_) {
+    LOGD("try to munmap (%p, %zu)", config_data_, sizeof(ConfigData));
+    if (munmap(config_data_, sizeof(config_data_)) != 0) {
+      LOGE("Failed to munmap %s", shm_name_.c_str());
+      return;
+    }
   }
-
-  if (config_data_)
-    munmap(config_data_, sizeof(ConfigData));
 }
 
-bool ShmConfigHandler::Create() {
-  if(shm_unlink(shm_name_) != 0) {
-    LOGD("failed to unlink(%s) %d", shm_name_, errno);
-  } else {
-    LOGD("success to unlink(%s)", shm_name_);
-  }
+ShmError ShmConfigHandler::Create() {
+  std::unique_lock<std::shared_mutex> u(lock_);
+  LOGD("shm_unlink (%s)", shm_name_.c_str());
+  if (shm_unlink(shm_name_.c_str()) != 0)
+    LOGD("failed to unlink(%s) %d", shm_name_.c_str(), errno);
 
-  int fd = shm_open(shm_name_, O_CREAT|O_RDWR, 0664);
+  int fd = shm_open(shm_name_.c_str(), O_CREAT|O_RDWR, 0664);
   if(fd == -1) {
-    LOGE("failed to open(%s). errno(%d)", shm_name_, errno);
-    return false;
+    LOGE("failed to open(%s). errno(%d)", shm_name_.c_str(), errno);
+    return ShmError::SYSTEM;
   }
+  LOGD("shm_open success fd(%d)", fd);
 
   if (fchmod(fd, 0666) != 0) {
     LOGE("Failed to change permission to 0666, %d", errno);
-    return false;
+    return ShmError::SYSTEM;
   }
 
   size_t len = sizeof(ConfigData);
-  LOGD("config_data len : %zu", len);
-  LOGD("pthread_rwlock_t len : %zu", sizeof(pthread_rwlock_t));
   if(ftruncate(fd, len) != 0) {
-    LOGE("failed to truncate (%d:%zu)", fd, len);
+    LOGE("failed to truncate (%d:%zu), close fd(%d)", fd, len, fd);
     close(fd);
-    return false;
+    return ShmError::SYSTEM;
   }
+  LOGD("ftruncate success fd(%d), size(%zu), name(%s)",
+      fd, len, shm_name_.c_str());
 
   config_data_ = (ConfigData*)mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
   if(config_data_ == MAP_FAILED) {
-    LOGE("failed to mmap(%s). errno(%d)", shm_name_, errno);
+    LOGE("failed to mmap(%s). errno(%d)", shm_name_.c_str(), errno);
     if(ftruncate(fd, 0) != 0)
       LOGE("failed to truncate (%d:0)", fd);
 
-    shm_unlink(shm_name_);
+    LOGD("shm_unlink (%s)", shm_name_.c_str());
+    shm_unlink(shm_name_.c_str());
+    LOGW("close fd(%d)", fd);
     close(fd);
-    return false;
+    return ShmError::SYSTEM;
   }
+  LOGD("mmap success (%p, %zu)", config_data_, len);
+  LOGW("close fd(%d)", fd);
   close(fd);
 
   pthread_rwlockattr_t attr;
   if (pthread_rwlockattr_init(&attr)) {
     LOGE("pthread_mutexattr_init fail");
-    return false;
+    return ShmError::SYSTEM;
   }
 
   if (pthread_rwlockattr_setpshared(&attr, PTHREAD_PROCESS_SHARED)) {
     LOGE("pthread_mutexattr_setpshared fail");
     pthread_rwlockattr_destroy(&attr);
-    return false;
+    return ShmError::SYSTEM;
   }
 
   if (pthread_rwlock_init(&config_data_->lock, &attr)) {
     LOGE("pthread_mutex_init fail");
     pthread_rwlockattr_destroy(&attr);
-    return false;
+    return ShmError::SYSTEM;
   }
 
   if (pthread_rwlockattr_destroy(&attr)) {
     LOGE("pthread_rwlockattr_destroy fail");
-    return false;
+    return ShmError::SYSTEM;
   }
 
-  return true;
+  return ShmError::NONE;
 }
 
-bool ShmConfigHandler::Load() {
-  int fd = shm_open(shm_name_, O_RDWR, 0664);
+ShmError ShmConfigHandler::Load() {
+  {
+    std::shared_lock<std::shared_mutex> s(lock_);
+    if (config_data_ != nullptr)
+      return ShmError::NONE;
+  }
+
+  std::unique_lock<std::shared_mutex> u(lock_);
+  if (config_data_ != nullptr)
+    return ShmError::NONE;
+
+  int fd = shm_open(shm_name_.c_str(), O_RDWR, 0664);
   if(fd == -1) {
-    LOGE("failed to open(%s). errno(%d)", shm_name_, errno);
-    return false;
+    LOGE("failed to open(%s). errno(%d)", shm_name_.c_str(), errno);
+    return (errno == ENOENT) ? ShmError::SHM_NOT_EXIST : ShmError::SYSTEM;
   }
+  LOGD("shm_open success fd(%d)", fd);
 
-  config_data_ = (ConfigData*)mmap(NULL, sizeof(ConfigData), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
-  if(config_data_ == MAP_FAILED) {
-    LOGE("failed to mmap(%s). errno(%d)", shm_name_, errno);
+  ConfigData* map_ptr = (ConfigData*)mmap(NULL, sizeof(ConfigData), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+  if(map_ptr == MAP_FAILED) {
+    LOGE("failed to mmap(%s). errno(%d), close fd(%d)", shm_name_.c_str(), errno, fd);
     close(fd);
-    return false;
+    return ShmError::SYSTEM;
   }
+  LOGD("mmap success (%p, %zu)", map_ptr, sizeof(ConfigData));
+  LOGW("close fd(%d)", fd);
   close(fd);
 
-  return true;
+  config_data_ = map_ptr;
+
+  return ShmError::NONE;
 }
 
-int ShmConfigHandler::GetWriteLock() {
-  if (has_lock_) {
-    LOGD("This object already has lock");
-    return 0;
+ShmError ShmConfigHandler::Clear() {
+  std::unique_lock<std::shared_mutex> u(lock_);
+
+  if (!config_data_)
+    return ShmError::NONE;
+
+  LOGD("try to munmap (%p, %zu)", config_data_, sizeof(ConfigData));
+  if (munmap(config_data_, sizeof(config_data_)) != 0) {
+    LOGE("Failed to munmap %s", shm_name_.c_str());
+    return ShmError::SYSTEM;
+  }
+
+  LOGD("shm_unlink (%s)", shm_name_.c_str());
+  if (shm_unlink(shm_name_.c_str()) != 0) {
+    LOGE("Failed to unlink(%s) %d", shm_name_.c_str(), errno);
+    return ShmError::SYSTEM;
+  }
+
+  config_data_ = nullptr;
+
+  return ShmError::NONE;
+}
+
+ShmError ShmConfigHandler::Reload() {
+  std::unique_lock<std::shared_mutex> u(lock_);
+
+  if (config_data_) {
+    LOGD("try to munmap (%p, %zu)", config_data_, sizeof(config_data_));
+    if (munmap(config_data_, sizeof(config_data_)) != 0)
+      LOGE("Failed to munmap %s", shm_name_.c_str());
+  }
+
+  config_data_ = nullptr;
+
+  int fd = shm_open(shm_name_.c_str(), O_RDWR, 0664);
+  if(fd == -1) {
+    LOGE("failed to open(%s). errno(%d)", shm_name_.c_str(), errno);
+    return (errno == ENOENT) ? ShmError::SHM_NOT_EXIST : ShmError::SYSTEM;
+  }
+  LOGD("shm_open success fd(%d)", fd);
+
+  ConfigData* map_ptr = (ConfigData*)mmap(NULL, sizeof(ConfigData), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+  if(map_ptr == MAP_FAILED) {
+    LOGE("failed to mmap(%s). errno(%d), close fd(%d)", shm_name_.c_str(), errno, fd);
+    close(fd);
+    return ShmError::SYSTEM;
   }
+  LOGD("mmap success (%p, %zu)", map_ptr, sizeof(ConfigData));
+  LOGW("close fd(%d)", fd);
+  close(fd);
+
+  config_data_ = map_ptr;
+
+  return ShmError::NONE;
+}
+
+ShmError ShmConfigHandler::Unload() {
+  if (!config_data_)
+    return ShmError::NONE;
+
+  LOGD("try to munmap (%p, %zu)", config_data_, sizeof(config_data_));
+  if (munmap(config_data_, sizeof(config_data_)) != 0)
+    LOGE("Failed to munmap %s", shm_name_.c_str());
 
+  config_data_ = nullptr;
+
+  return ShmError::NONE;
+}
+
+std::optional<ShmLockGuard> ShmConfigHandler::GetWriteLock() {
   timespec timeout;
   clock_gettime(CLOCK_REALTIME, &timeout);
-  timeout.tv_sec += 30;
+  timeout.tv_sec += 5;
 
-  LOGD("try get write lock");
   int ret = pthread_rwlock_timedwrlock(&config_data_->lock, &timeout);
   if (ret != 0) {
     LOGE("Failed to get write lock, %d", ret);
-    return ret;
+    return std::nullopt;
   }
+  LOGD("sucess to get write lock of (%s), (%p)",
+      shm_name_.c_str(), &config_data_->lock);
 
-  has_lock_ = true;
-  return 0;
+  return ShmLockGuard(&config_data_->lock);
 }
 
-int ShmConfigHandler::GetReadLock() {
-  if (has_lock_) {
-    LOGD("This object already has lock");
-    return 0;
-  }
-
-  LOGD("try get read lock");
+std::optional<ShmLockGuard> ShmConfigHandler::GetReadLock() {
   int ret = pthread_rwlock_tryrdlock(&config_data_->lock);
   if (ret != 0) {
     LOGE("Failed to get read lock, %d", ret);
-    return ret;
+    return std::nullopt;
   }
+  LOGD("sucess to get read lock of (%s), (%p)",
+      shm_name_.c_str(), &config_data_->lock);
 
-  has_lock_ = true;
-  return 0;
+  return ShmLockGuard(&config_data_->lock);
 }
 
-int ShmConfigHandler::Unlock() {
-  if (!has_lock_) {
-    LOGD("This object doesn't have a lock");
-    return 0;
-  }
-  LOGD("try unlock");
-  int ret = pthread_rwlock_unlock(&config_data_->lock);
+bool ShmConfigHandler::GetIsValid() const {
+  if (config_data_ == nullptr)
+    return false;
+
+  int ret = pthread_rwlock_rdlock(&config_data_->flag_lock);
   if (ret != 0) {
-    LOGE("Failed to unlock, %d", ret);
-    return ret;
+    LOGE("Failed to get flag lock, %d", ret);
+    return false;
   }
 
-  has_lock_ = false;
-  return ret;
+  ShmLockGuard lock_guard(&config_data_->flag_lock);
+  return config_data_->is_valid;
 }
 
-size_t ShmConfigHandler::GetMemSize() const {
-  return config_data_->mem_size;
-}
+void ShmConfigHandler::SetIsValid(bool is_valid) {
+  if (!config_data_)
+    return;
 
-size_t ShmConfigHandler::GetIndexMemSize() const {
-  return config_data_->index_mem_size;
-}
+  timespec timeout;
+  clock_gettime(CLOCK_REALTIME, &timeout);
+  timeout.tv_sec += 5;
 
-size_t ShmConfigHandler::GetKeyMemSize() const {
-  return config_data_->key_mem_size;
-}
+  int ret = pthread_rwlock_timedwrlock(&config_data_->flag_lock, &timeout);
+  if (ret != 0) {
+    LOGE("Failed to get flag lock, %d", ret);
+    // There is a high possibility that reader terminated abnormaly by holding the lock
+    config_data_->is_valid = is_valid;
+    return;
+  }
 
-void ShmConfigHandler::SetMemSize(size_t mem_size) {
-  config_data_->mem_size = mem_size;
-}
+  LOGD("sucess to get flag lock of (%s), (%p)",
+      shm_name_.c_str(), &config_data_->flag_lock);
 
-void ShmConfigHandler::SetIndexMemSize(size_t index_mem_size) {
-  config_data_->index_mem_size = index_mem_size;
-}
+  ShmLockGuard lock_guard(&config_data_->flag_lock);
 
-void ShmConfigHandler::SetKeyMemSize(size_t key_mem_size) {
-  config_data_->key_mem_size = key_mem_size;
+  config_data_->is_valid = is_valid;
 }
 
 
index 8e6df2b498109d5f936ae00f5004f20521b2cac8..4d10314c743419a33a78d5ccdff2801da3ad0d7c 100644 (file)
@@ -22,6 +22,9 @@
 #include <sys/types.h>
 
 #include <map>
+#include <mutex>
+#include <optional>
+#include <shared_mutex>
 #include <string>
 
 namespace pkgmgr_common {
@@ -31,96 +34,109 @@ namespace shared_memory {
 #define EXPORT_API __attribute__((visibility("default")))
 #endif
 
-class EXPORT_API ShmNameProvider {
- public:
-  static const char* PkgConfig(uid_t uid);
-  static const char* PkgHandle(uid_t uid);
-  static const char* PkgIndexs(uid_t uid);
-  static const char* PkgKeys(uid_t uid);
-  static const char* AppConfig(uid_t uid);
-  static const char* AppHandle(uid_t uid);
-  static const char* AppIndexs(uid_t uid);
-  static const char* AppKeys(uid_t uid);
-
- private:
-  ShmNameProvider() = delete;
-  static inline std::map<uid_t, std::string> pkg_config_names_;
-  static inline std::map<uid_t, std::string> pkg_handle_names_;
-  static inline std::map<uid_t, std::string> pkg_indexs_names_;
-  static inline std::map<uid_t, std::string> pkg_keys_names_;
-  static inline std::map<uid_t, std::string> app_config_names_;
-  static inline std::map<uid_t, std::string> app_handle_names_;
-  static inline std::map<uid_t, std::string> app_indexs_names_;
-  static inline std::map<uid_t, std::string> app_keys_names_;
+enum class EXPORT_API ShmError {
+  READ_LOCK,
+  SHM_NOT_EXIST,
+  SYSTEM,
+  PERMISSION,
+  NO_DATA,
+  INVALID_FLAG,
+  NONE,
 };
 
 class EXPORT_API ShmMapper {
  public:
-  ShmMapper(const char* shm_name);
+  ShmMapper(std::string shm_name);
   virtual ~ShmMapper();
   uint8_t* GetPtr() const;
-  size_t GetSize() const;
+  size_t GetMemSize() const;
 
  protected:
-  const char* shm_name_;
-  size_t mem_size_;
-  uint8_t* mem_ptr_;
+  struct ShmData {
+    size_t mem_size;
+    size_t version;
+  };
+
+  size_t GetMemSizeWithData(size_t mem_size);
+  size_t GetPowerOfTwoSizeWithData(size_t mem_size);
+
+  std::string shm_name_;
+  int fd_;
+  ShmData* mapping_ptr_;
 };
 
 class EXPORT_API ShmWriteMapper : public ShmMapper {
  public:
-  ShmWriteMapper(const char* shm_name);
+  ShmWriteMapper(std::string shm_name);
   ~ShmWriteMapper();
 
-  bool Init(size_t mem_size);
-  bool Resize(size_t mem_size);
+  ShmError Init(size_t mem_size);
+  ShmError Resize(size_t mem_size);
+  ShmError Clear();
+  size_t GetVersion() const;
 
  private:
-  int fd_;
+  size_t version_;
 };
 
 class EXPORT_API ShmReadMapper : public ShmMapper {
  public:
-  ShmReadMapper(const char* shm_name);
+  ShmReadMapper(std::string shm_name);
   ~ShmReadMapper();
 
-  bool Init();
-  bool LoadAll(size_t mem_size);
-  uint8_t* CopyPartial(size_t offset, size_t size);
+  ShmError LoadAll();
+  ShmError Reload();
+  ShmError Unload();
 
  private:
-  int fd_;
+  ShmError Init();
+  ShmError MappingShm(size_t mem_size, size_t version);
+
+  size_t last_version_;
+  size_t last_mem_size_;
+  std::shared_mutex lock_;
+};
+
+class EXPORT_API ShmLockGuard {
+ public:
+  ShmLockGuard(pthread_rwlock_t* lock);
+  ~ShmLockGuard();
+  ShmLockGuard(const ShmLockGuard&) = delete;
+  ShmLockGuard(ShmLockGuard&& guard) noexcept;
+  ShmLockGuard& operator=(ShmLockGuard&& p) noexcept;
+
+  void Unlock();
+
+ private:
+  pthread_rwlock_t* lock_;
 };
 
 class EXPORT_API ShmConfigHandler {
  public:
-  ShmConfigHandler(const char* shm_name) :
-      config_data_(nullptr), has_lock_(false), shm_name_(shm_name) {}
+  ShmConfigHandler(std::string shm_name) :
+      config_data_(nullptr), shm_name_(std::move(shm_name)) {}
   ~ShmConfigHandler();
 
-  bool Create();
-  bool Load();
-  int GetWriteLock();
-  int GetReadLock();
-  int Unlock();
-  size_t GetMemSize() const;
-  size_t GetIndexMemSize() const;
-  size_t GetKeyMemSize() const;
-  void SetMemSize(size_t app_mem_size);
-  void SetIndexMemSize(size_t app_index_mem_size);
-  void SetKeyMemSize(size_t pkg_mem_size);
+  ShmError Create();
+  ShmError Load();
+  ShmError Clear();
+  ShmError Reload();
+  ShmError Unload();
+  std::optional<ShmLockGuard> GetWriteLock();
+  std::optional<ShmLockGuard> GetReadLock();
+  bool GetIsValid() const;
+  void SetIsValid(bool is_valid);
 
  private:
   struct ConfigData {
     pthread_rwlock_t lock;
-    size_t mem_size;
-    size_t index_mem_size;
-    size_t key_mem_size;
+    pthread_rwlock_t flag_lock;
+    bool is_valid;
   };
 
   ConfigData* config_data_;
-  bool has_lock_;
-  const char* shm_name_;
+  std::string shm_name_;
+  std::shared_mutex lock_;
 };
 
 struct HandleMappingData {
index b4c7d4bd07b3bfa4d7943e42e5b8cefbd7df1d86..4b9645e910f35060791573496090d7b6e374d55b 100644 (file)
@@ -22,6 +22,9 @@
 #include <fcntl.h>
 #include <unistd.h>
 
+#include <mutex>
+#include <shared_mutex>
+
 #include "utils/logging.hh"
 
 #include "pkgmgrinfo_private.h"
 #undef LOG_TAG
 #define LOG_TAG "PKGMGR_INFO"
 
+namespace {
+
+uid_t globaluser_uid = -1;
+
+uid_t GetGlobalUID() {
+  if (globaluser_uid == (uid_t)-1)
+    globaluser_uid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
+
+  return globaluser_uid;
+}
+
+uid_t ConvertUID(uid_t uid) {
+  if (uid < REGULAR_USER)
+    return GetGlobalUID();
+  else
+    return uid;
+}
+
+}  // namespace
+
 namespace pkgmgr_common {
 namespace shared_memory {
 
+static const std::string PKG_SHM_PREFIX = ".pkgmgr_info_pkg_";
+
 inline bool CheckMetadataFilter(const PkgInfoHandle* info,
     const std::unordered_map<std::string, std::string>& metadata_map) {
   for (auto node : info->GetMetadata()) {
@@ -83,13 +108,13 @@ int ShmPkgReader::GetHandles(pkgmgrinfo_filter_x* filter,
   }
 
   if (filter_checker.PkgIdFilterValue()) {
-    for (auto& reader : readers_) {
-      int result;
-      auto handle = reader.GetHandle(filter_checker.PkgIdFilterValue(), &result);
+    for (auto reader : readers_) {
+      ShmError result;
+      auto handle = reader->GetHandle(filter_checker.PkgIdFilterValue(), &result);
       if (!handle) {
-        if (result == TIZEN_ERROR_NO_DATA)
+        if (result == ShmError::NO_DATA)
           continue;
-        else if (result != TIZEN_ERROR_NONE)
+        else if (result != ShmError::NONE)
           return PMINFO_R_ERROR;
       } else {
         if (filter_checker.Check(*handle))
@@ -98,10 +123,10 @@ int ShmPkgReader::GetHandles(pkgmgrinfo_filter_x* filter,
       }
     }
   } else {
-    for (auto& reader : readers_) {
-      int result;
-      auto handles = reader.GetHandles(&result);
-      if (!handles && result != TIZEN_ERROR_NONE)
+    for (auto reader : readers_) {
+      ShmError result;
+      auto handles = reader->GetHandles(&result);
+      if (!handles && result != ShmError::NONE)
         return PMINFO_R_ERROR;
 
       if (!handles)
@@ -117,13 +142,9 @@ int ShmPkgReader::GetHandles(pkgmgrinfo_filter_x* filter,
 }
 
 std::optional<PkgInfoHandle> ShmPkgReader::GetHandle(const char* pkgid) {
-  for (auto& reader : readers_) {
-    if (!reader.Init()) {
-      LOGE("reader.Init() fail");
-      continue;
-    }
-    int result;
-    auto handle = reader.GetHandle(pkgid, &result);
+  for (auto reader : readers_) {
+    ShmError result;
+    auto handle = reader->GetHandle(pkgid, &result);
     if (handle)
       return handle;
   }
@@ -133,32 +154,10 @@ std::optional<PkgInfoHandle> ShmPkgReader::GetHandle(const char* pkgid) {
 
 ShmPkgReader::ShmPkgReader(uid_t uid) {
   readers_.emplace_back(
-      ShmNameProvider::PkgConfig(uid),
-      ShmNameProvider::PkgHandle(uid),
-      ShmNameProvider::PkgIndexs(uid),
-      ShmNameProvider::PkgKeys(uid));
+      ShmPkgReader::ShmPkgReaderProvider::GetReader(uid));
   if (uid > REGULAR_USER)
     readers_.emplace_back(
-        ShmNameProvider::PkgConfig(GLOBAL_USER),
-        ShmNameProvider::PkgHandle(GLOBAL_USER),
-        ShmNameProvider::PkgIndexs(GLOBAL_USER),
-        ShmNameProvider::PkgKeys(GLOBAL_USER));
-}
-
-bool ShmPkgReader::Init() {
-  if (_is_writer()) {
-    LOGD("process(%d) is writer", getpid());
-    return false;
-  }
-
-  for (auto& reader : readers_) {
-    if (!reader.Init()) {
-      LOGE("Init reader fail");
-      return false;
-    }
-  }
-
-  return true;
+        ShmPkgReader::ShmPkgReaderProvider::GetReader(GLOBAL_USER));
 }
 
 bool ShmPkgReader::FilterChecker::Init(pkgmgrinfo_filter_x* filter) {
@@ -212,5 +211,25 @@ const char* ShmPkgReader::FilterChecker::PkgIdFilterValue() {
   return pkgid_filter_;
 }
 
+ShmReader<PkgInfoHandle>*
+    ShmPkgReader::ShmPkgReaderProvider::GetReader(uid_t uid) {
+  static std::shared_mutex lock_;
+  std::shared_lock<std::shared_mutex> s(lock_);
+
+  uid = ConvertUID(uid);
+  auto it = readers_map_.find(uid);
+  if (it != readers_map_.end())
+    return it->second;
+
+  s.unlock();
+  std::unique_lock<std::shared_mutex> u(lock_);
+  auto* prov = readers_map_[uid];
+  if (prov == nullptr)
+    readers_map_[uid] =
+        new ShmReader<PkgInfoHandle>(PKG_SHM_PREFIX + std::to_string(uid));
+
+  return readers_map_[uid];
+}
+
 }  // namespace shared_memory
 }  // namespace pkgmgr_common
index 54f04776667641d248d4893aa15101aa6131ba56..cde723499d366015e9cdbc59023c57b4c1033bf5 100644 (file)
@@ -21,7 +21,6 @@ class EXPORT_API ShmPkgReader {
  public:
   ShmPkgReader(uid_t uid);
 
-  bool Init();
   int GetHandles(pkgmgrinfo_filter_x* filter,
       std::map<std::string, PkgInfoHandle>& list);
   std::optional<PkgInfoHandle> GetHandle(const char* pkgid);
@@ -39,8 +38,19 @@ class EXPORT_API ShmPkgReader {
     std::vector<std::pair<IPkgFilterChecker*, const char*>> filter_checker_;
   };
 
+  class EXPORT_API ShmPkgReaderProvider {
+   public:
+    ShmPkgReaderProvider() = delete;
+
+    static ShmReader<PkgInfoHandle>* GetReader(uid_t uid);
+
+   private:
+    static inline std::unordered_map<uid_t,
+        ShmReader<PkgInfoHandle>*> readers_map_;
+  };
+
  private:
-  std::vector<ShmReader<PkgInfoHandle>> readers_;
+  std::vector<ShmReader<PkgInfoHandle>*> readers_;
 };
 
 }  // namespace shared_memory
index f4ff3e754fa39977abfa81d45364ec9678a793ec..067faeb6c5ac454568ab04f152c24d441d4053bd 100644 (file)
@@ -37,84 +37,148 @@ namespace pkgmgr_common {
 namespace shared_memory {
 
 template<typename T>
-bool ShmReader<T>::Init() {
-  if (!config_handler_.Load()) {
-    LOGE("Failed to load config handler");
-    return false;
+std::optional<ShmLockGuard> ShmReader<T>::Load(ShmError* result,
+    std::shared_lock<std::shared_mutex>& s) {
+  *result = config_handler_.Load();
+  if (*result != ShmError::NONE)
+    return std::nullopt;
+
+  if (!config_handler_.GetIsValid()) {
+    do {
+      LOGW("config is not valid, reload");
+      s.unlock();
+      std::unique_lock<std::shared_mutex> u(lock_);
+      if (config_handler_.GetIsValid()) {
+        u.unlock();
+        s.lock();
+        break;
+      }
+
+      ShmError ret = ShmError::NONE;
+      ret = config_handler_.Unload();
+      if (ret != ShmError::NONE)
+        LOGE("config_handler_.Unload() fail");
+
+      ret = handle_mapper_.Unload();
+      if (ret != ShmError::NONE)
+        LOGE("handle_mapper_.Unload() fail");
+
+      ret = index_mapper_.Unload();
+      if (ret != ShmError::NONE)
+        LOGE("index_mapper_.Unload() fail");
+
+      ret = key_mapper_.Unload();
+      if (ret != ShmError::NONE)
+        LOGE("key_mapper_.Unload() fail");
+
+      if (ret != ShmError::NONE) {
+        *result = ret;
+        return std::nullopt;
+      }
+
+      ret = config_handler_.Load();
+      if (ret != ShmError::NONE) {
+        *result = ret;
+        return std::nullopt;
+      }
+
+      u.unlock();
+      s.lock();
+
+      if (!config_handler_.GetIsValid()) {
+        LOGW("config is not valid, reload");
+        *result = ShmError::SYSTEM;
+        return std::nullopt;
+      }
+    } while (0);
+  }
+
+  auto read_lock = config_handler_.GetReadLock();
+  if (!read_lock) {
+    LOGE("Fail to get read lock");
+    *result = ShmError::READ_LOCK;
+    return std::nullopt;
+  }
+
+  *result = handle_mapper_.LoadAll();
+  if (*result != ShmError::NONE) {
+    LOGE("Failed to load handle");
+    return std::nullopt;
   }
 
-  int ret = config_handler_.GetReadLock();
-  if (ret != 0) {
-    LOGE("Fail to get read lock, %d", ret);
-    return false;
+  *result = index_mapper_.LoadAll();
+  if (*result != ShmError::NONE) {
+    LOGE("Failed to load index");
+    return std::nullopt;
   }
 
-  auto indexs = ReadIndexs();
-  if (!indexs) {
-    LOGE("Failed to get pkg indexs");
-    return false;
+  *result = key_mapper_.LoadAll();
+  if (*result != ShmError::NONE) {
+    LOGE("Failed to load key");
+    return std::nullopt;
   }
 
-  mapping_data_ = std::move(*indexs);
+  *result = ShmError::NONE;
 
-  return true;
+  return read_lock;
 }
 
 template<typename T>
-std::optional<std::vector<T>> ShmReader<T>::GetHandles(int* result) {
+std::optional<std::vector<T>> ShmReader<T>::GetHandles(ShmError* result) {
+  std::shared_lock<std::shared_mutex> s(lock_);
+  auto lock = Load(result, s);
+  if (!lock)
+    return std::nullopt;
+
   return ReadHandles(result);
 }
 
 template<typename T>
-std::optional<T> ShmReader<T>::GetHandle(const char* key, int* result) {
-  int index = FindIndex(key, result);
-  if (index < 0)
+std::optional<T> ShmReader<T>::GetHandle(const char* key, ShmError* result) {
+  std::shared_lock<std::shared_mutex> s(lock_);
+  auto lock = Load(result, s);
+  if (!lock)
+    return std::nullopt;
+
+  HandleMappingData* index_ptr = FindIndex(key, result);
+  if (!index_ptr) {
+    LOGD("Can't get index by key[%s]", key);
     return std::nullopt;
+  }
 
-  auto handle = ReadHandle(mapping_data_[index].index, mapping_data_[index].len);
+  auto handle = ReadHandle(index_ptr->index, index_ptr->len);
   if (!handle) {
     LOGE("Failed to read app");
-    *result = TIZEN_ERROR_IO_ERROR;
+    *result = ShmError::SYSTEM;
     return std::nullopt;
   }
 
-  *result = TIZEN_ERROR_NONE;
-  return std::move(*handle);
+  *result = ShmError::NONE;
+  return handle;
 }
 
 template<typename T>
-std::optional<std::vector<T>> ShmReader<T>::ReadHandles(int* result) {
-  if (!result)
-    return std::nullopt;
-  *result = TIZEN_ERROR_NONE;
-
-  auto indexs = ReadIndexs();
-  if (!indexs) {
-    LOGE("Failed to get app indexs");
-    *result = TIZEN_ERROR_IO_ERROR;
+std::optional<std::vector<T>> ShmReader<T>::ReadHandles(ShmError* result) {
+  if (!result) {
+    LOGE("Invalid parameter");
     return std::nullopt;
   }
 
-  if (indexs->empty()) {
-    LOGD("The app doesn't exist");
-    return std::vector<T>{};
-  }
-
-  if(!handle_mapper_.Init()) {
-    *result = TIZEN_ERROR_IO_ERROR;
-    return std::nullopt;
-  }
+  *result = ShmError::NONE;
 
-  size_t mapping_len = GetMemSize();
-  if(!handle_mapper_.LoadAll(mapping_len)) {
-    *result = TIZEN_ERROR_IO_ERROR;
-    return std::nullopt;
+  if (index_mapper_.GetMemSize() == 0) {
+    LOGD("Empty Shm Data");
+    return std::vector<T>{};
   }
 
   std::vector<T> handles;
   uint8_t* ptr = handle_mapper_.GetPtr();
-  for (const auto& mapping : *indexs)
-    handles.emplace_back(std::make_unique<tizen_base::Parcel>(ptr + mapping.index, mapping.len, true));
+  auto index_ptr = (HandleMappingData*)index_mapper_.GetPtr();
+  auto end_ptr =
+      (HandleMappingData*)(index_mapper_.GetPtr() + index_mapper_.GetMemSize());
+  for (; index_ptr != end_ptr; index_ptr++)
+    handles.emplace_back(std::make_unique<tizen_base::Parcel>(
+        ptr + index_ptr->index, index_ptr->len, true));
 
   return handles;
 }
@@ -122,117 +186,33 @@ std::optional<std::vector<T>> ShmReader<T>::ReadHandles(int* result) {
 template<typename T>
 std::optional<T> ShmReader<T>::ReadHandle(
     uint32_t index, uint32_t len) {
-  if (mapping_data_.empty()) {
-    LOGD("The handle doesn't exist");
-    return std::nullopt;
-  }
-
-  if(!handle_mapper_.Init()) {
-    return std::nullopt;
-  }
-
-  uint8_t* ptr = handle_mapper_.CopyPartial(index, len);
-  if (ptr == nullptr) {
-    return std::nullopt;
-  }
-
-  return T(std::make_unique<tizen_base::Parcel>(ptr, len, false));
+  return T(std::make_unique<tizen_base::Parcel>(
+      handle_mapper_.GetPtr() + index, len, true));
 }
 
 template<typename T>
-std::optional<std::vector<HandleMappingData>> ShmReader<T>::ReadIndexs() {
-  size_t indexs_len = GetIndexMemSize();
-  if (indexs_len == 0) {
-    LOGD("Empty index");
-    return std::vector<HandleMappingData>{};
-  }
-
-  if (indexs_len % sizeof(HandleMappingData) != 0) {
-    LOGE("Invalid app indexs size : %zu", indexs_len);
-    return std::nullopt;
-  }
-  int index_count = indexs_len / sizeof(HandleMappingData);
-
-  if(!index_mapper_.Init()) {
-    return std::nullopt;
-  }
-
-  if(!index_mapper_.LoadAll(indexs_len)) {
-    return std::nullopt;
-  }
-
-  std::vector<HandleMappingData> result;
-  auto ptr = (HandleMappingData*)index_mapper_.GetPtr();
-  while(index_count--) {
-    result.emplace_back(HandleMappingData {
-      .key_index = ptr->key_index,
-      .index = ptr->index,
-      .len = ptr->len
-    });
-    ptr++;
-  }
-
-  return result;
-}
-
-template<typename T>
-int ShmReader<T>::FindIndex(const char* key, int* result) {
-  if (mapping_data_.empty()) {
-    LOGD("The pkg doesn't exist");
-    *result = TIZEN_ERROR_NO_DATA;
-    return -1;
-  }
-
-  if(!key_mapper_.Init()) {
-    *result = TIZEN_ERROR_IO_ERROR;
-    return -1;
-  }
-
-  size_t mapping_len = GetKeyMemSize();
-  if(!key_mapper_.LoadAll(mapping_len)) {
-    *result = TIZEN_ERROR_IO_ERROR;
-    return -1;
-  }
-
-  std::vector<const char*> keys;
-  const char* ptr = reinterpret_cast<const char*>(key_mapper_.GetPtr());
-  for (const auto& mapping : mapping_data_)
-    keys.emplace_back(ptr + mapping.key_index);
+HandleMappingData* ShmReader<T>::FindIndex(const char* key, ShmError* result) {
+  const char* key_ptr = reinterpret_cast<const char*>(key_mapper_.GetPtr());
+  auto index_ptr = reinterpret_cast<HandleMappingData*>(index_mapper_.GetPtr());
 
   int l = 0;
-  int r = keys.size();
-  int index = -1;
-
+  int r = index_mapper_.GetMemSize() / sizeof(HandleMappingData);
+  HandleMappingData* result_ptr = nullptr;
   while (l < r) {
     int mid = (l + r) / 2;
-    int result = strcmp(key, keys[mid]);
-    if (result == 0) {
-      index = mid;
+    int cmp_result = strcmp(key, key_ptr + (index_ptr[mid].key_index));
+    if (cmp_result == 0) {
+      result_ptr = index_ptr + mid;
       break;
-    } else if (result < 0) {
+    } else if (cmp_result < 0) {
       r = mid;
     } else {
       l = mid+1;
     }
   }
 
-  *result = TIZEN_ERROR_NONE;
-  return index;
-}
-
-template<typename T>
-size_t ShmReader<T>::GetMemSize() const {
-  return config_handler_.GetMemSize();
-}
-
-template<typename T>
-size_t ShmReader<T>::GetIndexMemSize() const {
-  return config_handler_.GetIndexMemSize();
-}
-
-template<typename T>
-size_t ShmReader<T>::GetKeyMemSize() const {
-  return config_handler_.GetKeyMemSize();
+  *result = ShmError::NONE;
+  return result_ptr;
 }
 
 }  // namespace shared_memory
index 431a03a75f2698e389be52c3445e47bcc165f0e2..e1f8676dc30fe38c5577b5e3950f2385884886cd 100644 (file)
@@ -1,7 +1,9 @@
 #ifndef COMMON_SHM_READER_HH_
 #define COMMON_SHM_READER_HH_
 
+#include <mutex>
 #include <optional>
+#include <shared_mutex>
 #include <vector>
 
 #include "pkgmgr_info_handle.hh"
@@ -18,32 +20,29 @@ namespace shared_memory {
 template<typename T>
 class EXPORT_API ShmReader {
  public:
-  ShmReader(const char* config_shm_name,
-      const char* handle_shm_name, const char* index_shm_name,
-      const char* key_shm_name) :
-          config_handler_(config_shm_name),
-          handle_mapper_(handle_shm_name),
-          index_mapper_(index_shm_name),
-          key_mapper_(key_shm_name) {}
-  bool Init();
-  std::optional<std::vector<T>> GetHandles(int* result);
-  std::optional<T> GetHandle(const char* key, int* result);
+  ShmReader(std::string base_name) :
+      base_name_(std::move(base_name)),
+      config_handler_(base_name_ + "_config"),
+      handle_mapper_(base_name_ + "_handle"),
+      index_mapper_(base_name_ + "_indexs"),
+      key_mapper_(base_name_ + "_keys") {}
+  std::optional<std::vector<T>> GetHandles(ShmError* result);
+  std::optional<T> GetHandle(const char* key, ShmError* result);
 
  private:
-  std::optional<std::vector<HandleMappingData>> ReadIndexs();
-  std::optional<std::vector<T>> ReadHandles(int* result);
+  std::optional<ShmLockGuard> Load(ShmError* result,
+      std::shared_lock<std::shared_mutex>& s);
+  std::optional<std::vector<T>> ReadHandles(ShmError* result);
   std::optional<T> ReadHandle(uint32_t index, uint32_t len);
-  int FindIndex(const char* key, int* result);
-  size_t GetMemSize() const;
-  size_t GetIndexMemSize() const;
-  size_t GetKeyMemSize() const;
+  HandleMappingData* FindIndex(const char* key, ShmError* result);
 
  protected:
-  std::vector<HandleMappingData> mapping_data_;
+  std::string base_name_;
   ShmConfigHandler config_handler_;
   ShmReadMapper handle_mapper_;
   ShmReadMapper index_mapper_;
   ShmReadMapper key_mapper_;
+  std::shared_mutex lock_;
 };
 
 template class ShmReader<PkgInfoHandle>;
index 4e84974214bc09e4ecfb4bd9d58fb492a5a06b9e..7bc6e3beaf44fc1c1bd0fc5a0ebe87b7c8ab9a4b 100644 (file)
@@ -89,12 +89,17 @@ static int _pkgmgrinfo_get_appinfo(const char *appid, uid_t uid,
   }
 
   int ret = PMINFO_R_OK;
-  ps::ShmAppReader reader(uid);
   std::map<std::string, pc::AppInfoHandle> list;
   pkgmgr_appinfo_x *info;
 
-  if (reader.Init()) {
+  if (!_is_writer()) {
+    ps::ShmAppReader reader(uid);
     ret = reader.GetHandles(reinterpret_cast<pkgmgrinfo_filter_x*>(filter), list);
+    if (ret != PMINFO_R_OK) {
+      ret = _appinfo_get_applications(uid,
+          reinterpret_cast<pkgmgrinfo_filter_x*>(filter),
+          PMINFO_APPINFO_GET_ALL, &list);
+    }
   } else {
     ret = _appinfo_get_applications(uid,
         reinterpret_cast<pkgmgrinfo_filter_x*>(filter),
@@ -320,14 +325,21 @@ static int _appinfo_get_filtered_foreach_appinfo(uid_t uid,
 {
   int ret;
   pkgmgr_appinfo_x info;
-  ps::ShmAppReader reader(uid);
   std::map<std::string, pc::AppInfoHandle> list;
-  if (reader.Init())
+
+  if (!_is_writer()) {
+    ps::ShmAppReader reader(uid);
     ret = reader.GetHandles(reinterpret_cast<pkgmgrinfo_filter_x*>(filter), list);
-  else
+    if (ret != PMINFO_R_OK) {
+      ret = _appinfo_get_applications(uid,
+          reinterpret_cast<pkgmgrinfo_filter_x*>(filter),
+          PMINFO_APPINFO_GET_ALL, &list);
+    }
+  } else {
     ret = _appinfo_get_applications(uid,
         reinterpret_cast<pkgmgrinfo_filter_x*>(filter),
         PMINFO_APPINFO_GET_ALL, &list);
+  }
   if (ret == PMINFO_R_ERROR)
     return ret;
 
@@ -2170,15 +2182,21 @@ API int pkgmgrinfo_appinfo_usr_filter_count(
       return PMINFO_R_ERROR;
   }
 
-  ps::ShmAppReader reader(uid);
   std::map<std::string, pc::AppInfoHandle> list;
 
-  if (reader.Init())
+  if (!_is_writer()) {
+    ps::ShmAppReader reader(uid);
     ret = reader.GetHandles(reinterpret_cast<pkgmgrinfo_filter_x*>(filter), list);
-  else
+    if (ret != PMINFO_R_OK) {
+      ret = _appinfo_get_applications(uid,
+          reinterpret_cast<pkgmgrinfo_filter_x*>(filter),
+          PMINFO_APPINFO_GET_ALL, &list);
+    }
+  } else {
     ret = _appinfo_get_applications(uid,
         reinterpret_cast<pkgmgrinfo_filter_x*>(filter),
-        0, &list);
+        PMINFO_APPINFO_GET_ALL, &list);
+  }
   if (ret == PMINFO_R_ERROR)
     return ret;
 
index b6d5b692486490be68a635ae1799eaa4d4264aae..1861b61f23eb5854fb00a9ef7e525de4ace321d7 100644 (file)
@@ -126,7 +126,6 @@ static int _pkginfo_get_filtered_foreach_pkginfo(uid_t uid,
     pkgmgrinfo_pkg_list_cb pkg_list_cb, void *user_data)
 {
   int ret;
-  ps::ShmPkgReader reader(uid);
   std::map<std::string, pc::PkgInfoHandle> list;
   pkgmgr_pkginfo_x info;
 
@@ -138,12 +137,20 @@ static int _pkginfo_get_filtered_foreach_pkginfo(uid_t uid,
       return PMINFO_R_ERROR;
     }
   }
-  if (reader.Init())
+
+  if (!_is_writer()) {
+    ps::ShmPkgReader reader(uid);
     ret = reader.GetHandles(reinterpret_cast<pkgmgrinfo_filter_x*>(filter), list);
-  else
+    if (ret != PMINFO_R_OK) {
+      ret = _pkginfo_get_packages(uid,
+          reinterpret_cast<pkgmgrinfo_filter_x*>(filter),
+          PMINFO_PKGINFO_GET_ALL, &list);
+    }
+  } else {
     ret = _pkginfo_get_packages(uid,
         reinterpret_cast<pkgmgrinfo_filter_x*>(filter),
         PMINFO_PKGINFO_GET_ALL, &list);
+  }
   if (ret == PMINFO_R_ERROR)
     return ret;
 
@@ -167,10 +174,15 @@ static int _pkgmgrinfo_get_pkginfo(const char *pkgid, uid_t uid,
   }
 
   int ret;
-  ps::ShmPkgReader reader(uid);
   std::map<std::string, pc::PkgInfoHandle> list;
-  if (reader.Init()) {
+  if (!_is_writer()) {
+    ps::ShmPkgReader reader(uid);
     ret = reader.GetHandles(reinterpret_cast<pkgmgrinfo_filter_x*>(filter), list);
+    if (ret != PMINFO_R_OK) {
+      ret = _pkginfo_get_packages(uid,
+          reinterpret_cast<pkgmgrinfo_filter_x*>(filter),
+          PMINFO_PKGINFO_GET_ALL, &list);
+    }
   } else {
     ret = _pkginfo_get_packages(uid,
         reinterpret_cast<pkgmgrinfo_filter_x*>(filter),
@@ -1349,7 +1361,6 @@ API int pkgmgrinfo_pkginfo_filter_add_string(pkgmgrinfo_pkginfo_filter_h handle,
 API int pkgmgrinfo_pkginfo_usr_filter_count(pkgmgrinfo_pkginfo_filter_h filter, int *count, uid_t uid)
 {
   int ret;
-  ps::ShmPkgReader reader(uid);
   std::map<std::string, pc::PkgInfoHandle> list;
 
   if (filter == NULL || count == NULL) {
@@ -1364,12 +1375,19 @@ API int pkgmgrinfo_pkginfo_usr_filter_count(pkgmgrinfo_pkginfo_filter_h filter,
       return PMINFO_R_ERROR;
   }
 
-  if (reader.Init())
+  if (!_is_writer()) {
+    ps::ShmPkgReader reader(uid);
     ret = reader.GetHandles(reinterpret_cast<pkgmgrinfo_filter_x*>(filter), list);
-  else
+    if (ret != PMINFO_R_OK) {
+      ret = _pkginfo_get_packages(uid,
+          reinterpret_cast<pkgmgrinfo_filter_x*>(filter),
+          PMINFO_PKGINFO_GET_ALL, &list);
+    }
+  } else {
     ret = _pkginfo_get_packages(uid,
         reinterpret_cast<pkgmgrinfo_filter_x*>(filter),
         PMINFO_PKGINFO_GET_ALL, &list);
+  }
   if (ret == PMINFO_R_ERROR)
     return ret;
   *count = list.size();
index f52e62a861ae05ef58da6c33d00efd6cda45c6f8..c669d70a92d614a1234e6044361c11299e7c02ab 100644 (file)
 
 namespace {
 
-char* GetCString(int idx, const tizen_base::Database::Result::Record& rec) {
-  std::optional<std::string> str = rec.GetString(idx);
-  if (!str)
-    return nullptr;
-
-  return strdup(str->c_str());
-}
-
-const char* GetCString2(int idx, const tizen_base::Database::Result::Record& rec) {
+const char* GetCString(int idx, const tizen_base::Database::Result::Record& rec) {
   return rec.GetCString(idx);
 }
 
@@ -67,12 +59,12 @@ int GetSplashScreens(const tizen_base::Database& db,
   auto& list_writer = writer.GetSplashscreensListWriter();
   for (const auto& rec : r) {
     list_writer.AddItem()
-        .WriteSrc(GetCString2(0, rec))
-        .WriteType(GetCString2(1, rec))
-        .WriteOrientation(GetCString2(2, rec))
-        .WriteIndicatordisplay(GetCString2(3, rec))
-        .WriteOperation(GetCString2(4, rec))
-        .WriteColorDepth(GetCString2(5, rec));
+        .WriteSrc(GetCString(0, rec))
+        .WriteType(GetCString(1, rec))
+        .WriteOrientation(GetCString(2, rec))
+        .WriteIndicatordisplay(GetCString(3, rec))
+        .WriteOperation(GetCString(4, rec))
+        .WriteColorDepth(GetCString(5, rec));
   }
 
   return PMINFO_R_OK;
@@ -93,7 +85,7 @@ void GetAppControlPrivileges(const tizen_base::Database& db,
     _LOGE("db.Exec() failed: %s", static_cast<const char*>(r));
 
   for (const auto& rec : r) {
-    const char* val = GetCString2(0, rec);
+    const char* val = GetCString(0, rec);
     if (val)
       writer.Write(val);
   }
@@ -115,8 +107,8 @@ int GetMetadata(const tizen_base::Database& db,
   auto& list_writer = writer.GetMetadataListWriter();
   for (const auto& rec : r) {
     list_writer.AddItem()
-        .WriteKey(GetCString2(0, rec))
-        .WriteValue(GetCString2(1, rec));
+        .WriteKey(GetCString(0, rec))
+        .WriteValue(GetCString(1, rec));
   }
 
   return PMINFO_R_OK;
@@ -174,8 +166,8 @@ int GetAppControl(const tizen_base::Database& db,
   }
 
   for (const auto& rec : r) {
-    ParseAppControl(db, writer, GetCString2(0, rec),
-        GetCString2(1, rec), GetCString2(2, rec), appid);
+    ParseAppControl(db, writer, GetCString(0, rec),
+        GetCString(1, rec), GetCString(2, rec), appid);
   }
 
   return PMINFO_R_OK;
@@ -195,7 +187,7 @@ int GetCategory(const tizen_base::Database& db,
 
   auto& list_writer = writer.GetCategoryListWriter();
   for (const auto& rec : r) {
-    const char* val = GetCString2(0, rec);
+    const char* val = GetCString(0, rec);
     if (val)
       list_writer.Write(val);
   }
@@ -220,10 +212,10 @@ int GetResControl(const tizen_base::Database& db, const char* appid,
   auto& list_writer = writer.GetResControlListWriter();
   for (const auto& rec : r) {
     list_writer.AddItem()
-        .WriteResType(GetCString2(0, rec))
-        .WriteMinResVersion(GetCString2(1, rec))
-        .WriteMaxResVersion(GetCString2(2, rec))
-        .WriteAutoClose(GetCString2(3, rec));
+        .WriteResType(GetCString(0, rec))
+        .WriteMinResVersion(GetCString(1, rec))
+        .WriteMaxResVersion(GetCString(2, rec))
+        .WriteAutoClose(GetCString(3, rec));
   }
 
   return PMINFO_R_OK;
@@ -561,55 +553,55 @@ int DoGetAppInfo(const tizen_base::Database& db, uid_t db_uid, uid_t uid,
     const char* is_disabled = nullptr;
     const char* splash_screen_display = nullptr;
 
-    writer.WriteAppId(appid = GetCString2(idx++, rec));
-    writer.WriteInstalledStorage(installed_storage = GetCString2(idx++, rec));
-    writer.WriteExternalPath(external_path = GetCString2(idx++, rec));
-    is_disabled = GetCString2(idx++, rec);
+    writer.WriteAppId(appid = GetCString(idx++, rec));
+    writer.WriteInstalledStorage(installed_storage = GetCString(idx++, rec));
+    writer.WriteExternalPath(external_path = GetCString(idx++, rec));
+    is_disabled = GetCString(idx++, rec);
     if (flag & PMINFO_APPINFO_GET_BASICINFO) {
       writer.WriteIsDisabled(is_disabled);
-      writer.WriteComponent(GetCString2(idx++, rec));
-      writer.WriteExec(GetCString2(idx++, rec));
-      writer.WriteNodisplay(GetCString2(idx++, rec));
-      writer.WriteType(GetCString2(idx++, rec));
-      writer.WriteOnboot(GetCString2(idx++, rec));
-      writer.WriteMultiple(GetCString2(idx++, rec));
-      writer.WriteAutoRestart(GetCString2(idx++, rec));
-      writer.WriteTaskManage(GetCString2(idx++, rec));
-      writer.WriteHwAcceleration(GetCString2(idx++, rec));
-      writer.WriteScreenReader(GetCString2(idx++, rec));
-      writer.WriteMainApp(GetCString2(idx++, rec));
-      writer.WriteRecentimage(GetCString2(idx++, rec));
-      writer.WriteLaunchCondition(GetCString2(idx++, rec));
-      writer.WriteIndicatorDisplay(GetCString2(idx++, rec));
-      writer.WritePortraitImg(GetCString2(idx++, rec));
-      writer.WriteLandscapeImg(GetCString2(idx++, rec));
-      writer.WriteGuestModeVisibility(GetCString2(idx++, rec));
-      writer.WritePermissionType(GetCString2(idx++, rec));
-      writer.WritePreload(GetCString2(idx++, rec));
-      writer.WriteSubmode(GetCString2(idx++, rec));
-      writer.WriteSubmodeMainId(GetCString2(idx++, rec));
-      writer.WriteLaunchMode(GetCString2(idx++, rec));
-      writer.WriteUiGadget(GetCString2(idx++, rec));
-      writer.WriteSupportDisable(GetCString2(idx++, rec));
-      writer.WriteProcessPool(GetCString2(idx++, rec));
-      __get_background_category(GetCString2(idx++, rec), writer);
-      writer.WritePackageType(GetCString2(idx++, rec));
-      writer.WriteRootPath(GetCString2(idx++, rec));
-      writer.WriteApiVersion(GetCString2(idx++, rec));
-      writer.WriteEffectiveAppId(GetCString2(idx++, rec));
-      writer.WriteSplashScreenDisplay(splash_screen_display = GetCString2(idx++, rec));
-      writer.WriteTepName(GetCString2(idx++, rec));
-      writer.WriteZipMountFile(GetCString2(idx++, rec));
-      writer.WriteComponentType(GetCString2(idx++, rec));
-      package = GetCString2(idx++, rec);
+      writer.WriteComponent(GetCString(idx++, rec));
+      writer.WriteExec(GetCString(idx++, rec));
+      writer.WriteNodisplay(GetCString(idx++, rec));
+      writer.WriteType(GetCString(idx++, rec));
+      writer.WriteOnboot(GetCString(idx++, rec));
+      writer.WriteMultiple(GetCString(idx++, rec));
+      writer.WriteAutoRestart(GetCString(idx++, rec));
+      writer.WriteTaskManage(GetCString(idx++, rec));
+      writer.WriteHwAcceleration(GetCString(idx++, rec));
+      writer.WriteScreenReader(GetCString(idx++, rec));
+      writer.WriteMainApp(GetCString(idx++, rec));
+      writer.WriteRecentimage(GetCString(idx++, rec));
+      writer.WriteLaunchCondition(GetCString(idx++, rec));
+      writer.WriteIndicatorDisplay(GetCString(idx++, rec));
+      writer.WritePortraitImg(GetCString(idx++, rec));
+      writer.WriteLandscapeImg(GetCString(idx++, rec));
+      writer.WriteGuestModeVisibility(GetCString(idx++, rec));
+      writer.WritePermissionType(GetCString(idx++, rec));
+      writer.WritePreload(GetCString(idx++, rec));
+      writer.WriteSubmode(GetCString(idx++, rec));
+      writer.WriteSubmodeMainId(GetCString(idx++, rec));
+      writer.WriteLaunchMode(GetCString(idx++, rec));
+      writer.WriteUiGadget(GetCString(idx++, rec));
+      writer.WriteSupportDisable(GetCString(idx++, rec));
+      writer.WriteProcessPool(GetCString(idx++, rec));
+      __get_background_category(GetCString(idx++, rec), writer);
+      writer.WritePackageType(GetCString(idx++, rec));
+      writer.WriteRootPath(GetCString(idx++, rec));
+      writer.WriteApiVersion(GetCString(idx++, rec));
+      writer.WriteEffectiveAppId(GetCString(idx++, rec));
+      writer.WriteSplashScreenDisplay(splash_screen_display = GetCString(idx++, rec));
+      writer.WriteTepName(GetCString(idx++, rec));
+      writer.WriteZipMountFile(GetCString(idx++, rec));
+      writer.WriteComponentType(GetCString(idx++, rec));
+      package = GetCString(idx++, rec);
       writer.WritePackage(package);
-      writer.WritePackageSystem(GetCString2(idx++, rec));
-      writer.WriteRemovable(GetCString2(idx++, rec));
-      writer.WritePackageInstalledTime(GetCString2(idx++, rec));
-      writer.WriteSupportMode(GetCString2(idx++, rec));
-      writer.WriteSupportAmbient(GetCString2(idx++, rec));
-      writer.WriteSetupAppId(GetCString2(idx++, rec));
-      writer.WriteLightUserSwitchMode(GetCString2(idx++, rec));
+      writer.WritePackageSystem(GetCString(idx++, rec));
+      writer.WriteRemovable(GetCString(idx++, rec));
+      writer.WritePackageInstalledTime(GetCString(idx++, rec));
+      writer.WriteSupportMode(GetCString(idx++, rec));
+      writer.WriteSupportAmbient(GetCString(idx++, rec));
+      writer.WriteSetupAppId(GetCString(idx++, rec));
+      writer.WriteLightUserSwitchMode(GetCString(idx++, rec));
     }
 
     writer.WriteForAllUsers((db_uid != global_user_uid) ? "false" : "true");
@@ -617,14 +609,14 @@ int DoGetAppInfo(const tizen_base::Database& db, uid_t db_uid, uid_t uid,
     if (db_uid != global_user_uid) {
       idx = idx + 2;
     } else {
-      tmp_record = GetCString2(idx++, rec);
+      tmp_record = GetCString(idx++, rec);
       if (tmp_record != nullptr) {
         if (is_disabled &&
             strcasecmp(is_disabled, "false") == 0 &&
             strcasecmp(tmp_record, "false") == 0)
           writer.WriteIsDisabled(tmp_record);
       }
-      tmp_record = GetCString2(idx++, rec);
+      tmp_record = GetCString(idx++, rec);
       if (tmp_record != nullptr) {
         if (splash_screen_display &&
             strcasecmp(splash_screen_display, "false") == 0 &&
@@ -636,17 +628,17 @@ int DoGetAppInfo(const tizen_base::Database& db, uid_t db_uid, uid_t uid,
     if (flag & PMINFO_APPINFO_GET_LABEL) {
       auto& list_writer = writer.GetLabelListWriter();
       list_writer.AddItem()
-          .WriteText(GetCString2(idx++, rec))
+          .WriteText(GetCString(idx++, rec))
           .WriteLang(locale);
     }
 
     if (flag & PMINFO_APPINFO_GET_ICON) {
       auto& list_writer = writer.GetIconListWriter();
       list_writer.AddItem()
-          .WriteText(GetCString2(idx++, rec))
+          .WriteText(GetCString(idx++, rec))
           .WriteLang(locale);
     }
-    tmp_record = GetCString2(idx++, rec);
+    tmp_record = GetCString(idx++, rec);
     if (tmp_record) {
       writer.WriteIsPackageDisabled(tmp_record);
       if (pkg_disable_filter_status != PackageDisableFilterStatus::None) {
index 03915a6d461750b942297e9bc3651421573f261c..eb6569e3e7a974e561a78b56d4aec448191f9377 100644 (file)
@@ -80,7 +80,8 @@ constexpr const char join_metadata[] =
   " LEFT OUTER JOIN package_metadata"
   "  ON pi.package=package_metadata.package";
 
-char* GetCString(int idx, const tizen_base::Database::Result::Record& rec) {
+char* GetAllocatedCString(int idx,
+    const tizen_base::Database::Result::Record& rec) {
   std::optional<std::string> str = rec.GetString(idx);
   if (!str)
     return nullptr;
@@ -88,7 +89,7 @@ char* GetCString(int idx, const tizen_base::Database::Result::Record& rec) {
   return strdup(str->c_str());
 }
 
-const char* GetCString2(int idx, const tizen_base::Database::Result::Record& rec) {
+const char* GetCString(int idx, const tizen_base::Database::Result::Record& rec) {
   return rec.GetCString(idx);
 }
 
@@ -108,10 +109,10 @@ int GetPluginExecutionInfo(const tizen_base::Database& db,
   auto& plugin_writer = writer.GetPluginListWriter();
   for (const auto& rec : r) {
     plugin_writer.AddItem()
-      .WritePkgid(GetCString2(0, rec))
-      .WriteAppid(GetCString2(1, rec))
-      .WritePluginType(GetCString2(2, rec))
-      .WritePluginName(GetCString2(3, rec));
+      .WritePkgid(GetCString(0, rec))
+      .WriteAppid(GetCString(1, rec))
+      .WritePluginType(GetCString(2, rec))
+      .WritePluginName(GetCString(3, rec));
   }
 
   return PMINFO_R_OK;
@@ -132,8 +133,8 @@ int GetPrivilege(const tizen_base::Database& db, const char* pkgid,
   auto& privilege_list_writer = writer.GetPrivilegesListWriter();
   for (const auto& rec : r) {
     privilege_list_writer.AddItem()
-        .WriteValue(GetCString2(0, rec))
-        .WriteType(GetCString2(1, rec));
+        .WriteValue(GetCString(0, rec))
+        .WriteType(GetCString(1, rec));
   }
 
   return PMINFO_R_OK;
@@ -154,9 +155,9 @@ int GetAppdefinedPrivilege(const tizen_base::Database& db,
   auto& privilege_writer = writer.GetAppdefinedPrivilegesListWriter();
   for (const auto& rec : r) {
     privilege_writer.AddItem()
-        .WriteType(GetCString2(2, rec))
-        .WriteValue(GetCString2(0, rec))
-        .WriteLicense(GetCString2(1, rec));
+        .WriteType(GetCString(2, rec))
+        .WriteValue(GetCString(0, rec))
+        .WriteLicense(GetCString(1, rec));
   }
 
   return PMINFO_R_OK;
@@ -177,9 +178,9 @@ int GetDependency(const tizen_base::Database& db, const char* pkgid,
   auto& dependency_writer = writer.GetDependenciesListWriter();
   for (const auto& rec : r) {
     dependency_writer.AddItem()
-        .WriteDependsOn(GetCString2(0, rec))
-        .WriteType(GetCString2(1, rec))
-        .WriteRequiredVersion(GetCString2(2, rec));
+        .WriteDependsOn(GetCString(0, rec))
+        .WriteType(GetCString(1, rec))
+        .WriteRequiredVersion(GetCString(2, rec));
   }
 
   return PMINFO_R_OK;
@@ -202,12 +203,12 @@ int GetResAllowedPackages(const tizen_base::Database& db, const char* pkgid,
     const char* package = nullptr;
     const char* privilege = nullptr;
 
-    package = GetCString2(0, rec);
+    package = GetCString(0, rec);
     if (!package)
       continue;
 
     auto& required_privileges = allowed_packages_map[package];
-    privilege = GetCString2(1, rec);
+    privilege = GetCString(1, rec);
     if (!privilege)
       continue;
 
@@ -245,9 +246,9 @@ int GetResInfo(const tizen_base::Database& db, const char* pkgid,
   if (GetResAllowedPackages(db, pkgid, writer) != PMINFO_R_OK)
     return PMINFO_R_ERROR;
 
-  writer.WriteResType(GetCString2(0, *rec));
-  writer.WriteResVersion(GetCString2(1, *rec));
-  writer.WriteLib(GetCString2(2, *rec));
+  writer.WriteResType(GetCString(0, *rec));
+  writer.WriteResVersion(GetCString(1, *rec));
+  writer.WriteLib(GetCString(2, *rec));
 
   return PMINFO_R_OK;
 }
@@ -268,8 +269,8 @@ int GetPackageMetadata(const tizen_base::Database& db,
   auto& metadata_writer = writer.GetMetadataListWriter();
   for (const auto& rec : r) {
     metadata_writer.AddItem()
-        .WriteKey(GetCString2(0, rec))
-        .WriteValue(GetCString2(1, rec));
+        .WriteKey(GetCString(0, rec))
+        .WriteValue(GetCString(1, rec));
   }
 
   return PMINFO_R_OK;
@@ -484,35 +485,35 @@ int DoGetPkgInfo(const tizen_base::Database& db, uid_t uid,
     const char* installed_storage = nullptr;
     const char* external_path = nullptr;
     const char* is_disabled = nullptr;
-    writer.WritePackage(package = GetCString2(idx++, rec));
-    writer.WriteInstalledStorage(installed_storage = GetCString2(idx++, rec));
-    writer.WriteExternalPath(external_path = GetCString2(idx++, rec));
-    is_disabled = GetCString2(idx++, rec);
+    writer.WritePackage(package = GetCString(idx++, rec));
+    writer.WriteInstalledStorage(installed_storage = GetCString(idx++, rec));
+    writer.WriteExternalPath(external_path = GetCString(idx++, rec));
+    is_disabled = GetCString(idx++, rec);
     if (flag & PMINFO_APPINFO_GET_BASICINFO) {
       writer.WriteIsDisabled(is_disabled);
-      writer.WriteVersion(GetCString2(idx++, rec));
-      writer.WriteInstallLocation(GetCString2(idx++, rec));
-      writer.WriteRemovable(GetCString2(idx++, rec));
-      writer.WritePreload(GetCString2(idx++, rec));
-      writer.WriteReadonly(GetCString2(idx++, rec));
-      writer.WriteUpdate(GetCString2(idx++, rec));
-      writer.WriteAppSetting(GetCString2(idx++, rec));
-      writer.WriteSystem(GetCString2(idx++, rec));
-      writer.WriteType(GetCString2(idx++, rec));
-      writer.WritePackageSize(GetCString2(idx++, rec));
-      writer.WriteInstalledTime(GetCString2(idx++, rec));
-      writer.WriteStoreClientId(GetCString2(idx++, rec));
-      writer.WriteMainAppId(GetCString2(idx++, rec));
-      writer.WritePackageUrl(GetCString2(idx++, rec));
-      writer.WriteRootPath(GetCString2(idx++, rec));
-      writer.WriteCscPath(GetCString2(idx++, rec));
-      writer.WriteNoDisplaySetting(GetCString2(idx++, rec));
-      writer.WriteApiVersion(GetCString2(idx++, rec));
-      writer.WriteSupportDisable(GetCString2(idx++, rec));
-      writer.WriteTepName(GetCString2(idx++, rec));
-      writer.WriteZipMountFile(GetCString2(idx++, rec));
-      writer.WriteSupportMode(GetCString2(idx++, rec));
-      writer.WriteLightUserSwitchMode(GetCString2(idx++, rec));
+      writer.WriteVersion(GetCString(idx++, rec));
+      writer.WriteInstallLocation(GetCString(idx++, rec));
+      writer.WriteRemovable(GetCString(idx++, rec));
+      writer.WritePreload(GetCString(idx++, rec));
+      writer.WriteReadonly(GetCString(idx++, rec));
+      writer.WriteUpdate(GetCString(idx++, rec));
+      writer.WriteAppSetting(GetCString(idx++, rec));
+      writer.WriteSystem(GetCString(idx++, rec));
+      writer.WriteType(GetCString(idx++, rec));
+      writer.WritePackageSize(GetCString(idx++, rec));
+      writer.WriteInstalledTime(GetCString(idx++, rec));
+      writer.WriteStoreClientId(GetCString(idx++, rec));
+      writer.WriteMainAppId(GetCString(idx++, rec));
+      writer.WritePackageUrl(GetCString(idx++, rec));
+      writer.WriteRootPath(GetCString(idx++, rec));
+      writer.WriteCscPath(GetCString(idx++, rec));
+      writer.WriteNoDisplaySetting(GetCString(idx++, rec));
+      writer.WriteApiVersion(GetCString(idx++, rec));
+      writer.WriteSupportDisable(GetCString(idx++, rec));
+      writer.WriteTepName(GetCString(idx++, rec));
+      writer.WriteZipMountFile(GetCString(idx++, rec));
+      writer.WriteSupportMode(GetCString(idx++, rec));
+      writer.WriteLightUserSwitchMode(GetCString(idx++, rec));
     }
 
     writer.WriteForAllUsers((uid != global_user_uid) ? "false" : "true");
@@ -523,30 +524,30 @@ int DoGetPkgInfo(const tizen_base::Database& db, uid_t uid,
     if (flag & PMINFO_PKGINFO_GET_AUTHOR) {
       auto& author_list_writer = writer.GetAuthorListWriter();
       author_list_writer.AddItem()
-          .WriteText(GetCString2(idx, rec))
-          .WriteEmail(GetCString2(idx + 1, rec))
-          .WriteHref(GetCString2(idx + 2, rec));
+          .WriteText(GetCString(idx, rec))
+          .WriteEmail(GetCString(idx + 1, rec))
+          .WriteHref(GetCString(idx + 2, rec));
       idx += 3;
     }
 
     if (flag & PMINFO_PKGINFO_GET_LABEL) {
       auto& label_list_writer = writer.GetLabelListWriter();
       label_list_writer.AddItem()
-          .WriteText(GetCString2(idx++, rec))
+          .WriteText(GetCString(idx++, rec))
           .WriteLang(locale.c_str());
     }
 
     if (flag & PMINFO_PKGINFO_GET_ICON) {
       auto& icon_list_writer = writer.GetIconListWriter();
       icon_list_writer.AddItem()
-          .WriteText(GetCString2(idx++, rec))
+          .WriteText(GetCString(idx++, rec))
           .WriteLang(locale.c_str());
     }
 
     if (flag & PMINFO_PKGINFO_GET_DESCRIPTION) {
       auto& description_writer = writer.GetDescriptionListWriter();
       description_writer.AddItem()
-          .WriteText(GetCString2(idx++, rec))
+          .WriteText(GetCString(idx++, rec))
           .WriteLang(locale.c_str());
     }
 
@@ -616,10 +617,10 @@ int DoGetDependsOn(const tizen_base::Database& db, const std::string& pkgid,
       return PMINFO_R_ERROR;
     }
 
-    req->pkgid = GetCString(0, rec);
-    req->depends_on = GetCString(1, rec);
-    req->type = GetCString(2, rec);
-    req->required_version = GetCString(3, rec);
+    req->pkgid = GetAllocatedCString(0, rec);
+    req->depends_on = GetAllocatedCString(1, rec);
+    req->type = GetAllocatedCString(2, rec);
+    req->required_version = GetAllocatedCString(3, rec);
 
     dep_list.push_back(req);
     queue.push(req->pkgid);
index 62014c3fbbda91c14768e565f335271ae51f9055..08de668b08d965cca7fc25e82312339a3420fe0a 100644 (file)
@@ -60,24 +60,17 @@ uid_t ConvertUID(uid_t uid) {
 namespace pkgmgr_server {
 namespace shared_memory {
 
+static const std::string PKG_SHM_PREFIX = ".pkgmgr_info_pkg_";
+static const std::string APP_SHM_PREFIX = ".pkgmgr_info_app_";
+
 std::unordered_map<uid_t, std::unique_ptr<ShmManager>>
     ShmManager::shm_manager_map_;
 std::unordered_set<pid_t> ShmManager::writer_pid_list_;
 std::shared_mutex ShmManager::pid_list_lock_;
 
 ShmManager::ShmManager(uid_t uid) : uid_(uid),
-    pkg_writer_(
-      ps::ShmNameProvider::PkgConfig(uid),
-      ps::ShmNameProvider::PkgHandle(uid),
-      ps::ShmNameProvider::PkgIndexs(uid),
-      ps::ShmNameProvider::PkgKeys(uid)
-    ),
-    app_writer_(
-      ps::ShmNameProvider::AppConfig(uid),
-      ps::ShmNameProvider::AppHandle(uid),
-      ps::ShmNameProvider::AppIndexs(uid),
-      ps::ShmNameProvider::AppKeys(uid)
-    ) {}
+    pkg_writer_(PKG_SHM_PREFIX + std::to_string((uid))),
+    app_writer_(APP_SHM_PREFIX + std::to_string((uid))) {}
 
 ShmManager& ShmManager::GetInst(uid_t uid) {
   static std::shared_mutex singleton_lock_;
@@ -113,6 +106,7 @@ std::unordered_set<pid_t> ShmManager::CrashedWriteRequestPIDs() {
       LOG(ERROR) << "Process is crashed : " << pid;
       remove_pids.emplace(pid);
     } else {
+      LOGW("close fd(%d)", fd);
       close(fd);
     }
   }
@@ -242,6 +236,7 @@ void ShmManager::UpdatePendingPackageInfo(const tizen_base::Database& db,
   auto a_lock = app_writer_.GetLock();
 
   for (const auto& pkgid : pkgids) {
+    LOG(WARNING) << "try to find pending package : " << pkgid;
     auto pkg_it = pending_pkg_.find(pkgid);
     if (pkg_it == pending_pkg_.end())
       continue;
@@ -281,6 +276,9 @@ void ShmManager::TrimCache() {
 void ShmManager::ReleaseCache() {
   LOGD("ReleaseCache");
   pending_pkg_.clear();
+  pkg_app_map_.clear();
+  pkg_writer_.ClearSharedMemory();
+  app_writer_.ClearSharedMemory();
 
   released_ = true;
 }
index 69ad2ec0a806fa19eecb938adba9e684c6fc7377..27771d031c0122b3742e9a72547c7185a3aec016 100644 (file)
@@ -45,7 +45,7 @@ namespace ps = pkgmgr_common::shared_memory;
 
 template<typename T>
 bool ShmWriter<T>::Init() {
-  if (!config_handler_.Create()) {
+  if (config_handler_.Create() != ps::ShmError::NONE) {
     LOGE("Failed to create config handler");
     return false;
   }
@@ -57,12 +57,10 @@ template<typename T>
 bool ShmWriter<T>::CreateSharedMemory(const std::vector<T>& handles) {
   WriteHandles(handles);
 
-  config_handler_.SetMemSize(handle_mapper_.GetSize());
-  config_handler_.SetIndexMemSize(index_mapper_.GetSize());
-  config_handler_.SetKeyMemSize(key_mapper_.GetSize());
+  config_handler_.SetIsValid(true);
 
-  if (config_handler_.Unlock() != 0)
-    LOGE("Failed to unlock of config writer");
+  LOGW("handle(%zu) index(%zu) key(%zu)", handle_mapper_.GetMemSize(),
+      index_mapper_.GetMemSize(), key_mapper_.GetMemSize());
 
   return true;
 }
@@ -80,12 +78,12 @@ bool ShmWriter<T>::WriteHandles(const std::vector<T>& handles) {
   }
   LOGD("handle_mem_size : %zu", handle_mem_size);
 
-  if (!handle_mapper_.Init(handle_mem_size)) {
+  if (handle_mapper_.Init(handle_mem_size) != ps::ShmError::NONE) {
     LOGE("handle_mapper_ init fail");
     return false;
   }
 
-  if (!key_mapper_.Init(key_mem_size)) {
+  if (key_mapper_.Init(key_mem_size) != ps::ShmError::NONE) {
     LOGE("key_mapper_ init fail");
     return false;
   }
@@ -96,6 +94,9 @@ bool ShmWriter<T>::WriteHandles(const std::vector<T>& handles) {
   for (size_t i = 0; i < handles.size(); ++i) {
     WriteKey(handles[i].GetKey(), key_sizes[i], key_index);
     WriteHandle(handles[i], index);
+    LOGD("inserted handle (%d, %d, %u, %s, %s)", key_index, index,
+        handles[i].GetDataSize(), handles[i].GetKey(), base_name_.c_str());
+
     indexs.emplace_back(ps::HandleMappingData {
       .key_index = static_cast<uint32_t>(key_index),
       .index = static_cast<uint32_t>(index),
@@ -123,7 +124,8 @@ bool ShmWriter<T>::Erase(const std::string& key) {
     return true;
   }
 
-  LOGD("Erase key %s, index : %d, key_index : %d", key.c_str(), index, key_index);
+  LOGD("Erase key %s, handle_index : %d, key_index : %d",
+      key.c_str(), index, key_index);
 
   if (!RemoveKey(key_index)) {
     LOGE("Failed to remove key");
@@ -149,11 +151,32 @@ bool ShmWriter<T>::Insert(const T& handle) {
   return InsertHandle(handle, index, key_index);
 }
 
+template<typename T>
+bool ShmWriter<T>::ClearSharedMemory() {
+  bool ret = true;
+
+  handle_version_ = 0;
+  index_version_ = 0;
+  key_version_ = 0;
+
+  config_handler_.SetIsValid(false);
+  if (config_handler_.Clear() != ps::ShmError::NONE)
+    ret = false;
+  if (handle_mapper_.Clear() != ps::ShmError::NONE)
+    ret = false;
+  if (index_mapper_.Clear() != ps::ShmError::NONE)
+    ret = false;
+  if (key_mapper_.Clear() != ps::ShmError::NONE)
+    ret = false;
+
+  return ret;
+}
+
 template<typename T>
 bool ShmWriter<T>::WriteIndexs(
     const std::vector<ps::HandleMappingData>& indexs) {
   size_t mem_size = sizeof(ps::HandleMappingData) * indexs.size();
-  if (!index_mapper_.Init(mem_size)) {
+  if (index_mapper_.Init(mem_size) != ps::ShmError::NONE) {
     LOGE("index_mapper_ init fail");
     return false;
   }
@@ -196,7 +219,8 @@ std::pair<int, int> ShmWriter<T>::GetHandleInsertIndex(const char* key) const {
 
   while (l < r) {
     int mid = (l + r) / 2;
-    const char* key_ptr = reinterpret_cast<const char*>(key_mapper_.GetPtr() + ptr[mid].key_index);
+    const char* key_ptr = reinterpret_cast<const char*>(
+        key_mapper_.GetPtr() + ptr[mid].key_index);
     int result = strcmp(key, key_ptr);
     if (result == 0) {
       LOGE("The package[%s] to insert already exists", key);
@@ -208,9 +232,8 @@ std::pair<int, int> ShmWriter<T>::GetHandleInsertIndex(const char* key) const {
     }
   }
 
-  if (l == static_cast<int>(GetHandleSize())) {
-    return std::make_pair(l, key_mapper_.GetSize());
-  }
+  if (l == static_cast<int>(GetHandleSize()))
+    return std::make_pair(l, key_mapper_.GetMemSize());
   return std::make_pair(l, ptr[l].key_index);
 }
 
@@ -228,8 +251,7 @@ bool ShmWriter<T>::RemoveIndex(size_t index, size_t key_size) {
     moved_num * sizeof(ps::HandleMappingData));
 
   index_mapper_.Resize(
-      index_mapper_.GetSize() - sizeof(ps::HandleMappingData));
-  config_handler_.SetIndexMemSize(index_mapper_.GetSize());
+      index_mapper_.GetMemSize() - sizeof(ps::HandleMappingData));
 
   // Resize may change real ptr
   ptr = reinterpret_cast<ps::HandleMappingData*>(index_mapper_.GetPtr());
@@ -247,19 +269,17 @@ bool ShmWriter<T>::RemoveKey(int index) {
   }
 
   const char* ptr = reinterpret_cast<const char*>(key_mapper_.GetPtr());
-  size_t handle_size = key_mapper_.GetSize();
-  LOGE("remove key : %s", ptr + index);
+  size_t handle_size = key_mapper_.GetMemSize();
 
   size_t key_size = strlen(ptr + index) + 1;
   size_t moved_num = handle_size - index - key_size;
   if (moved_num > 0)
     memmove((void*)(ptr + index), (void*)(ptr + index + key_size), moved_num);
 
-  LOGE("key_mapper size from : %zu", key_mapper_.GetSize());
+  LOGE("key_mapper size from : %zu", key_mapper_.GetMemSize());
   key_mapper_.Resize(
-      key_mapper_.GetSize() - key_size);
-  config_handler_.SetKeyMemSize(key_mapper_.GetSize());
-  LOGE("key_mapper size to : %zu", key_mapper_.GetSize());
+      key_mapper_.GetMemSize() - key_size);
+  LOGE("key_mapper size to : %zu", key_mapper_.GetMemSize());
 
   return true;
 }
@@ -271,15 +291,15 @@ bool ShmWriter<T>::InsertHandle(const T& handle, int index, int key_index) {
     return false;
   }
 
-  int insert_index = PrepareHandleSpace(handle.GetDataSize());
-  if (index < 0) {
+  int handle_insert_index = PrepareHandleSpace(handle.GetDataSize());
+  if (handle_insert_index < 0) {
     LOGE("Failed to prepare handle space");
     return false;
   }
 
   ps::HandleMappingData data {
     .key_index = static_cast<uint32_t>(key_index),
-    .index = static_cast<uint32_t>(insert_index),
+    .index = static_cast<uint32_t>(handle_insert_index),
     .len = handle.GetDataSize(),
   };
   if (!InsertIndex(data, index, strlen(handle.GetKey()) + 1)) {
@@ -287,24 +307,29 @@ bool ShmWriter<T>::InsertHandle(const T& handle, int index, int key_index) {
     return false;
   }
 
-  WriteHandle(handle, insert_index);
+  WriteHandle(handle, handle_insert_index);
+
+  LOGD("inserted handle (%d, %d, %u, %s, %s)", key_index, index,
+      handle.GetDataSize(), handle.GetKey(), base_name_.c_str());
 
   return true;
 }
 
 template<typename T>
-bool ShmWriter<T>::InsertIndex(const ps::HandleMappingData& data, size_t index, size_t key_size) {
-  LOGD("index : %zu", index);
+bool ShmWriter<T>::InsertIndex(const ps::HandleMappingData& data,
+    size_t index, size_t key_size) {
   int moved_num = GetHandleSize() - index;
-  if (!index_mapper_.Resize(index_mapper_.GetSize() + sizeof(ps::HandleMappingData))) {
+  if (index_mapper_.Resize(
+      index_mapper_.GetMemSize() + sizeof(ps::HandleMappingData)) !=
+          ps::ShmError::NONE) {
     LOGE("Failed to resize index mapper");
     return false;
   }
-  config_handler_.SetIndexMemSize(index_mapper_.GetSize());
 
   auto* ptr = (ps::HandleMappingData*)index_mapper_.GetPtr();
   if (moved_num > 0)
-    memmove((void*)&ptr[index + 1], (void*)&ptr[index], moved_num * sizeof(ps::HandleMappingData));
+    memmove((void*)&ptr[index + 1], (void*)&ptr[index],
+        moved_num * sizeof(ps::HandleMappingData));
 
   for (size_t i = index + 1; i < GetHandleSize(); ++i)
     ptr[i].key_index += key_size;
@@ -317,14 +342,12 @@ template<typename T>
 bool ShmWriter<T>::InsertKey(const char* key, int index) {
   char* ptr = reinterpret_cast<char*>(key_mapper_.GetPtr());
   size_t key_size = strlen(key) + 1;
-  LOGE("insert key %s", ptr + index);
-  LOGE("key size : %zu\n", key_size);
-  int moved_num = key_mapper_.GetSize() - index;
-  if (!key_mapper_.Resize(key_mapper_.GetSize() + key_size)) {
+  int moved_num = key_mapper_.GetMemSize() - index;
+  if (key_mapper_.Resize(key_mapper_.GetMemSize() + key_size)
+      != ps::ShmError::NONE) {
     LOGE("Failed to resize index mapper");
     return false;
   }
-  config_handler_.SetKeyMemSize(key_mapper_.GetSize());
 
   // Resize may change real ptr
   ptr = reinterpret_cast<char*>(key_mapper_.GetPtr());
@@ -374,26 +397,25 @@ int ShmWriter<T>::PrepareHandleSpace(size_t size) {
     return result;
   }
 
-  LOGD("need to resize handle");
-  int result = handle_mapper_.GetSize();
-  if (!handle_mapper_.Resize(handle_mapper_.GetSize() + size)) {
+  int result = handle_mapper_.GetMemSize();
+  if (handle_mapper_.Resize(handle_mapper_.GetMemSize() + size)
+      != ps::ShmError::NONE) {
     LOGE("Failed to resize handle mapper");
     return -1;
   }
-  config_handler_.SetMemSize(handle_mapper_.GetSize());
-  LOGD("handle size from[%d] to [%zu]", result, handle_mapper_.GetSize());
+  LOGD("handle size from[%d] to [%zu]", result, handle_mapper_.GetMemSize());
 
   return result;
 }
 
 template<typename T>
 size_t ShmWriter<T>::GetHandleSize() const {
-  return index_mapper_.GetSize() / sizeof(ps::HandleMappingData);
+  return index_mapper_.GetMemSize() / sizeof(ps::HandleMappingData);
 }
 
 template<typename T>
-LockGuard ShmWriter<T>::GetLock() {
-  return LockGuard(config_handler_);
+std::optional<ps::ShmLockGuard> ShmWriter<T>::GetLock() {
+  return config_handler_.GetWriteLock();
 }
 
 }  // namespace shared_memory
index 5e2e3a9662de546af2848a093ceac22730e482dc..38749d50e2cee8e1aa31456f3921e90a6a14f025 100644 (file)
@@ -43,35 +43,24 @@ namespace shared_memory {
 namespace pc = pkgmgr_common;
 namespace ps = pkgmgr_common::shared_memory;
 
-class LockGuard {
- public:
-  LockGuard(ps::ShmConfigHandler& config_handler) : config_handler_(config_handler) {
-    config_handler_.GetWriteLock();
-  }
-
-  ~LockGuard() {
-    config_handler_.Unlock();
-  }
-
- private:
-  ps::ShmConfigHandler& config_handler_;
-};
-
 template <typename T>
 class ShmWriter {
  public:
-  ShmWriter(const char* config_shm_name,
-      const char* handle_shm_name, const char* index_shm_name,
-      const char* key_shm_name) :
-          config_handler_(config_shm_name),
-          handle_mapper_(handle_shm_name),
-          index_mapper_(index_shm_name),
-          key_mapper_(key_shm_name) {}
+  ShmWriter(std::string base_name) :
+          base_name_(std::move(base_name)),
+          config_handler_(base_name_ + "_config"),
+          handle_mapper_(base_name_ + "_handle"),
+          index_mapper_(base_name_ + "_indexs"),
+          key_mapper_(base_name_ + "_keys"),
+          handle_version_(0),
+          index_version_(0),
+          key_version_(0) {}
   bool Init();
   bool CreateSharedMemory(const std::vector<T>& handles);
   bool Erase(const std::string& key);
   bool Insert(const T& handle);
-  LockGuard GetLock();
+  bool ClearSharedMemory();
+  std::optional<ps::ShmLockGuard> GetLock();
 
  private:
   bool WriteHandles(const std::vector<T>& handles);
@@ -89,11 +78,16 @@ class ShmWriter {
   std::pair<int, int> GetHandleInsertIndex(const char* pkgid) const;
   size_t GetHandleSize() const;
 
+  std::string base_name_;
   ps::ShmConfigHandler config_handler_;
   ps::ShmWriteMapper handle_mapper_;
   ps::ShmWriteMapper index_mapper_;
   ps::ShmWriteMapper key_mapper_;
 
+  size_t handle_version_;
+  size_t index_version_;
+  size_t key_version_;
+
   std::set<std::pair<size_t, size_t>> free_space_;
 };