diff options
author | Saturn&Eric <[email protected]> | 2024-01-23 07:21:28 +0000 |
---|---|---|
committer | GitHub <[email protected]> | 2024-01-23 07:21:28 +0000 |
commit | 56acf161d439ce73eceaa145c40fe703bb2c3f02 (patch) | |
tree | a5d4790a6b2efc8786a3c0f74a07f5a8032d4e94 /src/core/function/CacheManager.cpp | |
parent | fix: use more secure cdn links (diff) | |
parent | fix: solve issues on detected gnupg path function and fix linking errors on w... (diff) | |
download | GpgFrontend-56acf161d439ce73eceaa145c40fe703bb2c3f02.tar.gz GpgFrontend-56acf161d439ce73eceaa145c40fe703bb2c3f02.zip |
Merge pull request #126 from saturneric/dev/2.1.1/main
Develop 2.1.2.1
Diffstat (limited to 'src/core/function/CacheManager.cpp')
-rw-r--r-- | src/core/function/CacheManager.cpp | 311 |
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 |