MXS-2302: Use STL containers for hint storage

The named hints and the hint stack are now stored in STL containers.
This commit is contained in:
Markus Mäkelä 2019-02-18 11:00:53 +02:00
parent a6ab05b673
commit f106864659
No known key found for this signature in database
GPG Key ID: 72D48FCE664F7B19
3 changed files with 30 additions and 231 deletions

View File

@ -101,13 +101,7 @@ extern "C"
*/ */
static MXS_FILTER* createInstance(const char* name, MXS_CONFIG_PARAMETER* params) static MXS_FILTER* createInstance(const char* name, MXS_CONFIG_PARAMETER* params)
{ {
HINT_INSTANCE* my_instance; return static_cast<MXS_FILTER*>(new (std::nothrow)HINT_INSTANCE);
if ((my_instance = static_cast<HINT_INSTANCE*>(MXS_CALLOC(1, sizeof(HINT_INSTANCE)))) != NULL)
{
my_instance->sessions = 0;
}
return (MXS_FILTER*)my_instance;
} }
/** /**
@ -119,15 +113,7 @@ static MXS_FILTER* createInstance(const char* name, MXS_CONFIG_PARAMETER* params
*/ */
static MXS_FILTER_SESSION* newSession(MXS_FILTER* instance, MXS_SESSION* session) static MXS_FILTER_SESSION* newSession(MXS_FILTER* instance, MXS_SESSION* session)
{ {
HINT_SESSION* my_session; return static_cast<MXS_FILTER_SESSION*>(new (std::nothrow)HINT_SESSION);
if ((my_session = static_cast<HINT_SESSION*>(MXS_CALLOC(1, sizeof(HINT_SESSION)))) != NULL)
{
my_session->stack = NULL;
my_session->named_hints = NULL;
}
return (MXS_FILTER_SESSION*)my_session;
} }
/** /**
@ -140,20 +126,15 @@ static MXS_FILTER_SESSION* newSession(MXS_FILTER* instance, MXS_SESSION* session
static void closeSession(MXS_FILTER* instance, MXS_FILTER_SESSION* session) static void closeSession(MXS_FILTER* instance, MXS_FILTER_SESSION* session)
{ {
HINT_SESSION* my_session = (HINT_SESSION*)session; HINT_SESSION* my_session = (HINT_SESSION*)session;
NAMEDHINTS* named_hints;
HINTSTACK* hint_stack;
/** Free named hints */ for (auto& a : my_session->named_hints)
named_hints = my_session->named_hints;
while ((named_hints = free_named_hint(named_hints)) != NULL)
{ {
hint_free(a.second);
} }
/** Free stacked hints */
hint_stack = my_session->stack;
while ((hint_stack = free_hint_stack(hint_stack)) != NULL) for (auto& a : my_session->stack)
{ {
hint_free(a);
} }
} }
@ -165,8 +146,7 @@ static void closeSession(MXS_FILTER* instance, MXS_FILTER_SESSION* session)
*/ */
static void freeSession(MXS_FILTER* instance, MXS_FILTER_SESSION* session) static void freeSession(MXS_FILTER* instance, MXS_FILTER_SESSION* session)
{ {
MXS_FREE(session); delete session;
return;
} }
/** /**

View File

@ -43,158 +43,6 @@ typedef enum
TOK_END TOK_END
} TOKEN_VALUE; } TOKEN_VALUE;
/**
* hint_pop - pop the hint off the top of the stack if it is not empty
*
* @param session The filter session.
*/
void hint_pop(HINT_SESSION* session)
{
HINTSTACK* ptr;
HINT* hint;
if ((ptr = session->stack) != NULL)
{
session->stack = ptr->next;
while (ptr->hint)
{
hint = ptr->hint;
ptr->hint = hint->next;
hint_free(hint);
}
MXS_FREE(ptr);
}
}
/**
* Push a hint onto the stack of actie hints
*
* @param session The filter session
* @param hint The hint to push, the hint ownership is retained
* by the stack and should not be freed by the caller
*/
static void hint_push(HINT_SESSION* session, HINT* hint)
{
HINTSTACK* item;
if ((item = (HINTSTACK*)MXS_MALLOC(sizeof(HINTSTACK))) == NULL)
{
return;
}
item->hint = hint;
item->next = session->stack;
session->stack = item;
}
/**
* Search for a hint block that already exists with this name
*
* @param session The filter session
* @param name The name to lookup
* @return the HINT or NULL if the name was not found.
*/
static HINT* lookup_named_hint(HINT_SESSION* session, const char* name)
{
NAMEDHINTS* ptr = session->named_hints;
while (ptr)
{
if (strcmp(ptr->name, name) == 0)
{
return ptr->hints;
}
ptr = ptr->next;
}
return NULL;
}
/**
* Create a named hint block
*
* @param session The filter session
* @param name The name of the block to ceate
* @param hint The hints themselves
*/
static void create_named_hint(HINT_SESSION* session, const char* name, HINT* hint)
{
NAMEDHINTS* block;
if ((block = (NAMEDHINTS*)MXS_MALLOC(sizeof(NAMEDHINTS))) == NULL)
{
return;
}
block->name = MXS_STRDUP(name);
block->hints = hint_dup(hint);
block->next = session->named_hints;
session->named_hints = block;
}
/**
* Release the given NAMEDHINTS struct and all included hints.
*
* @param named_hint NAMEDHINTS struct to be released
*
* @return pointer to next NAMEDHINTS struct.
*/
NAMEDHINTS* free_named_hint(NAMEDHINTS* named_hint)
{
NAMEDHINTS* next;
if (named_hint != NULL)
{
HINT* hint;
next = named_hint->next;
while (named_hint->hints != NULL)
{
hint = named_hint->hints->next;
hint_free(named_hint->hints);
named_hint->hints = hint;
}
MXS_FREE(named_hint->name);
MXS_FREE(named_hint);
return next;
}
else
{
return NULL;
}
}
/**
* Release the given HINTSTACK struct and all included hints.
*
* @param hint_stack HINTSTACK struct to be released
*
* @return pointer to next HINTSTACK struct.
*/
HINTSTACK* free_hint_stack(HINTSTACK* hint_stack)
{
HINTSTACK* next;
if (hint_stack != NULL)
{
HINT* hint;
next = hint_stack->next;
while (hint_stack->hint != NULL)
{
hint = hint_stack->hint->next;
hint_free(hint_stack->hint);
hint_stack->hint = hint;
}
MXS_FREE(hint_stack);
return next;
}
else
{
return NULL;
}
}
/** /**
* Advance an iterator until either an unescaped character `c` is found or `end` is reached * Advance an iterator until either an unescaped character `c` is found or `end` is reached
* *
@ -491,12 +339,16 @@ HINT* process_comment(HINT_SESSION* session, InputIter it, InputIter end)
{ {
if ((rval = process_definition(it, end))) if ((rval = process_definition(it, end)))
{ {
hint_push(session, hint_dup(rval)); session->stack.push_back(hint_dup(rval));
} }
} }
else if (t.type == TOK_STOP) else if (t.type == TOK_STOP)
{ {
hint_pop(session); if (!session->stack.empty())
{
hint_free(session->stack.back());
session->stack.pop_back();
}
} }
else if (t.type == TOK_STRING) else if (t.type == TOK_STRING)
{ {
@ -521,29 +373,29 @@ HINT* process_comment(HINT_SESSION* session, InputIter it, InputIter end)
if (hint) if (hint)
{ {
// Preparation of a named hint // Preparation of a named hint
create_named_hint(session, key.c_str(), hint); session->named_hints[key] = hint_dup(hint);
} }
} }
else if (t.type == TOK_START) else if (t.type == TOK_START)
{ {
if ((rval = process_definition(it, end))) if ((rval = process_definition(it, end)))
{ {
if (!lookup_named_hint(session, key.c_str())) if (session->named_hints.count(key) == 0)
{ {
// New hint defined, push it on to the stack // New hint defined, push it on to the stack
create_named_hint(session, key.c_str(), rval); session->named_hints[key] = hint_dup(rval);
hint_push(session, hint_dup(rval)); session->stack.push_back(hint_dup(rval));
} }
} }
else if (next_token(&it, end).type == TOK_END) else if (next_token(&it, end).type == TOK_END)
{ {
HINT* hint = lookup_named_hint(session, key.c_str()); auto it = session->named_hints.find(key);
if (hint) if (it != session->named_hints.end())
{ {
// We're starting an already define named hint // We're starting an already define named hint
hint_push(session, hint_dup(hint)); session->stack.push_back(hint_dup(it->second));
rval = hint_dup(hint); rval = hint_dup(it->second);
} }
} }
} }
@ -572,9 +424,9 @@ void process_hints(HINT_SESSION* session, GWBUF* buffer)
} }
} }
if (!buffer->hint && session->stack) if (!buffer->hint && !session->stack.empty())
{ {
buffer->hint = hint_dup(session->stack->hint); buffer->hint = hint_dup(session->stack.back());
} }
buf.release(); buf.release();

View File

@ -15,55 +15,22 @@
#include <maxscale/ccdefs.hh> #include <maxscale/ccdefs.hh>
#include <maxscale/hint.h> #include <maxscale/hint.h>
MXS_BEGIN_DECLS
/**
* A named hint set.
*
* The hint "MaxScale name PREPARE ..." can be used to defined a named set
* of hints that can be later applied.
*/
typedef struct namedhints
{
char* name; /*< Hintsets name */
HINT* hints;
struct namedhints
* next; /*< Next named hint */
} NAMEDHINTS;
/**
* A session meaintains a stack of hints, the hints BEGIN and STOP are used
* push hints on and off the stack. The current top of the stack is added to
* any statement that does not explicitly define a hint for that signle
* statement.
*/
typedef struct hintstack
{
HINT* hint;
struct hintstack
* next;
} HINTSTACK;
/** /**
* The hint instance structure * The hint instance structure
*/ */
typedef struct struct HINT_INSTANCE: public MXS_FILTER
{ {
int sessions; int sessions = 0;
} HINT_INSTANCE; };
/** /**
* A hint parser session structure * A hint parser session structure
*/ */
typedef struct struct HINT_SESSION: public MXS_FILTER_SESSION
{ {
MXS_DOWNSTREAM down; MXS_DOWNSTREAM down;
HINTSTACK* stack; std::vector<HINT*> stack;
NAMEDHINTS* named_hints; /* The named hints defined in this session */ std::unordered_map<std::string, HINT*> named_hints;
} HINT_SESSION; };
NAMEDHINTS* free_named_hint(NAMEDHINTS* named_hint);
HINTSTACK* free_hint_stack(HINTSTACK* hint_stack);
void process_hints(HINT_SESSION* session, GWBUF* buffer); void process_hints(HINT_SESSION* session, GWBUF* buffer);
MXS_END_DECLS