diff --git a/server/modules/filter/cache/CMakeLists.txt b/server/modules/filter/cache/CMakeLists.txt index 2592217bd..9934207f5 100644 --- a/server/modules/filter/cache/CMakeLists.txt +++ b/server/modules/filter/cache/CMakeLists.txt @@ -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) diff --git a/server/modules/filter/cache/cachefilter.cc b/server/modules/filter/cache/cachefilter.cc index 458a36060..ed97c4fb9 100644 --- a/server/modules/filter/cache/cachefilter.cc +++ b/server/modules/filter/cache/cachefilter.cc @@ -25,6 +25,7 @@ #include #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)) { diff --git a/server/modules/filter/cache/storage.cc b/server/modules/filter/cache/storage.cc index 165905dd1..2d724866a 100644 --- a/server/modules/filter/cache/storage.cc +++ b/server/modules/filter/cache/storage.cc @@ -12,85 +12,37 @@ */ #include "storage.h" -#include -#include -#include -#include -#include -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); } diff --git a/server/modules/filter/cache/storage.h b/server/modules/filter/cache/storage.h index f0d2f8bef..a2eadfaaf 100644 --- a/server/modules/filter/cache/storage.h +++ b/server/modules/filter/cache/storage.h @@ -17,17 +17,35 @@ #include #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 diff --git a/server/modules/filter/cache/storagefactory.cc b/server/modules/filter/cache/storagefactory.cc new file mode 100644 index 000000000..9b088da76 --- /dev/null +++ b/server/modules/filter/cache/storagefactory.cc @@ -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 +#include +#include +#include +#include +#include +#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; +} diff --git a/server/modules/filter/cache/storagefactory.h b/server/modules/filter/cache/storagefactory.h new file mode 100644 index 000000000..e87f57742 --- /dev/null +++ b/server/modules/filter/cache/storagefactory.h @@ -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 +#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