aboutsummaryrefslogtreecommitdiffstats
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/GpgContext.cpp4
-rw-r--r--src/core/GpgContext.h4
-rw-r--r--src/core/GpgCoreInit.cpp17
-rw-r--r--src/core/GpgFunctionObject.cpp143
-rw-r--r--src/core/GpgFunctionObject.h279
-rw-r--r--src/core/function/gpg/GpgKeyGetter.cpp84
-rw-r--r--src/core/function/gpg/GpgKeyGetter.h37
-rw-r--r--src/core/thread/CtxCheckThread.cpp4
8 files changed, 435 insertions, 137 deletions
diff --git a/src/core/GpgContext.cpp b/src/core/GpgContext.cpp
index 0da963ee..733354fc 100644
--- a/src/core/GpgContext.cpp
+++ b/src/core/GpgContext.cpp
@@ -224,4 +224,8 @@ gpgme_error_t GpgContext::test_status_cb(void *hook, const char *keyword,
return GPG_ERR_NO_ERROR;
}
+void GpgContext::_ctx_ref_deleter::operator()(gpgme_ctx_t _ctx) {
+ if (_ctx != nullptr) gpgme_release(_ctx);
+}
+
} // namespace GpgFrontend \ No newline at end of file
diff --git a/src/core/GpgContext.h b/src/core/GpgContext.h
index b148fcb5..e1f1bda4 100644
--- a/src/core/GpgContext.h
+++ b/src/core/GpgContext.h
@@ -116,9 +116,7 @@ class GPGFRONTEND_CORE_EXPORT GpgContext
*
*/
struct _ctx_ref_deleter {
- void operator()(gpgme_ctx_t _ctx) {
- if (_ctx != nullptr) gpgme_release(_ctx);
- }
+ void operator()(gpgme_ctx_t _ctx);
};
using CtxRefHandler =
diff --git a/src/core/GpgCoreInit.cpp b/src/core/GpgCoreInit.cpp
index e9b8fcdc..41cf99cb 100644
--- a/src/core/GpgCoreInit.cpp
+++ b/src/core/GpgCoreInit.cpp
@@ -28,6 +28,9 @@
#include "GpgCoreInit.h"
+#include <memory>
+
+#include "GpgFunctionObject.h"
#include "core/GpgContext.h"
#include "core/function/GlobalSettingStation.h"
@@ -70,27 +73,25 @@ void init_logging() {
void init_gpgfrontend_core() {
// init default channel
GpgFrontend::GpgContext::CreateInstance(
- GPGFRONTEND_DEFAULT_CHANNEL,
- [&]() -> std::unique_ptr<GpgFrontend::GpgContext> {
+ GPGFRONTEND_DEFAULT_CHANNEL, [&]() -> std::unique_ptr<ChannelObject> {
GpgFrontend::GpgContextInitArgs args;
- return std::make_unique<GpgFrontend::GpgContext>(args);
+ return std::unique_ptr<ChannelObject>(new GpgContext(args));
});
// init non-ascii channel
GpgFrontend::GpgContext::CreateInstance(
- GPGFRONTEND_NON_ASCII_CHANNEL,
- [&]() -> std::unique_ptr<GpgFrontend::GpgContext> {
+ GPGFRONTEND_NON_ASCII_CHANNEL, [&]() -> std::unique_ptr<ChannelObject> {
GpgFrontend::GpgContextInitArgs args;
args.ascii = false;
- return std::make_unique<GpgFrontend::GpgContext>(args);
+ return std::unique_ptr<ChannelObject>(new GpgContext(args));
});
}
void new_default_settings_channel(int channel) {
GpgFrontend::GpgContext::CreateInstance(
- channel, [&]() -> std::unique_ptr<GpgFrontend::GpgContext> {
+ channel, [&]() -> std::unique_ptr<ChannelObject> {
GpgFrontend::GpgContextInitArgs args;
- return std::make_unique<GpgFrontend::GpgContext>(args);
+ return std::unique_ptr<ChannelObject>(new GpgContext(args));
});
}
diff --git a/src/core/GpgFunctionObject.cpp b/src/core/GpgFunctionObject.cpp
new file mode 100644
index 00000000..9fb55247
--- /dev/null
+++ b/src/core/GpgFunctionObject.cpp
@@ -0,0 +1,143 @@
+/**
+ * Copyright (C) 2021 Saturneric
+ *
+ * This file is part of GpgFrontend.
+ *
+ * GpgFrontend is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GpgFrontend is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * The initial version of the source code is inherited from
+ * 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#include "core/GpgFunctionObject.h"
+
+#include <cassert>
+#include <functional>
+#include <memory>
+#include <mutex>
+#include <shared_mutex>
+
+#include "easylogging++.h"
+
+void GpgFrontend::ChannelObject::SetChannel(int channel) {
+ this->channel_ = channel;
+}
+
+int GpgFrontend::ChannelObject::GetChannel() const { return channel_; }
+
+int GpgFrontend::ChannelObject::GetDefaultChannel() { return _default_channel; }
+
+void GpgFrontend::SingletonStorage::ReleaseChannel(int channel) {
+ decltype(instances_map_.end()) _it;
+ {
+ std::shared_lock<std::shared_mutex> lock(instances_mutex_);
+ _it = instances_map_.find(channel);
+ }
+ if (_it != instances_map_.end()) instances_map_.erase(_it);
+ DLOG(INFO) << "channel" << channel << "released";
+}
+
+GpgFrontend::ChannelObject* GpgFrontend::SingletonStorage::FindObjectInChannel(
+ int channel) {
+ LOG(INFO) << "channel:" << channel << "instance address:" << &instances_map_;
+ // read instances_map_
+ decltype(instances_map_.end()) _it;
+ {
+ std::shared_lock<std::shared_mutex> lock(instances_mutex_);
+ _it = instances_map_.find(channel);
+ if (_it == instances_map_.end()) {
+ LOG(INFO) << "channel:" << channel << "not found";
+ return nullptr;
+ } else {
+ return _it->second.get();
+ }
+ }
+}
+
+std::vector<int> GpgFrontend::SingletonStorage::GetAllChannelId() {
+ std::vector<int> _channels;
+ for (const auto& [key, value] : instances_map_) {
+ _channels.push_back(key);
+ }
+ return _channels;
+}
+
+GpgFrontend::ChannelObject* GpgFrontend::SingletonStorage::SetObjectInChannel(
+ int channel, std::unique_ptr<ChannelObject> p_obj) {
+ {
+ LOG(INFO) << "channel:" << channel
+ << "instance address:" << &instances_map_;
+
+ assert(p_obj != nullptr);
+ if (p_obj == nullptr) return nullptr;
+
+ auto raw_obj = p_obj.get();
+ p_obj->SetChannel(channel);
+ {
+ std::unique_lock<std::shared_mutex> lock(instances_mutex_);
+ instances_map_.insert({channel, std::move(p_obj)});
+ }
+ return raw_obj;
+ }
+}
+
+GpgFrontend::SingletonStorage*
+GpgFrontend::SingletonStorageCollection::GetSingletonStorage(
+ const std::type_info& type_id) {
+ const auto hash = type_id.hash_code();
+ LOG(INFO) << "hash" << hash << "type_name:" << type_id.name();
+
+ while (true) {
+ decltype(storages_map_.end()) _it;
+ {
+ std::shared_lock<std::shared_mutex> lock(storages_mutex_);
+ _it = storages_map_.find(hash);
+ }
+ if (_it == storages_map_.end()) {
+ LOG(INFO) << "hash:" << hash << "not found";
+ {
+ std::unique_lock<std::shared_mutex> lock(storages_mutex_);
+ storages_map_.insert({hash, std::make_unique<SingletonStorage>()});
+ LOG(INFO) << "hash:" << hash << "created"
+ << "storage address:" << &storages_map_;
+ }
+ continue;
+ } else {
+ LOG(INFO) << "hash:" << hash << "found";
+ return _it->second.get();
+ }
+ }
+}
+
+GpgFrontend::SingletonStorageCollection*
+GpgFrontend::SingletonStorageCollection::GetInstance() {
+ static SingletonStorageCollection* instance = nullptr;
+ if (instance == nullptr) {
+ instance = new SingletonStorageCollection();
+ }
+ return instance;
+}
+
+GpgFrontend::ChannelObject::ChannelObject() noexcept = default;
+
+GpgFrontend::ChannelObject::ChannelObject(int channel) : channel_(channel) {
+ LOG(INFO) << "called"
+ << "channel:" << channel;
+}
diff --git a/src/core/GpgFunctionObject.h b/src/core/GpgFunctionObject.h
index 391b1585..f16e4cae 100644
--- a/src/core/GpgFunctionObject.h
+++ b/src/core/GpgFunctionObject.h
@@ -35,20 +35,144 @@
#include <shared_mutex>
#include <stdexcept>
#include <string>
+#include <typeinfo>
+#include <utility>
+#include <vector>
#include "GpgConstants.h"
+#include "easylogging++.h"
namespace GpgFrontend {
/**
+ * @brief object which in channel system
+ *
+ */
+class GPGFRONTEND_CORE_EXPORT ChannelObject {
+ public:
+ /**
+ * @brief Construct a new Default Channel Object object
+ *
+ */
+ ChannelObject() noexcept;
+
+ /**
+ * @brief Construct a new Channel Object object
+ *
+ * @param channel
+ */
+ ChannelObject(int channel);
+
+ /**
+ * @brief Get the Default Channel object
+ *
+ * @return int
+ */
+ static int GetDefaultChannel();
+
+ /**
+ * @brief Get the Channel object
+ *
+ * @return int
+ */
+ [[nodiscard]] int GetChannel() const;
+
+ /**
+ * @brief Set the Channel object
+ *
+ * @param channel
+ */
+ void SetChannel(int channel);
+
+ private:
+ int channel_ = _default_channel; ///< The channel id
+ static constexpr int _default_channel = 0; ///< The default channel id
+};
+
+class GPGFRONTEND_CORE_EXPORT SingletonStorage {
+ public:
+ /**
+ * @brief
+ *
+ * @param channel
+ */
+ void ReleaseChannel(int channel);
+
+ /**
+ * @brief
+ *
+ * @param channel
+ * @return T*
+ */
+ ChannelObject* FindObjectInChannel(int channel);
+
+ /**
+ * @brief Get all the channel ids
+ *
+ * @return std::vector<int>
+ */
+ std::vector<int> GetAllChannelId();
+
+ /**
+ * @brief Set a new object in channel object
+ *
+ * @param channel
+ * @param p_obj
+ * @return T*
+ */
+ ChannelObject* SetObjectInChannel(int channel,
+ std::unique_ptr<ChannelObject> p_obj);
+
+ private:
+ std::shared_mutex instances_mutex_; ///< mutex for _instances_map
+ std::map<int, std::unique_ptr<ChannelObject>>
+ instances_map_; ///< map of singleton instances
+};
+
+class GPGFRONTEND_CORE_EXPORT SingletonStorageCollection {
+ public:
+ /**
+ * @brief Get the Instance object
+ *
+ * @return SingletonStorageCollection*
+ */
+ static SingletonStorageCollection* GetInstance();
+
+ /**
+ * @brief Get the Singleton Storage object
+ *
+ * @param singleton_function_object
+ * @return SingletonStorage*
+ */
+ SingletonStorage* GetSingletonStorage(const std::type_info&);
+
+ private:
+ std::shared_mutex storages_mutex_; ///< mutex for storages_map_
+ std::map<size_t, std::unique_ptr<SingletonStorage>> storages_map_;
+};
+/**
* @brief
*
* @tparam T
*/
template <typename T>
-class SingletonFunctionObject {
+class SingletonFunctionObject : public ChannelObject {
public:
/**
+ * @brief prohibit copy
+ *
+ */
+ SingletonFunctionObject(const SingletonFunctionObject<T>&) = delete;
+
+ /**
+ * @brief prohibit copy
+ *
+ * @return SingletonFunctionObject&
+ */
+ SingletonFunctionObject& operator=(const SingletonFunctionObject<T>&) =
+ delete;
+
+ /**
* @brief Get the Instance object
*
* @param channel
@@ -59,10 +183,19 @@ class SingletonFunctionObject {
static_assert(std::is_base_of<SingletonFunctionObject<T>, T>::value,
"T not derived from SingletonFunctionObject<T>");
- auto _p_pbj = find_object_in_channel(channel);
- if (_p_pbj == nullptr)
- return *set_object_in_channel(channel, std::make_unique<T>(channel));
- else
+ auto p_storage =
+ SingletonStorageCollection::GetInstance()->GetSingletonStorage(
+ typeid(T));
+
+ auto* _p_pbj = (T*)(p_storage->FindObjectInChannel(channel));
+
+ LOG(INFO) << "object address" << _p_pbj;
+
+ if (_p_pbj == nullptr) {
+ auto new_obj = std::unique_ptr<ChannelObject>(new T(channel));
+ LOG(INFO) << "create new object";
+ return *(T*)(p_storage->SetObjectInChannel(channel, std::move(new_obj)));
+ } else
return *_p_pbj;
}
@@ -73,33 +206,22 @@ class SingletonFunctionObject {
* @param factory
* @return T&
*/
- static T& CreateInstance(int channel,
- std::function<std::unique_ptr<T>(void)> factory) {
+ static T& CreateInstance(
+ int channel,
+ std::function<std::unique_ptr<ChannelObject>(void)> factory) {
static_assert(std::is_base_of<SingletonFunctionObject<T>, T>::value,
"T not derived from SingletonFunctionObject<T>");
- auto _p_pbj = find_object_in_channel(channel);
- if (_p_pbj == nullptr)
- return *set_object_in_channel(channel, std::move(factory()));
- else
- return *_p_pbj;
- }
+ auto p_storage =
+ SingletonStorageCollection::GetInstance()->GetSingletonStorage(
+ typeid(T));
- /**
- * @brief Create a Instance object
- *
- * @param channel
- * @param p_obj
- * @return T&
- */
- static T& CreateInstance(int channel, std::unique_ptr<T> p_obj = nullptr) {
- static_assert(std::is_base_of<SingletonFunctionObject<T>, T>::value,
- "T not derived from SingletonFunctionObject<T>");
+ auto _p_pbj = (T*)(p_storage->FindObjectInChannel(channel));
- auto _p_pbj = find_object_in_channel(channel);
- if (_p_pbj == nullptr)
- return *set_object_in_channel(channel, std::move(p_obj));
- else
+ if (_p_pbj == nullptr) {
+ return *(
+ T*)(p_storage->SetObjectInChannel(channel, std::move(factory())));
+ } else
return *_p_pbj;
}
@@ -109,14 +231,10 @@ class SingletonFunctionObject {
* @param channel
* @return T&
*/
- static T& ReleaseChannel(int channel) {
- decltype(_instances_map.end()) _it;
- {
- std::shared_lock lock(_instances_mutex);
- _it = _instances_map.find(channel);
- }
- if (_it != _instances_map.end()) _instances_map.erase(_it);
- DLOG(INFO) << "channel" << channel << "released";
+ static void ReleaseChannel(int channel) {
+ SingletonStorageCollection::GetInstance()
+ ->GetSingletonStorage(typeid(T))
+ ->ReleaseChannel(channel);
}
/**
@@ -124,14 +242,25 @@ class SingletonFunctionObject {
*
* @return int
*/
- static int GetDefaultChannel() { return _default_channel; }
+ static int GetDefaultChannel() { return ChannelObject::GetDefaultChannel(); }
/**
* @brief Get the Channel object
*
* @return int
*/
- [[nodiscard]] int GetChannel() const { return channel_; }
+ [[nodiscard]] int GetChannel() const { return ChannelObject::GetChannel(); }
+
+ /**
+ * @brief Get all the channel ids
+ *
+ * @return std::vector<int>
+ */
+ static std::vector<int> GetAllChannelId() {
+ return SingletonStorageCollection::GetInstance()
+ ->GetSingletonStorage(typeid(T))
+ ->GetAllChannelId();
+ }
/**
* @brief Construct a new Singleton Function Object object
@@ -163,85 +292,17 @@ class SingletonFunctionObject {
*
* @param channel
*/
- explicit SingletonFunctionObject(int channel) : channel_(channel) {}
+ explicit SingletonFunctionObject(int channel) : ChannelObject(channel) {
+ LOG(INFO) << "called"
+ << "channel:" << channel;
+ }
/**
* @brief Destroy the Singleton Function Object object
*
*/
virtual ~SingletonFunctionObject() = default;
-
- /**
- * @brief Set the Channel object
- *
- * @param channel
- */
- void SetChannel(int channel) { this->channel_ = channel; }
-
- private:
- int channel_ = _default_channel; ///<
- static int _default_channel; ///<
- static std::mutex _instance_mutex; ///<
- static std::shared_mutex _instances_mutex; ///<
- static std::unique_ptr<T> _instance; ///<
- static std::map<int, std::unique_ptr<T>> _instances_map; ///<
-
- /**
- * @brief
- *
- * @param channel
- * @return T*
- */
- static T* find_object_in_channel(int channel) {
- // read _instances_map
- decltype(_instances_map.end()) _it;
- {
- std::shared_lock lock(_instances_mutex);
- _it = _instances_map.find(channel);
- if (_it == _instances_map.end())
- return nullptr;
- else
- return _it->second.get();
- }
- }
-
- /**
- * @brief Set the object in channel object
- *
- * @param channel
- * @param p_obj
- * @return T*
- */
- static T* set_object_in_channel(int channel, std::unique_ptr<T> p_obj) {
- {
- if (p_obj == nullptr) p_obj = std::make_unique<T>();
- T* obj = p_obj.get();
- obj->SetChannel(channel);
- {
- std::unique_lock lock(_instances_mutex);
- _instances_map.insert({channel, std::move(p_obj)});
- }
- return obj;
- }
- }
};
-
-template <typename T>
-int SingletonFunctionObject<T>::_default_channel =
- GpgFrontend::GPGFRONTEND_DEFAULT_CHANNEL;
-
-template <typename T>
-std::mutex SingletonFunctionObject<T>::_instance_mutex;
-
-template <typename T>
-std::shared_mutex SingletonFunctionObject<T>::_instances_mutex;
-
-template <typename T>
-std::unique_ptr<T> SingletonFunctionObject<T>::_instance = nullptr;
-
-template <typename T>
-std::map<int, std::unique_ptr<T>> SingletonFunctionObject<T>::_instances_map;
-
} // namespace GpgFrontend
#endif // GPGFRONTEND_ZH_CN_TS_FUNCTIONOBJECT_H
diff --git a/src/core/function/gpg/GpgKeyGetter.cpp b/src/core/function/gpg/GpgKeyGetter.cpp
index cbd40efc..9a7b505c 100644
--- a/src/core/function/gpg/GpgKeyGetter.cpp
+++ b/src/core/function/gpg/GpgKeyGetter.cpp
@@ -30,12 +30,32 @@
#include <gpg-error.h>
+#include <mutex>
+#include <shared_mutex>
+#include <utility>
+
#include "GpgConstants.h"
+#include "easylogging++.h"
+#include "model/GpgKey.h"
GpgFrontend::GpgKeyGetter::GpgKeyGetter(int channel)
- : SingletonFunctionObject<GpgKeyGetter>(channel) {}
+ : SingletonFunctionObject<GpgKeyGetter>(channel) {
+ LOG(INFO) << "called"
+ << "channel:" << channel;
+}
GpgFrontend::GpgKey GpgFrontend::GpgKeyGetter::GetKey(const std::string& fpr) {
+ LOG(INFO) << "called";
+
+ // find in cache first
+ {
+ std::lock_guard<std::mutex> lock(keys_cache_mutex_);
+ if (keys_cache_.find(fpr) != keys_cache_.end()) {
+ std::lock_guard<std::mutex> lock(ctx_mutex_);
+ return keys_cache_[fpr].Copy();
+ }
+ }
+
gpgme_key_t _p_key = nullptr;
gpgme_get_key(ctx_, fpr.c_str(), &_p_key, 1);
if (_p_key == nullptr) {
@@ -48,6 +68,15 @@ GpgFrontend::GpgKey GpgFrontend::GpgKeyGetter::GetKey(const std::string& fpr) {
GpgFrontend::GpgKey GpgFrontend::GpgKeyGetter::GetPubkey(
const std::string& fpr) {
+ // find in cache first
+ {
+ std::lock_guard<std::mutex> lock(keys_cache_mutex_);
+ if (keys_cache_.find(fpr) != keys_cache_.end()) {
+ std::lock_guard<std::mutex> lock(ctx_mutex_);
+ return keys_cache_[fpr].Copy();
+ }
+ }
+
gpgme_key_t _p_key = nullptr;
gpgme_get_key(ctx_, fpr.c_str(), &_p_key, 0);
if (_p_key == nullptr)
@@ -56,28 +85,59 @@ GpgFrontend::GpgKey GpgFrontend::GpgKeyGetter::GetPubkey(
}
GpgFrontend::KeyLinkListPtr GpgFrontend::GpgKeyGetter::FetchKey() {
- gpgme_error_t err;
+ // get the lock
+ std::lock_guard<std::mutex> lock(keys_cache_mutex_);
+
+ LOG(INFO) << "GpgKeyGetter FetchKey"
+ << "channel id:" << GetChannel();
auto keys_list = std::make_unique<GpgKeyLinkList>();
- LOG(INFO) << "GpgKeyGetter FetchKey"
- << "ctx address" << ctx_;
+ LOG(INFO) << "cache address:" << &keys_cache_ << "object address" << this;
- err = gpgme_op_keylist_start(ctx_, nullptr, 0);
+ for (const auto& [key, value] : keys_cache_) {
+ LOG(INFO) << "FetchKey Id:" << value.GetId();
+ keys_list->push_back(value.Copy());
+ }
+ LOG(INFO) << "ended";
+ return keys_list;
+}
+
+void GpgFrontend::GpgKeyGetter::FlushKeyCache() {
+ LOG(INFO) << "called"
+ << "channel id: " << GetChannel();
+
+ // clear the keys cache
+ keys_cache_.clear();
+
+ // init
+ GpgError err = gpgme_op_keylist_start(ctx_, nullptr, 0);
+
+ // for debug
assert(check_gpg_error_2_err_code(err) == GPG_ERR_NO_ERROR);
- gpgme_key_t key;
- while ((err = gpgme_op_keylist_next(ctx_, &key)) == GPG_ERR_NO_ERROR) {
- keys_list->push_back(GetKey(key->fpr));
+ // return when error
+ if (check_gpg_error_2_err_code(err) != GPG_ERR_NO_ERROR) return;
+
+ {
+ // get the lock
+ std::lock_guard<std::mutex> lock(keys_cache_mutex_);
+ gpgme_key_t key;
+ while ((err = gpgme_op_keylist_next(ctx_, &key)) == GPG_ERR_NO_ERROR) {
+ LOG(INFO) << "LoadKey Fpr:" << key->fpr << "Id:" << key->subkeys->keyid;
+ keys_cache_.insert({key->subkeys->keyid, GpgKey(std::move(key))});
+ }
}
+ LOG(INFO) << "cache address:" << &keys_cache_ << "object address" << this;
+
+ // for debug
assert(check_gpg_error_2_err_code(err, GPG_ERR_EOF) == GPG_ERR_EOF);
err = gpgme_op_keylist_end(ctx_);
-
assert(check_gpg_error_2_err_code(err, GPG_ERR_EOF) == GPG_ERR_NO_ERROR);
- return keys_list;
+ LOG(INFO) << "ended";
}
GpgFrontend::KeyListPtr GpgFrontend::GpgKeyGetter::GetKeys(
@@ -89,6 +149,8 @@ GpgFrontend::KeyListPtr GpgFrontend::GpgKeyGetter::GetKeys(
GpgFrontend::KeyLinkListPtr GpgFrontend::GpgKeyGetter::GetKeysCopy(
const GpgFrontend::KeyLinkListPtr& keys) {
+ // get the lock
+ std::lock_guard<std::mutex> lock(ctx_mutex_);
auto keys_copy = std::make_unique<GpgKeyLinkList>();
for (const auto& key : *keys) keys_copy->push_back(key.Copy());
return keys_copy;
@@ -96,6 +158,8 @@ GpgFrontend::KeyLinkListPtr GpgFrontend::GpgKeyGetter::GetKeysCopy(
GpgFrontend::KeyListPtr GpgFrontend::GpgKeyGetter::GetKeysCopy(
const GpgFrontend::KeyListPtr& keys) {
+ // get the lock
+ std::lock_guard<std::mutex> lock(ctx_mutex_);
auto keys_copy = std::make_unique<KeyArgsList>();
for (const auto& key : *keys) keys_copy->push_back(key.Copy());
return keys_copy;
diff --git a/src/core/function/gpg/GpgKeyGetter.h b/src/core/function/gpg/GpgKeyGetter.h
index d63238f5..72cd777c 100644
--- a/src/core/function/gpg/GpgKeyGetter.h
+++ b/src/core/function/gpg/GpgKeyGetter.h
@@ -29,6 +29,9 @@
#ifndef GPGFRONTEND_ZH_CN_TS_GPGKEYGETTER_H
#define GPGFRONTEND_ZH_CN_TS_GPGKEYGETTER_H
+#include <mutex>
+#include <vector>
+
#include "core/GpgContext.h"
#include "core/GpgFunctionObject.h"
#include "core/GpgModel.h"
@@ -56,7 +59,7 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyGetter
* @param fpr
* @return GpgKey
*/
- GpgKey GetKey(const std::string& fpr);
+ GpgKey GetKey(const std::string& id);
/**
* @brief Get the Keys object
@@ -72,22 +75,28 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyGetter
* @param fpr
* @return GpgKey
*/
- GpgKey GetPubkey(const std::string& fpr);
+ GpgKey GetPubkey(const std::string& id);
/**
- * @brief
+ * @brief Get all the keys by receiving a linked list
*
* @return KeyLinkListPtr
*/
KeyLinkListPtr FetchKey();
/**
+ * @brief flush the keys in the cache
+ *
+ */
+ void FlushKeyCache();
+
+ /**
* @brief Get the Keys Copy object
*
* @param keys
* @return KeyListPtr
*/
- static KeyListPtr GetKeysCopy(const KeyListPtr& keys);
+ KeyListPtr GetKeysCopy(const KeyListPtr& keys);
/**
* @brief Get the Keys Copy object
@@ -95,7 +104,7 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyGetter
* @param keys
* @return KeyLinkListPtr
*/
- static KeyLinkListPtr GetKeysCopy(const KeyLinkListPtr& keys);
+ KeyLinkListPtr GetKeysCopy(const KeyLinkListPtr& keys);
private:
/**
@@ -104,6 +113,24 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyGetter
*/
GpgContext& ctx_ =
GpgContext::GetInstance(SingletonFunctionObject::GetChannel());
+
+ /**
+ * @brief shared mutex for the keys cache
+ *
+ */
+ mutable std::mutex ctx_mutex_;
+
+ /**
+ * @brief cache the keys with key fpr
+ *
+ */
+ std::map<std::string, GpgKey> keys_cache_;
+
+ /**
+ * @brief shared mutex for the keys cache
+ *
+ */
+ mutable std::mutex keys_cache_mutex_;
};
} // namespace GpgFrontend
diff --git a/src/core/thread/CtxCheckThread.cpp b/src/core/thread/CtxCheckThread.cpp
index 77571dfd..edec8855 100644
--- a/src/core/thread/CtxCheckThread.cpp
+++ b/src/core/thread/CtxCheckThread.cpp
@@ -48,7 +48,7 @@ void GpgFrontend::CtxCheckThread::run() {
if (!GpgContext::GetInstance().good()) {
emit SignalGnupgNotInstall();
}
- // Try fetching key
+ // Try flushing key cache
else
- GpgFrontend::GpgKeyGetter::GetInstance().FetchKey();
+ GpgFrontend::GpgKeyGetter::GetInstance().FlushKeyCache();
}