Skip to content

Commit

Permalink
Don't create an unneeded blob copy when reading name/value cache items
Browse files Browse the repository at this point in the history
  • Loading branch information
jgriffiths committed Jan 21, 2021
1 parent 83dc284 commit e1f22a4
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 26 deletions.
23 changes: 21 additions & 2 deletions src/ga_cache.cpp
Expand Up @@ -210,6 +210,25 @@ namespace sdk {
return result;
}

static void get_blob(std::unique_ptr<sqlite3_stmt>& 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<const unsigned char*>(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<sqlite3_stmt>& stmt, int column, byte_span_t blob)
{
GDK_RUNTIME_ASSERT(
Expand Down Expand Up @@ -338,13 +357,13 @@ namespace sdk {
step_final(m_stmt_key_value_delete);
}

boost::optional<std::vector<unsigned char>> 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)
Expand Down
3 changes: 2 additions & 1 deletion src/ga_cache.hpp
Expand Up @@ -32,7 +32,8 @@ namespace sdk {
boost::optional<std::vector<unsigned char>> 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<std::vector<unsigned char>> get_key_value(const std::string& key);
typedef std::function<void(boost::optional<byte_span_t>)> 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);
Expand Down
49 changes: 26 additions & 23 deletions src/ga_session.cpp
Expand Up @@ -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) {
Expand All @@ -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;
}

Expand Down Expand Up @@ -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()) {
Expand Down

0 comments on commit e1f22a4

Please sign in to comment.