Formatted namedserverfilter
Namedserverfilter formatted according to the style guide.
This commit is contained in:
parent
036fd6f16c
commit
cbeead7c43
@ -15,6 +15,7 @@
|
||||
*
|
||||
* Copyright MariaDB Corporation Ab 2014
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <filter.h>
|
||||
#include <modinfo.h>
|
||||
@ -32,42 +33,44 @@
|
||||
*
|
||||
* A simple regular expression based query routing filter.
|
||||
* Two parameters should be defined in the filter configuration
|
||||
* match=<regular expression>
|
||||
* server=<server to route statement to>
|
||||
* match=<regular expression>
|
||||
* server=<server to route statement to>
|
||||
* Two optional parameters
|
||||
* source=<source address to limit filter>
|
||||
* user=<username to limit filter>
|
||||
* source=<source address to limit filter>
|
||||
* user=<username to limit filter>
|
||||
*
|
||||
* Date Who Description
|
||||
* 22/01/2015 Mark Riddoch Written as example based on regex filter
|
||||
* Date Who Description
|
||||
* 22/01/2015 Mark Riddoch Written as example based on regex filter
|
||||
* @endverbatim
|
||||
*/
|
||||
|
||||
MODULE_INFO info = {
|
||||
MODULE_API_FILTER,
|
||||
MODULE_GA,
|
||||
FILTER_VERSION,
|
||||
"A routing hint filter that uses regular expressions to direct queries"
|
||||
MODULE_INFO info =
|
||||
{
|
||||
MODULE_API_FILTER,
|
||||
MODULE_GA,
|
||||
FILTER_VERSION,
|
||||
"A routing hint filter that uses regular expressions to direct queries"
|
||||
};
|
||||
|
||||
static char *version_str = "V1.1.0";
|
||||
|
||||
static FILTER *createInstance(char **options, FILTER_PARAMETER **params);
|
||||
static void *newSession(FILTER *instance, SESSION *session);
|
||||
static void closeSession(FILTER *instance, void *session);
|
||||
static void freeSession(FILTER *instance, void *session);
|
||||
static void setDownstream(FILTER *instance, void *fsession, DOWNSTREAM *downstream);
|
||||
static int routeQuery(FILTER *instance, void *fsession, GWBUF *queue);
|
||||
static void diagnostic(FILTER *instance, void *fsession, DCB *dcb);
|
||||
static FILTER *createInstance(char **options, FILTER_PARAMETER **params);
|
||||
static void *newSession(FILTER *instance, SESSION *session);
|
||||
static void closeSession(FILTER *instance, void *session);
|
||||
static void freeSession(FILTER *instance, void *session);
|
||||
static void setDownstream(FILTER *instance, void *fsession, DOWNSTREAM *downstream);
|
||||
static int routeQuery(FILTER *instance, void *fsession, GWBUF *queue);
|
||||
static void diagnostic(FILTER *instance, void *fsession, DCB *dcb);
|
||||
|
||||
|
||||
static FILTER_OBJECT MyObject = {
|
||||
static FILTER_OBJECT MyObject =
|
||||
{
|
||||
createInstance,
|
||||
newSession,
|
||||
closeSession,
|
||||
freeSession,
|
||||
setDownstream,
|
||||
NULL, // No Upstream requirement
|
||||
NULL, // No Upstream requirement
|
||||
routeQuery,
|
||||
NULL,
|
||||
diagnostic,
|
||||
@ -76,23 +79,25 @@ static FILTER_OBJECT MyObject = {
|
||||
/**
|
||||
* Instance structure
|
||||
*/
|
||||
typedef struct {
|
||||
char *source; /* Source address to restrict matches */
|
||||
char *user; /* User name to restrict matches */
|
||||
char *match; /* Regular expression to match */
|
||||
char *server; /* Server to route to */
|
||||
int cflags; /* Regexec compile flags */
|
||||
regex_t re; /* Compiled regex text */
|
||||
typedef struct
|
||||
{
|
||||
char *source; /* Source address to restrict matches */
|
||||
char *user; /* User name to restrict matches */
|
||||
char *match; /* Regular expression to match */
|
||||
char *server; /* Server to route to */
|
||||
int cflags; /* Regexec compile flags */
|
||||
regex_t re; /* Compiled regex text */
|
||||
} REGEXHINT_INSTANCE;
|
||||
|
||||
/**
|
||||
* The session structuee for this regex filter
|
||||
*/
|
||||
typedef struct {
|
||||
DOWNSTREAM down; /* The downstream filter */
|
||||
int n_diverted; /* No. of statements diverted */
|
||||
int n_undiverted; /* No. of statements not diverted */
|
||||
int active; /* Is filter active */
|
||||
typedef struct
|
||||
{
|
||||
DOWNSTREAM down; /* The downstream filter */
|
||||
int n_diverted; /* No. of statements diverted */
|
||||
int n_undiverted; /* No. of statements not diverted */
|
||||
int active; /* Is filter active */
|
||||
} REGEXHINT_SESSION;
|
||||
|
||||
/**
|
||||
@ -103,7 +108,7 @@ typedef struct {
|
||||
char *
|
||||
version()
|
||||
{
|
||||
return version_str;
|
||||
return version_str;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -126,134 +131,142 @@ ModuleInit()
|
||||
FILTER_OBJECT *
|
||||
GetModuleObject()
|
||||
{
|
||||
return &MyObject;
|
||||
return &MyObject;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of the filter for a particular service
|
||||
* within MaxScale.
|
||||
*
|
||||
* @param options The options for this filter
|
||||
* @param params The array of name/value pair parameters for the filter
|
||||
*
|
||||
* @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 FILTER *
|
||||
static FILTER *
|
||||
createInstance(char **options, FILTER_PARAMETER **params)
|
||||
{
|
||||
REGEXHINT_INSTANCE *my_instance;
|
||||
int i, cflags = REG_ICASE;
|
||||
REGEXHINT_INSTANCE *my_instance;
|
||||
int i, cflags = REG_ICASE;
|
||||
|
||||
if ((my_instance = calloc(1, sizeof(REGEXHINT_INSTANCE))) != NULL)
|
||||
{
|
||||
my_instance->match = NULL;
|
||||
my_instance->server = NULL;
|
||||
if ((my_instance = calloc(1, sizeof(REGEXHINT_INSTANCE))) != NULL)
|
||||
{
|
||||
my_instance->match = NULL;
|
||||
my_instance->server = NULL;
|
||||
|
||||
for (i = 0; params && params[i]; i++)
|
||||
{
|
||||
if (!strcmp(params[i]->name, "match"))
|
||||
my_instance->match = strdup(params[i]->value);
|
||||
else if (!strcmp(params[i]->name, "server"))
|
||||
my_instance->server = strdup(params[i]->value);
|
||||
else if (!strcmp(params[i]->name, "source"))
|
||||
my_instance->source = strdup(params[i]->value);
|
||||
else if (!strcmp(params[i]->name, "user"))
|
||||
my_instance->user = strdup(params[i]->value);
|
||||
else if (!filter_standard_parameter(params[i]->name))
|
||||
{
|
||||
MXS_ERROR("namedserverfilter: Unexpected parameter '%s'.",
|
||||
params[i]->name);
|
||||
}
|
||||
}
|
||||
for (i = 0; params && params[i]; i++)
|
||||
{
|
||||
if (!strcmp(params[i]->name, "match"))
|
||||
{
|
||||
my_instance->match = strdup(params[i]->value);
|
||||
}
|
||||
else if (!strcmp(params[i]->name, "server"))
|
||||
{
|
||||
my_instance->server = strdup(params[i]->value);
|
||||
}
|
||||
else if (!strcmp(params[i]->name, "source"))
|
||||
{
|
||||
my_instance->source = strdup(params[i]->value);
|
||||
}
|
||||
else if (!strcmp(params[i]->name, "user"))
|
||||
{
|
||||
my_instance->user = strdup(params[i]->value);
|
||||
}
|
||||
else if (!filter_standard_parameter(params[i]->name))
|
||||
{
|
||||
MXS_ERROR("namedserverfilter: Unexpected parameter '%s'.",
|
||||
params[i]->name);
|
||||
}
|
||||
}
|
||||
|
||||
if (options)
|
||||
{
|
||||
for (i = 0; options[i]; i++)
|
||||
{
|
||||
if (!strcasecmp(options[i], "ignorecase"))
|
||||
{
|
||||
cflags |= REG_ICASE;
|
||||
}
|
||||
else if (!strcasecmp(options[i], "case"))
|
||||
{
|
||||
cflags &= ~REG_ICASE;
|
||||
}
|
||||
else
|
||||
{
|
||||
MXS_ERROR("namedserverfilter: unsupported option '%s'.",
|
||||
options[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
my_instance->cflags = cflags;
|
||||
if (options)
|
||||
{
|
||||
for (i = 0; options[i]; i++)
|
||||
{
|
||||
if (!strcasecmp(options[i], "ignorecase"))
|
||||
{
|
||||
cflags |= REG_ICASE;
|
||||
}
|
||||
else if (!strcasecmp(options[i], "case"))
|
||||
{
|
||||
cflags &= ~REG_ICASE;
|
||||
}
|
||||
else
|
||||
{
|
||||
MXS_ERROR("namedserverfilter: unsupported option '%s'.",
|
||||
options[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
my_instance->cflags = cflags;
|
||||
|
||||
if (my_instance->match == NULL || my_instance->server == NULL)
|
||||
{
|
||||
MXS_ERROR("namedserverfilter: Missing required configured"
|
||||
" option. You must specify a match and server "
|
||||
"option as a minimum.");
|
||||
free(my_instance);
|
||||
return NULL;
|
||||
}
|
||||
if (my_instance->match == NULL || my_instance->server == NULL)
|
||||
{
|
||||
MXS_ERROR("namedserverfilter: Missing required configured"
|
||||
" option. You must specify a match and server "
|
||||
"option as a minimum.");
|
||||
free(my_instance);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (regcomp(&my_instance->re, my_instance->match,
|
||||
my_instance->cflags))
|
||||
{
|
||||
MXS_ERROR("namedserverfilter: Invalid regular expression '%s'.\n",
|
||||
my_instance->match);
|
||||
free(my_instance->match);
|
||||
free(my_instance->server);
|
||||
free(my_instance);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return (FILTER *)my_instance;
|
||||
if (regcomp(&my_instance->re, my_instance->match,
|
||||
my_instance->cflags))
|
||||
{
|
||||
MXS_ERROR("namedserverfilter: Invalid regular expression '%s'.\n",
|
||||
my_instance->match);
|
||||
free(my_instance->match);
|
||||
free(my_instance->server);
|
||||
free(my_instance);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return(FILTER *) my_instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Associate a new session with this instance of the filter.
|
||||
*
|
||||
* @param instance The filter instance data
|
||||
* @param session The session itself
|
||||
* @param instance The filter instance data
|
||||
* @param session The session itself
|
||||
* @return Session specific data for this session
|
||||
*/
|
||||
static void *
|
||||
static void *
|
||||
newSession(FILTER *instance, SESSION *session)
|
||||
{
|
||||
REGEXHINT_INSTANCE *my_instance = (REGEXHINT_INSTANCE *)instance;
|
||||
REGEXHINT_SESSION *my_session;
|
||||
char *remote, *user;
|
||||
REGEXHINT_INSTANCE *my_instance = (REGEXHINT_INSTANCE *) instance;
|
||||
REGEXHINT_SESSION *my_session;
|
||||
char *remote, *user;
|
||||
|
||||
if ((my_session = calloc(1, sizeof(REGEXHINT_SESSION))) != NULL)
|
||||
{
|
||||
my_session->n_diverted = 0;
|
||||
my_session->n_undiverted = 0;
|
||||
my_session->active = 1;
|
||||
if (my_instance->source
|
||||
&& (remote = session_get_remote(session)) != NULL)
|
||||
{
|
||||
if (strcmp(remote, my_instance->source))
|
||||
my_session->active = 0;
|
||||
}
|
||||
if ((my_session = calloc(1, sizeof(REGEXHINT_SESSION))) != NULL)
|
||||
{
|
||||
my_session->n_diverted = 0;
|
||||
my_session->n_undiverted = 0;
|
||||
my_session->active = 1;
|
||||
if (my_instance->source
|
||||
&& (remote = session_get_remote(session)) != NULL)
|
||||
{
|
||||
if (strcmp(remote, my_instance->source))
|
||||
my_session->active = 0;
|
||||
}
|
||||
|
||||
if (my_instance->user && (user = session_getUser(session))
|
||||
&& strcmp(user, my_instance->user))
|
||||
{
|
||||
my_session->active = 0;
|
||||
}
|
||||
}
|
||||
if (my_instance->user && (user = session_getUser(session))
|
||||
&& strcmp(user, my_instance->user))
|
||||
{
|
||||
my_session->active = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return my_session;
|
||||
return my_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
|
||||
* @param instance The filter instance data
|
||||
* @param session The session being closed
|
||||
*/
|
||||
static void
|
||||
static void
|
||||
closeSession(FILTER *instance, void *session)
|
||||
{
|
||||
}
|
||||
@ -261,29 +274,28 @@ closeSession(FILTER *instance, void *session)
|
||||
/**
|
||||
* Free the memory associated with this filter session.
|
||||
*
|
||||
* @param instance The filter instance data
|
||||
* @param session The session being closed
|
||||
* @param instance The filter instance data
|
||||
* @param session The session being closed
|
||||
*/
|
||||
static void
|
||||
freeSession(FILTER *instance, void *session)
|
||||
{
|
||||
free(session);
|
||||
return;
|
||||
free(session);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @param instance The filter instance data
|
||||
* @param session The session being closed
|
||||
* @param downstream The downstream filter or router
|
||||
*/
|
||||
static void
|
||||
setDownstream(FILTER *instance, void *session, DOWNSTREAM *downstream)
|
||||
{
|
||||
REGEXHINT_SESSION *my_session = (REGEXHINT_SESSION *)session;
|
||||
|
||||
my_session->down = *downstream;
|
||||
REGEXHINT_SESSION *my_session = (REGEXHINT_SESSION *) session;
|
||||
my_session->down = *downstream;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -296,40 +308,41 @@ REGEXHINT_SESSION *my_session = (REGEXHINT_SESSION *)session;
|
||||
* filter definition matches the SQL text then add the hint
|
||||
* "Route to named server" with the name defined in the server parameter
|
||||
*
|
||||
* @param instance The filter instance data
|
||||
* @param session The filter session
|
||||
* @param queue The query data
|
||||
* @param instance The filter instance data
|
||||
* @param session The filter session
|
||||
* @param queue The query data
|
||||
*/
|
||||
static int
|
||||
static int
|
||||
routeQuery(FILTER *instance, void *session, GWBUF *queue)
|
||||
{
|
||||
REGEXHINT_INSTANCE *my_instance = (REGEXHINT_INSTANCE *)instance;
|
||||
REGEXHINT_SESSION *my_session = (REGEXHINT_SESSION *)session;
|
||||
char *sql;
|
||||
REGEXHINT_INSTANCE *my_instance = (REGEXHINT_INSTANCE *) instance;
|
||||
REGEXHINT_SESSION *my_session = (REGEXHINT_SESSION *) session;
|
||||
char *sql;
|
||||
|
||||
if (modutil_is_SQL(queue))
|
||||
{
|
||||
if (queue->next != NULL)
|
||||
{
|
||||
queue = gwbuf_make_contiguous(queue);
|
||||
}
|
||||
if ((sql = modutil_get_SQL(queue)) != NULL)
|
||||
{
|
||||
if (regexec(&my_instance->re,sql,0,NULL, 0) == 0)
|
||||
{
|
||||
queue->hint = hint_create_route(queue->hint,
|
||||
HINT_ROUTE_TO_NAMED_SERVER,
|
||||
my_instance->server);
|
||||
my_session->n_diverted++;
|
||||
}
|
||||
else
|
||||
my_session->n_undiverted++;
|
||||
free(sql);
|
||||
}
|
||||
|
||||
}
|
||||
return my_session->down.routeQuery(my_session->down.instance,
|
||||
my_session->down.session, queue);
|
||||
if (modutil_is_SQL(queue))
|
||||
{
|
||||
if (queue->next != NULL)
|
||||
{
|
||||
queue = gwbuf_make_contiguous(queue);
|
||||
}
|
||||
if ((sql = modutil_get_SQL(queue)) != NULL)
|
||||
{
|
||||
if (regexec(&my_instance->re, sql, 0, NULL, 0) == 0)
|
||||
{
|
||||
queue->hint = hint_create_route(queue->hint,
|
||||
HINT_ROUTE_TO_NAMED_SERVER,
|
||||
my_instance->server);
|
||||
my_session->n_diverted++;
|
||||
}
|
||||
else
|
||||
{
|
||||
my_session->n_undiverted++;
|
||||
}
|
||||
free(sql);
|
||||
}
|
||||
}
|
||||
return my_session->down.routeQuery(my_session->down.instance,
|
||||
my_session->down.session, queue);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -339,31 +352,35 @@ char *sql;
|
||||
* 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
|
||||
* @param instance The filter instance
|
||||
* @param fsession Filter session, may be NULL
|
||||
* @param dcb The DCB for diagnostic output
|
||||
*/
|
||||
static void
|
||||
static void
|
||||
diagnostic(FILTER *instance, void *fsession, DCB *dcb)
|
||||
{
|
||||
REGEXHINT_INSTANCE *my_instance = (REGEXHINT_INSTANCE *)instance;
|
||||
REGEXHINT_SESSION *my_session = (REGEXHINT_SESSION *)fsession;
|
||||
REGEXHINT_INSTANCE *my_instance = (REGEXHINT_INSTANCE *) instance;
|
||||
REGEXHINT_SESSION *my_session = (REGEXHINT_SESSION *) fsession;
|
||||
|
||||
dcb_printf(dcb, "\t\tMatch and route: /%s/ -> %s\n",
|
||||
my_instance->match, my_instance->server);
|
||||
if (my_session)
|
||||
{
|
||||
dcb_printf(dcb, "\t\tNo. of queries diverted by filter: %d\n",
|
||||
my_session->n_diverted);
|
||||
dcb_printf(dcb, "\t\tNo. of queries not diverted by filter: %d\n",
|
||||
my_session->n_undiverted);
|
||||
}
|
||||
if (my_instance->source)
|
||||
dcb_printf(dcb,
|
||||
"\t\tReplacement limited to connections from %s\n",
|
||||
my_instance->source);
|
||||
if (my_instance->user)
|
||||
dcb_printf(dcb,
|
||||
"\t\tReplacement limit to user %s\n",
|
||||
my_instance->user);
|
||||
dcb_printf(dcb, "\t\tMatch and route: /%s/ -> %s\n",
|
||||
my_instance->match, my_instance->server);
|
||||
if (my_session)
|
||||
{
|
||||
dcb_printf(dcb, "\t\tNo. of queries diverted by filter: %d\n",
|
||||
my_session->n_diverted);
|
||||
dcb_printf(dcb, "\t\tNo. of queries not diverted by filter: %d\n",
|
||||
my_session->n_undiverted);
|
||||
}
|
||||
if (my_instance->source)
|
||||
{
|
||||
dcb_printf(dcb,
|
||||
"\t\tReplacement limited to connections from %s\n",
|
||||
my_instance->source);
|
||||
}
|
||||
if (my_instance->user)
|
||||
{
|
||||
dcb_printf(dcb,
|
||||
"\t\tReplacement limit to user %s\n",
|
||||
my_instance->user);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user