diff --git a/server/core/session.cc b/server/core/session.cc index 23d5a7e75..9ae341a71 100644 --- a/server/core/session.cc +++ b/server/core/session.cc @@ -1121,7 +1121,7 @@ bool session_add_variable(MXS_SESSION* session, std::transform(key.begin(), key.end(), key.begin(), toupper); - if (session->variables->find(key) != session->variables->end()) + if (session->variables->find(key) == session->variables->end()) { SESSION_VARIABLE variable; variable.handler = handler; diff --git a/server/modules/filter/cache/cachefiltersession.cc b/server/modules/filter/cache/cachefiltersession.cc index 32df9e29c..62cd21e13 100644 --- a/server/modules/filter/cache/cachefiltersession.cc +++ b/server/modules/filter/cache/cachefiltersession.cc @@ -38,6 +38,8 @@ inline bool cache_max_resultset_size_exceeded(const CACHE_CONFIG& config, uint64 namespace { +const char SV_MAXSCALE_CACHE_ENABLED[] = "@maxscale.cache.enabled"; + const char* NON_CACHEABLE_FUNCTIONS[] = { "benchmark", @@ -185,14 +187,32 @@ CacheFilterSession::CacheFilterSession(MXS_SESSION* pSession, Cache* pCache, cha , m_zUseDb(NULL) , m_refreshing(false) , m_is_read_only(true) + , m_enabled(true) // TODO: Add configuration variable for initial mode. + , m_variable_added(false) { m_key.data = 0; reset_response_state(); + + if (session_add_variable(pSession, SV_MAXSCALE_CACHE_ENABLED, + &CacheFilterSession::session_variable_handler, this)) + { + m_variable_added = true; + } + else + { + MXS_ERROR("Could not add MaxScale user variable '%s', dynamically " + "enabling/disabling caching not possible.", SV_MAXSCALE_CACHE_ENABLED); + } } CacheFilterSession::~CacheFilterSession() { + if (m_variable_added) + { + session_remove_variable(m_pSession, SV_MAXSCALE_CACHE_ENABLED, NULL); + } + MXS_FREE(m_zUseDb); MXS_FREE(m_zDefaultDb); } @@ -953,7 +973,8 @@ CacheFilterSession::routing_action_t CacheFilterSession::route_COM_QUERY(GWBUF* * (as the data is obtained from the cache) or * ROUTING_CONTINUE if the normal processing should continue. */ -CacheFilterSession::routing_action_t CacheFilterSession::route_SELECT(cache_action_t cache_action, GWBUF* pPacket) +CacheFilterSession::routing_action_t CacheFilterSession::route_SELECT(cache_action_t cache_action, + GWBUF* pPacket) { routing_action_t routing_action = ROUTING_CONTINUE; @@ -1042,3 +1063,60 @@ CacheFilterSession::routing_action_t CacheFilterSession::route_SELECT(cache_acti return routing_action; } + + +char* CacheFilterSession::handle_session_variable(const char* zName, + const char* pValue_begin, + const char* pValue_end) +{ + static const char TRUE[] = "true"; + static const char FALSE[] = "false"; + + static const size_t nTrue = sizeof(TRUE) - 1; + static const size_t nFalse = sizeof(FALSE) - 1; + + char* message = NULL; + + int len = (pValue_end - pValue_begin); + + if (((len == nTrue) && (strncasecmp(pValue_begin, TRUE, nTrue) == 0)) || + ((len == 1) && (*pValue_begin == '1'))) + { + MXS_INFO("Caching enabled."); + m_enabled = true; + } + else if (((len == nFalse) && (strncasecmp(pValue_begin, FALSE, nFalse) == 0)) || + ((len == 1) && (*pValue_begin == '0'))) + { + MXS_INFO("Caching disabled."); + m_enabled = false; + } + else + { + static const char FORMAT[] = "The variable %s can only have the values true/false/1/0"; + int n = snprintf(NULL, 0, FORMAT, SV_MAXSCALE_CACHE_ENABLED) + 1; + + message = static_cast(MXS_MALLOC(n)); + + if (message) + { + sprintf(message, FORMAT, SV_MAXSCALE_CACHE_ENABLED); + } + + MXS_WARNING("Attempt to set the variable %s to the invalid value \"%.*s\".", + SV_MAXSCALE_CACHE_ENABLED, len, pValue_begin); + } + + return message; +} + +//static +char* CacheFilterSession::session_variable_handler(void* pContext, + const char* zName, + const char* pValue_begin, + const char* pValue_end) +{ + CacheFilterSession* pThis = static_cast(pContext); + + return pThis->handle_session_variable(zName, pValue_begin, pValue_end); +} diff --git a/server/modules/filter/cache/cachefiltersession.hh b/server/modules/filter/cache/cachefiltersession.hh index 7eea52ccd..695813cb9 100644 --- a/server/modules/filter/cache/cachefiltersession.hh +++ b/server/modules/filter/cache/cachefiltersession.hh @@ -21,6 +21,9 @@ class CacheFilterSession : public maxscale::FilterSession { + CacheFilterSession(const CacheFilterSession&); + CacheFilterSession& operator = (const CacheFilterSession&); + public: enum cache_session_state_t { @@ -138,12 +141,18 @@ private: routing_action_t route_COM_QUERY(GWBUF* pPacket); routing_action_t route_SELECT(cache_action_t action, GWBUF* pPacket); + char* handle_session_variable(const char* zName, + const char* pValue_begin, + const char* pValue_end); + + static char* session_variable_handler(void* pContext, + const char* zName, + const char* pValue_begin, + const char* pValue_end); + private: CacheFilterSession(MXS_SESSION* pSession, Cache* pCache, char* zDefaultDb); - CacheFilterSession(const CacheFilterSession&); - CacheFilterSession& operator = (const CacheFilterSession&); - private: cache_session_state_t m_state; /**< What state is the session in, what data is expected. */ Cache* m_pCache; /**< The cache instance the session is associated with. */ @@ -153,5 +162,7 @@ private: char* m_zUseDb; /**< Pending default database. Needs server response. */ bool m_refreshing; /**< Whether the session is updating a stale cache entry. */ bool m_is_read_only;/**< Whether the current trx has been read-only in pratice. */ + bool m_enabled; /**< Whether caching is enabled for this session. */ + bool m_variable_added; /*<< Whether the variable was added or not. */ };