Cache: Introduce StorageFactory and Storage
The storage module is abstracted with StorageFactory that is capable of creating Storage instances. The latter contains the data and provides the behaviour for using the actual storage implementation, which sits behing a C API, conveniently.
This commit is contained in:
parent
762da5f2df
commit
10deb9f07b
2
server/modules/filter/cache/CMakeLists.txt
vendored
2
server/modules/filter/cache/CMakeLists.txt
vendored
@ -1,5 +1,5 @@
|
||||
if (JANSSON_FOUND)
|
||||
add_library(cache SHARED cachefilter.cc rules.cc storage.cc)
|
||||
add_library(cache SHARED cachefilter.cc rules.cc storage.cc storagefactory.cc)
|
||||
target_link_libraries(cache maxscale-common jansson)
|
||||
set_target_properties(cache PROPERTIES VERSION "1.0.0")
|
||||
set_target_properties(cache PROPERTIES LINK_FLAGS -Wl,-z,defs)
|
||||
|
29
server/modules/filter/cache/cachefilter.cc
vendored
29
server/modules/filter/cache/cachefilter.cc
vendored
@ -25,6 +25,7 @@
|
||||
#include <maxscale/spinlock.h>
|
||||
#include "rules.h"
|
||||
#include "storage.h"
|
||||
#include "storagefactory.h"
|
||||
|
||||
static char VERSION_STRING[] = "V1.0.0";
|
||||
|
||||
@ -124,8 +125,8 @@ typedef struct cache_instance
|
||||
const char *name; // The name of the instance; the section name in the config.
|
||||
CACHE_CONFIG config; // The configuration of the cache instance.
|
||||
CACHE_RULES *rules; // The rules of the cache instance.
|
||||
CACHE_STORAGE_MODULE *module; // The storage module.
|
||||
CACHE_STORAGE *storage; // The storage API.
|
||||
StorageFactory *factory; // The storage factory.
|
||||
Storage *storage; // The storage instance to use.
|
||||
HASHTABLE *pending; // Pending items; being fetched from the backend.
|
||||
SPINLOCK pending_lock; // Lock used for protecting 'pending'.
|
||||
} CACHE_INSTANCE;
|
||||
@ -154,8 +155,7 @@ static void cache_response_state_reset(CACHE_RESPONSE_STATE *state);
|
||||
typedef struct cache_session_data
|
||||
{
|
||||
CACHE_INSTANCE *instance; /**< The cache instance the session is associated with. */
|
||||
CACHE_STORAGE_API *api; /**< The storage API to be used. */
|
||||
CACHE_STORAGE *storage; /**< The storage to be used with this session data. */
|
||||
Storage *storage; /**< The storage to be used with this session data. */
|
||||
DOWNSTREAM down; /**< The previous filter or equivalent. */
|
||||
UPSTREAM up; /**< The next filter or equivalent. */
|
||||
CACHE_RESPONSE_STATE res; /**< The response state. */
|
||||
@ -268,22 +268,22 @@ static FILTER *createInstance(const char *name, char **options, FILTER_PARAMETER
|
||||
|
||||
if (cinstance && pending)
|
||||
{
|
||||
CACHE_STORAGE_MODULE *module = cache_storage_open(config.storage);
|
||||
StorageFactory *factory = StorageFactory::Open(config.storage);
|
||||
|
||||
if (module)
|
||||
if (factory)
|
||||
{
|
||||
uint32_t ttl = config.ttl;
|
||||
int argc = config.storage_argc;
|
||||
char** argv = config.storage_argv;
|
||||
|
||||
CACHE_STORAGE *storage = module->api->createInstance(name, ttl, argc, argv);
|
||||
Storage *storage = factory->createStorage(name, ttl, argc, argv);
|
||||
|
||||
if (storage)
|
||||
{
|
||||
cinstance->name = name;
|
||||
cinstance->config = config;
|
||||
cinstance->rules = rules;
|
||||
cinstance->module = module;
|
||||
cinstance->factory = factory;
|
||||
cinstance->storage = storage;
|
||||
cinstance->pending = pending;
|
||||
|
||||
@ -293,7 +293,7 @@ static FILTER *createInstance(const char *name, char **options, FILTER_PARAMETER
|
||||
{
|
||||
MXS_ERROR("Could not create storage instance for '%s'.", name);
|
||||
cache_rules_free(rules);
|
||||
cache_storage_close(module);
|
||||
delete factory;
|
||||
MXS_FREE(cinstance);
|
||||
hashtable_free(pending);
|
||||
cinstance = NULL;
|
||||
@ -722,7 +722,6 @@ static CACHE_SESSION_DATA *cache_session_data_create(CACHE_INSTANCE *instance,
|
||||
if ((mysql_session->db[0] == 0) || default_db)
|
||||
{
|
||||
data->instance = instance;
|
||||
data->api = instance->module->api;
|
||||
data->storage = instance->storage;
|
||||
data->session = session;
|
||||
data->state = CACHE_EXPECTING_NOTHING;
|
||||
@ -1202,13 +1201,13 @@ static cache_result_t get_cached_response(CACHE_SESSION_DATA *csdata,
|
||||
const GWBUF *query,
|
||||
GWBUF **value)
|
||||
{
|
||||
cache_result_t result = csdata->api->getKey(csdata->storage, csdata->default_db, query, csdata->key);
|
||||
cache_result_t result = csdata->storage->getKey(csdata->default_db, query, csdata->key);
|
||||
|
||||
if (result == CACHE_RESULT_OK)
|
||||
{
|
||||
uint32_t flags = CACHE_FLAGS_INCLUDE_STALE;
|
||||
|
||||
result = csdata->api->getValue(csdata->storage, csdata->key, flags, value);
|
||||
result = csdata->storage->getValue(csdata->key, flags, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1250,15 +1249,13 @@ static void store_result(CACHE_SESSION_DATA *csdata)
|
||||
{
|
||||
csdata->res.data = data;
|
||||
|
||||
cache_result_t result = csdata->api->putValue(csdata->storage,
|
||||
csdata->key,
|
||||
csdata->res.data);
|
||||
cache_result_t result = csdata->storage->putValue(csdata->key, csdata->res.data);
|
||||
|
||||
if (result != CACHE_RESULT_OK)
|
||||
{
|
||||
MXS_ERROR("Could not store cache item, deleting it.");
|
||||
|
||||
result = csdata->api->delValue(csdata->storage, csdata->key);
|
||||
result = csdata->storage->delValue(csdata->key);
|
||||
|
||||
if ((result != CACHE_RESULT_OK) || (result != CACHE_RESULT_NOT_FOUND))
|
||||
{
|
||||
|
104
server/modules/filter/cache/storage.cc
vendored
104
server/modules/filter/cache/storage.cc
vendored
@ -12,85 +12,37 @@
|
||||
*/
|
||||
|
||||
#include "storage.h"
|
||||
#include <dlfcn.h>
|
||||
#include <sys/param.h>
|
||||
#include <maxscale/alloc.h>
|
||||
#include <maxscale/gwdirs.h>
|
||||
#include <maxscale/log_manager.h>
|
||||
|
||||
CACHE_STORAGE_MODULE* cache_storage_open(const char *name)
|
||||
|
||||
Storage::Storage(CACHE_STORAGE_API* pApi, CACHE_STORAGE* pStorage)
|
||||
: m_pApi(pApi)
|
||||
, m_pStorage(pStorage)
|
||||
{
|
||||
CACHE_STORAGE_MODULE* module = (CACHE_STORAGE_MODULE*)MXS_CALLOC(1, sizeof(CACHE_STORAGE_MODULE));
|
||||
|
||||
if (module)
|
||||
{
|
||||
char path[MAXPATHLEN + 1];
|
||||
sprintf(path, "%s/lib%s.so", get_libdir(), name);
|
||||
|
||||
void *handle = dlopen(path, RTLD_NOW | RTLD_LOCAL);
|
||||
|
||||
if (handle)
|
||||
{
|
||||
module->handle = handle;
|
||||
|
||||
void *f = dlsym(module->handle, CACHE_STORAGE_ENTRY_POINT);
|
||||
|
||||
if (f)
|
||||
{
|
||||
module->api = ((CacheGetStorageAPIFN)f)();
|
||||
|
||||
if (module->api)
|
||||
{
|
||||
if (!(module->api->initialize)())
|
||||
{
|
||||
MXS_ERROR("Initialization of %s failed.", path);
|
||||
|
||||
(void)dlclose(module->handle);
|
||||
MXS_FREE(module);
|
||||
module = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MXS_ERROR("Could not obtain API object from %s.", name);
|
||||
|
||||
(void)dlclose(module->handle);
|
||||
MXS_FREE(module);
|
||||
module = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const char* s = dlerror();
|
||||
MXS_ERROR("Could not look up symbol %s from %s: %s",
|
||||
name, CACHE_STORAGE_ENTRY_POINT, s ? s : "");
|
||||
MXS_FREE(module);
|
||||
module = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const char* s = dlerror();
|
||||
MXS_ERROR("Could not load %s: %s", name, s ? s : "");
|
||||
MXS_FREE(module);
|
||||
module = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return module;
|
||||
ss_dassert(m_pApi);
|
||||
ss_dassert(m_pStorage);
|
||||
}
|
||||
|
||||
|
||||
void cache_storage_close(CACHE_STORAGE_MODULE *module)
|
||||
cache_result_t Storage::getKey(const char* zDefaultDb,
|
||||
const GWBUF* pQuery,
|
||||
char* pKey)
|
||||
{
|
||||
if (module)
|
||||
{
|
||||
if (dlclose(module->handle) != 0)
|
||||
{
|
||||
const char *s = dlerror();
|
||||
MXS_ERROR("Could not close module %s: ", s ? s : "");
|
||||
}
|
||||
|
||||
MXS_FREE(module);
|
||||
}
|
||||
return m_pApi->getKey(m_pStorage, zDefaultDb, pQuery, pKey);
|
||||
}
|
||||
|
||||
cache_result_t Storage::getValue(const char* pKey,
|
||||
uint32_t flags,
|
||||
GWBUF** ppValue)
|
||||
{
|
||||
return m_pApi->getValue(m_pStorage, pKey, flags, ppValue);
|
||||
}
|
||||
|
||||
cache_result_t Storage::putValue(const char* pKey,
|
||||
const GWBUF* pValue)
|
||||
{
|
||||
return m_pApi->putValue(m_pStorage, pKey, pValue);
|
||||
}
|
||||
|
||||
cache_result_t Storage::delValue(const char* pKey)
|
||||
{
|
||||
return m_pApi->delValue(m_pStorage, pKey);
|
||||
}
|
||||
|
36
server/modules/filter/cache/storage.h
vendored
36
server/modules/filter/cache/storage.h
vendored
@ -17,17 +17,35 @@
|
||||
#include <maxscale/cdefs.h>
|
||||
#include "cache_storage_api.h"
|
||||
|
||||
MXS_BEGIN_DECLS
|
||||
|
||||
typedef struct cache_storage_module_t
|
||||
class Storage
|
||||
{
|
||||
void* handle;
|
||||
CACHE_STORAGE_API* api;
|
||||
} CACHE_STORAGE_MODULE;
|
||||
public:
|
||||
~Storage();
|
||||
|
||||
CACHE_STORAGE_MODULE* cache_storage_open(const char *name);
|
||||
void cache_storage_close(CACHE_STORAGE_MODULE *module);
|
||||
cache_result_t getKey(const char* zDefaultDb,
|
||||
const GWBUF* pQuery,
|
||||
char* pKey);
|
||||
|
||||
MXS_END_DECLS
|
||||
cache_result_t getValue(const char* pKey,
|
||||
uint32_t flags,
|
||||
GWBUF** ppValue);
|
||||
|
||||
cache_result_t putValue(const char* pKey,
|
||||
const GWBUF* pValue);
|
||||
|
||||
cache_result_t delValue(const char* pKey);
|
||||
|
||||
private:
|
||||
friend class StorageFactory;
|
||||
|
||||
Storage(CACHE_STORAGE_API* pApi, CACHE_STORAGE* pStorage);
|
||||
|
||||
Storage(const Storage&);
|
||||
Storage& operator = (const Storage&);
|
||||
|
||||
private:
|
||||
CACHE_STORAGE_API* m_pApi;
|
||||
CACHE_STORAGE* m_pStorage;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
154
server/modules/filter/cache/storagefactory.cc
vendored
Normal file
154
server/modules/filter/cache/storagefactory.cc
vendored
Normal file
@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Copyright (c) 2016 MariaDB Corporation Ab
|
||||
*
|
||||
* Use of this software is governed by the Business Source License included
|
||||
* in the LICENSE.TXT file and at www.mariadb.com/bsl.
|
||||
*
|
||||
* Change Date: 2019-07-01
|
||||
*
|
||||
* On the date above, in accordance with the Business Source License, use
|
||||
* of this software will be governed by version 2 or later of the General
|
||||
* Public License.
|
||||
*/
|
||||
|
||||
#include "storagefactory.h"
|
||||
#include <dlfcn.h>
|
||||
#include <sys/param.h>
|
||||
#include <new>
|
||||
#include <maxscale/alloc.h>
|
||||
#include <maxscale/gwdirs.h>
|
||||
#include <maxscale/log_manager.h>
|
||||
#include "storage.h"
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
bool open_cache_storage(const char* zName, void** pHandle, CACHE_STORAGE_API** ppApi)
|
||||
{
|
||||
bool rv = false;
|
||||
|
||||
char path[MAXPATHLEN + 1];
|
||||
sprintf(path, "%s/lib%s.so", get_libdir(), zName);
|
||||
|
||||
void* handle = dlopen(path, RTLD_NOW | RTLD_LOCAL);
|
||||
|
||||
if (handle)
|
||||
{
|
||||
void* f = dlsym(handle, CACHE_STORAGE_ENTRY_POINT);
|
||||
|
||||
if (f)
|
||||
{
|
||||
CACHE_STORAGE_API* pApi = ((CacheGetStorageAPIFN)f)();
|
||||
|
||||
if (pApi)
|
||||
{
|
||||
if ((pApi->initialize)())
|
||||
{
|
||||
*pHandle = handle;
|
||||
*ppApi = pApi;
|
||||
|
||||
rv = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
MXS_ERROR("Initialization of %s failed.", path);
|
||||
|
||||
(void)dlclose(handle);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MXS_ERROR("Could not obtain API object from %s.", zName);
|
||||
|
||||
(void)dlclose(handle);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const char* s = dlerror();
|
||||
MXS_ERROR("Could not look up symbol %s from %s: %s",
|
||||
zName, CACHE_STORAGE_ENTRY_POINT, s ? s : "");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const char* s = dlerror();
|
||||
MXS_ERROR("Could not load %s: %s", zName, s ? s : "");
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
void close_cache_storage(void* handle, CACHE_STORAGE_API* pApi)
|
||||
{
|
||||
// TODO: pApi->finalize();
|
||||
|
||||
if (dlclose(handle) != 0)
|
||||
{
|
||||
const char *s = dlerror();
|
||||
MXS_ERROR("Could not close module %s: ", s ? s : "");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
StorageFactory::StorageFactory(void* handle, CACHE_STORAGE_API* pApi)
|
||||
: m_handle(handle)
|
||||
, m_pApi(pApi)
|
||||
{
|
||||
ss_dassert(handle);
|
||||
ss_dassert(pApi);
|
||||
}
|
||||
|
||||
StorageFactory::~StorageFactory()
|
||||
{
|
||||
close_cache_storage(m_handle, m_pApi);
|
||||
m_handle = 0;
|
||||
m_pApi = 0;
|
||||
}
|
||||
|
||||
//static
|
||||
StorageFactory* StorageFactory::Open(const char* zName)
|
||||
{
|
||||
StorageFactory* pFactory = 0;
|
||||
|
||||
void* handle;
|
||||
CACHE_STORAGE_API* pApi;
|
||||
|
||||
if (open_cache_storage(zName, &handle, &pApi))
|
||||
{
|
||||
pFactory = new (std::nothrow) StorageFactory(handle, pApi);
|
||||
|
||||
if (!pFactory)
|
||||
{
|
||||
close_cache_storage(handle, pApi);
|
||||
}
|
||||
}
|
||||
|
||||
return pFactory;
|
||||
}
|
||||
|
||||
Storage* StorageFactory::createStorage(const char* zName,
|
||||
uint32_t ttl,
|
||||
int argc, char* argv[])
|
||||
{
|
||||
ss_dassert(m_handle);
|
||||
ss_dassert(m_pApi);
|
||||
|
||||
Storage* pStorage = 0;
|
||||
CACHE_STORAGE* pRawStorage = m_pApi->createInstance(zName, ttl, argc, argv);
|
||||
|
||||
if (pRawStorage)
|
||||
{
|
||||
pStorage = new (std::nothrow) Storage(m_pApi, pRawStorage);
|
||||
|
||||
if (!pStorage)
|
||||
{
|
||||
m_pApi->freeInstance(pRawStorage);
|
||||
}
|
||||
}
|
||||
|
||||
return pStorage;
|
||||
}
|
44
server/modules/filter/cache/storagefactory.h
vendored
Normal file
44
server/modules/filter/cache/storagefactory.h
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
#ifndef _MAXSCALE_FILTER_CACHE_STORAGEFACTORY_H
|
||||
#define _MAXSCALE_FILTER_CACHE_STORAGEFACTORY_H
|
||||
/*
|
||||
* Copyright (c) 2016 MariaDB Corporation Ab
|
||||
*
|
||||
* Use of this software is governed by the Business Source License included
|
||||
* in the LICENSE.TXT file and at www.mariadb.com/bsl.
|
||||
*
|
||||
* Change Date: 2019-07-01
|
||||
*
|
||||
* On the date above, in accordance with the Business Source License, use
|
||||
* of this software will be governed by version 2 or later of the General
|
||||
* Public License.
|
||||
*/
|
||||
|
||||
#include <maxscale/cdefs.h>
|
||||
#include "cache_storage_api.h"
|
||||
|
||||
class Storage;
|
||||
|
||||
class StorageFactory
|
||||
{
|
||||
public:
|
||||
~StorageFactory();
|
||||
|
||||
static StorageFactory* Open(const char* zName);
|
||||
|
||||
Storage* createStorage(const char* zName,
|
||||
uint32_t ttl,
|
||||
int argc, char* argv[]);
|
||||
|
||||
private:
|
||||
StorageFactory(void* handle, CACHE_STORAGE_API* pApi);
|
||||
|
||||
StorageFactory(const StorageFactory&);
|
||||
StorageFactory& operator = (const StorageFactory&);
|
||||
|
||||
private:
|
||||
void* m_handle;
|
||||
CACHE_STORAGE_API* m_pApi;
|
||||
};
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user