MXS-1475 Allow caller to specify (soft|hard) TTL

As the TTL is checked at lookup time, it need not be hardwired
when the storage instance is created. With this changed it is
possible to introduce @maxscale.cache.(soft|hard)_ttl user
variables using which a client can control what TTL should be
applied for a particular kind of data, which is requested by
MXS-1475.
This commit is contained in:
Johan Wikman
2018-03-15 13:15:46 +02:00
parent 0ef902621d
commit 2c49f90bc4
24 changed files with 131 additions and 33 deletions

View File

@ -119,6 +119,8 @@ public:
*/
virtual cache_result_t get_value(const CACHE_KEY& key,
uint32_t flags,
uint32_t soft_ttl,
uint32_t hard_ttl,
GWBUF** ppValue) const = 0;
/**

View File

@ -209,17 +209,26 @@ typedef struct cache_storage_api
* @param storage Pointer to a CACHE_STORAGE.
* @param key A key generated with get_key.
* @param flags Mask of cache_flags_t values.
* @param soft_ttl The soft TTL. A value if CACHE_USE_CONFIG_TTL (-1) indicates
* that the value specfied in the config, used in the creation,
* should be used.
* @param hard_ttl The hard TTL. A value if CACHE_USE_CONFIG_TTL (-1) indicates
* that the value specfied in the config, used in the creation,
* should be used.
* @param result Pointer to variable that after a successful return will
* point to a GWBUF.
*
* @return CACHE_RESULT_OK if item was found, CACHE_RESULT_NOT_FOUND if
* item was not found or some other error code. In the OK an NOT_FOUND
* cased, the bit CACHE_RESULT_STALE is set if the item exists but the
* soft TTL has passed.
* cases, the bit CACHE_RESULT_STALE is set if the item exists but the
* soft TTL has passed. In the NOT_FOUND case, the but CACHE_RESULT_DISCARDED
* if the item existed but the hard TTL had passed.
*/
cache_result_t (*getValue)(CACHE_STORAGE* storage,
const CACHE_KEY* key,
uint32_t flags,
uint32_t soft_ttl,
uint32_t hard_ttl,
GWBUF** result);
/**
@ -331,6 +340,12 @@ typedef struct cache_storage_api
uint64_t* items);
} CACHE_STORAGE_API;
#if defined __cplusplus
const uint32_t CACHE_USE_CONFIG_TTL = static_cast<uint32_t>(-1);
#else
#define CACHE_USE_CONFIG_TTL ((uint32_t)-1)
#endif
#define CACHE_STORAGE_ENTRY_POINT "CacheGetStorageAPI"
typedef CACHE_STORAGE_API* (*CacheGetStorageAPIFN)();

View File

@ -190,6 +190,8 @@ CacheFilterSession::CacheFilterSession(MXS_SESSION* pSession, Cache* pCache, cha
, m_is_read_only(true)
, m_use(pCache->config().enabled)
, m_populate(pCache->config().enabled)
, m_soft_ttl(pCache->config().soft_ttl)
, m_hard_ttl(pCache->config().hard_ttl)
{
m_key.data = 0;
@ -1024,7 +1026,7 @@ CacheFilterSession::routing_action_t CacheFilterSession::route_SELECT(cache_acti
{
uint32_t flags = CACHE_FLAGS_INCLUDE_STALE;
GWBUF* pResponse;
cache_result_t result = m_pCache->get_value(m_key, flags, &pResponse);
cache_result_t result = m_pCache->get_value(m_key, flags, m_soft_ttl, m_hard_ttl, &pResponse);
if (CACHE_RESULT_IS_OK(result))
{

View File

@ -164,5 +164,7 @@ private:
bool m_is_read_only;/**< Whether the current trx has been read-only in pratice. */
bool m_use; /**< Whether the cache should be used in this session. */
bool m_populate; /**< Whether the cache should be populated in this session. */
uint32_t m_soft_ttl; /**< The soft TTL used in the session. */
uint32_t m_hard_ttl; /**< The hard TTL used in the session. */
};

View File

@ -130,9 +130,11 @@ cache_result_t CachePT::get_key(const char* zDefault_db, const GWBUF* pQuery, CA
return thread_cache().get_key(zDefault_db, pQuery, pKey);
}
cache_result_t CachePT::get_value(const CACHE_KEY& key, uint32_t flags, GWBUF** ppValue) const
cache_result_t CachePT::get_value(const CACHE_KEY& key,
uint32_t flags, uint32_t soft_ttl, uint32_t hard_ttl,
GWBUF** ppValue) const
{
return thread_cache().get_value(key, flags, ppValue);
return thread_cache().get_value(key, flags, soft_ttl, hard_ttl, ppValue);
}
cache_result_t CachePT::put_value(const CACHE_KEY& key, const GWBUF* pValue)

View File

@ -32,7 +32,9 @@ public:
cache_result_t get_key(const char* zDefault_db, const GWBUF* pQuery, CACHE_KEY* pKey) const;
cache_result_t get_value(const CACHE_KEY& key, uint32_t flags, GWBUF** ppValue) const;
cache_result_t get_value(const CACHE_KEY& key,
uint32_t flags, uint32_t soft_ttl, uint32_t hard_ttl,
GWBUF** ppValue) const;
cache_result_t put_value(const CACHE_KEY& key, const GWBUF* pValue);

View File

@ -52,9 +52,11 @@ bool CacheSimple::Create(const CACHE_CONFIG& config,
cache_result_t CacheSimple::get_value(const CACHE_KEY& key,
uint32_t flags,
uint32_t soft_ttl,
uint32_t hard_ttl,
GWBUF** ppValue) const
{
return m_pStorage->get_value(key, flags, ppValue);
return m_pStorage->get_value(key, flags, soft_ttl, hard_ttl, ppValue);
}
cache_result_t CacheSimple::put_value(const CACHE_KEY& key,

View File

@ -25,7 +25,9 @@ class CacheSimple : public Cache
public:
~CacheSimple();
cache_result_t get_value(const CACHE_KEY& key, uint32_t flags, GWBUF** ppValue) const;
cache_result_t get_value(const CACHE_KEY& key,
uint32_t flags, uint32_t soft_ttl, uint32_t hard_ttl,
GWBUF** ppValue) const;
cache_result_t put_value(const CACHE_KEY& key, const GWBUF* pValue);

View File

@ -74,9 +74,11 @@ cache_result_t LRUStorage::do_get_info(uint32_t what,
cache_result_t LRUStorage::do_get_value(const CACHE_KEY& key,
uint32_t flags,
uint32_t soft_ttl,
uint32_t hard_ttl,
GWBUF** ppValue) const
{
return access_value(APPROACH_GET, key, flags, ppValue);
return access_value(APPROACH_GET, key, flags, soft_ttl, hard_ttl, ppValue);
}
cache_result_t LRUStorage::do_put_value(const CACHE_KEY& key, const GWBUF* pvalue)
@ -171,7 +173,9 @@ cache_result_t LRUStorage::do_get_head(CACHE_KEY* pKey, GWBUF** ppValue) const
while (m_pHead && (CACHE_RESULT_IS_NOT_FOUND(result)))
{
ss_dassert(m_pHead->key());
result = do_get_value(*m_pHead->key(), CACHE_FLAGS_INCLUDE_STALE, ppValue);
result = do_get_value(*m_pHead->key(),
CACHE_FLAGS_INCLUDE_STALE, CACHE_USE_CONFIG_TTL, CACHE_USE_CONFIG_TTL,
ppValue);
}
if (CACHE_RESULT_IS_OK(result))
@ -216,6 +220,8 @@ cache_result_t LRUStorage::do_get_items(uint64_t* pItems) const
cache_result_t LRUStorage::access_value(access_approach_t approach,
const CACHE_KEY& key,
uint32_t flags,
uint32_t soft_ttl,
uint32_t hard_ttl,
GWBUF** ppValue) const
{
cache_result_t result = CACHE_RESULT_NOT_FOUND;
@ -225,7 +231,7 @@ cache_result_t LRUStorage::access_value(access_approach_t approach,
if (existed)
{
result = m_pStorage->get_value(key, flags, ppValue);
result = m_pStorage->get_value(key, flags, soft_ttl, hard_ttl, ppValue);
if (CACHE_RESULT_IS_OK(result))
{

View File

@ -41,6 +41,8 @@ protected:
*/
cache_result_t do_get_value(const CACHE_KEY& key,
uint32_t flags,
uint32_t soft_ttl,
uint32_t hard_ttl,
GWBUF** ppValue) const;
/**
@ -89,13 +91,15 @@ private:
cache_result_t access_value(access_approach_t approach,
const CACHE_KEY& key,
uint32_t flags,
uint32_t soft_ttl,
uint32_t hard_ttl,
GWBUF** ppValue) const;
cache_result_t peek_value(const CACHE_KEY& key,
uint32_t flags,
GWBUF** ppValue) const
{
return access_value(APPROACH_PEEK, key, flags, ppValue);
return access_value(APPROACH_PEEK, key, flags, CACHE_USE_CONFIG_TTL, CACHE_USE_CONFIG_TTL, ppValue);
}
/**

View File

@ -47,11 +47,13 @@ cache_result_t LRUStorageMT::get_info(uint32_t what,
cache_result_t LRUStorageMT::get_value(const CACHE_KEY& key,
uint32_t flags,
uint32_t soft_ttl,
uint32_t hard_ttl,
GWBUF** ppValue) const
{
SpinLockGuard guard(m_lock);
return do_get_value(key, flags, ppValue);
return do_get_value(key, flags, soft_ttl, hard_ttl, ppValue);
}
cache_result_t LRUStorageMT::put_value(const CACHE_KEY& key, const GWBUF* pValue)

View File

@ -28,6 +28,8 @@ public:
cache_result_t get_value(const CACHE_KEY& key,
uint32_t flags,
uint32_t soft_ttl,
uint32_t hard_ttl,
GWBUF** ppValue) const;
cache_result_t put_value(const CACHE_KEY& key,

View File

@ -41,9 +41,11 @@ cache_result_t LRUStorageST::get_info(uint32_t what,
cache_result_t LRUStorageST::get_value(const CACHE_KEY& key,
uint32_t flags,
uint32_t soft_ttl,
uint32_t hard_ttl,
GWBUF** ppValue) const
{
return LRUStorage::do_get_value(key, flags, ppValue);
return LRUStorage::do_get_value(key, flags, soft_ttl, hard_ttl, ppValue);
}
cache_result_t LRUStorageST::put_value(const CACHE_KEY& key, const GWBUF* pValue)

View File

@ -27,6 +27,8 @@ public:
cache_result_t get_value(const CACHE_KEY& key,
uint32_t flags,
uint32_t soft_ttl,
uint32_t hard_ttl,
GWBUF** ppValue) const;
cache_result_t put_value(const CACHE_KEY& key,

View File

@ -47,20 +47,36 @@ public:
/**
* Get a value from the cache.
*
* @param key A key generated with get_key.
* @param flags Mask of cache_flags_t values.
* @param ppValue Pointer to variable that after a successful return will
* point to a GWBUF.
* @param key A key generated with get_key.
* @param flags Mask of cache_flags_t values.
* @param soft_ttl The soft TTL. A value if CACHE_USE_CONFIG_TTL (-1) indicates
* that the value specfied in the config, used in the creation,
* should be used.
* @param hard_ttl The hard TTL. A value if CACHE_USE_CONFIG_TTL (-1) indicates
* that the value specfied in the config, used in the creation,
* should be used.
* @param ppValue Pointer to variable that after a successful return will
* point to a GWBUF.
*
* @return CACHE_RESULT_OK if item was found, CACHE_RESULT_NOT_FOUND if
* item was not found or some other error code. In the OK an NOT_FOUND
* cased, the bit CACHE_RESULT_STALE is set if the item exists but the
* soft TTL has passed.
* cases, the bit CACHE_RESULT_STALE is set if the item exists but the
* soft TTL has passed. In the NOT_FOUND case, the but CACHE_RESULT_DISCARDED
* if the item existed but the hard TTL had passed.
*/
virtual cache_result_t get_value(const CACHE_KEY& key,
uint32_t flags,
uint32_t soft_ttl,
uint32_t hard_ttl,
GWBUF** ppValue) const = 0;
cache_result_t get_value(const CACHE_KEY& key,
uint32_t flags,
GWBUF** ppValue) const
{
return get_value(key, flags, CACHE_USE_CONFIG_TTL, CACHE_USE_CONFIG_TTL, ppValue);
}
/**
* Put a value to the cache.
*

View File

@ -128,7 +128,9 @@ cache_result_t InMemoryStorage::do_get_info(uint32_t what, json_t** ppInfo) cons
return *ppInfo ? CACHE_RESULT_OK : CACHE_RESULT_OUT_OF_RESOURCES;
}
cache_result_t InMemoryStorage::do_get_value(const CACHE_KEY& key, uint32_t flags, GWBUF** ppResult)
cache_result_t InMemoryStorage::do_get_value(const CACHE_KEY& key,
uint32_t flags, uint32_t soft_ttl, uint32_t hard_ttl,
GWBUF** ppResult)
{
cache_result_t result = CACHE_RESULT_NOT_FOUND;
@ -138,12 +140,27 @@ cache_result_t InMemoryStorage::do_get_value(const CACHE_KEY& key, uint32_t flag
{
m_stats.hits += 1;
if (soft_ttl == CACHE_USE_CONFIG_TTL)
{
soft_ttl = m_config.soft_ttl;
}
if (hard_ttl == CACHE_USE_CONFIG_TTL)
{
hard_ttl = m_config.hard_ttl;
}
if (soft_ttl > hard_ttl)
{
soft_ttl = hard_ttl;
}
Entry& entry = i->second;
uint32_t now = time(NULL);
bool is_hard_stale = m_config.hard_ttl == 0 ? false : (now - entry.time > m_config.hard_ttl);
bool is_soft_stale = m_config.soft_ttl == 0 ? false : (now - entry.time > m_config.soft_ttl);
bool is_hard_stale = hard_ttl == 0 ? false : (now - entry.time > hard_ttl);
bool is_soft_stale = soft_ttl == 0 ? false : (now - entry.time > soft_ttl);
bool include_stale = ((flags & CACHE_FLAGS_INCLUDE_STALE) != 0);
if (is_hard_stale)

View File

@ -32,7 +32,9 @@ public:
void get_config(CACHE_STORAGE_CONFIG* pConfig);
virtual cache_result_t get_info(uint32_t what, json_t** ppInfo) const = 0;
virtual cache_result_t get_value(const CACHE_KEY& key, uint32_t flags, GWBUF** ppResult) = 0;
virtual cache_result_t get_value(const CACHE_KEY& key,
uint32_t flags, uint32_t soft_ttl, uint32_t hard_ttl,
GWBUF** ppResult) = 0;
virtual cache_result_t put_value(const CACHE_KEY& key, const GWBUF& value) = 0;
virtual cache_result_t del_value(const CACHE_KEY& key) = 0;
@ -46,7 +48,9 @@ protected:
const CACHE_STORAGE_CONFIG& config);
cache_result_t do_get_info(uint32_t what, json_t** ppInfo) const;
cache_result_t do_get_value(const CACHE_KEY& key, uint32_t flags, GWBUF** ppResult);
cache_result_t do_get_value(const CACHE_KEY& key,
uint32_t flags, uint32_t soft_ttl, uint32_t hard_ttl,
GWBUF** ppResult);
cache_result_t do_put_value(const CACHE_KEY& key, const GWBUF& value);
cache_result_t do_del_value(const CACHE_KEY& key);

View File

@ -42,11 +42,13 @@ cache_result_t InMemoryStorageMT::get_info(uint32_t what, json_t** ppInfo) const
return do_get_info(what, ppInfo);
}
cache_result_t InMemoryStorageMT::get_value(const CACHE_KEY& key, uint32_t flags, GWBUF** ppResult)
cache_result_t InMemoryStorageMT::get_value(const CACHE_KEY& key,
uint32_t flags, uint32_t soft_ttl, uint32_t hard_ttl,
GWBUF** ppResult)
{
SpinLockGuard guard(m_lock);
return do_get_value(key, flags, ppResult);
return do_get_value(key, flags, soft_ttl, hard_ttl, ppResult);
}
cache_result_t InMemoryStorageMT::put_value(const CACHE_KEY& key, const GWBUF& value)

View File

@ -28,7 +28,9 @@ public:
int argc, char* argv[]);
cache_result_t get_info(uint32_t what, json_t** ppInfo) const;
cache_result_t get_value(const CACHE_KEY& key, uint32_t flags, GWBUF** ppResult);
cache_result_t get_value(const CACHE_KEY& key,
uint32_t flags, uint32_t soft_ttl, uint32_t hard_ttl,
GWBUF** ppResult);
cache_result_t put_value(const CACHE_KEY& key, const GWBUF& value);
cache_result_t del_value(const CACHE_KEY& key);

View File

@ -38,9 +38,11 @@ cache_result_t InMemoryStorageST::get_info(uint32_t what, json_t** ppInfo) const
return do_get_info(what, ppInfo);
}
cache_result_t InMemoryStorageST::get_value(const CACHE_KEY& key, uint32_t flags, GWBUF** ppResult)
cache_result_t InMemoryStorageST::get_value(const CACHE_KEY& key,
uint32_t flags, uint32_t soft_ttl, uint32_t hard_ttl,
GWBUF** ppResult)
{
return do_get_value(key, flags, ppResult);
return do_get_value(key, flags, soft_ttl, hard_ttl, ppResult);
}
cache_result_t InMemoryStorageST::put_value(const CACHE_KEY& key, const GWBUF& value)

View File

@ -27,7 +27,9 @@ public:
int argc, char* argv[]);
cache_result_t get_info(uint32_t what, json_t** ppInfo) const;
cache_result_t get_value(const CACHE_KEY& key, uint32_t flags, GWBUF** ppResult);
cache_result_t get_value(const CACHE_KEY& key,
uint32_t flags, uint32_t soft_ttl, uint32_t hard_ttl,
GWBUF** ppResult);
cache_result_t put_value(const CACHE_KEY& key, const GWBUF& pValue);
cache_result_t del_value(const CACHE_KEY& key);

View File

@ -71,6 +71,8 @@ public:
static cache_result_t getValue(CACHE_STORAGE* pCache_storage,
const CACHE_KEY* pKey,
uint32_t flags,
uint32_t soft_ttl,
uint32_t hard_ttl,
GWBUF** ppResult)
{
ss_dassert(pCache_storage);
@ -81,7 +83,7 @@ public:
StorageType* pStorage = reinterpret_cast<StorageType*>(pCache_storage);
MXS_EXCEPTION_GUARD(result = pStorage->get_value(*pKey, flags, ppResult));
MXS_EXCEPTION_GUARD(result = pStorage->get_value(*pKey, flags, soft_ttl, hard_ttl, ppResult));
return result;
}

View File

@ -40,9 +40,11 @@ cache_result_t StorageReal::get_info(uint32_t flags, json_t** ppInfo) const
cache_result_t StorageReal::get_value(const CACHE_KEY& key,
uint32_t flags,
uint32_t soft_ttl,
uint32_t hard_ttl,
GWBUF** ppValue) const
{
return m_pApi->getValue(m_pStorage, &key, flags, ppValue);
return m_pApi->getValue(m_pStorage, &key, flags, soft_ttl, hard_ttl, ppValue);
}
cache_result_t StorageReal::put_value(const CACHE_KEY& key, const GWBUF* pValue)

View File

@ -27,6 +27,8 @@ public:
cache_result_t get_value(const CACHE_KEY& key,
uint32_t flags,
uint32_t soft_ttl,
uint32_t hard_ttl,
GWBUF** ppValue) const;
cache_result_t put_value(const CACHE_KEY& key,