Formatted qlafilter

Qlafilter formatted according to the style guide.
This commit is contained in:
Markus Makela
2015-11-18 14:31:02 +02:00
parent a7c0952e66
commit 036fd6f16c

View File

@ -31,13 +31,14 @@
* file to which the queries are logged. A serial number is appended to this * file to which the queries are logged. A serial number is appended to this
* name in order that each session logs to a different file. * name in order that each session logs to a different file.
* *
* Date Who Description * Date Who Description
* 03/06/2014 Mark Riddoch Initial implementation * 03/06/2014 Mark Riddoch Initial implementation
* 11/06/2014 Mark Riddoch Addition of source and match parameters * 11/06/2014 Mark Riddoch Addition of source and match parameters
* 19/06/2014 Mark Riddoch Addition of user parameter * 19/06/2014 Mark Riddoch Addition of user parameter
* *
* @endverbatim * @endverbatim
*/ */
#include <stdio.h> #include <stdio.h>
#include <fcntl.h> #include <fcntl.h>
#include <errno.h> #include <errno.h>
@ -52,11 +53,12 @@
#include <string.h> #include <string.h>
#include <atomic.h> #include <atomic.h>
MODULE_INFO info = { MODULE_INFO info =
MODULE_API_FILTER, {
MODULE_GA, MODULE_API_FILTER,
FILTER_VERSION, MODULE_GA,
"A simple query logging filter" FILTER_VERSION,
"A simple query logging filter"
}; };
static char *version_str = "V1.1.1"; static char *version_str = "V1.1.1";
@ -64,24 +66,25 @@ static char *version_str = "V1.1.1";
/* /*
* The filter entry points * The filter entry points
*/ */
static FILTER *createInstance(char **options, FILTER_PARAMETER **); static FILTER *createInstance(char **options, FILTER_PARAMETER **);
static void *newSession(FILTER *instance, SESSION *session); static void *newSession(FILTER *instance, SESSION *session);
static void closeSession(FILTER *instance, void *session); static void closeSession(FILTER *instance, void *session);
static void freeSession(FILTER *instance, void *session); static void freeSession(FILTER *instance, void *session);
static void setDownstream(FILTER *instance, void *fsession, DOWNSTREAM *downstream); static void setDownstream(FILTER *instance, void *fsession, DOWNSTREAM *downstream);
static int routeQuery(FILTER *instance, void *fsession, GWBUF *queue); static int routeQuery(FILTER *instance, void *fsession, GWBUF *queue);
static void diagnostic(FILTER *instance, void *fsession, DCB *dcb); static void diagnostic(FILTER *instance, void *fsession, DCB *dcb);
static FILTER_OBJECT MyObject = { static FILTER_OBJECT MyObject =
{
createInstance, createInstance,
newSession, newSession,
closeSession, closeSession,
freeSession, freeSession,
setDownstream, setDownstream,
NULL, // No Upstream requirement NULL, // No Upstream requirement
routeQuery, routeQuery,
NULL, // No client reply NULL, // No client reply
diagnostic, diagnostic,
}; };
@ -93,30 +96,32 @@ static FILTER_OBJECT MyObject = {
* To this base a session number is attached such that each session will * To this base a session number is attached such that each session will
* have a unique name. * have a unique name.
*/ */
typedef struct { typedef struct
int sessions; /* The count of sessions */ {
char *filebase; /* The filename base */ int sessions; /* The count of sessions */
char *source; /* The source of the client connection */ char *filebase; /* The filename base */
char *userName; /* The user name to filter on */ char *source; /* The source of the client connection */
char *match; /* Optional text to match against */ char *userName; /* The user name to filter on */
regex_t re; /* Compiled regex text */ char *match; /* Optional text to match against */
char *nomatch; /* Optional text to match against for exclusion */ regex_t re; /* Compiled regex text */
regex_t nore; /* Compiled regex nomatch text */ char *nomatch; /* Optional text to match against for exclusion */
regex_t nore; /* Compiled regex nomatch text */
} QLA_INSTANCE; } QLA_INSTANCE;
/** /**
* The session structure for this QLA filter. * The session structure for this QLA filter.
* This stores the downstream filter information, such that the * This stores the downstream filter information, such that the
* filter is able to pass the query on to the next filter (or router) * filter is able to pass the query on to the next filter (or router)
* in the chain. * in the chain.
* *
* It also holds the file descriptor to which queries are written. * It also holds the file descriptor to which queries are written.
*/ */
typedef struct { typedef struct
DOWNSTREAM down; {
char *filename; DOWNSTREAM down;
FILE *fp; char *filename;
int active; FILE *fp;
int active;
} QLA_SESSION; } QLA_SESSION;
/** /**
@ -127,7 +132,7 @@ typedef struct {
char * char *
version() version()
{ {
return version_str; return version_str;
} }
/** /**
@ -150,100 +155,112 @@ ModuleInit()
FILTER_OBJECT * FILTER_OBJECT *
GetModuleObject() GetModuleObject()
{ {
return &MyObject; return &MyObject;
} }
/** /**
* Create an instance of the filter for a particular service * Create an instance of the filter for a particular service
* within MaxScale. * within MaxScale.
* *
* @param options The options for this filter * @param options The options for this filter
* @param params The array of name/value pair parameters for the filter * @param params The array of name/value pair parameters for the filter
* *
* @return The instance data for this new instance * @return The instance data for this new instance
*/ */
static FILTER * static FILTER *
createInstance(char **options, FILTER_PARAMETER **params) createInstance(char **options, FILTER_PARAMETER **params)
{ {
QLA_INSTANCE *my_instance; QLA_INSTANCE *my_instance;
int i; int i;
if ((my_instance = calloc(1, sizeof(QLA_INSTANCE))) != NULL) if ((my_instance = calloc(1, sizeof(QLA_INSTANCE))) != NULL)
{ {
if (options){ if (options)
my_instance->filebase = strdup(options[0]); {
}else{ my_instance->filebase = strdup(options[0]);
my_instance->filebase = strdup("qla"); }
} else
my_instance->source = NULL; {
my_instance->userName = NULL; my_instance->filebase = strdup("qla");
my_instance->match = NULL; }
my_instance->nomatch = NULL; my_instance->source = NULL;
if (params) my_instance->userName = NULL;
{ my_instance->match = NULL;
for (i = 0; params[i]; i++) my_instance->nomatch = NULL;
{ if (params)
if (!strcmp(params[i]->name, "match")) {
{ for (i = 0; params[i]; i++)
my_instance->match = strdup(params[i]->value); {
} if (!strcmp(params[i]->name, "match"))
else if (!strcmp(params[i]->name, "exclude")) {
{ my_instance->match = strdup(params[i]->value);
my_instance->nomatch = strdup(params[i]->value); }
} else if (!strcmp(params[i]->name, "exclude"))
else if (!strcmp(params[i]->name, "source")) {
my_instance->source = strdup(params[i]->value); my_instance->nomatch = strdup(params[i]->value);
else if (!strcmp(params[i]->name, "user")) }
my_instance->userName = strdup(params[i]->value); else if (!strcmp(params[i]->name, "source"))
else if (!strcmp(params[i]->name, "filebase")) {
{ my_instance->source = strdup(params[i]->value);
if (my_instance->filebase){ }
free(my_instance->filebase); else if (!strcmp(params[i]->name, "user"))
my_instance->filebase = NULL; {
} my_instance->userName = strdup(params[i]->value);
my_instance->filebase = strdup(params[i]->value); }
} else if (!strcmp(params[i]->name, "filebase"))
else if (!filter_standard_parameter(params[i]->name)) {
{ if (my_instance->filebase)
MXS_ERROR("qlafilter: Unexpected parameter '%s'.", {
params[i]->name);
}
}
}
my_instance->sessions = 0;
if (my_instance->match &&
regcomp(&my_instance->re, my_instance->match, REG_ICASE))
{
MXS_ERROR("qlafilter: Invalid regular expression '%s'"
" for the match parameter.\n",
my_instance->match);
free(my_instance->match);
free(my_instance->source);
if(my_instance->filebase){
free(my_instance->filebase); free(my_instance->filebase);
my_instance->filebase = NULL;
} }
free(my_instance); my_instance->filebase = strdup(params[i]->value);
return NULL; }
} else if (!filter_standard_parameter(params[i]->name))
if (my_instance->nomatch && {
regcomp(&my_instance->nore, my_instance->nomatch, MXS_ERROR("qlafilter: Unexpected parameter '%s'.",
REG_ICASE)) params[i]->name);
{ }
}
}
my_instance->sessions = 0;
if (my_instance->match &&
regcomp(&my_instance->re, my_instance->match, REG_ICASE))
{
MXS_ERROR("qlafilter: Invalid regular expression '%s'"
" for the match parameter.\n",
my_instance->match);
free(my_instance->match);
free(my_instance->source);
if (my_instance->filebase)
{
free(my_instance->filebase);
}
free(my_instance);
return NULL;
}
if (my_instance->nomatch &&
regcomp(&my_instance->nore, my_instance->nomatch,
REG_ICASE))
{
MXS_ERROR("qlafilter: Invalid regular expression '%s'" MXS_ERROR("qlafilter: Invalid regular expression '%s'"
" for the nomatch paramter.", " for the nomatch paramter.",
my_instance->match); my_instance->match);
if (my_instance->match) if (my_instance->match)
regfree(&my_instance->re); {
free(my_instance->match); regfree(&my_instance->re);
free(my_instance->source); }
if(my_instance->filebase){ free(my_instance->match);
free(my_instance->filebase); free(my_instance->source);
} if (my_instance->filebase)
free(my_instance); {
return NULL; free(my_instance->filebase);
} }
} free(my_instance);
return (FILTER *)my_instance; return NULL;
}
}
return(FILTER *) my_instance;
} }
/** /**
@ -251,80 +268,82 @@ int i;
* *
* Create the file to log to and open it. * Create the file to log to and open it.
* *
* @param instance The filter instance data * @param instance The filter instance data
* @param session The session itself * @param session The session itself
* @return Session specific data for this session * @return Session specific data for this session
*/ */
static void * static void *
newSession(FILTER *instance, SESSION *session) newSession(FILTER *instance, SESSION *session)
{ {
QLA_INSTANCE *my_instance = (QLA_INSTANCE *)instance; QLA_INSTANCE *my_instance = (QLA_INSTANCE *) instance;
QLA_SESSION *my_session; QLA_SESSION *my_session;
char *remote, *userName; char *remote, *userName;
if ((my_session = calloc(1, sizeof(QLA_SESSION))) != NULL) if ((my_session = calloc(1, sizeof(QLA_SESSION))) != NULL)
{ {
if ((my_session->filename = if ((my_session->filename =
(char *)malloc(strlen(my_instance->filebase) + 20)) (char *) malloc(strlen(my_instance->filebase) + 20))
== NULL) == NULL)
{ {
char errbuf[STRERROR_BUFLEN]; char errbuf[STRERROR_BUFLEN];
MXS_ERROR("Memory allocation for qla filter " MXS_ERROR("Memory allocation for qla filter "
"file name failed due to %d, %s.", "file name failed due to %d, %s.",
errno, errno,
strerror_r(errno, errbuf, sizeof(errbuf))); strerror_r(errno, errbuf, sizeof(errbuf)));
free(my_session); free(my_session);
return NULL; return NULL;
} }
my_session->active = 1; my_session->active = 1;
if (my_instance->source if (my_instance->source
&& (remote = session_get_remote(session)) != NULL) && (remote = session_get_remote(session)) != NULL)
{ {
if (strcmp(remote, my_instance->source)) if (strcmp(remote, my_instance->source))
my_session->active = 0; {
} my_session->active = 0;
userName = session_getUser(session); }
}
if (my_instance->userName && userName = session_getUser(session);
userName &&
strcmp(userName,my_instance->userName)) if (my_instance->userName &&
{ userName &&
my_session->active = 0; strcmp(userName, my_instance->userName))
} {
sprintf(my_session->filename, "%s.%d", my_session->active = 0;
my_instance->filebase, }
my_instance->sessions); sprintf(my_session->filename, "%s.%d",
my_instance->filebase,
my_instance->sessions);
// Multiple sessions can try to update my_instance->sessions simultaneously // Multiple sessions can try to update my_instance->sessions simultaneously
atomic_add(&(my_instance->sessions), 1); atomic_add(&(my_instance->sessions), 1);
if (my_session->active) if (my_session->active)
{ {
my_session->fp = fopen(my_session->filename, "w"); my_session->fp = fopen(my_session->filename, "w");
if (my_session->fp == NULL) if (my_session->fp == NULL)
{ {
char errbuf[STRERROR_BUFLEN];
MXS_ERROR("Opening output file for qla "
"fileter failed due to %d, %s",
errno,
strerror_r(errno, errbuf, sizeof(errbuf)));
free(my_session->filename);
free(my_session);
my_session = NULL;
}
}
}
else
{
char errbuf[STRERROR_BUFLEN]; char errbuf[STRERROR_BUFLEN];
MXS_ERROR("Memory allocation for qla filter failed due to " MXS_ERROR("Opening output file for qla "
"%d, %s.", "fileter failed due to %d, %s",
errno, errno,
strerror_r(errno, errbuf, sizeof(errbuf))); strerror_r(errno, errbuf, sizeof(errbuf)));
} free(my_session->filename);
return my_session; free(my_session);
my_session = NULL;
}
}
}
else
{
char errbuf[STRERROR_BUFLEN];
MXS_ERROR("Memory allocation for qla filter failed due to "
"%d, %s.",
errno,
strerror_r(errno, errbuf, sizeof(errbuf)));
}
return my_session;
} }
/** /**
@ -332,48 +351,50 @@ char *remote, *userName;
* by which a filter may cleanup data structure etc. * by which a filter may cleanup data structure etc.
* In the case of the QLA filter we simple close the file descriptor. * In the case of the QLA filter we simple close the file descriptor.
* *
* @param instance The filter instance data * @param instance The filter instance data
* @param session The session being closed * @param session The session being closed
*/ */
static void static void
closeSession(FILTER *instance, void *session) closeSession(FILTER *instance, void *session)
{ {
QLA_SESSION *my_session = (QLA_SESSION *)session; QLA_SESSION *my_session = (QLA_SESSION *) session;
if (my_session->active && my_session->fp) if (my_session->active && my_session->fp)
fclose(my_session->fp); {
fclose(my_session->fp);
}
} }
/** /**
* Free the memory associated with the session * Free the memory associated with the session
* *
* @param instance The filter instance * @param instance The filter instance
* @param session The filter session * @param session The filter session
*/ */
static void static void
freeSession(FILTER *instance, void *session) freeSession(FILTER *instance, void *session)
{ {
QLA_SESSION *my_session = (QLA_SESSION *)session; QLA_SESSION *my_session = (QLA_SESSION *) session;
free(my_session->filename); free(my_session->filename);
free(session); free(session);
return; return;
} }
/** /**
* Set the downstream filter or router to which queries will be * Set the downstream filter or router to which queries will be
* passed from this filter. * passed from this filter.
* *
* @param instance The filter instance data * @param instance The filter instance data
* @param session The filter session * @param session The filter session
* @param downstream The downstream filter or router. * @param downstream The downstream filter or router.
*/ */
static void static void
setDownstream(FILTER *instance, void *session, DOWNSTREAM *downstream) setDownstream(FILTER *instance, void *session, DOWNSTREAM *downstream)
{ {
QLA_SESSION *my_session = (QLA_SESSION *)session; QLA_SESSION *my_session = (QLA_SESSION *) session;
my_session->down = *downstream; my_session->down = *downstream;
} }
/** /**
@ -382,48 +403,48 @@ QLA_SESSION *my_session = (QLA_SESSION *)session;
* query should normally be passed to the downstream component * query should normally be passed to the downstream component
* (filter or router) in the filter chain. * (filter or router) in the filter chain.
* *
* @param instance The filter instance data * @param instance The filter instance data
* @param session The filter session * @param session The filter session
* @param queue The query data * @param queue The query data
*/ */
static int static int
routeQuery(FILTER *instance, void *session, GWBUF *queue) routeQuery(FILTER *instance, void *session, GWBUF *queue)
{ {
QLA_INSTANCE *my_instance = (QLA_INSTANCE *)instance; QLA_INSTANCE *my_instance = (QLA_INSTANCE *) instance;
QLA_SESSION *my_session = (QLA_SESSION *)session; QLA_SESSION *my_session = (QLA_SESSION *) session;
char *ptr; char *ptr;
int length = 0; int length = 0;
struct tm t; struct tm t;
struct timeval tv; struct timeval tv;
if (my_session->active) if (my_session->active)
{ {
if (queue->next != NULL) if (queue->next != NULL)
{ {
queue = gwbuf_make_contiguous(queue); queue = gwbuf_make_contiguous(queue);
} }
if ((ptr = modutil_get_SQL(queue)) != NULL) if ((ptr = modutil_get_SQL(queue)) != NULL)
{ {
if ((my_instance->match == NULL || if ((my_instance->match == NULL ||
regexec(&my_instance->re, ptr, 0, NULL, 0) == 0) && regexec(&my_instance->re, ptr, 0, NULL, 0) == 0) &&
(my_instance->nomatch == NULL || (my_instance->nomatch == NULL ||
regexec(&my_instance->nore,ptr,0,NULL, 0) != 0)) regexec(&my_instance->nore, ptr, 0, NULL, 0) != 0))
{ {
gettimeofday(&tv, NULL); gettimeofday(&tv, NULL);
localtime_r(&tv.tv_sec, &t); localtime_r(&tv.tv_sec, &t);
fprintf(my_session->fp, fprintf(my_session->fp,
"%02d:%02d:%02d.%-3d %d/%02d/%d, ", "%02d:%02d:%02d.%-3d %d/%02d/%d, ",
t.tm_hour, t.tm_min, t.tm_sec, (int)(tv.tv_usec / 1000), t.tm_hour, t.tm_min, t.tm_sec, (int) (tv.tv_usec / 1000),
t.tm_mday, t.tm_mon + 1, 1900 + t.tm_year); t.tm_mday, t.tm_mon + 1, 1900 + t.tm_year);
fprintf(my_session->fp,"%s\n",ptr); fprintf(my_session->fp, "%s\n", ptr);
} }
free(ptr); free(ptr);
} }
} }
/* Pass the query downstream */ /* Pass the query downstream */
return my_session->down.routeQuery(my_session->down.instance, return my_session->down.routeQuery(my_session->down.instance,
my_session->down.session, queue); my_session->down.session, queue);
} }
/** /**
@ -433,31 +454,39 @@ struct timeval tv;
* instance as a whole, otherwise print diagnostics for the * instance as a whole, otherwise print diagnostics for the
* particular session. * particular session.
* *
* @param instance The filter instance * @param instance The filter instance
* @param fsession Filter session, may be NULL * @param fsession Filter session, may be NULL
* @param dcb The DCB for diagnostic output * @param dcb The DCB for diagnostic output
*/ */
static void static void
diagnostic(FILTER *instance, void *fsession, DCB *dcb) diagnostic(FILTER *instance, void *fsession, DCB *dcb)
{ {
QLA_INSTANCE *my_instance = (QLA_INSTANCE *)instance; QLA_INSTANCE *my_instance = (QLA_INSTANCE *) instance;
QLA_SESSION *my_session = (QLA_SESSION *)fsession; QLA_SESSION *my_session = (QLA_SESSION *) fsession;
if (my_session) if (my_session)
{ {
dcb_printf(dcb, "\t\tLogging to file %s.\n", dcb_printf(dcb, "\t\tLogging to file %s.\n",
my_session->filename); my_session->filename);
} }
if (my_instance->source) if (my_instance->source)
dcb_printf(dcb, "\t\tLimit logging to connections from %s\n", {
my_instance->source); dcb_printf(dcb, "\t\tLimit logging to connections from %s\n",
if (my_instance->userName) my_instance->source);
dcb_printf(dcb, "\t\tLimit logging to user %s\n", }
my_instance->userName); if (my_instance->userName)
if (my_instance->match) {
dcb_printf(dcb, "\t\tInclude queries that match %s\n", dcb_printf(dcb, "\t\tLimit logging to user %s\n",
my_instance->match); my_instance->userName);
if (my_instance->nomatch) }
dcb_printf(dcb, "\t\tExclude queries that match %s\n", if (my_instance->match)
my_instance->nomatch); {
dcb_printf(dcb, "\t\tInclude queries that match %s\n",
my_instance->match);
}
if (my_instance->nomatch)
{
dcb_printf(dcb, "\t\tExclude queries that match %s\n",
my_instance->nomatch);
}
} }