Reindented server/core/filter.c

This commit is contained in:
Johan Wikman
2015-11-30 12:51:24 +02:00
parent bd94d8967a
commit 20c4a0aa67
2 changed files with 294 additions and 264 deletions

View File

@ -22,8 +22,8 @@
* @verbatim * @verbatim
* Revision History * Revision History
* *
* Date Who Description * Date Who Description
* 29/05/14 Mark Riddoch Initial implementation * 29/05/14 Mark Riddoch Initial implementation
* *
* @endverbatim * @endverbatim
*/ */
@ -38,116 +38,124 @@
#include <skygw_utils.h> #include <skygw_utils.h>
#include <log_manager.h> #include <log_manager.h>
static SPINLOCK filter_spin = SPINLOCK_INIT; /**< Protects the list of all filters */ static SPINLOCK filter_spin = SPINLOCK_INIT; /**< Protects the list of all filters */
static FILTER_DEF *allFilters = NULL; /**< The list of all filters */ static FILTER_DEF *allFilters = NULL; /**< The list of all filters */
/** /**
* Allocate a new filter within MaxScale * Allocate a new filter within MaxScale
* *
* *
* @param name The filter name * @param name The filter name
* @param module The module to load * @param module The module to load
* *
* @return The newly created filter or NULL if an error occured * @return The newly created filter or NULL if an error occured
*/ */
FILTER_DEF * FILTER_DEF *
filter_alloc(char *name, char *module) filter_alloc(char *name, char *module)
{ {
FILTER_DEF *filter; FILTER_DEF *filter;
if ((filter = (FILTER_DEF *)malloc(sizeof(FILTER_DEF))) == NULL) if ((filter = (FILTER_DEF *)malloc(sizeof(FILTER_DEF))) == NULL)
return NULL; {
filter->name = strdup(name); return NULL;
filter->module = strdup(module); }
filter->filter = NULL; filter->name = strdup(name);
filter->options = NULL; filter->module = strdup(module);
filter->obj = NULL; filter->filter = NULL;
filter->parameters = NULL; filter->options = NULL;
filter->obj = NULL;
filter->parameters = NULL;
spinlock_init(&filter->spin); spinlock_init(&filter->spin);
spinlock_acquire(&filter_spin); spinlock_acquire(&filter_spin);
filter->next = allFilters; filter->next = allFilters;
allFilters = filter; allFilters = filter;
spinlock_release(&filter_spin); spinlock_release(&filter_spin);
return filter; return filter;
} }
/** /**
* Deallocate the specified filter * Deallocate the specified filter
* *
* @param filter The filter to deallocate * @param filter The filter to deallocate
* @return Returns true if the server was freed * @return Returns true if the server was freed
*/ */
void void
filter_free(FILTER_DEF *filter) filter_free(FILTER_DEF *filter)
{ {
FILTER_DEF *ptr; FILTER_DEF *ptr;
if (filter) if (filter)
{ {
/* First of all remove from the linked list */ /* First of all remove from the linked list */
spinlock_acquire(&filter_spin); spinlock_acquire(&filter_spin);
if (allFilters == filter) if (allFilters == filter)
{ {
allFilters = filter->next; allFilters = filter->next;
} }
else else
{ {
ptr = allFilters; ptr = allFilters;
while (ptr && ptr->next != filter) while (ptr && ptr->next != filter)
{ {
ptr = ptr->next; ptr = ptr->next;
} }
if (ptr) if (ptr)
ptr->next = filter->next; {
} ptr->next = filter->next;
spinlock_release(&filter_spin); }
}
spinlock_release(&filter_spin);
/* Clean up session and free the memory */ /* Clean up session and free the memory */
free(filter->name); free(filter->name);
free(filter->module); free(filter->module);
free(filter); free(filter);
} }
} }
/** /**
* Find an existing filter using the unique section name in * Find an existing filter using the unique section name in
* configuration file * configuration file
* *
* @param name The filter name * @param name The filter name
* @return The server or NULL if not found * @return The server or NULL if not found
*/ */
FILTER_DEF * FILTER_DEF *
filter_find(char *name) filter_find(char *name)
{ {
FILTER_DEF *filter; FILTER_DEF *filter;
spinlock_acquire(&filter_spin); spinlock_acquire(&filter_spin);
filter = allFilters; filter = allFilters;
while (filter) while (filter)
{ {
if (strcmp(filter->name, name) == 0) if (strcmp(filter->name, name) == 0)
break; {
filter = filter->next; break;
} }
spinlock_release(&filter_spin); filter = filter->next;
return filter; }
spinlock_release(&filter_spin);
return filter;
} }
/** /**
* Check a parameter to see if it is a standard filter parameter * Check a parameter to see if it is a standard filter parameter
* *
* @param name Parameter name to check * @param name Parameter name to check
*/ */
int int
filter_standard_parameter(char *name) filter_standard_parameter(char *name)
{ {
if (strcmp(name, "type") == 0 || strcmp(name, "module") == 0) if (strcmp(name, "type") == 0 || strcmp(name, "module") == 0)
return 1; {
return 0; return 1;
}
return 0;
} }
/** /**
@ -159,29 +167,35 @@ filter_standard_parameter(char *name)
void void
dprintAllFilters(DCB *dcb) dprintAllFilters(DCB *dcb)
{ {
FILTER_DEF *ptr; FILTER_DEF *ptr;
int i; int i;
spinlock_acquire(&filter_spin); spinlock_acquire(&filter_spin);
ptr = allFilters; ptr = allFilters;
while (ptr) while (ptr)
{ {
dcb_printf(dcb, "Filter %p (%s)\n", ptr, ptr->name); dcb_printf(dcb, "Filter %p (%s)\n", ptr, ptr->name);
dcb_printf(dcb, "\tModule: %s\n", ptr->module); dcb_printf(dcb, "\tModule: %s\n", ptr->module);
if (ptr->options) if (ptr->options)
{ {
dcb_printf(dcb, "\tOptions: "); dcb_printf(dcb, "\tOptions: ");
for (i = 0; ptr->options && ptr->options[i]; i++) for (i = 0; ptr->options && ptr->options[i]; i++)
dcb_printf(dcb, "%s ", ptr->options[i]); {
dcb_printf(dcb, "\n"); dcb_printf(dcb, "%s ", ptr->options[i]);
} }
if (ptr->obj && ptr->filter) dcb_printf(dcb, "\n");
ptr->obj->diagnostics(ptr->filter, NULL, dcb); }
else if (ptr->obj && ptr->filter)
dcb_printf(dcb, "\tModule not loaded.\n"); {
ptr = ptr->next; ptr->obj->diagnostics(ptr->filter, NULL, dcb);
} }
spinlock_release(&filter_spin); else
{
dcb_printf(dcb, "\tModule not loaded.\n");
}
ptr = ptr->next;
}
spinlock_release(&filter_spin);
} }
/** /**
@ -193,19 +207,23 @@ int i;
void void
dprintFilter(DCB *dcb, FILTER_DEF *filter) dprintFilter(DCB *dcb, FILTER_DEF *filter)
{ {
int i; int i;
dcb_printf(dcb, "Filter %p (%s)\n", filter, filter->name); dcb_printf(dcb, "Filter %p (%s)\n", filter, filter->name);
dcb_printf(dcb, "\tModule: %s\n", filter->module); dcb_printf(dcb, "\tModule: %s\n", filter->module);
if (filter->options) if (filter->options)
{ {
dcb_printf(dcb, "\tOptions: "); dcb_printf(dcb, "\tOptions: ");
for (i = 0; filter->options && filter->options[i]; i++) for (i = 0; filter->options && filter->options[i]; i++)
dcb_printf(dcb, "%s ", filter->options[i]); {
dcb_printf(dcb, "\n"); dcb_printf(dcb, "%s ", filter->options[i]);
} }
if (filter->obj && filter->filter) dcb_printf(dcb, "\n");
filter->obj->diagnostics(filter->filter, NULL, dcb); }
if (filter->obj && filter->filter)
{
filter->obj->diagnostics(filter->filter, NULL, dcb);
}
} }
/** /**
@ -215,93 +233,101 @@ int i;
void void
dListFilters(DCB *dcb) dListFilters(DCB *dcb)
{ {
FILTER_DEF *ptr; FILTER_DEF *ptr;
int i; int i;
spinlock_acquire(&filter_spin); spinlock_acquire(&filter_spin);
ptr = allFilters; ptr = allFilters;
if (ptr) if (ptr)
{ {
dcb_printf(dcb, "Filters\n"); dcb_printf(dcb, "Filters\n");
dcb_printf(dcb, "--------------------+-----------------+----------------------------------------\n"); dcb_printf(dcb, "--------------------+-----------------+----------------------------------------\n");
dcb_printf(dcb, "%-19s | %-15s | Options\n", dcb_printf(dcb, "%-19s | %-15s | Options\n",
"Filter", "Module"); "Filter", "Module");
dcb_printf(dcb, "--------------------+-----------------+----------------------------------------\n"); dcb_printf(dcb, "--------------------+-----------------+----------------------------------------\n");
} }
while (ptr) while (ptr)
{ {
dcb_printf(dcb, "%-19s | %-15s | ", dcb_printf(dcb, "%-19s | %-15s | ",
ptr->name, ptr->module); ptr->name, ptr->module);
for (i = 0; ptr->options && ptr->options[i]; i++) for (i = 0; ptr->options && ptr->options[i]; i++)
dcb_printf(dcb, "%s ", ptr->options[i]); {
dcb_printf(dcb, "\n"); dcb_printf(dcb, "%s ", ptr->options[i]);
ptr = ptr->next; }
} dcb_printf(dcb, "\n");
if (allFilters) ptr = ptr->next;
dcb_printf(dcb, "--------------------+-----------------+----------------------------------------\n\n"); }
spinlock_release(&filter_spin); if (allFilters)
{
dcb_printf(dcb,
"--------------------+-----------------+----------------------------------------\n\n");
}
spinlock_release(&filter_spin);
} }
/** /**
* Add a router option to a service * Add a router option to a service
* *
* @param filter The filter to add the option to * @param filter The filter to add the option to
* @param option The option string * @param option The option string
*/ */
void void
filterAddOption(FILTER_DEF *filter, char *option) filterAddOption(FILTER_DEF *filter, char *option)
{ {
int i; int i;
spinlock_acquire(&filter->spin); spinlock_acquire(&filter->spin);
if (filter->options == NULL) if (filter->options == NULL)
{
filter->options = (char **)calloc(2, sizeof(char *));
filter->options[0] = strdup(option);
filter->options[1] = NULL;
}
else
{
for (i = 0; filter->options[i]; i++)
{ {
filter->options = (char **)calloc(2, sizeof(char *)); ;
filter->options[0] = strdup(option);
filter->options[1] = NULL;
} }
else filter->options = (char **)realloc(filter->options, (i + 2) * sizeof(char *));
{ filter->options[i] = strdup(option);
for (i = 0; filter->options[i]; i++) filter->options[i+1] = NULL;
; }
filter->options = (char **)realloc(filter->options, spinlock_release(&filter->spin);
(i + 2) * sizeof(char *));
filter->options[i] = strdup(option);
filter->options[i+1] = NULL;
}
spinlock_release(&filter->spin);
} }
/** /**
* Add a router parameter to a service * Add a router parameter to a service
* *
* @param filter The filter to add the parameter to * @param filter The filter to add the parameter to
* @param name The parameter name * @param name The parameter name
* @param value The parameter value * @param value The parameter value
*/ */
void void
filterAddParameter(FILTER_DEF *filter, char *name, char *value) filterAddParameter(FILTER_DEF *filter, char *name, char *value)
{ {
int i; int i;
spinlock_acquire(&filter->spin); spinlock_acquire(&filter->spin);
if (filter->parameters == NULL) if (filter->parameters == NULL)
{
filter->parameters = (FILTER_PARAMETER **)calloc(2, sizeof(FILTER_PARAMETER *));
i = 0;
}
else
{
for (i = 0; filter->parameters[i]; i++)
{ {
filter->parameters = (FILTER_PARAMETER **)calloc(2, sizeof(FILTER_PARAMETER *)); ;
i = 0;
} }
else filter->parameters = (FILTER_PARAMETER **)realloc(filter->parameters,
{ (i + 2) * sizeof(FILTER_PARAMETER *));
for (i = 0; filter->parameters[i]; i++) }
; filter->parameters[i] = (FILTER_PARAMETER *)calloc(1, sizeof(FILTER_PARAMETER));
filter->parameters = (FILTER_PARAMETER **)realloc(filter->parameters, filter->parameters[i]->name = strdup(name);
(i + 2) * sizeof(FILTER_PARAMETER *)); filter->parameters[i]->value = strdup(value);
} filter->parameters[i+1] = NULL;
filter->parameters[i] = (FILTER_PARAMETER *)calloc(1, sizeof(FILTER_PARAMETER)); spinlock_release(&filter->spin);
filter->parameters[i]->name = strdup(name);
filter->parameters[i]->value = strdup(value);
filter->parameters[i+1] = NULL;
spinlock_release(&filter->spin);
} }
/** /**
@ -344,38 +370,38 @@ bool filter_load(FILTER_DEF* filter)
* This will create the filter instance, loading the filter module, and * This will create the filter instance, loading the filter module, and
* conenct the fitler into the downstream chain. * conenct the fitler into the downstream chain.
* *
* @param filter The filter to add into the chain * @param filter The filter to add into the chain
* @param session The client session * @param session The client session
* @param downstream The filter downstream of this filter * @param downstream The filter downstream of this filter
* @return The downstream component for the next filter or NULL * @return The downstream component for the next filter or NULL
* if the filter could not be created * if the filter could not be created
*/ */
DOWNSTREAM * DOWNSTREAM *
filterApply(FILTER_DEF *filter, SESSION *session, DOWNSTREAM *downstream) filterApply(FILTER_DEF *filter, SESSION *session, DOWNSTREAM *downstream)
{ {
DOWNSTREAM *me; DOWNSTREAM *me;
if ((me = (DOWNSTREAM *)calloc(1, sizeof(DOWNSTREAM))) == NULL) if ((me = (DOWNSTREAM *)calloc(1, sizeof(DOWNSTREAM))) == NULL)
{ {
char errbuf[STRERROR_BUFLEN]; char errbuf[STRERROR_BUFLEN];
MXS_ERROR("Memory allocation for filter session failed " MXS_ERROR("Memory allocation for filter session failed "
"due to %d,%s.", "due to %d,%s.",
errno, errno,
strerror_r(errno, errbuf, sizeof(errbuf))); strerror_r(errno, errbuf, sizeof(errbuf)));
return NULL; return NULL;
} }
me->instance = filter->filter; me->instance = filter->filter;
me->routeQuery = (void *)(filter->obj->routeQuery); me->routeQuery = (void *)(filter->obj->routeQuery);
if ((me->session=filter->obj->newSession(me->instance, session)) == NULL) if ((me->session=filter->obj->newSession(me->instance, session)) == NULL)
{ {
free(me); free(me);
return NULL; return NULL;
} }
filter->obj->setDownstream(me->instance, me->session, downstream); filter->obj->setDownstream(me->instance, me->session, downstream);
return me; return me;
} }
/** /**
@ -386,33 +412,35 @@ filterApply(FILTER_DEF *filter, SESSION *session, DOWNSTREAM *downstream)
* Note all filters require to be in the upstream chain, so this routine * Note all filters require to be in the upstream chain, so this routine
* may skip a filter if it does not provide an upstream interface. * may skip a filter if it does not provide an upstream interface.
* *
* @param filter The fitler to add to the chain * @param filter The fitler to add to the chain
* @param fsession The filter session * @param fsession The filter session
* @param upstream The filter that should be upstream of this filter * @param upstream The filter that should be upstream of this filter
* @return The upstream component for the next filter * @return The upstream component for the next filter
*/ */
UPSTREAM * UPSTREAM *
filterUpstream(FILTER_DEF *filter, void *fsession, UPSTREAM *upstream) filterUpstream(FILTER_DEF *filter, void *fsession, UPSTREAM *upstream)
{ {
UPSTREAM *me = NULL; UPSTREAM *me = NULL;
/* /*
* The the filter has no setUpstream entry point then is does * The the filter has no setUpstream entry point then is does
* not require to see results and can be left out of the chain. * not require to see results and can be left out of the chain.
*/ */
if (filter->obj->setUpstream == NULL) if (filter->obj->setUpstream == NULL)
return upstream; {
return upstream;
}
if (filter->obj->clientReply != NULL) if (filter->obj->clientReply != NULL)
{ {
if ((me = (UPSTREAM *)calloc(1, sizeof(UPSTREAM))) == NULL) if ((me = (UPSTREAM *)calloc(1, sizeof(UPSTREAM))) == NULL)
{ {
return NULL; return NULL;
} }
me->instance = filter->filter; me->instance = filter->filter;
me->session = fsession; me->session = fsession;
me->clientReply = (void *)(filter->obj->clientReply); me->clientReply = (void *)(filter->obj->clientReply);
filter->obj->setUpstream(me->instance, me->session, upstream); filter->obj->setUpstream(me->instance, me->session, upstream);
} }
return me; return me;
} }

View File

@ -23,8 +23,8 @@
* *
* Revision History * Revision History
* *
* Date Who Description * Date Who Description
* 27/05/2014 Mark Riddoch Initial implementation * 27/05/2014 Mark Riddoch Initial implementation
* *
*/ */
#include <dcb.h> #include <dcb.h>
@ -41,9 +41,10 @@ typedef void *FILTER;
/** /**
* The structure used to pass name, value pairs to the filter instances * The structure used to pass name, value pairs to the filter instances
*/ */
typedef struct { typedef struct
char *name; /**< Name of the parameter */ {
char *value; /**< Value of the parameter */ char *name; /**< Name of the parameter */
char *value; /**< Value of the parameter */
} FILTER_PARAMETER; } FILTER_PARAMETER;
/** /**
@ -51,34 +52,35 @@ typedef struct {
* The "module object" structure for a query router module * The "module object" structure for a query router module
* *
* The entry points are: * The entry points are:
* createInstance Called by the service to create a new * createInstance Called by the service to create a new
* instance of the filter * instance of the filter
* newSession Called to create a new user session * newSession Called to create a new user session
* within the filter * within the filter
* closeSession Called when a session is closed * closeSession Called when a session is closed
* freeSession Called when a session is freed * freeSession Called when a session is freed
* setDownstream Sets the downstream component of the * setDownstream Sets the downstream component of the
* filter pipline * filter pipline
* routeQuery Called on each query that requires * routeQuery Called on each query that requires
* routing * routing
* clientReply Called for each reply packet * clientReply Called for each reply packet
* diagnostics Called to force the filter to print * diagnostics Called to force the filter to print
* diagnostic output * diagnostic output
* *
* @endverbatim * @endverbatim
* *
* @see load_module * @see load_module
*/ */
typedef struct filter_object { typedef struct filter_object
FILTER *(*createInstance)(char **options, FILTER_PARAMETER **); {
void *(*newSession)(FILTER *instance, SESSION *session); FILTER *(*createInstance)(char **options, FILTER_PARAMETER **);
void (*closeSession)(FILTER *instance, void *fsession); void *(*newSession)(FILTER *instance, SESSION *session);
void (*freeSession)(FILTER *instance, void *fsession); void (*closeSession)(FILTER *instance, void *fsession);
void (*setDownstream)(FILTER *instance, void *fsession, DOWNSTREAM *downstream); void (*freeSession)(FILTER *instance, void *fsession);
void (*setUpstream)(FILTER *instance, void *fsession, UPSTREAM *downstream); void (*setDownstream)(FILTER *instance, void *fsession, DOWNSTREAM *downstream);
int (*routeQuery)(FILTER *instance, void *fsession, GWBUF *queue); void (*setUpstream)(FILTER *instance, void *fsession, UPSTREAM *downstream);
int (*clientReply)(FILTER *instance, void *fsession, GWBUF *queue); int (*routeQuery)(FILTER *instance, void *fsession, GWBUF *queue);
void (*diagnostics)(FILTER *instance, void *fsession, DCB *dcb); int (*clientReply)(FILTER *instance, void *fsession, GWBUF *queue);
void (*diagnostics)(FILTER *instance, void *fsession, DCB *dcb);
} FILTER_OBJECT; } FILTER_OBJECT;
/** /**
@ -86,35 +88,35 @@ typedef struct filter_object {
* is changed these values must be updated in line with the rules in the * is changed these values must be updated in line with the rules in the
* file modinfo.h. * file modinfo.h.
*/ */
#define FILTER_VERSION {1, 1, 0} #define FILTER_VERSION {1, 1, 0}
/** /**
* The definition of a filter from the configuration file. * The definition of a filter from the configuration file.
* This is basically the link between a plugin to load and the * This is basically the link between a plugin to load and the
* optons to pass to that plugin. * optons to pass to that plugin.
*/ */
typedef struct filter_def { typedef struct filter_def
char *name; /**< The Filter name */ {
char *module; /**< The module to load */ char *name; /**< The Filter name */
char **options; /**< The options set for this filter */ char *module; /**< The module to load */
FILTER_PARAMETER char **options; /**< The options set for this filter */
**parameters; /**< The filter parameters */ FILTER_PARAMETER **parameters; /**< The filter parameters */
FILTER filter; /**< The runtime filter */ FILTER filter; /**< The runtime filter */
FILTER_OBJECT *obj; /**< The "MODULE_OBJECT" for the filter */ FILTER_OBJECT *obj; /**< The "MODULE_OBJECT" for the filter */
SPINLOCK spin; /**< Spinlock to protect the filter definition */ SPINLOCK spin; /**< Spinlock to protect the filter definition */
struct filter_def struct filter_def *next; /**< Next filter in the chain of all filters */
*next; /**< Next filter in the chain of all filters */
} FILTER_DEF; } FILTER_DEF;
FILTER_DEF *filter_alloc(char *, char *); FILTER_DEF *filter_alloc(char *, char *);
void filter_free(FILTER_DEF *); void filter_free(FILTER_DEF *);
bool filter_load(FILTER_DEF* filter); bool filter_load(FILTER_DEF* filter);
FILTER_DEF *filter_find(char *); FILTER_DEF *filter_find(char *);
void filterAddOption(FILTER_DEF *, char *); void filterAddOption(FILTER_DEF *, char *);
void filterAddParameter(FILTER_DEF *, char *, char *); void filterAddParameter(FILTER_DEF *, char *, char *);
DOWNSTREAM *filterApply(FILTER_DEF *, SESSION *, DOWNSTREAM *); DOWNSTREAM *filterApply(FILTER_DEF *, SESSION *, DOWNSTREAM *);
UPSTREAM *filterUpstream(FILTER_DEF *, void *, UPSTREAM *); UPSTREAM *filterUpstream(FILTER_DEF *, void *, UPSTREAM *);
int filter_standard_parameter(char *); int filter_standard_parameter(char *);
void dprintAllFilters(DCB *); void dprintAllFilters(DCB *);
void dprintFilter(DCB *, FILTER_DEF *); void dprintFilter(DCB *, FILTER_DEF *);
void dListFilters(DCB *); void dListFilters(DCB *);
#endif #endif