mirror of
https://github.com/MariaDB/server.git
synced 2026-10-23 18:49:29 +03:00
MDEV-37187 hashicorp plugin: avoid expensive clock() in hot path
The plugin used clock() only to timestamp cache entries and measure elapsed time against millisecond timeouts. As shown in MDEV-12345, clock() is prohibitively expensive, and we do not need per-thread or per-process CPU time here, only time differences. Replace clock()/clock_t with the monotonic std::chrono::steady_clock. Timeouts are kept as std::chrono::milliseconds
This commit is contained in:
@@ -27,18 +27,32 @@
|
||||
#include <algorithm>
|
||||
#include <unordered_map>
|
||||
#include <mutex>
|
||||
#include <chrono>
|
||||
|
||||
#define HASHICORP_DEBUG_LOGGING 0
|
||||
|
||||
#define PLUGIN_ERROR_HEADER "hashicorp: "
|
||||
|
||||
typedef std::chrono::steady_clock::time_point time_point;
|
||||
|
||||
static inline time_point now ()
|
||||
{
|
||||
return std::chrono::steady_clock::now();
|
||||
}
|
||||
|
||||
static inline std::chrono::milliseconds elapsed_ms (time_point from,
|
||||
time_point to)
|
||||
{
|
||||
return std::chrono::duration_cast<std::chrono::milliseconds>(to - from);
|
||||
}
|
||||
|
||||
/* Key version information structure: */
|
||||
typedef struct VER_INFO
|
||||
{
|
||||
unsigned int key_version;
|
||||
clock_t timestamp;
|
||||
VER_INFO() : key_version(0), timestamp(0) {};
|
||||
VER_INFO(unsigned int key_version_, clock_t timestamp_) :
|
||||
time_point timestamp;
|
||||
VER_INFO() : key_version(0), timestamp() {};
|
||||
VER_INFO(unsigned int key_version_, time_point timestamp_) :
|
||||
key_version(key_version_), timestamp(timestamp_) {};
|
||||
} VER_INFO;
|
||||
|
||||
@@ -47,13 +61,13 @@ typedef struct KEY_INFO
|
||||
{
|
||||
unsigned int key_id;
|
||||
unsigned int key_version;
|
||||
clock_t timestamp;
|
||||
time_point timestamp;
|
||||
unsigned int length;
|
||||
unsigned char data [MY_AES_MAX_KEY_LENGTH];
|
||||
KEY_INFO() : key_id(0), key_version(0), timestamp(0), length(0) {};
|
||||
KEY_INFO() : key_id(0), key_version(0), timestamp(), length(0) {};
|
||||
KEY_INFO(unsigned int key_id_,
|
||||
unsigned int key_version_,
|
||||
clock_t timestamp_,
|
||||
time_point timestamp_,
|
||||
unsigned int length_) :
|
||||
key_id(key_id_), key_version(key_version_),
|
||||
timestamp(timestamp_), length(length_) {};
|
||||
@@ -154,19 +168,8 @@ private:
|
||||
|
||||
static HCData data;
|
||||
|
||||
static clock_t cache_max_time;
|
||||
static clock_t cache_max_ver_time;
|
||||
|
||||
/*
|
||||
Convert milliseconds to timer ticks with rounding
|
||||
to nearest integer:
|
||||
*/
|
||||
static clock_t ms_to_ticks (long long ms)
|
||||
{
|
||||
long long ticks_1000 = ms * (long long) CLOCKS_PER_SEC;
|
||||
clock_t ticks = (clock_t) (ticks_1000 / 1000);
|
||||
return ticks + ((clock_t) (ticks_1000 % 1000) >= 500);
|
||||
}
|
||||
static std::chrono::milliseconds cache_max_time;
|
||||
static std::chrono::milliseconds cache_max_ver_time;
|
||||
|
||||
void HCData::cache_add (const KEY_INFO& info, bool update_version)
|
||||
{
|
||||
@@ -183,10 +186,9 @@ void HCData::cache_add (const KEY_INFO& info, bool update_version)
|
||||
#if HASHICORP_DEBUG_LOGGING
|
||||
my_printf_error(ER_UNKNOWN_ERROR, PLUGIN_ERROR_HEADER
|
||||
"cache_add: key_id = %u, key_version = %u, "
|
||||
"timestamp = %u, update_version = %u, new version = %u",
|
||||
"update_version = %u, new version = %u",
|
||||
ME_ERROR_LOG_ONLY | ME_NOTE, key_id, key_version,
|
||||
ver_info.timestamp, (int) update_version,
|
||||
ver_info.key_version);
|
||||
(int) update_version, ver_info.key_version);
|
||||
#endif
|
||||
mtx.unlock();
|
||||
}
|
||||
@@ -197,11 +199,11 @@ unsigned int
|
||||
bool with_timeouts)
|
||||
{
|
||||
unsigned int version = key_version;
|
||||
clock_t current_time = clock();
|
||||
time_point current_time = now();
|
||||
mtx.lock();
|
||||
if (key_version == ENCRYPTION_KEY_VERSION_INVALID)
|
||||
{
|
||||
clock_t timestamp;
|
||||
time_point timestamp;
|
||||
VER_MAP::const_iterator ver_iter = latest_version_cache.find(key_id);
|
||||
if (ver_iter != latest_version_cache.end())
|
||||
{
|
||||
@@ -216,13 +218,12 @@ unsigned int
|
||||
#if HASHICORP_DEBUG_LOGGING
|
||||
my_printf_error(ER_UNKNOWN_ERROR, PLUGIN_ERROR_HEADER
|
||||
"cache_get: key_id = %u, key_version = %u, "
|
||||
"last version = %u, version timestamp = %u, "
|
||||
"current time = %u, diff = %u",
|
||||
"last version = %u, diff (ms) = %lld",
|
||||
ME_ERROR_LOG_ONLY | ME_NOTE, key_id, key_version,
|
||||
version, timestamp, current_time,
|
||||
current_time - timestamp);
|
||||
version,
|
||||
(long long) elapsed_ms(timestamp, current_time).count());
|
||||
#endif
|
||||
if (with_timeouts && current_time - timestamp > cache_max_ver_time)
|
||||
if (with_timeouts && elapsed_ms(timestamp, current_time) > cache_max_ver_time)
|
||||
{
|
||||
mtx.unlock();
|
||||
return ENCRYPTION_KEY_VERSION_INVALID;
|
||||
@@ -244,14 +245,13 @@ unsigned int
|
||||
#if HASHICORP_DEBUG_LOGGING
|
||||
my_printf_error(ER_UNKNOWN_ERROR, PLUGIN_ERROR_HEADER
|
||||
"cache_get: key_id = %u, key_version = %u, "
|
||||
"effective version = %u, key data timestamp = %u, "
|
||||
"current time = %u, diff = %u",
|
||||
"effective version = %u, diff (ms) = %lld",
|
||||
ME_ERROR_LOG_ONLY | ME_NOTE, key_id, key_version,
|
||||
version, info.timestamp, current_time,
|
||||
current_time - info.timestamp);
|
||||
version,
|
||||
(long long) elapsed_ms(info.timestamp, current_time).count());
|
||||
#endif
|
||||
unsigned int length= info.length;
|
||||
if (with_timeouts && current_time - info.timestamp > cache_max_time)
|
||||
if (with_timeouts && elapsed_ms(info.timestamp, current_time) > cache_max_time)
|
||||
{
|
||||
return ENCRYPTION_KEY_VERSION_INVALID;
|
||||
}
|
||||
@@ -296,7 +296,7 @@ unsigned int HCData::cache_get_version (unsigned int key_id)
|
||||
unsigned int HCData::cache_check_version (unsigned int key_id)
|
||||
{
|
||||
unsigned int version;
|
||||
clock_t timestamp;
|
||||
time_point timestamp;
|
||||
mtx.lock();
|
||||
VER_MAP::const_iterator ver_iter = latest_version_cache.find(key_id);
|
||||
if (ver_iter != latest_version_cache.end())
|
||||
@@ -316,17 +316,15 @@ unsigned int HCData::cache_check_version (unsigned int key_id)
|
||||
return ENCRYPTION_KEY_VERSION_INVALID;
|
||||
}
|
||||
mtx.unlock();
|
||||
clock_t current_time = clock();
|
||||
time_point current_time = now();
|
||||
#if HASHICORP_DEBUG_LOGGING
|
||||
my_printf_error(ER_UNKNOWN_ERROR, PLUGIN_ERROR_HEADER
|
||||
"cache_check_version: key_id = %u, "
|
||||
"last version = %u, version timestamp = %u, "
|
||||
"current time = %u, diff = %u",
|
||||
"last version = %u, diff (ms) = %lld",
|
||||
ME_ERROR_LOG_ONLY | ME_NOTE, key_id, version,
|
||||
version, timestamp, current_time,
|
||||
current_time - timestamp);
|
||||
(long long) elapsed_ms(timestamp, current_time).count());
|
||||
#endif
|
||||
if (current_time - timestamp <= cache_max_ver_time)
|
||||
if (elapsed_ms(timestamp, current_time) <= cache_max_ver_time)
|
||||
{
|
||||
return version;
|
||||
}
|
||||
@@ -395,7 +393,7 @@ static void cache_timeout_update (MYSQL_THD thd,
|
||||
{
|
||||
long long timeout = * (long long *) save;
|
||||
* (long long *) var_ptr = timeout;
|
||||
cache_max_time = ms_to_ticks(timeout);
|
||||
cache_max_time = std::chrono::milliseconds(timeout);
|
||||
}
|
||||
|
||||
static MYSQL_SYSVAR_LONGLONG(cache_timeout, cache_timeout,
|
||||
@@ -411,7 +409,7 @@ static void
|
||||
{
|
||||
long timeout = * (long *) save;
|
||||
* (long *) var_ptr = timeout;
|
||||
cache_max_ver_time = ms_to_ticks(timeout);
|
||||
cache_max_ver_time = std::chrono::milliseconds(timeout);
|
||||
}
|
||||
|
||||
static MYSQL_SYSVAR_LONG(cache_version_timeout, cache_version_timeout,
|
||||
@@ -784,7 +782,7 @@ unsigned int HCData::get_latest_version (unsigned int key_id)
|
||||
return ENCRYPTION_KEY_VERSION_INVALID;
|
||||
}
|
||||
unsigned int length = (unsigned int) key_len >> 1;
|
||||
KEY_INFO info(key_id, version, clock(), length);
|
||||
KEY_INFO info(key_id, version, now(), length);
|
||||
if (length > sizeof(info.data))
|
||||
{
|
||||
my_printf_error(ER_UNKNOWN_ERROR, PLUGIN_ERROR_HEADER
|
||||
@@ -910,7 +908,7 @@ unsigned int HCData::get_key_from_vault (unsigned int key_id,
|
||||
}
|
||||
if (caching_enabled)
|
||||
{
|
||||
KEY_INFO info(key_id, (unsigned int) version, clock(), length);
|
||||
KEY_INFO info(key_id, (unsigned int) version, now(), length);
|
||||
memcpy(info.data, dstbuf, length);
|
||||
cache_add(info, key_version == ENCRYPTION_KEY_VERSION_INVALID);
|
||||
}
|
||||
@@ -1152,8 +1150,8 @@ No_Secret:
|
||||
}
|
||||
memcpy(vault_url_data, vault_url, vault_url_len);
|
||||
memcpy(vault_url_data + vault_url_len, "/data/", 7);
|
||||
cache_max_time = ms_to_ticks(cache_timeout);
|
||||
cache_max_ver_time = ms_to_ticks(cache_version_timeout);
|
||||
cache_max_time = std::chrono::milliseconds(cache_timeout);
|
||||
cache_max_ver_time = std::chrono::milliseconds(cache_version_timeout);
|
||||
/* Initialize curl: */
|
||||
CURLcode curl_res = curl_global_init(CURL_GLOBAL_ALL);
|
||||
if (curl_res != CURLE_OK)
|
||||
|
||||
Reference in New Issue
Block a user