MXS-2302: Use filter template in hintfilter

This commit is contained in:
Markus Mäkelä
2019-02-18 11:37:14 +02:00
parent 1d49e45036
commit 684ddfd12d
3 changed files with 93 additions and 174 deletions

View File

@ -26,17 +26,75 @@
*
*/
static MXS_FILTER* createInstance(const char* name, MXS_CONFIG_PARAMETER* params);
static MXS_FILTER_SESSION* newSession(MXS_FILTER* instance, MXS_SESSION* session);
static void closeSession(MXS_FILTER* instance, MXS_FILTER_SESSION* session);
static void freeSession(MXS_FILTER* instance, MXS_FILTER_SESSION* session);
static void setDownstream(MXS_FILTER* instance,
MXS_FILTER_SESSION* fsession,
MXS_DOWNSTREAM* downstream);
static int routeQuery(MXS_FILTER* instance, MXS_FILTER_SESSION* fsession, GWBUF* queue);
static void diagnostic(MXS_FILTER* instance, MXS_FILTER_SESSION* fsession, DCB* dcb);
static json_t* diagnostic_json(const MXS_FILTER* instance, const MXS_FILTER_SESSION* fsession);
static uint64_t getCapabilities(MXS_FILTER* instance);
// static
HINT_INSTANCE* HINT_INSTANCE::create(const char* zName, MXS_CONFIG_PARAMETER* ppParams)
{
return new(std::nothrow) HINT_INSTANCE;
}
HINT_SESSION* HINT_INSTANCE::newSession(MXS_SESSION* pSession)
{
return new(std::nothrow) HINT_SESSION(pSession);
}
void HINT_INSTANCE::diagnostics(DCB* pDcb) const
{
}
json_t* HINT_INSTANCE::diagnostics_json() const
{
return nullptr;
}
uint64_t HINT_INSTANCE::getCapabilities()
{
return RCAP_TYPE_CONTIGUOUS_INPUT;
}
HINT_SESSION::HINT_SESSION(MXS_SESSION* session)
: mxs::FilterSession(session)
{
}
/**
* Close a session with the filter, this is the mechanism
* by which a filter may cleanup data structure etc.
*
* @param instance The filter instance data
* @param session The session being closed
*/
HINT_SESSION::~HINT_SESSION()
{
for (auto& a : named_hints)
{
hint_free(a.second);
}
for (auto& a : stack)
{
hint_free(a);
}
}
/**
* The routeQuery entry point. This is passed the query buffer
* to which the filter should be applied. Once applied the
* query should normally be passed to the downstream component
* (filter or router) in the filter chain.
*
* @param instance The filter instance data
* @param session The filter session
* @param queue The query data
*/
int HINT_SESSION::routeQuery(GWBUF* queue)
{
if (modutil_is_SQL(queue) && gwbuf_length(queue) > 5)
{
process_hints(queue);
}
return mxs::FilterSession::routeQuery(queue);
}
extern "C"
{
@ -51,22 +109,6 @@ extern "C"
*/
MXS_MODULE* MXS_CREATE_MODULE()
{
static MXS_FILTER_OBJECT MyObject =
{
createInstance,
newSession,
closeSession,
freeSession,
setDownstream,
NULL, // No upstream requirement
routeQuery,
NULL, // No clientReply
diagnostic,
diagnostic_json,
getCapabilities,
NULL, // No destroyInstance
};
static MXS_MODULE info =
{
MXS_MODULE_API_FILTER,
@ -75,7 +117,7 @@ extern "C"
"A hint parsing filter",
"V1.0.0",
RCAP_TYPE_CONTIGUOUS_INPUT,
&MyObject,
&HINT_INSTANCE::s_object,
NULL, /* Process init. */
NULL, /* Process finish. */
NULL, /* Thread init. */
@ -88,138 +130,3 @@ extern "C"
return &info;
}
}
/**
* Create an instance of the filter for a particular service
* within MaxScale.
*
* @param name The name of the instance (as defined in the config file).
* @param options The options for this filter
* @param params The array of name/value pair parameters for the filter
*
* @return The instance data for this new instance
*/
static MXS_FILTER* createInstance(const char* name, MXS_CONFIG_PARAMETER* params)
{
return static_cast<MXS_FILTER*>(new(std::nothrow) HINT_INSTANCE);
}
/**
* Associate a new session with this instance of the filter.
*
* @param instance The filter instance data
* @param session The session itself
* @return Session specific data for this session
*/
static MXS_FILTER_SESSION* newSession(MXS_FILTER* instance, MXS_SESSION* session)
{
return static_cast<MXS_FILTER_SESSION*>(new(std::nothrow) HINT_SESSION);
}
/**
* Close a session with the filter, this is the mechanism
* by which a filter may cleanup data structure etc.
*
* @param instance The filter instance data
* @param session The session being closed
*/
static void closeSession(MXS_FILTER* instance, MXS_FILTER_SESSION* session)
{
HINT_SESSION* my_session = (HINT_SESSION*)session;
for (auto& a : my_session->named_hints)
{
hint_free(a.second);
}
for (auto& a : my_session->stack)
{
hint_free(a);
}
}
/**
* Free the memory associated with this filter session.
*
* @param instance The filter instance data
* @param session The session being closed
*/
static void freeSession(MXS_FILTER* instance, MXS_FILTER_SESSION* session)
{
delete session;
}
/**
* Set the downstream component for this filter.
*
* @param instance The filter instance data
* @param session The session being closed
* @param downstream The downstream filter or router
*/
static void setDownstream(MXS_FILTER* instance, MXS_FILTER_SESSION* session, MXS_DOWNSTREAM* downstream)
{
HINT_SESSION* my_session = (HINT_SESSION*)session;
my_session->down = *downstream;
}
/**
* The routeQuery entry point. This is passed the query buffer
* to which the filter should be applied. Once applied the
* query should normally be passed to the downstream component
* (filter or router) in the filter chain.
*
* @param instance The filter instance data
* @param session The filter session
* @param queue The query data
*/
static int routeQuery(MXS_FILTER* instance, MXS_FILTER_SESSION* session, GWBUF* queue)
{
HINT_SESSION* my_session = (HINT_SESSION*)session;
if (modutil_is_SQL(queue) && gwbuf_length(queue) > 5)
{
my_session->process_hints(queue);
}
/* Now process the request */
return my_session->down.routeQuery(my_session->down.instance,
my_session->down.session,
queue);
}
/**
* Diagnostics routine
*
* If fsession is NULL then print diagnostics on the filter
* instance as a whole, otherwise print diagnostics for the
* particular session.
*
* @param instance The filter instance
* @param fsession Filter session, may be NULL
* @param dcb The DCB for diagnostic output
*/
static void diagnostic(MXS_FILTER* instance, MXS_FILTER_SESSION* fsession, DCB* dcb)
{
}
/**
* Diagnostics routine
*
* @param instance The filter instance
* @param fsession Filter session, may be NULL
*/
static json_t* diagnostic_json(const MXS_FILTER* instance, const MXS_FILTER_SESSION* fsession)
{
return NULL;
}
/**
* Capability routine.
*
* @return The capabilities of the filter.
*/
static uint64_t getCapabilities(MXS_FILTER* instance)
{
return RCAP_TYPE_NONE;
}

View File

@ -14,25 +14,36 @@
#include <maxscale/ccdefs.hh>
#include <maxscale/hint.h>
#include <maxscale/filter.hh>
/**
* The hint instance structure
*/
struct HINT_INSTANCE : public MXS_FILTER
class HINT_SESSION;
class HINT_INSTANCE : public mxs::Filter<HINT_INSTANCE, HINT_SESSION>
{
int sessions = 0;
public:
static HINT_INSTANCE* create(const char* zName, MXS_CONFIG_PARAMETER* ppParams);
HINT_SESSION* newSession(MXS_SESSION* pSession);
void diagnostics(DCB* pDcb) const;
json_t* diagnostics_json() const;
uint64_t getCapabilities();
};
/**
* A hint parser session structure
*/
struct HINT_SESSION : public MXS_FILTER_SESSION
class HINT_SESSION : public mxs::FilterSession
{
MXS_DOWNSTREAM down;
public:
HINT_SESSION(MXS_SESSION* session);
~HINT_SESSION();
int routeQuery(GWBUF* queue);
private:
std::vector<HINT*> stack;
std::unordered_map<std::string, HINT*> named_hints;
template<class InputIter>
HINT* process_comment(InputIter it, InputIter end);
void process_hints(GWBUF* buffer);
// Unit testing functions
friend void count_hints(const std::string& input, int num_expected);
friend void test_parse(const std::string& input, int expected_type);
};

View File

@ -16,6 +16,7 @@
#endif
#include "../hintparser.cc"
#include "../hintfilter.cc"
#include <maxbase/log.hh>
#include <algorithm>
@ -71,7 +72,7 @@ void test(const std::string& input, std::initializer_list<std::string> expected)
mxb_assert(rval);
}
static HINT_SESSION session = {};
static HINT_SESSION session(nullptr);
void test_parse(const std::string& input, int expected_type)
{