Cache: Make config and storage factory sharable

In antecipation of a CachePT (cache per thread), rearrange things
so that the storage factory and config can be shared between cache
instances.
This commit is contained in:
Johan Wikman 2016-11-27 15:44:32 +02:00
parent c3319b24a6
commit 4f1f71a05a
9 changed files with 297 additions and 139 deletions

View File

@ -20,15 +20,14 @@
#include "storage.h"
Cache::Cache(const char* zName,
CACHE_CONFIG& config,
const CACHE_CONFIG* pConfig,
CACHE_RULES* pRules,
StorageFactory* pFactory)
: m_zName(zName)
, m_config(config)
, m_config(*pConfig)
, m_pRules(pRules)
, m_pFactory(pFactory)
{
cache_config_reset(config);
}
Cache::~Cache()
@ -39,11 +38,9 @@ Cache::~Cache()
//static
bool Cache::Create(const CACHE_CONFIG& config,
CACHE_RULES** ppRules,
StorageFactory** ppFactory)
CACHE_RULES** ppRules)
{
CACHE_RULES* pRules = NULL;
StorageFactory* pFactory = NULL;
if (config.rules)
{
@ -55,29 +52,42 @@ bool Cache::Create(const CACHE_CONFIG& config,
}
if (pRules)
{
pFactory = StorageFactory::Open(config.storage);
if (!pFactory)
{
MXS_ERROR("Could not open storage factory '%s'.", config.storage);
}
}
bool rv = (pRules && pFactory);
if (rv)
{
*ppRules = pRules;
*ppFactory = pFactory;
}
else
{
cache_rules_free(pRules);
delete pFactory;
MXS_ERROR("Could not create rules.");
}
return rv;
return pRules != NULL;
}
//static
bool Cache::Create(const CACHE_CONFIG& config,
CACHE_RULES** ppRules,
StorageFactory** ppFactory)
{
CACHE_RULES* pRules = NULL;
StorageFactory* pFactory = NULL;
if (Create(config, &pRules))
{
pFactory = StorageFactory::Open(config.storage);
if (pFactory)
{
*ppFactory = pFactory;
*ppRules = pRules;
}
else
{
MXS_ERROR("Could not open storage factory '%s'.", config.storage);
cache_rules_free(pRules);
}
}
return pFactory != NULL;
}
bool Cache::shouldStore(const char* zDefaultDb, const GWBUF* pQuery)

View File

@ -74,10 +74,13 @@ public:
protected:
Cache(const char* zName,
CACHE_CONFIG& config,
const CACHE_CONFIG* pConfig,
CACHE_RULES* pRules,
StorageFactory* pFactory);
static bool Create(const CACHE_CONFIG& config,
CACHE_RULES** ppRules);
static bool Create(const CACHE_CONFIG& config,
CACHE_RULES** ppRules,
StorageFactory** ppFactory);
@ -87,8 +90,8 @@ private:
Cache& operator = (const Cache&);
protected:
const char* m_zName; // The name of the instance; the section name in the config.
CACHE_CONFIG m_config; // The configuration of the cache instance.
CACHE_RULES* m_pRules; // The rules of the cache instance.
StorageFactory* m_pFactory; // The storage factory.
const char* m_zName; // The name of the instance; the section name in the config.
const CACHE_CONFIG& m_config; // The configuration of the cache instance.
CACHE_RULES* m_pRules; // The rules of the cache instance.
StorageFactory* m_pFactory; // The storage factory.
};

View File

@ -14,6 +14,7 @@
#define MXS_MODULE_NAME "cache"
#include "cachefilter.h"
#include <exception>
#include <new>
#include <maxscale/alloc.h>
#include <maxscale/filter.h>
#include <maxscale/gwdirs.h>
@ -35,6 +36,28 @@ static const CACHE_CONFIG DEFAULT_CONFIG =
CACHE_DEFAULT_DEBUG
};
typedef struct cache_filter
{
cache_filter()
: config(DEFAULT_CONFIG)
, pCache(NULL)
{
}
~cache_filter()
{
delete pCache;
cache_config_finish(config);
}
CACHE_CONFIG config;
Cache* pCache;
private:
cache_filter(const cache_filter&);
cache_filter& operator = (const cache_filter&);
} CACHE_FILTER;
static FILTER* createInstance(const char* zName, char** pzOptions, FILTER_PARAMETER** ppParams);
static void* newSession(FILTER* pInstance, SESSION* pSession);
static void closeSession(FILTER* pInstance, void* pSessionData);
@ -114,20 +137,24 @@ extern "C" FILTER_OBJECT *GetModuleObject()
*/
static FILTER *createInstance(const char* zName, char** pzOptions, FILTER_PARAMETER** ppParams)
{
Cache* pCache = NULL;
CACHE_CONFIG config = DEFAULT_CONFIG;
CACHE_FILTER* pFilter = new (std::nothrow) CACHE_FILTER;
if (process_params(pzOptions, ppParams, config))
if (pFilter)
{
CPP_GUARD(pCache = CacheMT::Create(zName, config));
if (!pCache)
if (process_params(pzOptions, ppParams, pFilter->config))
{
cache_config_finish(config);
CPP_GUARD(pFilter->pCache = CacheMT::Create(zName, &pFilter->config));
if (!pFilter->pCache)
{
cache_config_finish(pFilter->config);
delete pFilter;
pFilter = NULL;
}
}
}
return reinterpret_cast<FILTER*>(pCache);
return reinterpret_cast<FILTER*>(pFilter);
}
/**
@ -140,7 +167,8 @@ static FILTER *createInstance(const char* zName, char** pzOptions, FILTER_PARAME
*/
static void *newSession(FILTER* pInstance, SESSION* pSession)
{
Cache* pCache = reinterpret_cast<Cache*>(pInstance);
CACHE_FILTER *pFilter = reinterpret_cast<CACHE_FILTER*>(pInstance);
Cache* pCache = pFilter->pCache;
SessionCache* pSessionCache = NULL;
CPP_GUARD(pSessionCache = SessionCache::Create(pCache, pSession));
@ -447,11 +475,7 @@ void cache_config_finish(CACHE_CONFIG& config)
MXS_FREE(config.rules);
MXS_FREE(config.storage);
MXS_FREE(config.storage_options);
for (int i = 0; i < config.storage_argc; ++i)
{
MXS_FREE(config.storage_argv[i]);
}
MXS_FREE(config.storage_argv); // The items need not be freed, they point into storage_options.
config.max_resultset_rows = 0;
config.max_resultset_size = 0;

View File

@ -16,12 +16,12 @@
#include "storagefactory.h"
CacheMT::CacheMT(const char* zName,
CACHE_CONFIG& config,
const CACHE_CONFIG* pConfig,
CACHE_RULES* pRules,
StorageFactory* pFactory,
Storage* pStorage,
HASHTABLE* pPending)
: CacheSimple(zName, config, pRules, pFactory, pStorage, pPending)
HASHTABLE* pPending,
Storage* pStorage)
: CacheSimple(zName, pConfig, pRules, pFactory, pPending, pStorage)
{
spinlock_init(&m_lockPending);
}
@ -30,39 +30,38 @@ CacheMT::~CacheMT()
{
}
CacheMT* CacheMT::Create(const char* zName, CACHE_CONFIG& config)
CacheMT* CacheMT::Create(const char* zName, const CACHE_CONFIG* pConfig)
{
ss_dassert(pConfig);
CacheMT* pCache = NULL;
CACHE_RULES* pRules = NULL;
HASHTABLE* pPending = NULL;
StorageFactory* pFactory = NULL;
if (CacheSimple::Create(config, &pRules, &pFactory, &pPending))
if (CacheSimple::Create(*pConfig, &pRules, &pPending, &pFactory))
{
uint32_t ttl = config.ttl;
int argc = config.storage_argc;
char** argv = config.storage_argv;
pCache = Create(zName, pConfig, pRules, pFactory, pPending);
}
Storage* pStorage = pFactory->createStorage(CACHE_THREAD_MODEL_MT, zName, ttl, argc, argv);
return pCache;
}
if (pStorage)
{
CPP_GUARD(pCache = new CacheMT(zName,
config,
pRules,
pFactory,
pStorage,
pPending));
// static
CacheMT* CacheMT::Create(const char* zName, StorageFactory* pFactory, const CACHE_CONFIG* pConfig)
{
ss_dassert(pConfig);
ss_dassert(pFactory);
if (!pCache)
{
cache_rules_free(pRules);
hashtable_free(pPending);
delete pStorage;
delete pFactory;
}
}
CacheMT* pCache = NULL;
CACHE_RULES* pRules = NULL;
HASHTABLE* pPending = NULL;
if (CacheSimple::Create(*pConfig, &pRules, &pPending))
{
pCache = Create(zName, pConfig, pRules, pFactory, pPending);
}
return pCache;
@ -87,3 +86,39 @@ void CacheMT::refreshed(const CACHE_KEY& key, const SessionCache* pSessionCache
CacheSimple::refreshed(k, pSessionCache);
spinlock_release(&m_lockPending);
}
// static
CacheMT* CacheMT::Create(const char* zName,
const CACHE_CONFIG* pConfig,
CACHE_RULES* pRules,
StorageFactory* pFactory,
HASHTABLE* pPending)
{
CacheMT* pCache = NULL;
uint32_t ttl = pConfig->ttl;
int argc = pConfig->storage_argc;
char** argv = pConfig->storage_argv;
Storage* pStorage = pFactory->createStorage(CACHE_THREAD_MODEL_MT, zName, ttl, argc, argv);
if (pStorage)
{
CPP_GUARD(pCache = new CacheMT(zName,
pConfig,
pRules,
pFactory,
pPending,
pStorage));
if (!pCache)
{
delete pStorage;
cache_rules_free(pRules);
hashtable_free(pPending);
delete pFactory;
}
}
return pCache;
}

View File

@ -21,19 +21,26 @@ class CacheMT : public CacheSimple
public:
~CacheMT();
static CacheMT* Create(const char* zName, CACHE_CONFIG& config);
static CacheMT* Create(const char* zName, const CACHE_CONFIG* pConfig);
static CacheMT* Create(const char* zName, StorageFactory* pFactory, const CACHE_CONFIG* pConfig);
bool mustRefresh(const CACHE_KEY& key, const SessionCache* pSessionCache);
void refreshed(const CACHE_KEY& key, const SessionCache* pSessionCache);
private:
CacheMT(const char* zName,
CACHE_CONFIG& config,
CACHE_RULES* pRules,
StorageFactory* pFactory,
Storage* pStorage,
HASHTABLE* pPending);
CacheMT(const char* zName,
const CACHE_CONFIG* pConfig,
CACHE_RULES* pRules,
StorageFactory* pFactory,
HASHTABLE* pPending,
Storage* pStorage);
static CacheMT* Create(const char* zName,
const CACHE_CONFIG* pConfig,
CACHE_RULES* pRules,
StorageFactory* pFactory,
HASHTABLE* pPending);
private:
CacheMT(const CacheMT&);

View File

@ -60,15 +60,15 @@ int hashcmp(const void* address1, const void* address2)
}
CacheSimple::CacheSimple(const char* zName,
CACHE_CONFIG& config,
CACHE_RULES* pRules,
StorageFactory* pFactory,
Storage* pStorage,
HASHTABLE* pPending)
: Cache(zName, config, pRules, pFactory)
, m_pStorage(pStorage)
CacheSimple::CacheSimple(const char* zName,
const CACHE_CONFIG* pConfig,
CACHE_RULES* pRules,
StorageFactory* pFactory,
HASHTABLE* pPending,
Storage* pStorage)
: Cache(zName, pConfig, pRules, pFactory)
, m_pPending(pPending)
, m_pStorage(pStorage)
{
}
@ -79,33 +79,51 @@ CacheSimple::~CacheSimple()
}
// static protected
// static
bool CacheSimple::Create(const CACHE_CONFIG& config,
CACHE_RULES** ppRules,
StorageFactory** ppFactory,
HASHTABLE** ppPending)
{
int rv = false;
CACHE_RULES* pRules = NULL;
HASHTABLE* pPending = NULL;
if (Cache::Create(config, &pRules) && Create(&pPending))
{
*ppRules = pRules;
*ppPending = pPending;
}
else
{
cache_rules_free(pRules);
}
return pPending != NULL;;
}
// static
bool CacheSimple::Create(const CACHE_CONFIG& config,
CACHE_RULES** ppRules,
HASHTABLE** ppPending,
StorageFactory** ppFactory)
{
int rv = false;
CACHE_RULES* pRules = NULL;
StorageFactory* pFactory = NULL;
HASHTABLE* pPending = NULL;
if (Cache::Create(config, &pRules, &pFactory))
if (Cache::Create(config, &pRules, &pFactory) && Create(&pPending))
{
pPending = hashtable_alloc(CACHE_PENDING_ITEMS, hashfn, hashcmp);
if (pPending)
{
*ppRules = pRules;
*ppPending = pPending;
*ppFactory = pFactory;
}
else
{
cache_rules_free(pRules);
delete pFactory;
}
*ppRules = pRules;
*ppPending = pPending;
*ppFactory = pFactory;
}
else
{
cache_rules_free(pRules);
delete pFactory;
}
return pPending != NULL;
@ -162,3 +180,16 @@ void CacheSimple::refreshed(long key, const SessionCache* pSessionCache)
ss_debug(int n =) hashtable_delete(m_pPending, (void*)key);
ss_dassert(n == 1);
}
// static
bool CacheSimple::Create(HASHTABLE** ppPending)
{
HASHTABLE* pPending = hashtable_alloc(CACHE_PENDING_ITEMS, hashfn, hashcmp);
if (pPending)
{
*ppPending = pPending;
}
return pPending != NULL;
}

View File

@ -32,18 +32,23 @@ public:
cache_result_t delValue(const CACHE_KEY& key);
protected:
CacheSimple(const char* zName,
CACHE_CONFIG& config,
CACHE_RULES* pRules,
StorageFactory* pFactory,
Storage* pStorage,
HASHTABLE* pPending);
CacheSimple(const char* zName,
const CACHE_CONFIG* pConfig,
CACHE_RULES* pRules,
StorageFactory* pFactory,
HASHTABLE* pPending,
Storage* pStorage);
static bool Create(const CACHE_CONFIG& config,
CACHE_RULES** ppRules,
StorageFactory** ppFactory,
HASHTABLE** ppPending);
static bool Create(const CACHE_CONFIG& config,
CACHE_RULES** ppRules,
HASHTABLE** ppPending,
StorageFactory** ppFactory);
long hashOfKey(const CACHE_KEY& key);
bool mustRefresh(long key, const SessionCache* pSessionCache);
@ -54,7 +59,9 @@ private:
CacheSimple(const Cache&);
CacheSimple& operator = (const CacheSimple&);
static bool Create(HASHTABLE** ppPending);
protected:
Storage* m_pStorage; // The storage instance to use.
HASHTABLE* m_pPending; // Pending items; being fetched from the backend.
Storage* m_pStorage; // The storage instance to use.
};

View File

@ -16,12 +16,12 @@
#include "storagefactory.h"
CacheST::CacheST(const char* zName,
CACHE_CONFIG& config,
const CACHE_CONFIG* pConfig,
CACHE_RULES* pRules,
StorageFactory* pFactory,
Storage* pStorage,
HASHTABLE* pPending)
: CacheSimple(zName, config, pRules, pFactory, pStorage, pPending)
HASHTABLE* pPending,
Storage* pStorage)
: CacheSimple(zName, pConfig, pRules, pFactory, pPending, pStorage)
{
}
@ -29,39 +29,38 @@ CacheST::~CacheST()
{
}
CacheST* CacheST::Create(const char* zName, CACHE_CONFIG& config)
CacheST* CacheST::Create(const char* zName, const CACHE_CONFIG* pConfig)
{
ss_dassert(pConfig);
CacheST* pCache = NULL;
CACHE_RULES* pRules = NULL;
HASHTABLE* pPending = NULL;
StorageFactory* pFactory = NULL;
if (CacheSimple::Create(config, &pRules, &pFactory, &pPending))
if (CacheSimple::Create(*pConfig, &pRules, &pPending, &pFactory))
{
uint32_t ttl = config.ttl;
int argc = config.storage_argc;
char** argv = config.storage_argv;
pCache = Create(zName, pConfig, pRules, pFactory, pPending);
}
Storage* pStorage = pFactory->createStorage(CACHE_THREAD_MODEL_ST, zName, ttl, argc, argv);
return pCache;
}
if (pStorage)
{
CPP_GUARD(pCache = new CacheST(zName,
config,
pRules,
pFactory,
pStorage,
pPending));
// static
CacheST* CacheST::Create(const char* zName, StorageFactory* pFactory, const CACHE_CONFIG* pConfig)
{
ss_dassert(pConfig);
ss_dassert(pFactory);
if (!pCache)
{
cache_rules_free(pRules);
hashtable_free(pPending);
delete pStorage;
delete pFactory;
}
}
CacheST* pCache = NULL;
CACHE_RULES* pRules = NULL;
HASHTABLE* pPending = NULL;
if (CacheSimple::Create(*pConfig, &pRules, &pPending))
{
pCache = Create(zName, pConfig, pRules, pFactory, pPending);
}
return pCache;
@ -80,3 +79,39 @@ void CacheST::refreshed(const CACHE_KEY& key, const SessionCache* pSessionCache
CacheSimple::refreshed(k, pSessionCache);
}
// statis
CacheST* CacheST::Create(const char* zName,
const CACHE_CONFIG* pConfig,
CACHE_RULES* pRules,
StorageFactory* pFactory,
HASHTABLE* pPending)
{
CacheST* pCache = NULL;
uint32_t ttl = pConfig->ttl;
int argc = pConfig->storage_argc;
char** argv = pConfig->storage_argv;
Storage* pStorage = pFactory->createStorage(CACHE_THREAD_MODEL_ST, zName, ttl, argc, argv);
if (pStorage)
{
CPP_GUARD(pCache = new CacheST(zName,
pConfig,
pRules,
pFactory,
pPending,
pStorage));
if (!pCache)
{
delete pStorage;
cache_rules_free(pRules);
hashtable_free(pPending);
delete pFactory;
}
}
return pCache;
}

View File

@ -20,20 +20,26 @@ class CacheST : public CacheSimple
public:
~CacheST();
static CacheST* Create(const char* zName, CACHE_CONFIG& config);
static CacheST* Create(const char* zName, const CACHE_CONFIG* pConfig);
static CacheST* Create(const char* zName, StorageFactory* pFactory, const CACHE_CONFIG* pConfig);
bool mustRefresh(const CACHE_KEY& key, const SessionCache* pSessionCache);
void refreshed(const CACHE_KEY& key, const SessionCache* pSessionCache);
private:
CacheST(const char* zName,
CACHE_CONFIG& config,
CACHE_RULES* pRules,
StorageFactory* pFactory,
Storage* pStorage,
HASHTABLE* pPending);
CacheST(const char* zName,
const CACHE_CONFIG* pConfig,
CACHE_RULES* pRules,
StorageFactory* pFactory,
HASHTABLE* pPending,
Storage* pStorage);
static CacheST* Create(const char* zName,
const CACHE_CONFIG* pConfig,
CACHE_RULES* pRules,
StorageFactory* pFactory,
HASHTABLE* pPending);
private:
CacheST(const CacheST&);
CacheST& operator = (const CacheST&);