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" #include "storage.h"
Cache::Cache(const char* zName, Cache::Cache(const char* zName,
CACHE_CONFIG& config, const CACHE_CONFIG* pConfig,
CACHE_RULES* pRules, CACHE_RULES* pRules,
StorageFactory* pFactory) StorageFactory* pFactory)
: m_zName(zName) : m_zName(zName)
, m_config(config) , m_config(*pConfig)
, m_pRules(pRules) , m_pRules(pRules)
, m_pFactory(pFactory) , m_pFactory(pFactory)
{ {
cache_config_reset(config);
} }
Cache::~Cache() Cache::~Cache()
@ -39,11 +38,9 @@ Cache::~Cache()
//static //static
bool Cache::Create(const CACHE_CONFIG& config, bool Cache::Create(const CACHE_CONFIG& config,
CACHE_RULES** ppRules, CACHE_RULES** ppRules)
StorageFactory** ppFactory)
{ {
CACHE_RULES* pRules = NULL; CACHE_RULES* pRules = NULL;
StorageFactory* pFactory = NULL;
if (config.rules) if (config.rules)
{ {
@ -55,29 +52,42 @@ bool Cache::Create(const CACHE_CONFIG& config,
} }
if (pRules) 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; *ppRules = pRules;
*ppFactory = pFactory;
} }
else else
{ {
cache_rules_free(pRules); MXS_ERROR("Could not create rules.");
delete pFactory;
} }
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) bool Cache::shouldStore(const char* zDefaultDb, const GWBUF* pQuery)

View File

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

View File

@ -14,6 +14,7 @@
#define MXS_MODULE_NAME "cache" #define MXS_MODULE_NAME "cache"
#include "cachefilter.h" #include "cachefilter.h"
#include <exception> #include <exception>
#include <new>
#include <maxscale/alloc.h> #include <maxscale/alloc.h>
#include <maxscale/filter.h> #include <maxscale/filter.h>
#include <maxscale/gwdirs.h> #include <maxscale/gwdirs.h>
@ -35,6 +36,28 @@ static const CACHE_CONFIG DEFAULT_CONFIG =
CACHE_DEFAULT_DEBUG 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 FILTER* createInstance(const char* zName, char** pzOptions, FILTER_PARAMETER** ppParams);
static void* newSession(FILTER* pInstance, SESSION* pSession); static void* newSession(FILTER* pInstance, SESSION* pSession);
static void closeSession(FILTER* pInstance, void* pSessionData); 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) static FILTER *createInstance(const char* zName, char** pzOptions, FILTER_PARAMETER** ppParams)
{ {
Cache* pCache = NULL; CACHE_FILTER* pFilter = new (std::nothrow) CACHE_FILTER;
CACHE_CONFIG config = DEFAULT_CONFIG;
if (process_params(pzOptions, ppParams, config)) if (pFilter)
{ {
CPP_GUARD(pCache = CacheMT::Create(zName, config)); if (process_params(pzOptions, ppParams, pFilter->config))
if (!pCache)
{ {
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) 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; SessionCache* pSessionCache = NULL;
CPP_GUARD(pSessionCache = SessionCache::Create(pCache, pSession)); 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.rules);
MXS_FREE(config.storage); MXS_FREE(config.storage);
MXS_FREE(config.storage_options); MXS_FREE(config.storage_options);
MXS_FREE(config.storage_argv); // The items need not be freed, they point into storage_options.
for (int i = 0; i < config.storage_argc; ++i)
{
MXS_FREE(config.storage_argv[i]);
}
config.max_resultset_rows = 0; config.max_resultset_rows = 0;
config.max_resultset_size = 0; config.max_resultset_size = 0;

View File

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

View File

@ -60,15 +60,15 @@ int hashcmp(const void* address1, const void* address2)
} }
CacheSimple::CacheSimple(const char* zName, CacheSimple::CacheSimple(const char* zName,
CACHE_CONFIG& config, const CACHE_CONFIG* pConfig,
CACHE_RULES* pRules, CACHE_RULES* pRules,
StorageFactory* pFactory, StorageFactory* pFactory,
Storage* pStorage, HASHTABLE* pPending,
HASHTABLE* pPending) Storage* pStorage)
: Cache(zName, config, pRules, pFactory) : Cache(zName, pConfig, pRules, pFactory)
, m_pStorage(pStorage)
, m_pPending(pPending) , m_pPending(pPending)
, m_pStorage(pStorage)
{ {
} }
@ -79,33 +79,51 @@ CacheSimple::~CacheSimple()
} }
// static protected // static
bool CacheSimple::Create(const CACHE_CONFIG& config, bool CacheSimple::Create(const CACHE_CONFIG& config,
CACHE_RULES** ppRules, CACHE_RULES** ppRules,
StorageFactory** ppFactory,
HASHTABLE** ppPending) HASHTABLE** ppPending)
{ {
int rv = false; 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; CACHE_RULES* pRules = NULL;
StorageFactory* pFactory = NULL; StorageFactory* pFactory = NULL;
HASHTABLE* pPending = 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); *ppRules = pRules;
*ppPending = pPending;
if (pPending) *ppFactory = pFactory;
{ }
*ppRules = pRules; else
*ppPending = pPending; {
*ppFactory = pFactory; cache_rules_free(pRules);
} delete pFactory;
else
{
cache_rules_free(pRules);
delete pFactory;
}
} }
return pPending != NULL; 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_debug(int n =) hashtable_delete(m_pPending, (void*)key);
ss_dassert(n == 1); 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); cache_result_t delValue(const CACHE_KEY& key);
protected: protected:
CacheSimple(const char* zName, CacheSimple(const char* zName,
CACHE_CONFIG& config, const CACHE_CONFIG* pConfig,
CACHE_RULES* pRules, CACHE_RULES* pRules,
StorageFactory* pFactory, StorageFactory* pFactory,
Storage* pStorage, HASHTABLE* pPending,
HASHTABLE* pPending); Storage* pStorage);
static bool Create(const CACHE_CONFIG& config, static bool Create(const CACHE_CONFIG& config,
CACHE_RULES** ppRules, CACHE_RULES** ppRules,
StorageFactory** ppFactory,
HASHTABLE** ppPending); HASHTABLE** ppPending);
static bool Create(const CACHE_CONFIG& config,
CACHE_RULES** ppRules,
HASHTABLE** ppPending,
StorageFactory** ppFactory);
long hashOfKey(const CACHE_KEY& key); long hashOfKey(const CACHE_KEY& key);
bool mustRefresh(long key, const SessionCache* pSessionCache); bool mustRefresh(long key, const SessionCache* pSessionCache);
@ -54,7 +59,9 @@ private:
CacheSimple(const Cache&); CacheSimple(const Cache&);
CacheSimple& operator = (const CacheSimple&); CacheSimple& operator = (const CacheSimple&);
static bool Create(HASHTABLE** ppPending);
protected: protected:
Storage* m_pStorage; // The storage instance to use.
HASHTABLE* m_pPending; // Pending items; being fetched from the backend. 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" #include "storagefactory.h"
CacheST::CacheST(const char* zName, CacheST::CacheST(const char* zName,
CACHE_CONFIG& config, const CACHE_CONFIG* pConfig,
CACHE_RULES* pRules, CACHE_RULES* pRules,
StorageFactory* pFactory, StorageFactory* pFactory,
Storage* pStorage, HASHTABLE* pPending,
HASHTABLE* pPending) Storage* pStorage)
: CacheSimple(zName, config, pRules, pFactory, pStorage, pPending) : 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; CacheST* pCache = NULL;
CACHE_RULES* pRules = NULL; CACHE_RULES* pRules = NULL;
HASHTABLE* pPending = NULL; HASHTABLE* pPending = NULL;
StorageFactory* pFactory = NULL; StorageFactory* pFactory = NULL;
if (CacheSimple::Create(config, &pRules, &pFactory, &pPending)) if (CacheSimple::Create(*pConfig, &pRules, &pPending, &pFactory))
{ {
uint32_t ttl = config.ttl; pCache = Create(zName, pConfig, pRules, pFactory, pPending);
int argc = config.storage_argc; }
char** argv = config.storage_argv;
Storage* pStorage = pFactory->createStorage(CACHE_THREAD_MODEL_ST, zName, ttl, argc, argv); return pCache;
}
if (pStorage) // static
{ CacheST* CacheST::Create(const char* zName, StorageFactory* pFactory, const CACHE_CONFIG* pConfig)
CPP_GUARD(pCache = new CacheST(zName, {
config, ss_dassert(pConfig);
pRules, ss_dassert(pFactory);
pFactory,
pStorage,
pPending));
if (!pCache) CacheST* pCache = NULL;
{
cache_rules_free(pRules); CACHE_RULES* pRules = NULL;
hashtable_free(pPending); HASHTABLE* pPending = NULL;
delete pStorage;
delete pFactory; if (CacheSimple::Create(*pConfig, &pRules, &pPending))
} {
} pCache = Create(zName, pConfig, pRules, pFactory, pPending);
} }
return pCache; return pCache;
@ -80,3 +79,39 @@ void CacheST::refreshed(const CACHE_KEY& key, const SessionCache* pSessionCache
CacheSimple::refreshed(k, 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: public:
~CacheST(); ~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); bool mustRefresh(const CACHE_KEY& key, const SessionCache* pSessionCache);
void refreshed(const CACHE_KEY& key, const SessionCache* pSessionCache); void refreshed(const CACHE_KEY& key, const SessionCache* pSessionCache);
private: private:
CacheST(const char* zName, CacheST(const char* zName,
CACHE_CONFIG& config, const CACHE_CONFIG* pConfig,
CACHE_RULES* pRules, CACHE_RULES* pRules,
StorageFactory* pFactory, StorageFactory* pFactory,
Storage* pStorage, HASHTABLE* pPending,
HASHTABLE* pPending); Storage* pStorage);
static CacheST* Create(const char* zName,
const CACHE_CONFIG* pConfig,
CACHE_RULES* pRules,
StorageFactory* pFactory,
HASHTABLE* pPending);
private: private:
CacheST(const CacheST&); CacheST(const CacheST&);
CacheST& operator = (const CacheST&); CacheST& operator = (const CacheST&);