aboutsummaryrefslogtreecommitdiffstats
path: root/src/core/function/CacheManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/function/CacheManager.cpp')
-rw-r--r--src/core/function/CacheManager.cpp311
1 files changed, 224 insertions, 87 deletions
diff --git a/src/core/function/CacheManager.cpp b/src/core/function/CacheManager.cpp
index d9aead66..719c962d 100644
--- a/src/core/function/CacheManager.cpp
+++ b/src/core/function/CacheManager.cpp
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2021 Saturneric
+ * Copyright (C) 2021 Saturneric <[email protected]>
*
* This file is part of GpgFrontend.
*
@@ -20,7 +20,7 @@
* the gpg4usb project, which is under GPL-3.0-or-later.
*
* All the source code of GpgFrontend was modified and released by
- * Saturneric<[email protected]> starting on May 12, 2021.
+ * Saturneric <[email protected]> starting on May 12, 2021.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*
@@ -29,119 +29,256 @@
#include "CacheManager.h"
#include <algorithm>
-#include <boost/format.hpp>
-#include <string>
+#include <shared_mutex>
+#include <utility>
-#include "function/DataObjectOperator.h"
-#include "spdlog/spdlog.h"
+#include "core/function/DataObjectOperator.h"
+#include "core/utils/MemoryUtils.h"
-GpgFrontend::CacheManager::CacheManager(int channel)
- : m_timer_(new QTimer(this)),
- SingletonFunctionObject<CacheManager>(channel) {
- connect(m_timer_, &QTimer::timeout, this, &CacheManager::flush_cache_storage);
- m_timer_->start(15000);
+namespace GpgFrontend {
- load_all_cache_storage();
-}
+template <typename Key, typename Value>
+class ThreadSafeMap {
+ public:
+ using MapType = std::map<Key, Value>;
+ using IteratorType = typename MapType::iterator;
-void GpgFrontend::CacheManager::SaveCache(std::string key,
- const nlohmann::json& value,
- bool flush) {
- auto data_object_key = get_data_object_key(key);
- cache_storage_.insert(key, value);
+ void insert(const Key& key, const Value& value) {
+ std::unique_lock lock(mutex_);
+ (*map_)[key] = value;
+ }
- if (std::find(key_storage_.begin(), key_storage_.end(), key) ==
- key_storage_.end()) {
- SPDLOG_DEBUG("register new key of cache", key);
- key_storage_.push_back(key);
+ auto get(const Key& key) -> std::optional<Value> {
+ std::shared_lock lock(mutex_);
+ auto it = map_->find(key);
+ if (it != map_->end()) {
+ return it->second;
+ }
+ return std::nullopt;
}
- if (flush) {
- flush_cache_storage();
+ auto exists(const Key& key) -> bool {
+ std::shared_lock lock(mutex_);
+ return map_->count(key) > 0;
}
-}
-nlohmann::json GpgFrontend::CacheManager::LoadCache(std::string key) {
- auto data_object_key = get_data_object_key(key);
+ auto begin() -> IteratorType { return map_mirror_->begin(); }
+
+ auto end() -> IteratorType { return map_mirror_->end(); }
- if (!cache_storage_.exists(key)) {
- cache_storage_.insert(key, load_cache_storage(key, {}));
+ auto mirror() -> ThreadSafeMap& {
+ std::shared_lock lock(mutex_);
+ *map_mirror_ = *map_;
+ return *this;
}
- auto cache = cache_storage_.get(key);
- if (cache)
- return *cache;
- else
- return {};
-}
+ auto remove(QString key) -> bool {
+ std::unique_lock lock(mutex_);
+ auto it = map_->find(key);
+ if (it != map_->end()) {
+ map_->erase(it);
+ return true;
+ }
+ return false;
+ }
-nlohmann::json GpgFrontend::CacheManager::LoadCache(
- std::string key, nlohmann::json default_value) {
- auto data_object_key = get_data_object_key(key);
- if (!cache_storage_.exists(key)) {
- cache_storage_.insert(key, load_cache_storage(key, default_value));
+ private:
+ std::unique_ptr<MapType, SecureObjectDeleter<MapType>> map_mirror_ =
+ std::move(SecureCreateUniqueObject<MapType>());
+ std::unique_ptr<MapType, SecureObjectDeleter<MapType>> map_ =
+ std::move(SecureCreateUniqueObject<MapType>());
+ mutable std::shared_mutex mutex_;
+};
+
+class CacheManager::Impl : public QObject {
+ Q_OBJECT
+ public:
+ Impl() : flush_timer_(new QTimer(this)) {
+ connect(flush_timer_, &QTimer::timeout, this,
+ &Impl::slot_flush_cache_storage);
+ flush_timer_->start(15000);
+
+ // load data from storage
+ load_all_cache_storage();
}
- auto cache = cache_storage_.get(key);
- if (cache)
- return *cache;
- else
- return {};
-}
+ void SaveDurableCache(QString key, const QJsonDocument& value, bool flush) {
+ auto data_object_key = get_data_object_key(key);
+ durable_cache_storage_.insert(key, value);
-std::string GpgFrontend::CacheManager::get_data_object_key(std::string key) {
- return (boost::format("__cache_data_%1%") % key).str();
-}
+ if (!key_storage_.contains(key)) {
+ GF_CORE_LOG_DEBUG("register new key of cache", key);
+ key_storage_.push_back(key);
+ }
-nlohmann::json GpgFrontend::CacheManager::load_cache_storage(
- std::string key, nlohmann::json default_value) {
- auto data_object_key = get_data_object_key(key);
- auto stored_data =
- GpgFrontend::DataObjectOperator::GetInstance().GetDataObject(
- data_object_key);
+ if (flush) slot_flush_cache_storage();
+ }
- if (stored_data.has_value()) {
- return stored_data.value();
- } else {
- return default_value;
+ auto LoadDurableCache(const QString& key) -> QJsonDocument {
+ auto data_object_key = get_data_object_key(key);
+
+ if (!durable_cache_storage_.exists(key)) {
+ durable_cache_storage_.insert(key, load_cache_storage(key, {}));
+ }
+
+ auto cache = durable_cache_storage_.get(key);
+ if (cache.has_value()) return cache.value();
+ return {};
}
-}
-void GpgFrontend::CacheManager::flush_cache_storage() {
- for (auto cache : cache_storage_.mirror()) {
- auto key = get_data_object_key(cache.first);
- SPDLOG_DEBUG("save cache into filesystem, key {}, value size: {}", key,
- cache.second.size());
- GpgFrontend::DataObjectOperator::GetInstance().SaveDataObj(key,
- cache.second);
+ auto LoadDurableCache(const QString& key, QJsonDocument default_value)
+ -> QJsonDocument {
+ auto data_object_key = get_data_object_key(key);
+ if (!durable_cache_storage_.exists(key)) {
+ durable_cache_storage_.insert(
+ key, load_cache_storage(key, std::move(default_value)));
+ }
+
+ auto cache = durable_cache_storage_.get(key);
+ if (cache.has_value()) return cache.value();
+ return {};
}
- GpgFrontend::DataObjectOperator::GetInstance().SaveDataObj(drk_key_,
- key_storage_);
-}
-void GpgFrontend::CacheManager::register_cache_key(std::string key) {}
+ auto ResetDurableCache(const QString& key) -> bool {
+ auto data_object_key = get_data_object_key(key);
+ return durable_cache_storage_.remove(key);
+ }
+
+ void FlushCacheStorage() { this->slot_flush_cache_storage(); }
-void GpgFrontend::CacheManager::load_all_cache_storage() {
- SPDLOG_DEBUG("start to load all cache from file system");
- auto stored_data =
- GpgFrontend::DataObjectOperator::GetInstance().GetDataObject(drk_key_);
+ void SaveCache(const QString& key, QString value) {
+ runtime_cache_storage_.insert(key, new QString(std::move(value)));
+ }
- // get cache data list from file system
- nlohmann::json registered_key_list;
- if (stored_data.has_value()) {
- registered_key_list = std::move(stored_data.value());
+ auto LoadCache(const QString& key) -> QString {
+ auto* value = runtime_cache_storage_.object(key);
+ if (value == nullptr) return {};
+ return *value;
}
- if (!registered_key_list.is_array()) {
+ void ResetCache(const QString& key) { runtime_cache_storage_.remove(key); }
+
+ private slots:
+
+ /**
+ * @brief
+ *
+ */
+ void slot_flush_cache_storage() {
+ for (const auto& cache : durable_cache_storage_.mirror()) {
+ auto key = get_data_object_key(cache.first);
+ GF_CORE_LOG_TRACE("save cache into filesystem, key {}", key);
+ GpgFrontend::DataObjectOperator::GetInstance().SaveDataObj(
+ key, QJsonDocument(cache.second));
+ }
GpgFrontend::DataObjectOperator::GetInstance().SaveDataObj(
- drk_key_, nlohmann::json::array());
- SPDLOG_ERROR("drk_key_ is not an array, abort.");
- return;
+ drk_key_, QJsonDocument(key_storage_));
}
- for (auto key : registered_key_list) {
- load_cache_storage(key, {});
+ private:
+ QCache<QString, QString> runtime_cache_storage_;
+ ThreadSafeMap<QString, QJsonDocument> durable_cache_storage_;
+ QJsonArray key_storage_;
+ QTimer* flush_timer_;
+ const QString drk_key_ = "__cache_manage_data_register_key_list";
+
+ /**
+ * @brief Get the data object key object
+ *
+ * @param key
+ * @return QString
+ */
+ static auto get_data_object_key(const QString& key) -> QString {
+ return QString("__cache_data_%1").arg(key);
}
- key_storage_ = registered_key_list;
-} \ No newline at end of file
+ /**
+ * @brief
+ *
+ * @param key
+ * @param default_value
+ * @return QJsonObject
+ */
+ static auto load_cache_storage(const QString& key,
+ QJsonDocument default_value) -> QJsonDocument {
+ auto data_object_key = get_data_object_key(key);
+ auto stored_data =
+ GpgFrontend::DataObjectOperator::GetInstance().GetDataObject(
+ data_object_key);
+
+ if (stored_data.has_value()) return stored_data.value();
+ return default_value;
+ }
+
+ /**
+ * @brief
+ *
+ */
+ void load_all_cache_storage() {
+ GF_CORE_LOG_DEBUG("start to load all cache from file system");
+ auto stored_data =
+ GpgFrontend::DataObjectOperator::GetInstance().GetDataObject(drk_key_);
+
+ // get cache data list from file system
+ QJsonArray registered_key_list;
+ if (stored_data->isArray()) {
+ registered_key_list = stored_data->array();
+ } else {
+ GpgFrontend::DataObjectOperator::GetInstance().SaveDataObj(
+ drk_key_, QJsonDocument(QJsonArray()));
+ }
+
+ for (const auto& key : registered_key_list) {
+ load_cache_storage(key.toString(), {});
+ }
+
+ key_storage_ = registered_key_list;
+ }
+
+ /**
+ * @brief
+ *
+ * @param key
+ */
+ void register_cache_key(const QString& key) {}
+};
+
+CacheManager::CacheManager(int channel)
+ : SingletonFunctionObject<CacheManager>(channel),
+ p_(SecureCreateUniqueObject<Impl>()) {}
+
+CacheManager::~CacheManager() { p_->FlushCacheStorage(); }
+
+void CacheManager::SaveDurableCache(const QString& key,
+ const QJsonDocument& value, bool flush) {
+ p_->SaveDurableCache(key, value, flush);
+}
+
+auto CacheManager::LoadDurableCache(const QString& key) -> QJsonDocument {
+ return p_->LoadDurableCache(key);
+}
+
+auto CacheManager::LoadDurableCache(const QString& key,
+ QJsonDocument default_value)
+ -> QJsonDocument {
+ return p_->LoadDurableCache(key, std::move(default_value));
+}
+
+auto CacheManager::ResetDurableCache(const QString& key) -> bool {
+ return p_->ResetDurableCache(key);
+}
+
+void CacheManager::SaveCache(const QString& key, QString value) {
+ p_->SaveCache(key, std::move(value));
+}
+
+auto CacheManager::LoadCache(const QString& key) -> QString {
+ return p_->LoadCache(key);
+}
+
+void CacheManager::ResetCache(const QString& key) {
+ return p_->ResetCache(key);
+}
+} // namespace GpgFrontend
+
+#include "CacheManager.moc" \ No newline at end of file