diff options
author | Saturneric <[email protected]> | 2022-05-09 14:40:54 +0000 |
---|---|---|
committer | Saturneric <[email protected]> | 2022-05-09 14:40:54 +0000 |
commit | 670733f7a90d337d546afab22ddedeedec6d3d67 (patch) | |
tree | 2c64c0667d2cac45040257802c40963f89737700 /src/core/function/gpg | |
parent | doc: add entry to developer document. (diff) | |
download | GpgFrontend-670733f7a90d337d546afab22ddedeedec6d3d67.tar.gz GpgFrontend-670733f7a90d337d546afab22ddedeedec6d3d67.zip |
fix: fix crash poblem when doing operations
1. refactor GpgFunctionObject to solve shared library problem.
2. fix multi-threading issues in refreshing.
3. improve loading speed for key list
4. improve ui operation
5. do other fixing and improving operations
Diffstat (limited to 'src/core/function/gpg')
-rw-r--r-- | src/core/function/gpg/GpgKeyGetter.cpp | 84 | ||||
-rw-r--r-- | src/core/function/gpg/GpgKeyGetter.h | 37 |
2 files changed, 106 insertions, 15 deletions
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 |