Compile filter.c as C++

The contents of the existing filter.cc was copied into filter.c that
subsequently was renamed to filter.cc.

The way the session is called as the last filter in the filter chain
is really dubious and ought to be rearranged so that the blind casting
of a session to a filter and back is not needed.
This commit is contained in:
Johan Wikman 2017-03-23 16:36:21 +02:00
parent db18e19d3c
commit 9a22d1cb92
7 changed files with 489 additions and 488 deletions

View File

@ -94,11 +94,14 @@ typedef struct
* The downstream element in the filter chain. This may refer to
* another filter or to a router.
*/
struct mxs_filter;
struct mxs_filter_session;
typedef struct mxs_downstream
{
void *instance;
void *session;
int32_t (*routeQuery)(void *instance, void *session, GWBUF *request);
struct mxs_filter *instance;
struct mxs_filter_session *session;
int32_t (*routeQuery)(struct mxs_filter *instance, struct mxs_filter_session *session, GWBUF *request);
} MXS_DOWNSTREAM;
/**
@ -107,9 +110,9 @@ typedef struct mxs_downstream
*/
typedef struct mxs_upstream
{
void *instance;
void *session;
int32_t (*clientReply)(void *instance, void *session, GWBUF *response);
struct mxs_filter *instance;
struct mxs_filter_session *session;
int32_t (*clientReply)(struct mxs_filter *instance, struct mxs_filter_session *session, GWBUF *response);
int32_t (*error)(void *instance, void *session, void *);
} MXS_UPSTREAM;

View File

@ -7,7 +7,8 @@ add_library(maxscale-common SHARED
config.cc
config_runtime.cc
dcb.cc
filter.c filter.cc externcmd.c paths.c hashtable.c hint.c housekeeper.c load_utils.c log_manager.cc maxscale_pcre2.c misc.c mlist.c modutil.c monitor.c queuemanager.c query_classifier.cc poll.c random_jkiss.c resultset.c router.cc secrets.c server.c service.c session.c spinlock.c thread.c users.c utils.c skygw_utils.cc statistics.c listener.c ssl.c mysql_utils.c mysql_binlog.c modulecmd.c)
filter.cc
externcmd.c paths.c hashtable.c hint.c housekeeper.c load_utils.c log_manager.cc maxscale_pcre2.c misc.c mlist.c modutil.c monitor.c queuemanager.c query_classifier.cc poll.c random_jkiss.c resultset.c router.cc secrets.c server.c service.c session.c spinlock.c thread.c users.c utils.c skygw_utils.cc statistics.c listener.c ssl.c mysql_utils.c mysql_binlog.c modulecmd.c)
if(WITH_JEMALLOC)
target_link_libraries(maxscale-common ${JEMALLOC_LIBRARIES})

View File

@ -1,474 +0,0 @@
/*
* Copyright (c) 2016 MariaDB Corporation Ab
*
* Use of this software is governed by the Business Source License included
* in the LICENSE.TXT file and at www.mariadb.com/bsl11.
*
* Change Date: 2019-07-01
*
* On the date above, in accordance with the Business Source License, use
* of this software will be governed by version 2 or later of the General
* Public License.
*/
/**
* @file filter.c - A representation of a filter within MaxScale.
*
* @verbatim
* Revision History
*
* Date Who Description
* 29/05/14 Mark Riddoch Initial implementation
*
* @endverbatim
*/
#include <maxscale/filter.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <maxscale/alloc.h>
#include <maxscale/log_manager.h>
#include <maxscale/session.h>
#include <maxscale/spinlock.h>
#include "maxscale/filter.h"
#include "maxscale/config.h"
#include "maxscale/modules.h"
static SPINLOCK filter_spin = SPINLOCK_INIT; /**< Protects the list of all filters */
static MXS_FILTER_DEF *allFilters = NULL; /**< The list of all filters */
static void filter_free_parameters(MXS_FILTER_DEF *filter);
/**
* Allocate a new filter within MaxScale
*
*
* @param name The filter name
* @param module The module to load
*
* @return The newly created filter or NULL if an error occured
*/
MXS_FILTER_DEF *
filter_alloc(const char *name, const char *module)
{
char* my_name = MXS_STRDUP(name);
char* my_module = MXS_STRDUP(module);
MXS_FILTER_DEF *filter = (MXS_FILTER_DEF *)MXS_MALLOC(sizeof(MXS_FILTER_DEF));
if (!my_name || !my_module || !filter)
{
MXS_FREE(my_name);
MXS_FREE(my_module);
MXS_FREE(filter);
return NULL;
}
filter->name = my_name;
filter->module = my_module;
filter->filter = NULL;
filter->options = NULL;
filter->obj = NULL;
filter->parameters = NULL;
spinlock_init(&filter->spin);
spinlock_acquire(&filter_spin);
filter->next = allFilters;
allFilters = filter;
spinlock_release(&filter_spin);
return filter;
}
/**
* Deallocate the specified filter
*
* @param filter The filter to deallocate
* @return Returns true if the server was freed
*/
void
filter_free(MXS_FILTER_DEF *filter)
{
MXS_FILTER_DEF *ptr;
if (filter)
{
/* First of all remove from the linked list */
spinlock_acquire(&filter_spin);
if (allFilters == filter)
{
allFilters = filter->next;
}
else
{
ptr = allFilters;
while (ptr && ptr->next != filter)
{
ptr = ptr->next;
}
if (ptr)
{
ptr->next = filter->next;
}
}
spinlock_release(&filter_spin);
/* Clean up session and free the memory */
MXS_FREE(filter->name);
MXS_FREE(filter->module);
if (filter->options)
{
for (int i = 0; filter->options[i]; i++)
{
MXS_FREE(filter->options[i]);
}
MXS_FREE(filter->options);
}
filter_free_parameters(filter);
MXS_FREE(filter);
}
}
MXS_FILTER_DEF *
filter_def_find(const char *name)
{
MXS_FILTER_DEF *filter;
spinlock_acquire(&filter_spin);
filter = allFilters;
while (filter)
{
if (strcmp(filter->name, name) == 0)
{
break;
}
filter = filter->next;
}
spinlock_release(&filter_spin);
return filter;
}
const char* filter_def_get_name(const MXS_FILTER_DEF* filter_def)
{
return filter_def->name;
}
const char* filter_def_get_module_name(const MXS_FILTER_DEF* filter_def)
{
return filter_def->module;
}
MXS_FILTER* filter_def_get_instance(const MXS_FILTER_DEF* filter_def)
{
return filter_def->filter;
}
/**
* Check a parameter to see if it is a standard filter parameter
*
* @param name Parameter name to check
*/
int
filter_standard_parameter(const char *name)
{
if (strcmp(name, "type") == 0 || strcmp(name, "module") == 0)
{
return 1;
}
return 0;
}
/**
* Print all filters to a DCB
*
* Designed to be called within a debugger session in order
* to display all active filters within MaxScale
*/
void
dprintAllFilters(DCB *dcb)
{
MXS_FILTER_DEF *ptr;
int i;
spinlock_acquire(&filter_spin);
ptr = allFilters;
while (ptr)
{
dcb_printf(dcb, "Filter %p (%s)\n", ptr, ptr->name);
dcb_printf(dcb, "\tModule: %s\n", ptr->module);
if (ptr->options)
{
dcb_printf(dcb, "\tOptions: ");
for (i = 0; ptr->options && ptr->options[i]; i++)
{
dcb_printf(dcb, "%s ", ptr->options[i]);
}
dcb_printf(dcb, "\n");
}
if (ptr->obj && ptr->filter)
{
ptr->obj->diagnostics(ptr->filter, NULL, dcb);
}
else
{
dcb_printf(dcb, "\tModule not loaded.\n");
}
ptr = ptr->next;
}
spinlock_release(&filter_spin);
}
/**
* Print filter details to a DCB
*
* Designed to be called within a debug CLI in order
* to display all active filters in MaxScale
*/
void
dprintFilter(DCB *dcb, const MXS_FILTER_DEF *filter)
{
int i;
dcb_printf(dcb, "Filter %p (%s)\n", filter, filter->name);
dcb_printf(dcb, "\tModule: %s\n", filter->module);
if (filter->options)
{
dcb_printf(dcb, "\tOptions: ");
for (i = 0; filter->options && filter->options[i]; i++)
{
dcb_printf(dcb, "%s ", filter->options[i]);
}
dcb_printf(dcb, "\n");
}
if (filter->obj && filter->filter)
{
filter->obj->diagnostics(filter->filter, NULL, dcb);
}
}
/**
* List all filters in a tabular form to a DCB
*
*/
void
dListFilters(DCB *dcb)
{
MXS_FILTER_DEF *ptr;
int i;
spinlock_acquire(&filter_spin);
ptr = allFilters;
if (ptr)
{
dcb_printf(dcb, "Filters\n");
dcb_printf(dcb, "--------------------+-----------------+----------------------------------------\n");
dcb_printf(dcb, "%-19s | %-15s | Options\n",
"Filter", "Module");
dcb_printf(dcb, "--------------------+-----------------+----------------------------------------\n");
}
while (ptr)
{
dcb_printf(dcb, "%-19s | %-15s | ",
ptr->name, ptr->module);
for (i = 0; ptr->options && ptr->options[i]; i++)
{
dcb_printf(dcb, "%s ", ptr->options[i]);
}
dcb_printf(dcb, "\n");
ptr = ptr->next;
}
if (allFilters)
{
dcb_printf(dcb,
"--------------------+-----------------+----------------------------------------\n\n");
}
spinlock_release(&filter_spin);
}
/**
* Add a router option to a service
*
* @param filter The filter to add the option to
* @param option The option string
*/
void
filter_add_option(MXS_FILTER_DEF *filter, const char *option)
{
int i;
spinlock_acquire(&filter->spin);
if (filter->options == NULL)
{
filter->options = (char **)MXS_CALLOC(2, sizeof(char *));
MXS_ABORT_IF_NULL(filter->options);
filter->options[0] = MXS_STRDUP_A(option);
filter->options[1] = NULL;
}
else
{
for (i = 0; filter->options[i]; i++)
{
;
}
filter->options = (char **)MXS_REALLOC(filter->options, (i + 2) * sizeof(char *));
MXS_ABORT_IF_NULL(filter->options);
filter->options[i] = MXS_STRDUP_A(option);
MXS_ABORT_IF_NULL(filter->options[i]);
filter->options[i + 1] = NULL;
}
spinlock_release(&filter->spin);
}
/**
* Add a router parameter to a service
*
* @param filter The filter to add the parameter to
* @param name The parameter name
* @param value The parameter value
*/
void
filter_add_parameter(MXS_FILTER_DEF *filter, const char *name, const char *value)
{
CONFIG_CONTEXT ctx = {.object = ""};
config_add_param(&ctx, name, value);
ctx.parameters->next = filter->parameters;
filter->parameters = ctx.parameters;
}
/**
* Free filter parameters
* @param filter Filter whose parameters are to be freed
*/
static void filter_free_parameters(MXS_FILTER_DEF *filter)
{
config_parameter_free(filter->parameters);
}
/**
* Load a filter module for use and create an instance of it for a service.
* @param filter Filter definition
* @return True if module was successfully loaded, false if an error occurred
*/
bool filter_load(MXS_FILTER_DEF* filter)
{
bool rval = false;
if (filter)
{
if (filter->filter)
{
// Already loaded and created.
rval = true;
}
else
{
if (filter->obj == NULL)
{
/* Filter not yet loaded */
if ((filter->obj = load_module(filter->module, MODULE_FILTER)) == NULL)
{
MXS_ERROR("Failed to load filter module '%s'.", filter->module);
}
}
if (filter->obj)
{
ss_dassert(!filter->filter);
if ((filter->filter = (filter->obj->createInstance)(filter->name,
filter->options,
filter->parameters)))
{
rval = true;
}
else
{
MXS_ERROR("Failed to create filter '%s' instance.", filter->name);
}
}
}
}
return rval;
}
/**
* Connect the downstream filter chain for a filter.
*
* This will create the filter instance, loading the filter module, and
* conenct the fitler into the downstream chain.
*
* @param filter The filter to add into the chain
* @param session The client session
* @param downstream The filter downstream of this filter
* @return The downstream component for the next filter or NULL
* if the filter could not be created
*/
MXS_DOWNSTREAM *
filter_apply(MXS_FILTER_DEF *filter, MXS_SESSION *session, MXS_DOWNSTREAM *downstream)
{
MXS_DOWNSTREAM *me;
if ((me = (MXS_DOWNSTREAM *)MXS_CALLOC(1, sizeof(MXS_DOWNSTREAM))) == NULL)
{
return NULL;
}
me->instance = filter->filter;
me->routeQuery = (void *)(filter->obj->routeQuery);
if ((me->session = filter->obj->newSession(me->instance, session)) == NULL)
{
MXS_FREE(me);
return NULL;
}
filter->obj->setDownstream(me->instance, me->session, downstream);
return me;
}
/**
* Connect a filter in the up stream filter chain for a session
*
* Note, the filter will have been created when the downstream chian was
* previously setup.
* 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.
*
* @param filter The fitler to add to the chain
* @param fsession The filter session
* @param upstream The filter that should be upstream of this filter
* @return The upstream component for the next filter
*/
MXS_UPSTREAM *
filter_upstream(MXS_FILTER_DEF *filter, void *fsession, MXS_UPSTREAM *upstream)
{
MXS_UPSTREAM *me = NULL;
/*
* The the filter has no setUpstream entry point then is does
* not require to see results and can be left out of the chain.
*/
if (filter->obj->setUpstream == NULL)
{
return upstream;
}
if (filter->obj->clientReply != NULL)
{
if ((me = (MXS_UPSTREAM *)MXS_CALLOC(1, sizeof(MXS_UPSTREAM))) == NULL)
{
return NULL;
}
me->instance = filter->filter;
me->session = fsession;
me->clientReply = (void *)(filter->obj->clientReply);
filter->obj->setUpstream(me->instance, me->session, upstream);
}
return me;
}

View File

@ -11,7 +11,462 @@
* Public License.
*/
/**
* @file filter.c - A representation of a filter within MaxScale.
*/
#include <maxscale/filter.h>
#include <maxscale/filter.hh>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <maxscale/alloc.h>
#include <maxscale/log_manager.h>
#include <maxscale/session.h>
#include <maxscale/spinlock.h>
#include "maxscale/filter.h"
#include "maxscale/config.h"
#include "maxscale/modules.h"
static SPINLOCK filter_spin = SPINLOCK_INIT; /**< Protects the list of all filters */
static MXS_FILTER_DEF *allFilters = NULL; /**< The list of all filters */
static void filter_free_parameters(MXS_FILTER_DEF *filter);
/**
* Allocate a new filter within MaxScale
*
*
* @param name The filter name
* @param module The module to load
*
* @return The newly created filter or NULL if an error occured
*/
MXS_FILTER_DEF *
filter_alloc(const char *name, const char *module)
{
char* my_name = MXS_STRDUP(name);
char* my_module = MXS_STRDUP(module);
MXS_FILTER_DEF *filter = (MXS_FILTER_DEF *)MXS_MALLOC(sizeof(MXS_FILTER_DEF));
if (!my_name || !my_module || !filter)
{
MXS_FREE(my_name);
MXS_FREE(my_module);
MXS_FREE(filter);
return NULL;
}
filter->name = my_name;
filter->module = my_module;
filter->filter = NULL;
filter->options = NULL;
filter->obj = NULL;
filter->parameters = NULL;
spinlock_init(&filter->spin);
spinlock_acquire(&filter_spin);
filter->next = allFilters;
allFilters = filter;
spinlock_release(&filter_spin);
return filter;
}
/**
* Deallocate the specified filter
*
* @param filter The filter to deallocate
* @return Returns true if the server was freed
*/
void
filter_free(MXS_FILTER_DEF *filter)
{
MXS_FILTER_DEF *ptr;
if (filter)
{
/* First of all remove from the linked list */
spinlock_acquire(&filter_spin);
if (allFilters == filter)
{
allFilters = filter->next;
}
else
{
ptr = allFilters;
while (ptr && ptr->next != filter)
{
ptr = ptr->next;
}
if (ptr)
{
ptr->next = filter->next;
}
}
spinlock_release(&filter_spin);
/* Clean up session and free the memory */
MXS_FREE(filter->name);
MXS_FREE(filter->module);
if (filter->options)
{
for (int i = 0; filter->options[i]; i++)
{
MXS_FREE(filter->options[i]);
}
MXS_FREE(filter->options);
}
filter_free_parameters(filter);
MXS_FREE(filter);
}
}
MXS_FILTER_DEF *
filter_def_find(const char *name)
{
MXS_FILTER_DEF *filter;
spinlock_acquire(&filter_spin);
filter = allFilters;
while (filter)
{
if (strcmp(filter->name, name) == 0)
{
break;
}
filter = filter->next;
}
spinlock_release(&filter_spin);
return filter;
}
const char* filter_def_get_name(const MXS_FILTER_DEF* filter_def)
{
return filter_def->name;
}
const char* filter_def_get_module_name(const MXS_FILTER_DEF* filter_def)
{
return filter_def->module;
}
MXS_FILTER* filter_def_get_instance(const MXS_FILTER_DEF* filter_def)
{
return filter_def->filter;
}
/**
* Check a parameter to see if it is a standard filter parameter
*
* @param name Parameter name to check
*/
int
filter_standard_parameter(const char *name)
{
if (strcmp(name, "type") == 0 || strcmp(name, "module") == 0)
{
return 1;
}
return 0;
}
/**
* Print all filters to a DCB
*
* Designed to be called within a debugger session in order
* to display all active filters within MaxScale
*/
void
dprintAllFilters(DCB *dcb)
{
MXS_FILTER_DEF *ptr;
int i;
spinlock_acquire(&filter_spin);
ptr = allFilters;
while (ptr)
{
dcb_printf(dcb, "Filter %p (%s)\n", ptr, ptr->name);
dcb_printf(dcb, "\tModule: %s\n", ptr->module);
if (ptr->options)
{
dcb_printf(dcb, "\tOptions: ");
for (i = 0; ptr->options && ptr->options[i]; i++)
{
dcb_printf(dcb, "%s ", ptr->options[i]);
}
dcb_printf(dcb, "\n");
}
if (ptr->obj && ptr->filter)
{
ptr->obj->diagnostics(ptr->filter, NULL, dcb);
}
else
{
dcb_printf(dcb, "\tModule not loaded.\n");
}
ptr = ptr->next;
}
spinlock_release(&filter_spin);
}
/**
* Print filter details to a DCB
*
* Designed to be called within a debug CLI in order
* to display all active filters in MaxScale
*/
void
dprintFilter(DCB *dcb, const MXS_FILTER_DEF *filter)
{
int i;
dcb_printf(dcb, "Filter %p (%s)\n", filter, filter->name);
dcb_printf(dcb, "\tModule: %s\n", filter->module);
if (filter->options)
{
dcb_printf(dcb, "\tOptions: ");
for (i = 0; filter->options && filter->options[i]; i++)
{
dcb_printf(dcb, "%s ", filter->options[i]);
}
dcb_printf(dcb, "\n");
}
if (filter->obj && filter->filter)
{
filter->obj->diagnostics(filter->filter, NULL, dcb);
}
}
/**
* List all filters in a tabular form to a DCB
*
*/
void
dListFilters(DCB *dcb)
{
MXS_FILTER_DEF *ptr;
int i;
spinlock_acquire(&filter_spin);
ptr = allFilters;
if (ptr)
{
dcb_printf(dcb, "Filters\n");
dcb_printf(dcb, "--------------------+-----------------+----------------------------------------\n");
dcb_printf(dcb, "%-19s | %-15s | Options\n",
"Filter", "Module");
dcb_printf(dcb, "--------------------+-----------------+----------------------------------------\n");
}
while (ptr)
{
dcb_printf(dcb, "%-19s | %-15s | ",
ptr->name, ptr->module);
for (i = 0; ptr->options && ptr->options[i]; i++)
{
dcb_printf(dcb, "%s ", ptr->options[i]);
}
dcb_printf(dcb, "\n");
ptr = ptr->next;
}
if (allFilters)
{
dcb_printf(dcb,
"--------------------+-----------------+----------------------------------------\n\n");
}
spinlock_release(&filter_spin);
}
/**
* Add a router option to a service
*
* @param filter The filter to add the option to
* @param option The option string
*/
void
filter_add_option(MXS_FILTER_DEF *filter, const char *option)
{
int i;
spinlock_acquire(&filter->spin);
if (filter->options == NULL)
{
filter->options = (char **)MXS_CALLOC(2, sizeof(char *));
MXS_ABORT_IF_NULL(filter->options);
filter->options[0] = MXS_STRDUP_A(option);
filter->options[1] = NULL;
}
else
{
for (i = 0; filter->options[i]; i++)
{
;
}
filter->options = (char **)MXS_REALLOC(filter->options, (i + 2) * sizeof(char *));
MXS_ABORT_IF_NULL(filter->options);
filter->options[i] = MXS_STRDUP_A(option);
MXS_ABORT_IF_NULL(filter->options[i]);
filter->options[i + 1] = NULL;
}
spinlock_release(&filter->spin);
}
/**
* Add a router parameter to a service
*
* @param filter The filter to add the parameter to
* @param name The parameter name
* @param value The parameter value
*/
void
filter_add_parameter(MXS_FILTER_DEF *filter, const char *name, const char *value)
{
CONFIG_CONTEXT ctx = {.object = (char*)""};
config_add_param(&ctx, name, value);
ctx.parameters->next = filter->parameters;
filter->parameters = ctx.parameters;
}
/**
* Free filter parameters
* @param filter Filter whose parameters are to be freed
*/
static void filter_free_parameters(MXS_FILTER_DEF *filter)
{
config_parameter_free(filter->parameters);
}
/**
* Load a filter module for use and create an instance of it for a service.
* @param filter Filter definition
* @return True if module was successfully loaded, false if an error occurred
*/
bool filter_load(MXS_FILTER_DEF* filter)
{
bool rval = false;
if (filter)
{
if (filter->filter)
{
// Already loaded and created.
rval = true;
}
else
{
if (filter->obj == NULL)
{
/* Filter not yet loaded */
if ((filter->obj = (MXS_FILTER_OBJECT*)load_module(filter->module, MODULE_FILTER)) == NULL)
{
MXS_ERROR("Failed to load filter module '%s'.", filter->module);
}
}
if (filter->obj)
{
ss_dassert(!filter->filter);
if ((filter->filter = (filter->obj->createInstance)(filter->name,
filter->options,
filter->parameters)))
{
rval = true;
}
else
{
MXS_ERROR("Failed to create filter '%s' instance.", filter->name);
}
}
}
}
return rval;
}
/**
* Connect the downstream filter chain for a filter.
*
* This will create the filter instance, loading the filter module, and
* conenct the fitler into the downstream chain.
*
* @param filter The filter to add into the chain
* @param session The client session
* @param downstream The filter downstream of this filter
* @return The downstream component for the next filter or NULL
* if the filter could not be created
*/
MXS_DOWNSTREAM *
filter_apply(MXS_FILTER_DEF *filter, MXS_SESSION *session, MXS_DOWNSTREAM *downstream)
{
MXS_DOWNSTREAM *me;
if ((me = (MXS_DOWNSTREAM *)MXS_CALLOC(1, sizeof(MXS_DOWNSTREAM))) == NULL)
{
return NULL;
}
me->instance = filter->filter;
me->routeQuery = filter->obj->routeQuery;
if ((me->session = filter->obj->newSession(me->instance, session)) == NULL)
{
MXS_FREE(me);
return NULL;
}
filter->obj->setDownstream(me->instance, me->session, downstream);
return me;
}
/**
* Connect a filter in the up stream filter chain for a session
*
* Note, the filter will have been created when the downstream chian was
* previously setup.
* 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.
*
* @param filter The fitler to add to the chain
* @param fsession The filter session
* @param upstream The filter that should be upstream of this filter
* @return The upstream component for the next filter
*/
MXS_UPSTREAM *
filter_upstream(MXS_FILTER_DEF *filter, MXS_FILTER_SESSION *fsession, MXS_UPSTREAM *upstream)
{
MXS_UPSTREAM *me = NULL;
/*
* The the filter has no setUpstream entry point then is does
* not require to see results and can be left out of the chain.
*/
if (filter->obj->setUpstream == NULL)
{
return upstream;
}
if (filter->obj->clientReply != NULL)
{
if ((me = (MXS_UPSTREAM *)MXS_CALLOC(1, sizeof(MXS_UPSTREAM))) == NULL)
{
return NULL;
}
me->instance = filter->filter;
me->session = fsession;
me->clientReply = filter->obj->clientReply;
filter->obj->setUpstream(me->instance, me->session, upstream);
}
return me;
}
namespace maxscale
{
@ -58,4 +513,3 @@ void FilterSession::diagnostics(DCB* pDcb)
}
}

View File

@ -44,6 +44,8 @@ MXS_DOWNSTREAM *filter_apply(MXS_FILTER_DEF *filter_def, MXS_SESSION *session, M
void filter_free(MXS_FILTER_DEF *filter_def);
bool filter_load(MXS_FILTER_DEF *filter_def);
int filter_standard_parameter(const char *name);
MXS_UPSTREAM *filter_upstream(MXS_FILTER_DEF *filter_def, void *fsession, MXS_UPSTREAM *upstream);
MXS_UPSTREAM *filter_upstream(MXS_FILTER_DEF *filter_def,
MXS_FILTER_SESSION *fsession,
MXS_UPSTREAM *upstream);
MXS_END_DECLS

View File

@ -41,7 +41,6 @@ typedef enum
} SESSIONLISTFILTER;
int session_isvalid(MXS_SESSION *);
int session_reply(void *inst, void *session, GWBUF *data);
char *session_state(mxs_session_state_t);
bool session_link_dcb(MXS_SESSION *, struct dcb *);

View File

@ -63,6 +63,15 @@ static void session_add_to_all_list(MXS_SESSION *session);
static MXS_SESSION *session_find_free();
static void session_final_free(MXS_SESSION *session);
/**
* The clientReply of the session.
*
* @param inst In reality an MXS_SESSION*.
* @param session In reality an MXS_SESSION*.
* @param data The data to send to the client.
*/
static int session_reply(MXS_FILTER *inst, MXS_FILTER_SESSION *session, GWBUF *data);
/**
* @brief Initialize a session
*
@ -162,8 +171,12 @@ session_alloc(SERVICE *service, DCB *client_dcb)
session->head.routeQuery = (void *)(service->router->routeQuery);
session->tail.instance = session;
session->tail.session = session;
// NOTE: Here we cast the session into a MXS_FILTER and MXS_FILTER_SESSION
// NOTE: and session_reply into a filter clientReply. That's dubious but ok
// NOTE: as session_reply will know what to do. In practice, the session
// NOTE: will be called as if it would be the last filter.
session->tail.instance = (MXS_FILTER*)session;
session->tail.session = (MXS_FILTER_SESSION*)session;
session->tail.clientReply = session_reply;
if (SESSION_STATE_TO_BE_FREED != session->state
@ -664,14 +677,17 @@ session_setup_filters(MXS_SESSION *session)
* Entry point for the final element in the upstream filter, i.e. the writing
* of the data to the client.
*
* Looks like a filter `clientReply`, but in this case both the instance and
* the session argument will be a MXS_SESSION*.
*
* @param instance The "instance" data
* @param session The session
* @param data The buffer chain to write
*/
int
session_reply(void *instance, void *session, GWBUF *data)
session_reply(MXS_FILTER *instance, MXS_FILTER_SESSION *session, GWBUF *data)
{
MXS_SESSION *the_session = (MXS_SESSION *)session;
MXS_SESSION *the_session = (MXS_SESSION*)session;
return the_session->client_dcb->func.write(the_session->client_dcb, data);
}