MXS-1346: Refactor dbfwfilter user template creation

The user templates now use ValueList instead of STRLINK to store the
string values and they are stored as a list of shared pointers.

Minor cleanups to the user creation related grammar rules.
This commit is contained in:
Markus Mäkelä
2017-08-30 12:55:17 +03:00
parent f28ba678ac
commit d3893f2e83
3 changed files with 60 additions and 103 deletions

View File

@ -71,6 +71,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string> #include <string>
#include <list> #include <list>
#include <tr1/memory>
#include <maxscale/filter.h> #include <maxscale/filter.h>
#include <maxscale/atomic.h> #include <maxscale/atomic.h>
@ -298,18 +299,22 @@ thread_local int thr_rule_version = 0;
thread_local RULE *thr_rules = NULL; thread_local RULE *thr_rules = NULL;
thread_local HASHTABLE *thr_users = NULL; thread_local HASHTABLE *thr_users = NULL;
typedef std::list<std::string> ValueList;
/** /**
* A temporary template structure used in the creation of actual users. * A temporary template structure used in the creation of actual users.
* This is also used to link the user definitions with the rules. * This is also used to link the user definitions with the rules.
* @see struct user_t * @see struct user_t
*/ */
typedef struct user_template struct UserTemplate
{ {
char *name; std::string name; /** Name of the user */
enum match_type type; /** Matching type */ enum match_type type; /** Matching type */
STRLINK *rulenames; /** names of the rules */ ValueList rulenames; /** Names of the rules */
struct user_template *next; };
} user_template_t;
typedef std::tr1::shared_ptr<UserTemplate> SUserTemplate;
typedef std::list<SUserTemplate> TemplateList;
/** /**
* A user definition * A user definition
@ -1097,18 +1102,16 @@ char* get_regex_string(char** saved)
return NULL; return NULL;
} }
typedef std::list<std::string> ValueList;
/** /**
* Structure used to hold rules and users that are being parsed * Structure used to hold rules and users that are being parsed
*/ */
struct parser_stack struct parser_stack
{ {
RULE* rule; RULE* rule;
STRLINK* user; ValueList user;
STRLINK* active_rules; ValueList active_rules;
enum match_type active_mode; enum match_type active_mode;
user_template_t* templates; TemplateList templates;
ValueList values; ValueList values;
std::string name; std::string name;
}; };
@ -1259,18 +1262,11 @@ static void rule_free_all(RULE* rule)
* @param scanner Current scanner * @param scanner Current scanner
* @param name Name of the user * @param name Name of the user
*/ */
bool add_active_user(void* scanner, const char* name) void add_active_user(void* scanner, const char* name)
{ {
struct parser_stack* rstack = (struct parser_stack*)dbfw_yyget_extra((yyscan_t) scanner); struct parser_stack* rstack = (struct parser_stack*)dbfw_yyget_extra((yyscan_t) scanner);
ss_dassert(rstack); ss_dassert(rstack);
STRLINK *tmp = strlink_push(rstack->user, name); rstack->user.push_back(name);
if (tmp)
{
rstack->user = tmp;
}
return tmp != NULL;
} }
/** /**
@ -1278,18 +1274,11 @@ bool add_active_user(void* scanner, const char* name)
* @param scanner Current scanner * @param scanner Current scanner
* @param name Name of the rule * @param name Name of the rule
*/ */
bool add_active_rule(void* scanner, const char* name) void add_active_rule(void* scanner, const char* name)
{ {
struct parser_stack* rstack = (struct parser_stack*)dbfw_yyget_extra((yyscan_t) scanner); struct parser_stack* rstack = (struct parser_stack*)dbfw_yyget_extra((yyscan_t) scanner);
ss_dassert(rstack); ss_dassert(rstack);
STRLINK *tmp = strlink_push(rstack->active_rules, name); rstack->active_rules.push_back(name);
if (tmp)
{
rstack->active_rules = tmp;
}
return tmp != NULL;
} }
/** /**
@ -1333,57 +1322,22 @@ bool create_user_templates(void* scanner)
{ {
struct parser_stack* rstack = (struct parser_stack*)dbfw_yyget_extra((yyscan_t) scanner); struct parser_stack* rstack = (struct parser_stack*)dbfw_yyget_extra((yyscan_t) scanner);
ss_dassert(rstack); ss_dassert(rstack);
user_template_t* templates = NULL;
STRLINK* user = rstack->user;
while (user) for (ValueList::const_iterator it = rstack->user.begin(); it != rstack->user.end(); it++)
{ {
user_template_t* newtemp = (user_template_t*)MXS_MALLOC(sizeof(user_template_t)); SUserTemplate newtemp = SUserTemplate(new UserTemplate);
STRLINK* tmp; newtemp->name = *it;
if (newtemp && (newtemp->name = MXS_STRDUP(user->value)) && newtemp->rulenames = rstack->active_rules;
(newtemp->rulenames = strlink_reverse_clone(rstack->active_rules))) newtemp->type = rstack->active_mode;
{ rstack->templates.push_back(newtemp);
newtemp->type = rstack->active_mode;
newtemp->next = templates;
templates = newtemp;
}
else
{
if (newtemp)
{
MXS_FREE(newtemp->name);
MXS_FREE(newtemp);
}
MXS_FREE(templates->name);
strlink_free(templates->rulenames);
MXS_FREE(templates);
return false;
}
user = user->next;
} }
templates->next = rstack->templates; rstack->user.clear();
rstack->templates = templates; rstack->active_rules.clear();
strlink_free(rstack->user);
strlink_free(rstack->active_rules);
rstack->user = NULL;
rstack->active_rules = NULL;
return true; return true;
} }
void free_user_templates(user_template_t *templates)
{
while (templates)
{
user_template_t *tmp = templates;
templates = templates->next;
strlink_free(tmp->rulenames);
MXS_FREE(tmp->name);
MXS_FREE(tmp);
}
}
void set_matching_mode(void* scanner, enum match_type mode) void set_matching_mode(void* scanner, enum match_type mode)
{ {
struct parser_stack* rstack = (struct parser_stack*)dbfw_yyget_extra((yyscan_t) scanner); struct parser_stack* rstack = (struct parser_stack*)dbfw_yyget_extra((yyscan_t) scanner);
@ -1552,24 +1506,25 @@ bool define_regex_rule(void* scanner, char* pattern)
* @param rules List of all rules * @param rules List of all rules
* @return True on success, false on error. * @return True on success, false on error.
*/ */
static bool process_user_templates(HASHTABLE *users, user_template_t *templates, static bool process_user_templates(HASHTABLE *users, const TemplateList& templates,
RULE* rules) RULE* rules)
{ {
bool rval = true; bool rval = true;
if (templates == NULL) if (templates.size() == 0)
{ {
MXS_ERROR("No user definitions found in the rule file."); MXS_ERROR("No user definitions found in the rule file.");
rval = false; rval = false;
} }
while (templates) for (TemplateList::const_iterator it = templates.begin(); it != templates.end(); it++)
{ {
DBFW_USER *user = (DBFW_USER*)hashtable_fetch(users, templates->name); const SUserTemplate& ut = *it;
DBFW_USER *user = (DBFW_USER*)hashtable_fetch(users, (void*)ut->name.c_str());
if (user == NULL) if (user == NULL)
{ {
if ((user = (DBFW_USER*)MXS_MALLOC(sizeof(DBFW_USER))) && (user->name = MXS_STRDUP(templates->name))) if ((user = (DBFW_USER*)MXS_MALLOC(sizeof(DBFW_USER))) && (user->name = MXS_STRDUP(ut->name.c_str())))
{ {
user->rules_and = NULL; user->rules_and = NULL;
user->rules_or = NULL; user->rules_or = NULL;
@ -1587,13 +1542,21 @@ static bool process_user_templates(HASHTABLE *users, user_template_t *templates,
} }
RULE_BOOK *foundrules = NULL; RULE_BOOK *foundrules = NULL;
RULE *rule;
STRLINK *names = templates->rulenames;
while (names && (rule = find_rule_by_name(rules, names->value))) for (ValueList::const_iterator r_it = ut->rulenames.begin();
r_it != ut->rulenames.end(); r_it++)
{ {
foundrules = rulebook_push(foundrules, rule); RULE* rule = find_rule_by_name(rules, r_it->c_str());
names = names->next;
if (rule)
{
foundrules = rulebook_push(foundrules, rule);
}
else
{
MXS_ERROR("Could not find definition for rule '%s'.", r_it->c_str());
rval = false;
}
} }
if (foundrules) if (foundrules)
@ -1605,7 +1568,7 @@ static bool process_user_templates(HASHTABLE *users, user_template_t *templates,
tail = tail->next; tail = tail->next;
} }
switch (templates->type) switch (ut->type)
{ {
case FWTOK_MATCH_ANY: case FWTOK_MATCH_ANY:
tail->next = user->rules_or; tail->next = user->rules_or;
@ -1623,13 +1586,6 @@ static bool process_user_templates(HASHTABLE *users, user_template_t *templates,
break; break;
} }
} }
else
{
MXS_ERROR("Could not find definition for rule '%s'.", names->value);
rval = false;
break;
}
templates = templates->next;
} }
return rval; return rval;
@ -1652,9 +1608,6 @@ static bool process_rule_file(const char* filename, RULE** rules, HASHTABLE **us
struct parser_stack pstack; struct parser_stack pstack;
pstack.rule = NULL; pstack.rule = NULL;
pstack.user = NULL;
pstack.active_rules = NULL;
pstack.templates = NULL;
dbfw_yylex_init(&scanner); dbfw_yylex_init(&scanner);
YY_BUFFER_STATE buf = dbfw_yy_create_buffer(file, YY_BUF_SIZE, scanner); YY_BUFFER_STATE buf = dbfw_yy_create_buffer(file, YY_BUF_SIZE, scanner);
@ -1681,10 +1634,6 @@ static bool process_rule_file(const char* filename, RULE** rules, HASHTABLE **us
hashtable_free(new_users); hashtable_free(new_users);
MXS_ERROR("Failed to process rule file '%s'.", filename); MXS_ERROR("Failed to process rule file '%s'.", filename);
} }
free_user_templates(pstack.templates);
strlink_free(pstack.active_rules);
strlink_free(pstack.user);
} }
else else
{ {

View File

@ -49,8 +49,8 @@ bool add_at_times_rule(void* scanner, const char* range);
void add_on_queries_rule(void* scanner, const char* sql); void add_on_queries_rule(void* scanner, const char* sql);
/** User creation functions */ /** User creation functions */
bool add_active_user(void* scanner, const char* name); void add_active_user(void* scanner, const char* name);
bool add_active_rule(void* scanner, const char* name); void add_active_rule(void* scanner, const char* name);
void set_matching_mode(void* scanner, enum match_type mode); void set_matching_mode(void* scanner, enum match_type mode);
bool create_user_templates(void* scanner); bool create_user_templates(void* scanner);

View File

@ -93,14 +93,22 @@ user
{if (!create_user_templates(scanner)){YYERROR;}} {if (!create_user_templates(scanner)){YYERROR;}}
; ;
uservalue
: FWTOK_USER {add_active_user(scanner, $1);}
;
userlist userlist
: FWTOK_USER {if (!add_active_user(scanner, $1)){YYERROR;}} : uservalue
| userlist FWTOK_USER {if (!add_active_user(scanner, $2)){YYERROR;}} | userlist uservalue
;
namevalue
: rulename {add_active_rule(scanner, $1);}
; ;
namelist namelist
: rulename {if (!add_active_rule(scanner, $1)){YYERROR;}} : namevalue
| namelist rulename {if (!add_active_rule(scanner, $2)){YYERROR;}} | namelist namevalue
; ;
cond cond