Cache: Introduce soft and hard TTL
- Hard TTL; the maximum time a value will be used from the cache. - Soft TLL; the time after which the cache value should be updated from the server. So as not to unnecessarily fetch the same value multiple times, when the soft TTL has been reached, the value will be updated for the first client, while all other clients will use the stale value until it has become updated. With different soft and hard TTLs there is a definite upper bound for how old a value can be used.
This commit is contained in:
@ -13,7 +13,8 @@ existing service.
|
||||
[Cache]
|
||||
type=filter
|
||||
module=cache
|
||||
ttl=5
|
||||
hard_ttl=30
|
||||
soft_ttl=20
|
||||
storage=...
|
||||
storage_options=...
|
||||
rules=...
|
||||
@ -59,6 +60,34 @@ depend upon the specific module. For instance,
|
||||
storage_options=storage_specific_option1=value1,storage_specific_option2=value2
|
||||
```
|
||||
|
||||
#### `hard_ttl`
|
||||
|
||||
_Hard time to live_; the maximum amount of time - in seconds - the cached
|
||||
result is used before it is discarded and the result is fetched from the
|
||||
backend (and cached). See also `soft_ttl` below.
|
||||
|
||||
```
|
||||
hard_ttl=60
|
||||
```
|
||||
The default value is `0`, which means no limit.
|
||||
|
||||
#### `soft_ttl`
|
||||
|
||||
_Soft time to live_; the amount of time - in seconds - the cached result is
|
||||
used before it is refreshed from the server. When `soft_ttl` has passed, the
|
||||
result will be refreshed when the _first_ client requests the value.
|
||||
|
||||
However, as long as `hard_ttl` has not passed, _all_ other clients requesting
|
||||
the same value will use the result from the cache while it is being fetched
|
||||
from the backend. That is, as long as `soft_ttl` but not `hard_ttl` has passed,
|
||||
even if several clients request the same value at the same time, there will be
|
||||
just one request to the backend.
|
||||
```
|
||||
soft_ttl=60
|
||||
```
|
||||
The default value is `0`, which means no limit. If the value of `soft_ttl` is
|
||||
larger than `hard_ttl` it will be adjusted down to the same value.
|
||||
|
||||
#### `max_resultset_rows`
|
||||
|
||||
Specifies the maximum number of rows a resultset can have in order to be
|
||||
@ -78,16 +107,6 @@ max_resultset_size=128
|
||||
```
|
||||
The default value is `0`, which means no limit.
|
||||
|
||||
#### `ttl`
|
||||
|
||||
_Time to live_; the amount of time - in seconds - the cached result is used
|
||||
before it is refreshed from the server.
|
||||
|
||||
```
|
||||
ttl=60
|
||||
```
|
||||
The default value is `0`, which means no limit.
|
||||
|
||||
#### `max_count`
|
||||
|
||||
The maximum number of items the cache may contain. If the limit has been
|
||||
|
13
server/modules/filter/cache/cache_storage_api.h
vendored
13
server/modules/filter/cache/cache_storage_api.h
vendored
@ -114,11 +114,20 @@ typedef struct cache_storage_config_t
|
||||
cache_thread_model_t thread_model;
|
||||
|
||||
/**
|
||||
* Time to live; number of seconds the value is valid. A value of 0 means
|
||||
* Hard Time-to-live; number of seconds the value is valid. A value of 0 means
|
||||
* that there is no time-to-live, but that the value is considered fresh
|
||||
* as long as it is available.
|
||||
*/
|
||||
uint32_t ttl;
|
||||
uint32_t hard_ttl;
|
||||
|
||||
/**
|
||||
* Soft Time-to-live; number of seconds the value is valid. A value of 0 means
|
||||
* that there is no time-to-live, but that the value is considered fresh
|
||||
* as long as it is available. When the soft TTL has passed, but the hard TTL
|
||||
* has not yet been reached, the stale cached value will be returned, provided
|
||||
* the flag @c CACHE_FLAGS_INCLUDE_STALE is specified when getting the value.
|
||||
*/
|
||||
uint32_t soft_ttl;
|
||||
|
||||
/**
|
||||
* The maximum number of items the storage may store, before it should
|
||||
|
14
server/modules/filter/cache/cache_storage_api.hh
vendored
14
server/modules/filter/cache/cache_storage_api.hh
vendored
@ -72,20 +72,23 @@ class CacheStorageConfig : public CACHE_STORAGE_CONFIG
|
||||
{
|
||||
public:
|
||||
CacheStorageConfig(cache_thread_model_t thread_model,
|
||||
uint32_t ttl = 0,
|
||||
uint32_t hard_ttl = 0,
|
||||
uint32_t soft_ttl = 0,
|
||||
uint32_t max_count = 0,
|
||||
uint64_t max_size = 0)
|
||||
{
|
||||
this->thread_model = thread_model;
|
||||
this->ttl = ttl;
|
||||
this->hard_ttl = hard_ttl;
|
||||
this->soft_ttl = soft_ttl;
|
||||
this->max_count = max_count;
|
||||
this->max_size = max_count;
|
||||
this->max_size = max_size;
|
||||
}
|
||||
|
||||
CacheStorageConfig()
|
||||
{
|
||||
thread_model = CACHE_THREAD_MODEL_MT;
|
||||
ttl = 0;
|
||||
hard_ttl = 0;
|
||||
soft_ttl = 0;
|
||||
max_count = 0;
|
||||
max_size = 0;
|
||||
}
|
||||
@ -93,7 +96,8 @@ public:
|
||||
CacheStorageConfig(const CACHE_STORAGE_CONFIG& config)
|
||||
{
|
||||
thread_model = config.thread_model;
|
||||
ttl = config.ttl;
|
||||
hard_ttl = config.hard_ttl;
|
||||
soft_ttl = config.soft_ttl;
|
||||
max_count = config.max_count;
|
||||
max_size = config.max_size;
|
||||
}
|
||||
|
34
server/modules/filter/cache/cachefilter.cc
vendored
34
server/modules/filter/cache/cachefilter.cc
vendored
@ -31,12 +31,13 @@ static const CACHE_CONFIG DEFAULT_CONFIG =
|
||||
{
|
||||
CACHE_DEFAULT_MAX_RESULTSET_ROWS,
|
||||
CACHE_DEFAULT_MAX_RESULTSET_SIZE,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
CACHE_DEFAULT_TTL,
|
||||
NULL, // rules
|
||||
NULL, // storage
|
||||
NULL, // storage_options
|
||||
NULL, // storage_argv
|
||||
0, // storage_argc
|
||||
CACHE_DEFAULT_HARD_TTL,
|
||||
CACHE_DEFAULT_SOFT_TTL,
|
||||
CACHE_DEFAULT_MAX_COUNT,
|
||||
CACHE_DEFAULT_MAX_SIZE,
|
||||
CACHE_DEFAULT_DEBUG,
|
||||
@ -62,7 +63,8 @@ void cache_config_finish(CACHE_CONFIG& config)
|
||||
config.storage_options = NULL;
|
||||
config.storage_argc = 0;
|
||||
config.storage_argv = NULL;
|
||||
config.ttl = 0;
|
||||
config.hard_ttl = 0;
|
||||
config.soft_ttl = 0;
|
||||
config.debug = 0;
|
||||
}
|
||||
|
||||
@ -403,9 +405,16 @@ bool CacheFilter::process_params(char **pzOptions, FILTER_PARAMETER **ppParams,
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
else if (strcmp(pParam->name, "ttl") == 0)
|
||||
else if (strcmp(pParam->name, "hard_ttl") == 0)
|
||||
{
|
||||
if (!config_get_uint32(*pParam, &config.ttl))
|
||||
if (!config_get_uint32(*pParam, &config.hard_ttl))
|
||||
{
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
else if (strcmp(pParam->name, "soft_ttl") == 0)
|
||||
{
|
||||
if (!config_get_uint32(*pParam, &config.soft_ttl))
|
||||
{
|
||||
error = true;
|
||||
}
|
||||
@ -470,6 +479,13 @@ bool CacheFilter::process_params(char **pzOptions, FILTER_PARAMETER **ppParams,
|
||||
|
||||
if (!error)
|
||||
{
|
||||
if (config.soft_ttl > config.hard_ttl)
|
||||
{
|
||||
MXS_WARNING("The value of 'soft_ttl' must be less than or equal to that of 'hard_ttl'. "
|
||||
"Setting 'soft_ttl' to the same value as 'hard_ttl'.");
|
||||
config.soft_ttl = config.hard_ttl;
|
||||
}
|
||||
|
||||
if (config.max_size < config.max_resultset_size)
|
||||
{
|
||||
MXS_ERROR("The value of 'max_size' must be at least as larged as that "
|
||||
|
7
server/modules/filter/cache/cachefilter.h
vendored
7
server/modules/filter/cache/cachefilter.h
vendored
@ -43,7 +43,9 @@
|
||||
// Bytes
|
||||
#define CACHE_DEFAULT_MAX_RESULTSET_SIZE 0
|
||||
// Seconds
|
||||
#define CACHE_DEFAULT_TTL 0
|
||||
#define CACHE_DEFAULT_HARD_TTL 0
|
||||
// Seconds
|
||||
#define CACHE_DEFAULT_SOFT_TTL 0
|
||||
// Integer value
|
||||
#define CACHE_DEFAULT_DEBUG 0
|
||||
// Positive integer
|
||||
@ -62,7 +64,8 @@ typedef struct cache_config
|
||||
char* storage_options; /**< Raw options for storage module. */
|
||||
char** storage_argv; /**< Cooked options for storage module. */
|
||||
int storage_argc; /**< Number of cooked options. */
|
||||
uint32_t ttl; /**< Time to live. */
|
||||
uint32_t hard_ttl; /**< Hard time to live. */
|
||||
uint32_t soft_ttl; /**< Soft time to live. */
|
||||
uint64_t max_count; /**< Maximum number of entries in the cache.*/
|
||||
uint64_t max_size; /**< Maximum size of the cache.*/
|
||||
uint32_t debug; /**< Debug settings. */
|
||||
|
3
server/modules/filter/cache/cachemt.cc
vendored
3
server/modules/filter/cache/cachemt.cc
vendored
@ -85,7 +85,8 @@ CacheMT* CacheMT::Create(const std::string& name,
|
||||
CacheMT* pCache = NULL;
|
||||
|
||||
CacheStorageConfig storage_config(CACHE_THREAD_MODEL_MT,
|
||||
pConfig->ttl,
|
||||
pConfig->hard_ttl,
|
||||
pConfig->soft_ttl,
|
||||
pConfig->max_count,
|
||||
pConfig->max_size);
|
||||
|
||||
|
4
server/modules/filter/cache/cachesimple.cc
vendored
4
server/modules/filter/cache/cachesimple.cc
vendored
@ -89,7 +89,9 @@ json_t* CacheSimple::do_get_info(uint32_t what) const
|
||||
{
|
||||
json_t* pStorageInfo;
|
||||
|
||||
if (m_pStorage->get_info(Storage::INFO_ALL, &pStorageInfo) == CACHE_RESULT_OK)
|
||||
cache_result_t result = m_pStorage->get_info(Storage::INFO_ALL, &pStorageInfo);
|
||||
|
||||
if (CACHE_RESULT_IS_OK(result))
|
||||
{
|
||||
json_object_set(pInfo, "storage", pStorageInfo);
|
||||
json_decref(pStorageInfo);
|
||||
|
3
server/modules/filter/cache/cachest.cc
vendored
3
server/modules/filter/cache/cachest.cc
vendored
@ -89,7 +89,8 @@ CacheST* CacheST::Create(const std::string& name,
|
||||
CacheST* pCache = NULL;
|
||||
|
||||
CacheStorageConfig storage_config(CACHE_THREAD_MODEL_ST,
|
||||
pConfig->ttl,
|
||||
pConfig->hard_ttl,
|
||||
pConfig->soft_ttl,
|
||||
pConfig->max_count,
|
||||
pConfig->max_size);
|
||||
|
||||
|
@ -208,10 +208,15 @@ cache_result_t InMemoryStorage::do_get_value(const CACHE_KEY& key, uint32_t flag
|
||||
|
||||
uint32_t now = time(NULL);
|
||||
|
||||
bool is_stale = m_config.ttl == 0 ? false : (now - entry.time > m_config.ttl);
|
||||
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 include_stale = ((flags & CACHE_FLAGS_INCLUDE_STALE) != 0);
|
||||
|
||||
if (!is_stale || include_stale)
|
||||
if (is_hard_stale)
|
||||
{
|
||||
m_entries.erase(i);
|
||||
}
|
||||
else if (!is_soft_stale || include_stale)
|
||||
{
|
||||
size_t length = entry.value.size();
|
||||
|
||||
@ -223,7 +228,7 @@ cache_result_t InMemoryStorage::do_get_value(const CACHE_KEY& key, uint32_t flag
|
||||
|
||||
result = CACHE_RESULT_OK;
|
||||
|
||||
if (is_stale)
|
||||
if (is_soft_stale)
|
||||
{
|
||||
result |= CACHE_RESULT_STALE;
|
||||
}
|
||||
@ -235,7 +240,7 @@ cache_result_t InMemoryStorage::do_get_value(const CACHE_KEY& key, uint32_t flag
|
||||
}
|
||||
else
|
||||
{
|
||||
ss_dassert(is_stale);
|
||||
ss_dassert(is_soft_stale);
|
||||
result |= CACHE_RESULT_STALE;
|
||||
}
|
||||
}
|
||||
|
@ -15,21 +15,14 @@
|
||||
#include "rocksdbinternals.hh"
|
||||
#include <rocksdb/env.h>
|
||||
#include <util/coding.h>
|
||||
#include <maxscale/debug.h>
|
||||
|
||||
/**
|
||||
* Check whether a value is stale or not.
|
||||
*
|
||||
* @param value A value with the timestamp at the end.
|
||||
* @param ttl The time-to-live in seconds.
|
||||
* @param pEnv The used RocksDB environment instance.
|
||||
*
|
||||
* @return True of the value is stale.
|
||||
*
|
||||
* Basically a copy from RocksDB/utilities/ttl/db_ttl_impl.cc:160
|
||||
* but note that the here we claim the data is stale if we fail to
|
||||
* get the time while the original code claims it is fresh.
|
||||
* The following is basically a copy from RocksDB/utilities/ttl/db_ttl_impl.cc:160
|
||||
* but note that the here we claim the data is stale if we fail to get the time
|
||||
* while the original code claims it is fresh.
|
||||
*/
|
||||
bool RocksDBInternals::IsStale(const rocksdb::Slice& value, int32_t ttl, rocksdb::Env* pEnv)
|
||||
bool RocksDBInternals::is_stale(const rocksdb::Slice& value, int32_t ttl, rocksdb::Env* pEnv)
|
||||
{
|
||||
if (ttl <= 0)
|
||||
{ // Data is fresh if TTL is non-positive
|
||||
@ -45,3 +38,9 @@ bool RocksDBInternals::IsStale(const rocksdb::Slice& value, int32_t ttl, rocksdb
|
||||
int32_t timestamp = rocksdb::DecodeFixed32(value.data() + value.size() - TS_LENGTH);
|
||||
return (timestamp + ttl) < curtime;
|
||||
}
|
||||
|
||||
int32_t RocksDBInternals::extract_timestamp(const rocksdb::Slice& value)
|
||||
{
|
||||
ss_dassert(value.size() >= TS_LENGTH);
|
||||
return rocksdb::DecodeFixed32(value.data() + value.size() - TS_LENGTH);
|
||||
}
|
||||
|
@ -32,6 +32,24 @@ namespace RocksDBInternals
|
||||
*/
|
||||
static const uint32_t TS_LENGTH = sizeof(int32_t);
|
||||
|
||||
bool IsStale(const rocksdb::Slice& slice, int32_t ttl, rocksdb::Env* pEnv);
|
||||
/**
|
||||
* Check whether a value is stale or not.
|
||||
*
|
||||
* @param value A value with the timestamp at the end.
|
||||
* @param ttl The time-to-live in seconds.
|
||||
* @param pEnv The used RocksDB environment instance.
|
||||
*
|
||||
* @return True of the value is stale.
|
||||
*/
|
||||
bool is_stale(const rocksdb::Slice& slice, int32_t ttl, rocksdb::Env* pEnv);
|
||||
|
||||
/**
|
||||
* Extract the timestamp from a slice coming from a rocksdb::DBWithTTL.
|
||||
*
|
||||
* @param value The slice whose timestamp should be extracted.
|
||||
*
|
||||
* @return The timestamp
|
||||
*/
|
||||
int32_t extract_timestamp(const rocksdb::Slice& value);
|
||||
|
||||
}
|
||||
|
@ -320,7 +320,7 @@ RocksDBStorage* RocksDBStorage::Create(const char* zName,
|
||||
rocksdb::Status status;
|
||||
rocksdb::Slice key(STORAGE_ROCKSDB_VERSION_KEY);
|
||||
|
||||
status = rocksdb::DBWithTTL::Open(options, path, &pDb, config.ttl);
|
||||
status = rocksdb::DBWithTTL::Open(options, path, &pDb, config.hard_ttl);
|
||||
|
||||
if (status.ok())
|
||||
{
|
||||
@ -464,10 +464,32 @@ cache_result_t RocksDBStorage::get_value(const CACHE_KEY& key, uint32_t flags, G
|
||||
case rocksdb::Status::kOk:
|
||||
if (value.length() >= RocksDBInternals::TS_LENGTH)
|
||||
{
|
||||
bool is_stale = RocksDBInternals::IsStale(value, m_config.ttl, rocksdb::Env::Default());
|
||||
rocksdb::Env* pEnv = rocksdb::Env::Default();
|
||||
int64_t now;
|
||||
|
||||
if (!pEnv->GetCurrentTime(&now).ok())
|
||||
{
|
||||
ss_dassert(!true);
|
||||
now = INT64_MAX;
|
||||
}
|
||||
|
||||
int32_t timestamp = RocksDBInternals::extract_timestamp(value);
|
||||
|
||||
bool is_hard_stale = m_config.hard_ttl == 0 ? false : (now - timestamp > m_config.hard_ttl);
|
||||
bool is_soft_stale = m_config.soft_ttl == 0 ? false : (now - timestamp > m_config.soft_ttl);
|
||||
bool include_stale = ((flags & CACHE_FLAGS_INCLUDE_STALE) != 0);
|
||||
|
||||
if (!is_stale || include_stale)
|
||||
if (is_hard_stale)
|
||||
{
|
||||
status = m_sDb->Delete(Write_options(), rocksdb_key);
|
||||
|
||||
if (!status.ok())
|
||||
{
|
||||
MXS_WARNING("Failed when deleting stale item from RocksDB.");
|
||||
}
|
||||
result = CACHE_RESULT_NOT_FOUND;
|
||||
}
|
||||
else if (!is_soft_stale || include_stale)
|
||||
{
|
||||
size_t length = value.length() - RocksDBInternals::TS_LENGTH;
|
||||
|
||||
@ -479,15 +501,19 @@ cache_result_t RocksDBStorage::get_value(const CACHE_KEY& key, uint32_t flags, G
|
||||
|
||||
result = CACHE_RESULT_OK;
|
||||
|
||||
if (is_stale)
|
||||
if (is_soft_stale)
|
||||
{
|
||||
result |= CACHE_RESULT_STALE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = CACHE_RESULT_OUT_OF_RESOURCES;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ss_dassert(is_stale);
|
||||
ss_dassert(is_soft_stale);
|
||||
result = (CACHE_RESULT_NOT_FOUND | CACHE_RESULT_STALE);
|
||||
}
|
||||
}
|
||||
|
@ -167,7 +167,7 @@ Storage* StorageFactory::createStorage(const char* zName,
|
||||
used_config.max_size = 0;
|
||||
}
|
||||
|
||||
Storage* pStorage = createRawStorage(zName, config, argc, argv);
|
||||
Storage* pStorage = createRawStorage(zName, used_config, argc, argv);
|
||||
|
||||
if (pStorage)
|
||||
{
|
||||
|
@ -274,7 +274,8 @@ int TesterStorage::test_ttl(const CacheItems& cache_items)
|
||||
out() << "ST" << endl;
|
||||
|
||||
config.thread_model = CACHE_THREAD_MODEL_ST;
|
||||
config.ttl = 5;
|
||||
config.hard_ttl = 6;
|
||||
config.soft_ttl = 3;
|
||||
|
||||
Storage* pStorage;
|
||||
|
||||
@ -290,7 +291,8 @@ int TesterStorage::test_ttl(const CacheItems& cache_items)
|
||||
out() << "MT" << endl;
|
||||
|
||||
config.thread_model = CACHE_THREAD_MODEL_MT;
|
||||
config.ttl = 5;
|
||||
config.hard_ttl = 6;
|
||||
config.soft_ttl = 3;
|
||||
|
||||
int rv2 = EXIT_FAILURE;
|
||||
pStorage = get_storage(config);
|
||||
@ -313,12 +315,19 @@ int TesterStorage::test_ttl(const CacheItems& cache_items, Storage& storage)
|
||||
CacheStorageConfig config;
|
||||
storage.get_config(&config);
|
||||
|
||||
uint32_t ttl = config.ttl;
|
||||
uint32_t hard_ttl = config.hard_ttl;
|
||||
uint32_t soft_ttl = config.soft_ttl;
|
||||
uint32_t diff = hard_ttl - soft_ttl;
|
||||
|
||||
if (ttl != 0)
|
||||
if (diff != 0)
|
||||
{
|
||||
ss_dassert(cache_items.size() > 0);
|
||||
|
||||
out() << "Hard TTL: " << hard_ttl << endl;
|
||||
out() << "Soft TTL: " << soft_ttl << endl;
|
||||
|
||||
uint32_t slept = 0;
|
||||
|
||||
const CacheItems::value_type& cache_item = cache_items[0];
|
||||
|
||||
cache_result_t result = storage.put_value(cache_item.first, cache_item.second);
|
||||
@ -330,34 +339,59 @@ int TesterStorage::test_ttl(const CacheItems& cache_items, Storage& storage)
|
||||
}
|
||||
else
|
||||
{
|
||||
sleep(ttl - 1);
|
||||
// Let's stay just below the soft_ttl value.
|
||||
sleep(soft_ttl - 1);
|
||||
slept += soft_ttl - 1;
|
||||
|
||||
GWBUF* pValue;
|
||||
|
||||
pValue = NULL;
|
||||
result = storage.get_value(cache_item.first, 0, &pValue);
|
||||
|
||||
if (!CACHE_RESULT_IS_OK(result))
|
||||
// We should get the item normally as we are below the soft ttl, i.e. no stale bit.
|
||||
if (result != CACHE_RESULT_OK)
|
||||
{
|
||||
out() << "Did not get value withing ttl." << endl;
|
||||
out() << "Excpected to be found, and without stale bit." << endl;
|
||||
rv = EXIT_FAILURE;
|
||||
}
|
||||
|
||||
gwbuf_free(pValue);
|
||||
|
||||
sleep(2); // Should get us past the ttl
|
||||
sleep(2); // Expected to get us passed the soft ttl.
|
||||
slept += 2;
|
||||
|
||||
pValue = NULL;
|
||||
result = storage.get_value(cache_item.first, 0, &pValue);
|
||||
|
||||
// We should not get the item and the stale bit should be on.
|
||||
if (!(CACHE_RESULT_IS_NOT_FOUND(result) && CACHE_RESULT_IS_STALE(result)))
|
||||
{
|
||||
out() << "Expected not to be found, and with stale bit." << endl;
|
||||
rv = EXIT_FAILURE;
|
||||
}
|
||||
|
||||
gwbuf_free(pValue);
|
||||
|
||||
pValue = NULL;
|
||||
result = storage.get_value(cache_item.first, CACHE_FLAGS_INCLUDE_STALE, &pValue);
|
||||
|
||||
if (CACHE_RESULT_IS_OK(result) && !CACHE_RESULT_IS_STALE(result))
|
||||
if (!(CACHE_RESULT_IS_OK(result) && CACHE_RESULT_IS_STALE(result)))
|
||||
{
|
||||
out() << "Got value normally when accepting stale, although ttl has passed." << endl;
|
||||
out() << "Expected to be found, and with stale bit." << endl;
|
||||
rv = EXIT_FAILURE;
|
||||
}
|
||||
else if (!CACHE_RESULT_IS_STALE(result))
|
||||
|
||||
gwbuf_free(pValue);
|
||||
|
||||
sleep(hard_ttl - slept + 1); // Expected to get us passed the hard ttl.
|
||||
slept += hard_ttl - slept + 1;
|
||||
|
||||
pValue = NULL;
|
||||
result = storage.get_value(cache_item.first, CACHE_FLAGS_INCLUDE_STALE, &pValue);
|
||||
|
||||
if (result != CACHE_RESULT_NOT_FOUND)
|
||||
{
|
||||
out() << "Did not get expected stale value after ttl." << endl;
|
||||
out() << "Expected not to be found, and without stale bit." << endl;
|
||||
rv = EXIT_FAILURE;
|
||||
}
|
||||
|
||||
@ -366,23 +400,19 @@ int TesterStorage::test_ttl(const CacheItems& cache_items, Storage& storage)
|
||||
pValue = NULL;
|
||||
result = storage.get_value(cache_item.first, 0, &pValue);
|
||||
|
||||
if (CACHE_RESULT_IS_OK(result))
|
||||
if (result != CACHE_RESULT_NOT_FOUND)
|
||||
{
|
||||
out() << "Got value normally, although ttl has passed." << endl;
|
||||
rv = EXIT_FAILURE;
|
||||
}
|
||||
else if (!CACHE_RESULT_IS_NOT_FOUND(result))
|
||||
{
|
||||
out() << "Unexpected failure." << endl;
|
||||
out() << "Expected not to be found, and without stale bit." << endl;
|
||||
rv = EXIT_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
gwbuf_free(pValue);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
out() << "No ttl, not testing." << endl;
|
||||
out() << "No difference between soft and hard ttl, not testing." << endl;
|
||||
}
|
||||
|
||||
return rv;
|
||||
|
Reference in New Issue
Block a user