From e1f22a49892e308b4186c2d3429f02db64891971 Mon Sep 17 00:00:00 2001 From: Jon Griffiths Date: Sun, 17 Jan 2021 02:45:44 +1300 Subject: [PATCH] Don't create an unneeded blob copy when reading name/value cache items --- src/ga_cache.cpp | 23 ++++++++++++++++++++-- src/ga_cache.hpp | 3 ++- src/ga_session.cpp | 49 ++++++++++++++++++++++++---------------------- 3 files changed, 49 insertions(+), 26 deletions(-) diff --git a/src/ga_cache.cpp b/src/ga_cache.cpp index a1f6c65f9..c7c7f7453 100644 --- a/src/ga_cache.cpp +++ b/src/ga_cache.cpp @@ -210,6 +210,25 @@ namespace sdk { return result; } + static void get_blob(std::unique_ptr& stmt, int column, const cache::get_key_value_fn& callback) + { + const int rc = sqlite3_step(stmt.get()); + if (rc == SQLITE_DONE) { + callback(boost::none); + return; + } + GDK_RUNTIME_ASSERT(rc == SQLITE_ROW); + + const auto res = reinterpret_cast(sqlite3_column_blob(stmt.get(), column)); + const auto len = sqlite3_column_bytes(stmt.get(), column); + try { + callback(gsl::make_span(res, len)); + } catch (const std::exception& ex) { + GDK_LOG_SEV(log_level::error) << "Blob callback exception: " << ex.what(); + } + step_final(stmt); + } + static void bind_blob(std::unique_ptr& stmt, int column, byte_span_t blob) { GDK_RUNTIME_ASSERT( @@ -338,13 +357,13 @@ namespace sdk { step_final(m_stmt_key_value_delete); } - boost::optional> cache::get_key_value(const std::string& key) + void cache::get_key_value(const std::string& key, const cache::get_key_value_fn& callback) { GDK_RUNTIME_ASSERT(!key.empty()); const auto _stmt_clean = gsl::finally([this] { stmt_check_clean(m_stmt_key_value_search); }); const auto key_span = ustring_span(key); bind_blob(m_stmt_key_value_search, 1, key_span); - return get_blob(m_stmt_key_value_search, 0); + get_blob(m_stmt_key_value_search, 0, callback); } bool cache::has_liquid_blinding_nonce(byte_span_t pubkey, byte_span_t script) diff --git a/src/ga_cache.hpp b/src/ga_cache.hpp index 6af454925..a4eb029ac 100644 --- a/src/ga_cache.hpp +++ b/src/ga_cache.hpp @@ -32,7 +32,8 @@ namespace sdk { boost::optional> get_liquid_blinding_nonce(byte_span_t pubkey, byte_span_t script); void insert_liquid_blinding_nonce(byte_span_t pubkey, byte_span_t script, byte_span_t nonce); - boost::optional> get_key_value(const std::string& key); + typedef std::function)> get_key_value_fn; + void get_key_value(const std::string& key, const get_key_value_fn& callback); void upsert_key_value(const std::string& key, byte_span_t value); void clear_key_value(const std::string& key); diff --git a/src/ga_session.cpp b/src/ga_session.cpp index dc02b7755..fe9e4e4af 100644 --- a/src/ga_session.cpp +++ b/src/ga_session.cpp @@ -835,21 +835,23 @@ namespace sdk { nlohmann::json ga_session::refresh_http_data(const std::string& type, bool refresh) { - const auto cached_value = [this, &type] { - locker_t locker(m_mutex); - return m_cache.get_key_value(type); - }(); - - std::string last_modified; nlohmann::json cached_data = nlohmann::json::object(); - if (cached_value) { - try { - cached_data = nlohmann::json::from_msgpack(cached_value->begin(), cached_value->end()); - last_modified = cached_data.at("headers").at("last-modified"); - } catch (const std::exception& e) { - GDK_LOG_SEV(log_level::warning) << "Error reading cached json: " << e.what(); - cached_data = nlohmann::json::object(); - } + std::string last_modified; + + { + locker_t locker(m_mutex); + m_cache.get_key_value(type, { [&cached_data, &last_modified](const auto& db_blob) { + if (!db_blob) { + return; + } + try { + cached_data = nlohmann::json::from_msgpack(db_blob->begin(), db_blob->end()); + last_modified = cached_data.at("headers").at("last-modified"); + } catch (const std::exception& e) { + GDK_LOG_SEV(log_level::warning) << "Error reading cached json: " << e.what(); + cached_data = nlohmann::json::object(); + } + } }); } if (!refresh) { @@ -867,6 +869,7 @@ namespace sdk { GDK_RUNTIME_ASSERT_MSG(!data.contains("error"), "error during refresh"); if (data.value("not_modified", false)) { + // Our cached copy is up to date, return it return cached_data; } @@ -1501,16 +1504,16 @@ namespace sdk { if (m_blob_hmac.empty()) { // Load our client blob from from the cache if we have one - const auto cached = m_cache.get_key_value("client_blob"); - if (cached) { - const auto& db_blob = cached.value(); - std::string db_hmac = client_blob::compute_hmac(m_blob_key.get(), db_blob); - if (db_hmac == server_hmac) { - // Cached blob is current, load it - m_blob.load(db_blob); - m_blob_hmac = server_hmac; + m_cache.get_key_value("client_blob", { [this, &server_hmac](const auto& db_blob) GDK_REQUIRES(m_mutex) { + if (db_blob) { + std::string db_hmac = client_blob::compute_hmac(m_blob_key.get(), *db_blob); + if (db_hmac == server_hmac) { + // Cached blob is current, load it + m_blob.load(*db_blob); + m_blob_hmac = server_hmac; + } } - } + } }); } if (m_blob_hmac.empty()) {