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
static MXS_FILTER_SESSION* newSession(MXS_FILTER* instance, MXS_SESSION* session); HINT_INSTANCE* HINT_INSTANCE::create(const char* zName, MXS_CONFIG_PARAMETER* ppParams)
static void closeSession(MXS_FILTER* instance, MXS_FILTER_SESSION* session); {
static void freeSession(MXS_FILTER* instance, MXS_FILTER_SESSION* session); return new(std::nothrow) HINT_INSTANCE;
static void setDownstream(MXS_FILTER* instance, }
MXS_FILTER_SESSION* fsession,
MXS_DOWNSTREAM* downstream); HINT_SESSION* HINT_INSTANCE::newSession(MXS_SESSION* pSession)
static int routeQuery(MXS_FILTER* instance, MXS_FILTER_SESSION* fsession, GWBUF* queue); {
static void diagnostic(MXS_FILTER* instance, MXS_FILTER_SESSION* fsession, DCB* dcb); return new(std::nothrow) HINT_SESSION(pSession);
static json_t* diagnostic_json(const MXS_FILTER* instance, const MXS_FILTER_SESSION* fsession); }
static uint64_t getCapabilities(MXS_FILTER* instance);
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" extern "C"
{ {
@ -51,22 +109,6 @@ extern "C"
*/ */
MXS_MODULE* MXS_CREATE_MODULE() 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 = static MXS_MODULE info =
{ {
MXS_MODULE_API_FILTER, MXS_MODULE_API_FILTER,
@ -75,7 +117,7 @@ extern "C"
"A hint parsing filter", "A hint parsing filter",
"V1.0.0", "V1.0.0",
RCAP_TYPE_CONTIGUOUS_INPUT, RCAP_TYPE_CONTIGUOUS_INPUT,
&MyObject, &HINT_INSTANCE::s_object,
NULL, /* Process init. */ NULL, /* Process init. */
NULL, /* Process finish. */ NULL, /* Process finish. */
NULL, /* Thread init. */ NULL, /* Thread init. */
@ -88,138 +130,3 @@ extern "C"
return &info; 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/ccdefs.hh>
#include <maxscale/hint.h> #include <maxscale/hint.h>
#include <maxscale/filter.hh>
/** class HINT_SESSION;
* The hint instance structure
*/ class HINT_INSTANCE : public mxs::Filter<HINT_INSTANCE, HINT_SESSION>
struct HINT_INSTANCE : public MXS_FILTER
{ {
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();
}; };
/** class HINT_SESSION : public mxs::FilterSession
* A hint parser session structure
*/
struct HINT_SESSION : public MXS_FILTER_SESSION
{ {
MXS_DOWNSTREAM down; public:
HINT_SESSION(MXS_SESSION* session);
~HINT_SESSION();
int routeQuery(GWBUF* queue);
private:
std::vector<HINT*> stack; std::vector<HINT*> stack;
std::unordered_map<std::string, HINT*> named_hints; std::unordered_map<std::string, HINT*> named_hints;
template<class InputIter> template<class InputIter>
HINT* process_comment(InputIter it, InputIter end); HINT* process_comment(InputIter it, InputIter end);
void process_hints(GWBUF* buffer); 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 #endif
#include "../hintparser.cc" #include "../hintparser.cc"
#include "../hintfilter.cc"
#include <maxbase/log.hh> #include <maxbase/log.hh>
#include <algorithm> #include <algorithm>
@ -71,7 +72,7 @@ void test(const std::string& input, std::initializer_list<std::string> expected)
mxb_assert(rval); mxb_assert(rval);
} }
static HINT_SESSION session = {}; static HINT_SESSION session(nullptr);
void test_parse(const std::string& input, int expected_type) void test_parse(const std::string& input, int expected_type)
{ {