All changes 2.0.0...develop

973b983 Merge branch 'release-2.0.0' into develop
255dd23 Make spinlock functions take const argument
6e23bab Fix bitmask reallocation
338c189 Rename and clean up slavelag filter
3ea8f28 Fix possible NULL pointer dereference
bfe6738 MXS-830: Add module information to logged messages
1fad962 Fix strncat usage
d38997a Adjust log throttling policy
0be4e4b Add hashtable_item_strcasecmp
726100e Take hashtable convenience functions into use
5e7744a Fix typo in maxadmin.md
c5778c8 Merge branch 'release-2.0.0' into develop
b5762af Move from tmpnam to mkstemp
d6f2c71 Add convenience functions to hashtable
359058a MXS-825: Add support for --execdir
636347c Enable runtime reconfiguration of log throttling
ef9fba9 Improve log throttling documentation
aef917a Implement log throttling
e3a5349 Remove shardrouter.c
8051e80 Remove custom qc_sqlite allocation functions
fd34d60 Initial implementation of the learning firewall
a8752a8 Removed "filestem option" from example
1ef2519 Removed "filestem option" from example
0815cc8 Cleanup spinlock.h
ab4dc99 Clean up hashtable.h
ef2c078 Add prototypes for hashtable copy and free functions
fb5cfaf Add 'log_throttling' configuration entry
300d823 Add proper prototypes for hashtable hash and cmp functions
1c649aa qc_mysqlembedded: Include skygw_...h without path.
d276160 Add missing RPM scripts
e70e644 Fix HTTPAuth installation
1b2b389 Combine utils into the server directory
3ff9913 Add missing utils headers to devel package
407efb2 Fix minor packaging problems
99aa6ad Split MaxScale into core, experimental and devel packages
1290386 Merge branch 'develop' of ssh://github.com/mariadb-corporation/maxscale-new into develop
e59f148 Make scripts POSIX sh compatible
7319266 Fixed SHOW SLAVE STATUS in bonlog router
f8d760a Update Binlogrouter.md
0a904ed Update Replication-Proxy-Binlog-Router-Tutorial.md
75d4202 Update Replication-Proxy-Binlog-Router-Tutorial.md
b8651fc Add missing newline in listmanager.h
c7ad047 Add note about user data caches to release notes
70ccc2b Merge branch 'release-2.0.0' into develop
575d1b6 Mistake - dummy session needs list markers set.
8364508 Merge branch 'develop' into binlog_server_semisync
868b902 Update MaxScale limitations
2c8b327 Store listener caches in separate directories
6e183ec Create unique user data caches for each listeners
f643685 Don't free orphaned tee filter sessions
4179afa Allow binlogrouter to be used without a listener
7ad79af Add function for freeing a listener
677a0a2 Move authentication data from services to listeners
4f12af7 Merge remote-tracking branch 'origin/MXS-677' into develop
1419b81 Semi-Sync support to binlog server: code review updtate
0ea0f01 Semi-Sync support to binlog server: added missing routine
4aad909 Semi-Sync support to binlog server
b824e1e Add authenticator support to httpd.c
705a688 Change tabs to spaces
d0c419e Change method of adding list fields to e.g. DCB
25504fc Document the changed routing priority of hints
41666d1 Remove use_ssl_if_enabled global option
a3584e9 Make routing hints have highest priority
34a1d24 Updated document with new binlog router option
01eedc5 Updated documentation with SSL usage
8a4c0f6 Update Replication-Proxy-Binlog-Router-Tutorial.md
4e374aa Update Replication-Proxy-Binlog-Router-Tutorial.md
f3f3c57 Update Replication-Proxy-Binlog-Router-Tutorial.md
617b79f Binlog Server: error messages typo fix
fa8dfae Binlog Server: error messages review
1b8819c Fix freeing of schemarouter session memory
07f49e1 MXS-788: new code review fix
1fd3b09 MXS-788: show services now displays SSL info
6ca2584 MXS-788 code review fix
ae6a7d0 MXS-788 code review
43d3474 Master server SSL connection
90b2377 Use correct variable in listmanager pre-allocation
9a5b238 Fix listmanager pre-allocation
9c78625 Fix a memory leak when backend authentication fails
e59a966 Fix hang in list_find_free
ff30223 Fix freeing of shared data in schemarouter
fc8f9d3 Add missing include in luafilter
ecf7f53 Add missing NULL value to filter parameter array
636d849 Update memory allocation approach
f0d1d38 Add new allocation functions
97d00a0 Fix writing of uninitialized data to logs
e72c9b2 Merge branch 'release-2.0.0' into develop
cf2b712 Merge branch 'release-2.0.0' into develop
8917c5c Change the logic behind valid list entry checks
c10deff Improve documentation about version_string
f59f1f7 Merge branch 'develop' of ssh://github.com/mariadb-corporation/maxscale-new into develop
c88edb3 Backend authentication failure improvement
abd5bee Revert "Backend authentication failure improvement"
5bb3107 Backend authentication failure improvement
b7f434a Add new allocation functions
3f022fa Fix stupid mistake
99c4317 Merge remote-tracking branch 'origin/MXS-677' into develop
3c1ded6 Added connection/authentication failure error reporting in SHOW SLAVE STATUS
0a60f7b Tidy up and deal with review points.
ba103ff blr_slave.c: Update strncpy usage
467331e blr_master.c: Strncpy usage updates
d2b7c0c Merge remote-tracking branch 'origin/develop-nullauth-merge' into develop
5a8c1d0 qc: Measure execution time at the right place.
bccdb93 Merge branch 'NullAuthDeny' into develop
2e6511c Add 5.5.5 prefix to all version strings that lack it
314655a Improve DCB and session initialization and list handling
e1c43f0 MXS-655: Make MaxScale logging logrotate(8) compatible
ce36afd MXS-626: Don't log a header unless maxlog enabled
dcd47a7 blr_file.c: Replace uses of strncpy
6b8f576 bls_slave.c: Replace strncpy with memcpy
68a0039 Add list preallocation, tidy up, simplify init.
cb37d1b Fix copyright etc headers.
11a400d Tidy; comment; fix bad copies and mistakes.
7e36ec4 Add list manager files.
c4794e3 Initial code for list manager.
1b42e25 Merge remote-tracking branch 'origin/MXS-765' into develop
d50f617 Fix problems, extend tests, respond to review.
dcb4a91 Filter test folder removed
0b60dbe Add a couple of comments.
83cdba0 Fix overwriting problem.
ba5d353 Fix overwriting problem.
53671cb Small fixes in response to review.
173d049 blr.c: Review strncpy usage
4ff6ef2 binlog_common.c: Replace strncpy with memcpy
f238e03 maxbinlogcheck.s: Replace strncpy
9807f8d harness: Replace unnecessary use of strncpy
8c7fe6a avro: Modify strncpy usage
9b8008e Small improvements.
b7f784f Fix mistakes in testqueuemanager.c
cc26962 Restore missing poll.c code; add testqueuemanager.c.
2e91806 Format the filter harness
22059e6 Initial implementation connection queueing.
c604dc2 readwritesplit.c: Improve COM_INIT_DB handling
454d920 schemarouter.c: Replace strncpy with strcpy
8e85d66 sharding_common.c: Too long a database name handled explicitly
77f4446 Astyle schemarouter
491f7c2 maxinfo.c: Replace strncpy with memcpy
6b98105 maxinfo: Reformat with astyle
c1dbf08 Handle oversize user and database names
5fa4a0f Merge branch 'develop' of ssh://github.com/mariadb-corporation/maxscale-new into develop
706963b BLR_DBUSERS_TAIL new var in blr.h
d75b9af Tweak comments, remove trailing blanks.
ab2400a Optimise statistics gathering by inline & simpler fns.
fb59ddc Remove unnecessary strncpy/strncat usage in Binlog Server
bdcd551 resultset.c: Change strncpy to memcpy
c6b1c5e Reject rather than cut too long a path
6d8f112 Remove unnecessary strncpy/strncat usage
18bf5ed Remove unnecessary strncpy usage
dc0e2db Make maxpasswd more userfriendly
c9c8695 Fix calculation of padded_len in encryptPassword
2cfd2c6 dbusers.c: Check strncpy usage
7ab9342 Make more thorough checks in secrets_readKeys
be7d593 Format cli.c debugcli.c testroute.c webserver.c
1ee5efb config.c: Check usage of strncpy
3043b12 gq_utils.c: Unnecessary use of strncpy removed
77874ac Add help to maxkeys
38392a3 Update secrets_writeKeys documentation
2d1325c Make SSL optional in MaxScale's own communication
bda00da Fix avro build failures
b2cb31a Add more OOM macros
41ccf17 Fix strdup usage
a48f732 Fix realloc calls
20771f6 Add forgotten extern "C" block
8faf35a Add maxscale allocation functions
bb47890 Add macros for OOM logging
afea388 Fix silly mistakes.
6dafd22 Make deny default for null auth; move code from common to auth.
This commit is contained in:
Johan Wikman
2016-08-17 08:36:01 +03:00
parent b2035745fc
commit dc7f7b6fb4
360 changed files with 11641 additions and 15856 deletions

View File

@ -1,64 +1,66 @@
if(BUILD_RABBITMQ)
if(RABBITMQ_FOUND)
include_directories(${RABBITMQ_HEADERS})
add_library(mqfilter SHARED mqfilter.c)
target_link_libraries(mqfilter maxscale-common ${RABBITMQ_LIBRARIES})
add_dependencies(mqfilter pcre2)
install(TARGETS mqfilter DESTINATION ${MAXSCALE_LIBDIR})
else()
message(WARNING "Could not find librabbitmq, the mqfilter will not be built.")
endif()
find_package(RabbitMQ)
if(RABBITMQ_FOUND)
include_directories(${RABBITMQ_HEADERS})
add_library(mqfilter SHARED mqfilter.c)
target_link_libraries(mqfilter maxscale-common ${RABBITMQ_LIBRARIES})
add_dependencies(mqfilter pcre2)
set_target_properties(mqfilter PROPERTIES VERSION "1.0.2")
install_module(mqfilter core)
else()
message(WARNING "Could not find librabbitmq, the mqfilter will not be built.")
endif()
add_library(regexfilter SHARED regexfilter.c)
target_link_libraries(regexfilter maxscale-common)
add_dependencies(regexfilter pcre2)
set_target_properties(regexfilter PROPERTIES VERSION "1.1.0")
install(TARGETS regexfilter DESTINATION ${MAXSCALE_LIBDIR})
install_module(regexfilter core)
add_library(testfilter SHARED testfilter.c)
target_link_libraries(testfilter maxscale-common)
set_target_properties(testfilter PROPERTIES VERSION "1.0.0")
install(TARGETS testfilter DESTINATION ${MAXSCALE_LIBDIR})
install_module(testfilter core)
add_library(gatekeeper SHARED gatekeeper.c)
target_link_libraries(gatekeeper maxscale-common)
set_target_properties(gatekeeper PROPERTIES VERSION "1.0.0")
install_module(gatekeeper experimental)
add_library(qlafilter SHARED qlafilter.c)
target_link_libraries(qlafilter maxscale-common)
set_target_properties(qlafilter PROPERTIES VERSION "1.1.1")
install(TARGETS qlafilter DESTINATION ${MAXSCALE_LIBDIR})
install_module(qlafilter core)
add_library(tee SHARED tee.c)
target_link_libraries(tee maxscale-common)
set_target_properties(tee PROPERTIES VERSION "1.0.0")
install(TARGETS tee DESTINATION ${MAXSCALE_LIBDIR})
install_module(tee core)
add_library(topfilter SHARED topfilter.c)
target_link_libraries(topfilter maxscale-common)
set_target_properties(topfilter PROPERTIES VERSION "1.0.1")
install(TARGETS topfilter DESTINATION ${MAXSCALE_LIBDIR})
install_module(topfilter core)
if(BUILD_LUAFILTER)
find_package(Lua)
if(LUA_FOUND)
include_directories(${LUA_INCLUDE_DIR})
add_library(luafilter SHARED luafilter.c)
target_link_libraries(luafilter maxscale-common ${LUA_LIBRARIES})
install(TARGETS luafilter DESTINATION ${MAXSCALE_LIBDIR})
else()
message(STATUS "Lua was not found, luafilter will not be built.")
endif()
find_package(Lua)
if(LUA_FOUND)
include_directories(${LUA_INCLUDE_DIR})
add_library(luafilter SHARED luafilter.c)
set_target_properties(luafilter PROPERTIES VERSION "1.0.0")
target_link_libraries(luafilter maxscale-common ${LUA_LIBRARIES})
install_module(luafilter experimental)
else()
message(STATUS "Lua was not found, luafilter will not be built.")
endif()
add_library(namedserverfilter SHARED namedserverfilter.c)
target_link_libraries(namedserverfilter maxscale-common)
set_target_properties(namedserverfilter PROPERTIES VERSION "1.1.0")
install(TARGETS namedserverfilter DESTINATION ${MAXSCALE_LIBDIR})
install_module(namedserverfilter core)
if(BUILD_SLAVELAG)
add_library(slavelag SHARED slavelag.c)
target_link_libraries(slavelag maxscale-common)
set_target_properties(slavelag PROPERTIES VERSION "1.1.0")
install(TARGETS slavelag DESTINATION ${MAXSCALE_LIBDIR})
endif()
add_library(ccrfilter SHARED ccrfilter.c)
target_link_libraries(ccrfilter maxscale-common)
set_target_properties(ccrfilter PROPERTIES VERSION "1.0.0")
install_module(ccrfilter experimental)
add_subdirectory(hint)
add_subdirectory(dbfwfilter)

View File

@ -4,7 +4,7 @@
* Use of this software is governed by the Business Source License included
* in the LICENSE.TXT file and at www.mariadb.com/bsl.
*
* Change Date: 2019-01-01
* 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
@ -20,9 +20,10 @@
#include <hint.h>
#include <query_classifier.h>
#include <regex.h>
#include <maxscale/alloc.h>
/**
* @file slavelag.c - a very simple filter designed to send queries to the
* @file ccrfilter.c - a very simple filter designed to send queries to the
* master server after data modification has occurred. This is done to prevent
* replication lag affecting the outcome of a select query.
*
@ -42,6 +43,7 @@
*
* Date Who Description
* 03/03/2015 Markus Mäkelä Written for demonstrative purposes
* 10/08/2016 Markus Mäkelä Cleaned up code and renamed to ccrfilter
* @endverbatim
*/
@ -77,6 +79,8 @@ static FILTER_OBJECT MyObject =
diagnostic,
};
#define CCR_DEFAULT_TIME 60
typedef struct lagstats
{
int n_add_count; /*< No. of statements diverted based on count */
@ -99,7 +103,7 @@ typedef struct
LAGSTATS stats;
regex_t re; /* Compiled regex text of match */
regex_t nore; /* Compiled regex text of ignore */
} LAG_INSTANCE;
} CCR_INSTANCE;
/**
* The session structure for this filter
@ -108,9 +112,8 @@ typedef struct
{
DOWNSTREAM down; /*< The downstream filter */
int hints_left; /*< Number of hints left to add to queries*/
time_t last_modification; /*< Time of the last modifying operation */
int active; /*< Is filter active */
} LAG_SESSION;
time_t last_modification; /*< Time of the last data modifying operation */
} CCR_SESSION;
/**
* Implementation of the mandatory version entry point
@ -161,14 +164,14 @@ GetModuleObject()
static FILTER *
createInstance(char **options, FILTER_PARAMETER **params)
{
LAG_INSTANCE *my_instance;
CCR_INSTANCE *my_instance;
int i;
int cflags = 0;
int cflags = REG_ICASE;
if ((my_instance = calloc(1, sizeof(LAG_INSTANCE))) != NULL)
if ((my_instance = MXS_CALLOC(1, sizeof(CCR_INSTANCE))) != NULL)
{
my_instance->count = 0;
my_instance->time = 0;
my_instance->time = CCR_DEFAULT_TIME;
my_instance->stats.n_add_count = 0;
my_instance->stats.n_add_time = 0;
my_instance->stats.n_modified = 0;
@ -187,15 +190,15 @@ createInstance(char **options, FILTER_PARAMETER **params)
}
else if (!strcmp(params[i]->name, "match"))
{
my_instance->match = strdup(params[i]->value);
my_instance->match = MXS_STRDUP_A(params[i]->value);
}
else if (!strcmp(params[i]->name, "ignore"))
{
my_instance->nomatch = strdup(params[i]->value);
my_instance->nomatch = MXS_STRDUP_A(params[i]->value);
}
else
else if (!filter_standard_parameter(params[i]->name))
{
MXS_ERROR("lagfilter: Unexpected parameter '%s'.\n", params[i]->name);
MXS_ERROR("ccrfilter: Unexpected parameter '%s'.\n", params[i]->name);
}
}
@ -211,9 +214,13 @@ createInstance(char **options, FILTER_PARAMETER **params)
{
cflags &= ~REG_ICASE;
}
else if (!strcasecmp(options[i], "extended"))
{
cflags |= REG_EXTENDED;
}
else
{
MXS_ERROR("lagfilter: unsupported option '%s'.", options[i]);
MXS_ERROR("ccrfilter: unsupported option '%s'.", options[i]);
}
}
}
@ -222,7 +229,7 @@ createInstance(char **options, FILTER_PARAMETER **params)
{
if (regcomp(&my_instance->re, my_instance->match, cflags))
{
MXS_ERROR("lagfilter: Failed to compile regex '%s'.", my_instance->match);
MXS_ERROR("ccrfilter: Failed to compile regex '%s'.", my_instance->match);
}
}
@ -230,7 +237,7 @@ createInstance(char **options, FILTER_PARAMETER **params)
{
if (regcomp(&my_instance->nore, my_instance->nomatch, cflags))
{
MXS_ERROR("lagfilter: Failed to compile regex '%s'.", my_instance->nomatch);
MXS_ERROR("ccrfilter: Failed to compile regex '%s'.", my_instance->nomatch);
}
}
}
@ -249,12 +256,11 @@ createInstance(char **options, FILTER_PARAMETER **params)
static void *
newSession(FILTER *instance, SESSION *session)
{
LAG_INSTANCE *my_instance = (LAG_INSTANCE *)instance;
LAG_SESSION *my_session;
CCR_INSTANCE *my_instance = (CCR_INSTANCE *)instance;
CCR_SESSION *my_session = MXS_MALLOC(sizeof(CCR_SESSION));
if ((my_session = malloc(sizeof(LAG_SESSION))) != NULL)
if (my_session)
{
my_session->active = 1;
my_session->hints_left = 0;
my_session->last_modification = 0;
}
@ -283,7 +289,7 @@ closeSession(FILTER *instance, void *session)
static void
freeSession(FILTER *instance, void *session)
{
free(session);
MXS_FREE(session);
}
/**
@ -296,7 +302,7 @@ freeSession(FILTER *instance, void *session)
static void
setDownstream(FILTER *instance, void *session, DOWNSTREAM *downstream)
{
LAG_SESSION *my_session = (LAG_SESSION *)session;
CCR_SESSION *my_session = (CCR_SESSION *)session;
my_session->down = *downstream;
}
@ -318,19 +324,23 @@ setDownstream(FILTER *instance, void *session, DOWNSTREAM *downstream)
static int
routeQuery(FILTER *instance, void *session, GWBUF *queue)
{
LAG_INSTANCE *my_instance = (LAG_INSTANCE *)instance;
LAG_SESSION *my_session = (LAG_SESSION *)session;
CCR_INSTANCE *my_instance = (CCR_INSTANCE *)instance;
CCR_SESSION *my_session = (CCR_SESSION *)session;
char *sql;
time_t now = time(NULL);
if (modutil_is_SQL(queue))
{
if (queue->next != NULL)
if (queue->next)
{
queue = gwbuf_make_contiguous(queue);
}
if (qc_get_operation(queue) & (QUERY_OP_DELETE | QUERY_OP_INSERT | QUERY_OP_UPDATE))
/**
* Not a simple SELECT statement, possibly modifies data. If we're processing a statement
* with unknown query type, the safest thing to do is to treat it as a data modifying statement.
*/
if ((qc_get_operation(queue) & ~QUERY_OP_SELECT) != 0)
{
if ((sql = modutil_get_SQL(queue)) != NULL)
{
@ -346,7 +356,7 @@ routeQuery(FILTER *instance, void *session, GWBUF *queue)
}
}
free(sql);
MXS_FREE(sql);
}
}
else if (my_session->hints_left > 0)
@ -381,12 +391,23 @@ routeQuery(FILTER *instance, void *session, GWBUF *queue)
static void
diagnostic(FILTER *instance, void *fsession, DCB *dcb)
{
LAG_INSTANCE *my_instance = (LAG_INSTANCE *)instance;
LAG_SESSION *my_session = (LAG_SESSION *)fsession;
CCR_INSTANCE *my_instance = (CCR_INSTANCE *)instance;
CCR_SESSION *my_session = (CCR_SESSION *)fsession;
dcb_printf(dcb, "Configuration:\n\tCount: %d\n", my_instance->count);
dcb_printf(dcb, "\tTime: %d seconds\n\n", my_instance->time);
dcb_printf(dcb, "Statistics:\n");
dcb_printf(dcb, "\tTime: %d seconds\n", my_instance->time);
if (my_instance->match)
{
dcb_printf(dcb, "\tMatch regex: %s\n", my_instance->match);
}
if (my_instance->nomatch)
{
dcb_printf(dcb, "\tExclude regex: %s\n", my_instance->nomatch);
}
dcb_printf(dcb, "\nStatistics:\n");
dcb_printf(dcb, "\tNo. of data modifications: %d\n", my_instance->stats.n_modified);
dcb_printf(dcb, "\tNo. of hints added based on count: %d\n", my_instance->stats.n_add_count);
dcb_printf(dcb, "\tNo. of hints added based on time: %d\n", my_instance->stats.n_add_time);

View File

@ -9,13 +9,13 @@ if(BISON_FOUND AND FLEX_FOUND)
add_library(dbfwfilter SHARED dbfwfilter.c ${BISON_ruleparser_OUTPUTS} ${FLEX_token_OUTPUTS})
target_link_libraries(dbfwfilter maxscale-common)
set_target_properties(dbfwfilter PROPERTIES VERSION "1.0.0")
install(TARGETS dbfwfilter DESTINATION ${MAXSCALE_LIBDIR})
install_module(dbfwfilter core)
if(BUILD_TOOLS)
add_executable(dbfwruleparser dbfwfilter.c ${BISON_ruleparser_OUTPUTS} ${FLEX_token_OUTPUTS})
target_compile_definitions(dbfwruleparser PUBLIC "BUILD_RULE_PARSER")
target_link_libraries(dbfwruleparser maxscale-common)
install(TARGETS dbfwruleparser DESTINATION ${MAXSCALE_BINDIR})
install_module(dbfwruleparser core)
endif()
else()
message(FATAL_ERROR "Could not find Bison or Flex: ${BISON_EXECUTABLE} ${FLEX_EXECUTABLE}")

View File

@ -4,7 +4,7 @@
* Use of this software is governed by the Business Source License included
* in the LICENSE.TXT file and at www.mariadb.com/bsl.
*
* Change Date: 2019-01-01
* 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
@ -79,6 +79,7 @@
#include <ruleparser.yy.h>
#include <lex.yy.h>
#include <stdlib.h>
#include <maxscale/alloc.h>
/** Older versions of Bison don't include the parsing function in the header */
#ifndef dbfw_yyparse
@ -291,17 +292,16 @@ bool parse_limit_queries(FW_INSTANCE* instance, RULE* ruledef, const char* rule,
*/
static STRLINK* strlink_push(STRLINK* head, const char* value)
{
STRLINK* link = malloc(sizeof(STRLINK));
STRLINK* link = MXS_MALLOC(sizeof(STRLINK));
if (link && (link->value = strdup(value)))
if (link && (link->value = MXS_STRDUP(value)))
{
link->next = head;
}
else
{
free(link);
MXS_FREE(link);
link = NULL;
MXS_ERROR("dbfwfilter: Memory allocation failed.");
}
return link;
}
@ -316,8 +316,8 @@ static STRLINK* strlink_pop(STRLINK* head)
if (head)
{
STRLINK* next = head->next;
free(head->value);
free(head);
MXS_FREE(head->value);
MXS_FREE(head);
return next;
}
return NULL;
@ -333,8 +333,8 @@ static void strlink_free(STRLINK* head)
{
STRLINK* tmp = head;
head = head->next;
free(tmp->value);
free(tmp);
MXS_FREE(tmp->value);
MXS_FREE(tmp);
}
}
@ -366,7 +366,7 @@ static STRLINK* strlink_reverse_clone(STRLINK* head)
static RULELIST* rulelist_push(RULELIST *head, RULE *rule)
{
RULELIST *rval = malloc(sizeof(RULELIST));
RULELIST *rval = MXS_MALLOC(sizeof(RULELIST));
if (rval)
{
@ -385,7 +385,8 @@ static void* rulelist_clone(void* fval)
while (ptr)
{
RULELIST* tmp = (RULELIST*) malloc(sizeof(RULELIST));
RULELIST* tmp = (RULELIST*) MXS_MALLOC(sizeof(RULELIST));
MXS_ABORT_IF_NULL(tmp);
tmp->next = rule;
tmp->rule = ptr->rule;
rule = tmp;
@ -402,22 +403,21 @@ static void* rulelist_free(void* fval)
{
RULELIST *tmp = ptr;
ptr = ptr->next;
free(tmp);
MXS_FREE(tmp);
}
return NULL;
}
static void* huserfree(void* fval)
static void huserfree(void* fval)
{
USER* value = (USER*) fval;
rulelist_free(value->rules_and);
rulelist_free(value->rules_or);
rulelist_free(value->rules_strict_and);
free(value->qs_limit);
free(value->name);
free(value);
return NULL;
MXS_FREE(value->qs_limit);
MXS_FREE(value->name);
MXS_FREE(value);
}
/**
@ -622,7 +622,7 @@ static TIMERANGE* parse_time(const char* str)
CHK_TIMES((&start));
CHK_TIMES((&end));
tr = (TIMERANGE*) malloc(sizeof(TIMERANGE));
tr = (TIMERANGE*) MXS_MALLOC(sizeof(TIMERANGE));
if (tr)
{
@ -630,10 +630,6 @@ static TIMERANGE* parse_time(const char* str)
tr->end = end;
tr->next = NULL;
}
else
{
MXS_ERROR("dbfwfilter: malloc returned NULL.");
}
}
}
return tr;
@ -649,7 +645,8 @@ TIMERANGE* split_reverse_time(TIMERANGE* tr)
{
TIMERANGE* tmp = NULL;
tmp = (TIMERANGE*) calloc(1, sizeof(TIMERANGE));
tmp = (TIMERANGE*) MXS_CALLOC(1, sizeof(TIMERANGE));
MXS_ABORT_IF_NULL(tmp);
tmp->next = tr;
tmp->start.tm_hour = 0;
tmp->start.tm_min = 0;
@ -724,15 +721,14 @@ static bool apply_rule_to_user(FW_INSTANCE *instance, char *username,
if ((user = (USER*) hashtable_fetch(instance->htable, username)) == NULL)
{
/**New user*/
if ((user = (USER*) calloc(1, sizeof(USER))) == NULL)
if ((user = (USER*) MXS_CALLOC(1, sizeof(USER))) == NULL)
{
MXS_ERROR("dbfwfilter: failed to allocate memory when parsing rules.");
return false;
}
spinlock_init(&user->lock);
}
user->name = (char*) strdup(username);
user->name = (char*) MXS_STRDUP_A(username);
user->qs_limit = NULL;
RULELIST *tl = (RULELIST*) rulelist_clone(rulelist);
RULELIST *tail = tl;
@ -775,7 +771,7 @@ void tr_free(TIMERANGE* tr)
{
tmp = node;
node = node->next;
free(tmp);
MXS_FREE(tmp);
}
}
@ -874,9 +870,9 @@ void dbfw_yyerror(void* scanner, const char* error)
bool create_rule(void* scanner, const char* name)
{
bool rval = true;
RULE *ruledef = malloc(sizeof(RULE));
RULE *ruledef = MXS_MALLOC(sizeof(RULE));
if (ruledef && (ruledef->name = strdup(name)))
if (ruledef && (ruledef->name = MXS_STRDUP(name)))
{
ruledef->type = RT_UNDEFINED;
ruledef->on_queries = QUERY_OP_UNDEFINED;
@ -890,8 +886,7 @@ bool create_rule(void* scanner, const char* name)
}
else
{
MXS_ERROR("Memory allocation failed when creating rule '%s'.", name);
free(ruledef);
MXS_FREE(ruledef);
rval = false;
}
@ -911,7 +906,7 @@ static void free_rules(RULE* rule)
{
TIMERANGE *tr = rule->active;
rule->active = rule->active->next;
free(tr);
MXS_FREE(tr);
}
switch (rule->type)
@ -921,7 +916,7 @@ static void free_rules(RULE* rule)
break;
case RT_THROTTLE:
free(rule->data);
MXS_FREE(rule->data);
break;
case RT_REGEX:
@ -932,7 +927,7 @@ static void free_rules(RULE* rule)
break;
}
free(rule->name);
MXS_FREE(rule->name);
rule = tmp;
}
}
@ -1021,9 +1016,9 @@ bool create_user_templates(void* scanner)
while (user)
{
user_template_t* newtemp = malloc(sizeof(user_template_t));
user_template_t* newtemp = MXS_MALLOC(sizeof(user_template_t));
STRLINK* tmp;
if (newtemp && (newtemp->name = strdup(user->value)) &&
if (newtemp && (newtemp->name = MXS_STRDUP(user->value)) &&
(newtemp->rulenames = strlink_reverse_clone(rstack->active_rules)))
{
newtemp->type = rstack->active_mode;
@ -1034,13 +1029,12 @@ bool create_user_templates(void* scanner)
{
if (newtemp)
{
free(newtemp->name);
free(newtemp);
MXS_FREE(newtemp->name);
MXS_FREE(newtemp);
}
free(templates->name);
MXS_FREE(templates->name);
strlink_free(templates->rulenames);
free(templates);
MXS_ERROR("Memory allocation failed when processing rule file users definitions.");
MXS_FREE(templates);
return false;
}
user = user->next;
@ -1063,8 +1057,8 @@ void free_user_templates(user_template_t *templates)
user_template_t *tmp = templates;
templates = templates->next;
strlink_free(tmp->rulenames);
free(tmp->name);
free(tmp);
MXS_FREE(tmp->name);
MXS_FREE(tmp);
}
}
@ -1143,7 +1137,7 @@ bool define_limit_queries_rule(void* scanner, int max, int timeperiod, int holdo
{
struct parser_stack* rstack = dbfw_yyget_extra((yyscan_t) scanner);
ss_dassert(rstack);
QUERYSPEED* qs = malloc(sizeof(QUERYSPEED));
QUERYSPEED* qs = MXS_MALLOC(sizeof(QUERYSPEED));
if (qs)
{
@ -1153,10 +1147,6 @@ bool define_limit_queries_rule(void* scanner, int max, int timeperiod, int holdo
rstack->rule->type = RT_THROTTLE;
rstack->rule->data = qs;
}
else
{
MXS_ERROR("dbfwfilter: Memory allocation failed when adding limit_queries rule.");
}
return qs != NULL;
}
@ -1239,7 +1229,7 @@ static bool process_user_templates(FW_INSTANCE *instance, user_template_t *templ
if (user == NULL)
{
if ((user = malloc(sizeof(USER))) && (user->name = strdup(templates->name)))
if ((user = MXS_MALLOC(sizeof(USER))) && (user->name = MXS_STRDUP(templates->name)))
{
user->rules_and = NULL;
user->rules_or = NULL;
@ -1249,11 +1239,9 @@ static bool process_user_templates(FW_INSTANCE *instance, user_template_t *templ
}
else
{
free(user);
MXS_FREE(user);
rval = false;
break;
MXS_ERROR("Memory allocation failed when creating user '%s'.",
templates->name);
}
}
@ -1382,23 +1370,22 @@ createInstance(char **options, FILTER_PARAMETER **params)
char *filename = NULL;
bool err = false;
if ((my_instance = calloc(1, sizeof(FW_INSTANCE))) == NULL)
if ((my_instance = MXS_CALLOC(1, sizeof(FW_INSTANCE))) == NULL)
{
free(my_instance);
MXS_ERROR("Memory allocation for firewall filter failed.");
MXS_FREE(my_instance);
return NULL;
}
spinlock_init(&my_instance->lock);
if ((ht = hashtable_alloc(100, simple_str_hash, strcmp)) == NULL)
if ((ht = hashtable_alloc(100, hashtable_item_strhash, hashtable_item_strcmp)) == NULL)
{
MXS_ERROR("Unable to allocate hashtable.");
free(my_instance);
MXS_FREE(my_instance);
return NULL;
}
hashtable_memory_fns(ht, (HASHMEMORYFN) strdup, NULL, (HASHMEMORYFN) free, huserfree);
hashtable_memory_fns(ht, hashtable_item_strdup, NULL, hashtable_item_free, huserfree);
my_instance->htable = ht;
my_instance->action = FW_ACTION_BLOCK;
@ -1459,7 +1446,7 @@ createInstance(char **options, FILTER_PARAMETER **params)
if (err || !process_rule_file(filename, my_instance))
{
hashtable_free(my_instance->htable);
free(my_instance);
MXS_FREE(my_instance);
my_instance = NULL;
}
@ -1478,7 +1465,7 @@ newSession(FILTER *instance, SESSION *session)
{
FW_SESSION *my_session;
if ((my_session = calloc(1, sizeof(FW_SESSION))) == NULL)
if ((my_session = MXS_CALLOC(1, sizeof(FW_SESSION))) == NULL)
{
return NULL;
}
@ -1510,9 +1497,9 @@ freeSession(FILTER *instance, void *session)
FW_SESSION *my_session = (FW_SESSION *) session;
if (my_session->errmsg)
{
free(my_session->errmsg);
MXS_FREE(my_session->errmsg);
}
free(my_session);
MXS_FREE(my_session);
}
/**
@ -1555,11 +1542,10 @@ GWBUF* gen_dummy_error(FW_SESSION* session, char* msg)
dcb = session->session->client_dcb;
mysql_session = (MYSQL_session*) dcb->data;
errlen = msg != NULL ? strlen(msg) : 0;
errmsg = (char*) malloc((512 + errlen) * sizeof(char));
errmsg = (char*) MXS_MALLOC((512 + errlen) * sizeof(char));
if (errmsg == NULL)
{
MXS_ERROR("Memory allocation failed.");
return NULL;
}
@ -1582,7 +1568,7 @@ GWBUF* gen_dummy_error(FW_SESSION* session, char* msg)
}
buf = modutil_create_mysql_err_msg(1, 0, 1141, "HY000", (const char*) errmsg);
free(errmsg);
MXS_FREE(errmsg);
return buf;
}
@ -1679,7 +1665,7 @@ static char* create_parse_error(FW_INSTANCE* my_instance,
{
char msgbuf[len + 1]; // +1 for the "."
sprintf(msgbuf, "%s.", message);
msg = strdup(msgbuf);
msg = MXS_STRDUP_A(msgbuf);
if (my_instance->action == FW_ACTION_ALLOW)
{
@ -1799,7 +1785,7 @@ bool rule_matches(FW_INSTANCE* my_instance,
pcre2_match_data_free(mdata);
if (matches)
{
msg = strdup("Permission denied, query matched regular expression.");
msg = MXS_STRDUP_A("Permission denied, query matched regular expression.");
MXS_INFO("dbfwfilter: rule '%s': regex matched on query", rulelist->rule->name);
goto queryresolved;
}
@ -1815,7 +1801,7 @@ bool rule_matches(FW_INSTANCE* my_instance,
case RT_PERMISSION:
{
matches = true;
msg = strdup("Permission denied at this time.");
msg = MXS_STRDUP_A("Permission denied at this time.");
char buffer[32]; // asctime documentation requires 26
asctime_r(&tm_now, buffer);
MXS_INFO("dbfwfilter: rule '%s': query denied at: %s", rulelist->rule->name, buffer);
@ -1843,15 +1829,15 @@ bool rule_matches(FW_INSTANCE* my_instance,
sprintf(emsg, "Permission denied to column '%s'.", strln->value);
MXS_INFO("dbfwfilter: rule '%s': query targets forbidden column: %s",
rulelist->rule->name, strln->value);
msg = strdup(emsg);
free(where);
msg = MXS_STRDUP_A(emsg);
MXS_FREE(where);
goto queryresolved;
}
strln = strln->next;
}
tok = strtok_r(NULL, ",", &saveptr);
}
free(where);
MXS_FREE(where);
}
}
break;
@ -1869,13 +1855,13 @@ bool rule_matches(FW_INSTANCE* my_instance,
if (strchr(strptr, '*'))
{
matches = true;
msg = strdup("Usage of wildcard denied.");
msg = MXS_STRDUP_A("Usage of wildcard denied.");
MXS_INFO("dbfwfilter: rule '%s': query contains a wildcard.",
rulelist->rule->name);
free(where);
MXS_FREE(where);
goto queryresolved;
}
free(where);
MXS_FREE(where);
}
}
break;
@ -1906,7 +1892,8 @@ bool rule_matches(FW_INSTANCE* my_instance,
{
/**No match found*/
queryspeed = (QUERYSPEED*) calloc(1, sizeof(QUERYSPEED));
queryspeed = (QUERYSPEED*) MXS_CALLOC(1, sizeof(QUERYSPEED));
MXS_ABORT_IF_NULL(queryspeed);
queryspeed->period = rule_qs->period;
queryspeed->cooldown = rule_qs->cooldown;
queryspeed->limit = rule_qs->limit;
@ -1926,7 +1913,7 @@ bool rule_matches(FW_INSTANCE* my_instance,
sprintf(emsg, "Queries denied for %f seconds", blocked_for);
MXS_INFO("dbfwfilter: rule '%s': user denied for %f seconds",
rulelist->rule->name, blocked_for);
msg = strdup(emsg);
msg = MXS_STRDUP_A(emsg);
matches = true;
}
else
@ -1952,7 +1939,7 @@ bool rule_matches(FW_INSTANCE* my_instance,
double blocked_for =
queryspeed->cooldown - difftime(time_now, queryspeed->triggered);
sprintf(emsg, "Queries denied for %f seconds", blocked_for);
msg = strdup(emsg);
msg = MXS_STRDUP_A(emsg);
}
else if (queryspeed->count > 0 &&
difftime(time_now, queryspeed->first_query) <= queryspeed->period)
@ -1972,7 +1959,7 @@ bool rule_matches(FW_INSTANCE* my_instance,
!qc_query_has_clause(queue))
{
matches = true;
msg = strdup("Required WHERE/HAVING clause is missing.");
msg = MXS_STRDUP_A("Required WHERE/HAVING clause is missing.");
MXS_INFO("dbfwfilter: rule '%s': query has no where/having "
"clause, query is denied.", rulelist->rule->name);
}
@ -1989,7 +1976,7 @@ queryresolved:
{
if (my_session->errmsg)
{
free(my_session->errmsg);
MXS_FREE(my_session->errmsg);
}
my_session->errmsg = msg;
@ -2031,14 +2018,14 @@ bool check_match_any(FW_INSTANCE* my_instance, FW_SESSION* my_session,
}
if (rule_matches(my_instance, my_session, queue, user, rulelist, fullquery))
{
*rulename = strdup(rulelist->rule->name);
*rulename = MXS_STRDUP_A(rulelist->rule->name);
rval = true;
break;
}
rulelist = rulelist->next;
}
free(fullquery);
MXS_FREE(fullquery);
}
return rval;
}
@ -2054,7 +2041,7 @@ void append_string(char** dest, size_t* size, const char* src)
{
if (*dest == NULL)
{
*dest = strdup(src);
*dest = MXS_STRDUP_A(src);
*size = strlen(src);
}
else
@ -2062,7 +2049,7 @@ void append_string(char** dest, size_t* size, const char* src)
if (*size < strlen(*dest) + strlen(src) + 3)
{
size_t newsize = strlen(*dest) + strlen(src) + 3;
char* tmp = realloc(*dest, newsize);
char* tmp = MXS_REALLOC(*dest, newsize);
if (tmp)
{
*size = newsize;
@ -2070,7 +2057,6 @@ void append_string(char** dest, size_t* size, const char* src)
}
else
{
MXS_ERROR("Memory allocation failed");
return;
}
}
@ -2131,7 +2117,7 @@ bool check_match_all(FW_INSTANCE* my_instance, FW_SESSION* my_session,
/** No active rules */
rval = false;
}
free(fullquery);
MXS_FREE(fullquery);
}
/** Set the list of matched rule names */
@ -2198,7 +2184,7 @@ routeQuery(FILTER *instance, void *session, GWBUF *queue)
GWBUF* err = gen_dummy_error(my_session, "This filter does not support "
"multi-statements.");
gwbuf_free(queue);
free(my_session->errmsg);
MXS_FREE(my_session->errmsg);
my_session->errmsg = NULL;
rval = dcb->func.write(dcb, err);
}
@ -2268,7 +2254,7 @@ routeQuery(FILTER *instance, void *session, GWBUF *queue)
}
}
free(rname);
MXS_FREE(rname);
}
/** If the instance is in whitelist mode, only users that have a rule
* defined for them are allowed */
@ -2286,7 +2272,7 @@ routeQuery(FILTER *instance, void *session, GWBUF *queue)
{
GWBUF* forward = gen_dummy_error(my_session, my_session->errmsg);
gwbuf_free(queue);
free(my_session->errmsg);
MXS_FREE(my_session->errmsg);
my_session->errmsg = NULL;
rval = dcb->func.write(dcb, forward);
}
@ -2378,10 +2364,11 @@ int main(int argc, char** argv)
return 1;
}
home = malloc(sizeof(char) * (PATH_MAX + 1));
home = MXS_MALLOC(sizeof(char) * (PATH_MAX + 1));
MXS_ABORT_IF_NULL(home);
if (getcwd(home, PATH_MAX) == NULL)
{
free(home);
MXS_FREE(home);
home = NULL;
}
@ -2399,8 +2386,8 @@ int main(int argc, char** argv)
init_test_env(home);
ruleparam.name = strdup("rules");
ruleparam.value = strdup(argv[1]);
ruleparam.name = MXS_STRDUP_A("rules");
ruleparam.value = MXS_STRDUP_A(argv[1]);
paramlist[0] = &ruleparam;
paramlist[1] = NULL;

View File

@ -6,7 +6,7 @@
* Use of this software is governed by the Business Source License included
* in the LICENSE.TXT file and at www.mariadb.com/bsl.
*
* Change Date: 2019-01-01
* 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

View File

@ -4,7 +4,7 @@
* Use of this software is governed by the Business Source License included
* in the LICENSE.TXT file and at www.mariadb.com/bsl.
*
* Change Date: 2019-01-01
* 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

View File

@ -4,7 +4,7 @@
* Use of this software is governed by the Business Source License included
* in the LICENSE.TXT file and at www.mariadb.com/bsl.
*
* Change Date: 2019-01-01
* 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

View File

@ -0,0 +1,587 @@
/*
* 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/bsl.
*
* 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.
*/
#include <stdio.h>
#include <filter.h>
#include <modinfo.h>
#include <modutil.h>
#include <atomic.h>
#include <query_classifier.h>
#include <hashtable.h>
#include <gwdirs.h>
#include <maxscale/alloc.h>
#define GK_DEFAULT_HASHTABLE_SIZE 1000
/**
* @file gatekeeper.c - A learning firewall
*
* This filter will learn from input data read during a learning phase.
* After learning the characteristics of the input, the filter can then
* be set into an enforcing mode. In this mode the filter will block any
* queries that do not conform to the training set.
*/
MODULE_INFO info =
{
MODULE_API_FILTER,
MODULE_ALPHA_RELEASE,
FILTER_VERSION,
"Learning firewall filter"
};
enum firewall_mode
{
ENFORCE,
LEARN
};
typedef struct
{
unsigned long queries; /**< Number of queries received */
unsigned int hit; /**< Number of queries that match a pattern */
unsigned int miss; /**< Number of queries that do not match a pattern */
unsigned int entries; /**< Number of new patterns created */
} GK_STATS;
typedef struct
{
HASHTABLE *queryhash; /**< Canonicalized forms of the queries */
char* datadir; /**< The data is stored in this directory as lfw.data */
enum firewall_mode mode; /**< Filter mode, either ENFORCE or LEARN */
GK_STATS stats; /**< Instance statistics */
SPINLOCK lock; /**< Instance lock */
bool updating; /**< If the datafile is being updated */
bool need_update; /**< If the datafile needs updating */
} GK_INSTANCE;
typedef struct
{
DCB* dcb; /**< Client DCB, used to send error messages */
DOWNSTREAM down;
GK_STATS stats; /**< Session statistics */
} GK_SESSION;
static char *version_str = "V1.0.0";
static const char* datafile_name = "gatekeeper.data";
/** Prefix all log messages with this tag */
#define MODNAME "[gatekeeper] "
/** This is passed as a value to @c hashtable_add to have @c hashtable_fetch
* return a non-NULL value when a hash hit is made */
static bool trueval = true;
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 bool read_stored_data(GK_INSTANCE *inst);
static bool write_stored_data(GK_INSTANCE *inst);
static FILTER_OBJECT MyObject =
{
createInstance,
newSession,
closeSession,
freeSession,
setDownstream,
NULL, // No upstream requirement
routeQuery,
NULL,
diagnostic,
};
/**
* Implementation of the mandatory version entry point
*
* @return version string of the module
*/
char* version()
{
return version_str;
}
/**
* The module initialization routine, called when the module
* is first loaded.
*/
void ModuleInit()
{
}
/**
* The module entry point routine. It is this routine that
* must populate the structure that is referred to as the
* "module object", this is a structure with the set of
* external entry points for this module.
*
* @return The module object
*/
FILTER_OBJECT* GetModuleObject()
{
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
*
* @return The instance data for this new instance
*/
static FILTER* createInstance(char **options, FILTER_PARAMETER **params)
{
GK_INSTANCE *inst = MXS_CALLOC(1, sizeof(GK_INSTANCE));
if (inst)
{
const char* datadir = get_datadir();
bool ok = true;
spinlock_init(&inst->lock);
inst->mode = LEARN;
for (int i = 0; params && params[i]; i++)
{
if (strcmp(params[i]->name, "mode") == 0)
{
if (strcasecmp(params[i]->value, "enforce") == 0)
{
inst->mode = ENFORCE;
}
else if (strcasecmp(params[i]->value, "learn") == 0)
{
inst->mode = LEARN;
}
else
{
MXS_ERROR(MODNAME"Unknown value for 'mode': %s", params[i]->value);
ok = false;
}
}
else if (strcmp(params[i]->name, "datadir") == 0)
{
if (access(params[i]->value, F_OK) == 0)
{
datadir = params[i]->value;
}
else
{
char err[STRERROR_BUFLEN];
MXS_ERROR(MODNAME"File is not accessible: %d, %s", errno,
strerror_r(errno, err, sizeof(err)));
ok = false;
}
}
else if (!filter_standard_parameter(params[i]->name))
{
MXS_ERROR(MODNAME"Unknown parameter '%s'.", params[i]->name);
ok = false;
}
}
if (ok)
{
inst->queryhash = hashtable_alloc(GK_DEFAULT_HASHTABLE_SIZE,
hashtable_item_strhash,
hashtable_item_strcasecmp);
inst->datadir = MXS_STRDUP(datadir);
if (inst->queryhash && inst->datadir)
{
hashtable_memory_fns(inst->queryhash, NULL, NULL, hashtable_item_free, NULL);
if (read_stored_data(inst))
{
MXS_NOTICE(MODNAME"Started in [%s] mode. Data is stored at: %s",
inst->mode == ENFORCE ? "ENFORCE" : "LEARN", inst->datadir);
}
else
{
ok = false;
}
}
else
{
ok = false;
}
}
if (!ok)
{
hashtable_free(inst->queryhash);
MXS_FREE(inst->datadir);
MXS_FREE(inst);
inst = NULL;
}
}
return (FILTER*)inst;
}
/**
* Associate a new session with this instance of the filter.
*
* @param instance The filter instance data
* @param session The session itself
* @return Session specific data for this session
*/
static void* newSession(FILTER *instance, SESSION *session)
{
GK_INSTANCE *inst = (GK_INSTANCE *) instance;
GK_SESSION *ses;
if ((ses = MXS_CALLOC(1, sizeof(GK_SESSION))) != NULL)
{
ses->dcb = session->client_dcb;
}
return ses;
}
/**
* Close a session with the filter, this is the mechanism
* by which a filter may cleanup data structure etc.
*
* The gatekeeper flushes the hashtable to disk every time a session is closed.
*
* @param instance The filter instance data
* @param session The session being closed
*/
static void closeSession(FILTER *instance, void *session)
{
GK_INSTANCE *inst = (GK_INSTANCE*) instance;
GK_SESSION *ses = (GK_SESSION *) session;
/** If we added new data into the queryhash, update the datafile on disk */
if (ses->stats.entries > 0)
{
spinlock_acquire(&inst->lock);
bool update = !inst->updating;
if (update)
{
inst->updating = true;
inst->need_update = false;
}
else
{
/** If another thread is already updating the file, set
* the need_update flag */
inst->need_update = true;
}
spinlock_release(&inst->lock);
while (update)
{
/** Store the hashtable to disk */
write_stored_data(inst);
spinlock_acquire(&inst->lock);
/** Check if the hashtable has been update while we were writing
* the data to disk. */
if ((update = inst->need_update))
{
inst->need_update = false;
}
else
{
inst->updating = false;
}
spinlock_release(&inst->lock);
}
}
/** Add session stats to instance stats */
spinlock_acquire(&inst->lock);
inst->stats.entries += ses->stats.entries;
inst->stats.hit += ses->stats.hit;
inst->stats.miss += ses->stats.miss;
inst->stats.queries += ses->stats.queries;
spinlock_release(&inst->lock);
}
/**
* Free the memory associated with this filter session.
*
* @param instance The filter instance data
* @param session The session being closed
*/
static void freeSession(FILTER *instance, void *session)
{
MXS_FREE(session);
}
/**
* 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
*/
static void setDownstream(FILTER *instance, void *session, DOWNSTREAM *downstream)
{
GK_SESSION *ses = (GK_SESSION *) session;
ses->down = *downstream;
}
/**
* @brief Main routing function
*
* @param instance The filter instance data
* @param session The filter session
* @param queue The query data
* @return 1 on success, 0 on error
*/
static int routeQuery(FILTER *instance, void *session, GWBUF *queue)
{
GK_INSTANCE *inst = (GK_INSTANCE*) instance;
GK_SESSION *ses = (GK_SESSION *) session;
int rval = 1;
bool ok = true;
char* canon = qc_get_canonical(queue);
ses->stats.queries++;
/** Non-COM_QUERY packets are better handled on the backend database. For
* example a COM_INIT_DB does not get canonicalized and would be always
* denied. For this reason, queries that are not canonicalized are allowed.
* This means that the binary protocol and prepared statements are not
* processed by this filter. */
if (canon)
{
if (inst->mode == ENFORCE)
{
if (hashtable_fetch(inst->queryhash, canon))
{
ses->stats.hit++;
}
else
{
ses->stats.miss++;
ok = false;
MXS_WARNING(MODNAME"Query by %s@%s was not found from queryhash: %s",
ses->dcb->user, ses->dcb->remote, canon);
GWBUF* errbuf = modutil_create_mysql_err_msg(1, 0, 1, "00000", "Permission denied.");
rval = errbuf ? ses->dcb->func.write(ses->dcb, errbuf) : 0;
}
MXS_FREE(canon);
}
else if (inst->mode == LEARN)
{
if (hashtable_add(inst->queryhash, canon, &trueval))
{
ses->stats.entries++;
}
else
{
MXS_FREE(canon);
}
}
}
if (ok)
{
rval = ses->down.routeQuery(ses->down.instance, ses->down.session, queue);
}
return rval;
}
/**
* @brief Diagnostics routine
*
* @param instance The filter instance
* @param fsession Filter session
* @param dcb The DCB for output
*/
static void diagnostic(FILTER *instance, void *fsession, DCB *dcb)
{
GK_INSTANCE *inst = (GK_INSTANCE *) instance;
dcb_printf(dcb, "\t\tQueries: %lu\n", inst->stats.queries);
dcb_printf(dcb, "\t\tQueryhash entries: %u\n", inst->stats.entries);
dcb_printf(dcb, "\t\tQueryhash hits: %u\n", inst->stats.hit);
dcb_printf(dcb, "\t\tQueryhash misses: %u\n", inst->stats.miss);
}
/**
* @brief Write query patterns from memory to disk
*
* The data is stored as length-encoded strings. A length-encoded string contains
* a 4 byte integer, which tells the length of the string, followed by the string
* itself. The stored file will consist of multiple consecutive length-encoded strings.
*
* @param inst Filter instance
* @return True on success
*/
static bool write_stored_data(GK_INSTANCE *inst)
{
bool rval = false;
char filepath[PATH_MAX];
sprintf(filepath, "%s/%s.tmp.XXXXXX", inst->datadir, datafile_name);
int fd = mkstemp(filepath);
HASHITERATOR *iter = hashtable_iterator(inst->queryhash);
if (fd > 0 && iter)
{
char *key;
bool ok = true;
while ((key = hashtable_next(iter)))
{
uint32_t len = strlen(key);
/** First write the length of the string and then the string itself */
if (write(fd, &len, sizeof(len)) != sizeof(len) ||
write(fd, key, len) != len)
{
char err[STRERROR_BUFLEN];
MXS_ERROR(MODNAME"Failed to write key '%s' to disk (%d, %s). The datafile at '%s' was "
"not updated but it will be updated when the next session closes. ",
key, errno, strerror_r(errno, err, sizeof(err)), inst->datadir);
ok = false;
break;
}
}
if (ok)
{
/** Update the file by renaming the temporary file to the original one*/
char newfilepath[PATH_MAX + 1];
snprintf(newfilepath, sizeof(newfilepath), "%s/%s", inst->datadir, datafile_name);
rval = rename(filepath, newfilepath) == 0;
if (!rval)
{
char err[STRERROR_BUFLEN];
MXS_ERROR(MODNAME"Failed to rename file '%s' to '%s' when writing data: %d, %s",
filepath, newfilepath, errno, strerror_r(errno, err, sizeof(err)));
}
}
}
else if (fd == -1)
{
char err[STRERROR_BUFLEN];
MXS_ERROR(MODNAME"Failed to open file '%s' when writing data: %d, %s",
filepath, errno, strerror_r(errno, err, sizeof(err)));
}
if (fd > 0)
{
close(fd);
}
hashtable_iterator_free(iter);
return rval;
}
static void report_failed_read(FILE *file, int nexpected, int nread)
{
if (ferror(file))
{
char err[STRERROR_BUFLEN];
MXS_ERROR(MODNAME"Failed to read %d bytes, only %d bytes read: %d, %s",
nexpected, nread, errno, strerror_r(errno, err, sizeof(err)));
}
else
{
MXS_ERROR(MODNAME"Partial read, expected %d bytes but read only %d.",
nexpected, nread);
}
}
/**
* @brief Read query patterns from disk to memory
*
* See write_stored_data() for details on how the data is stored.
*
* @param inst Filter instance
* @return True if data was successfully read
*/
static bool read_stored_data(GK_INSTANCE *inst)
{
char filepath[PATH_MAX + 1];
snprintf(filepath, sizeof(filepath), "%s/%s", inst->datadir, datafile_name);
if (access(filepath, F_OK) != 0)
{
if (inst->mode == ENFORCE)
{
MXS_ERROR(MODNAME"Started in ENFORCE mode but no datafile was found at '%s'.", filepath);
return false;
}
/** Not finding a datafile in LEARN mode is OK since it will be created later on */
return true;
}
bool rval = true;
FILE *file = fopen(filepath, "rb");
if (file)
{
do
{
uint32_t len;
size_t nread;
char *data;
/** Read the length of the string */
if ((nread = fread(&len, 1, sizeof(len), file)) != sizeof(len))
{
if (nread > 0 || !feof(file))
{
report_failed_read(file, sizeof(len), nread);
rval = false;
}
break;
}
if ((data = MXS_MALLOC(len + 1)) == NULL)
{
rval = false;
break;
}
/** Read the string itself */
if ((nread = fread(data, 1, len, file)) != len)
{
MXS_FREE(data);
report_failed_read(file, sizeof(len), nread);
rval = false;
break;
}
data[len] = '\0';
hashtable_add(inst->queryhash, data, &trueval);
}
while (!feof(file));
fclose(file);
}
else
{
char err[STRERROR_BUFLEN];
MXS_ERROR(MODNAME"Failed to open file '%s' when reading stored data: %d, %s",
filepath, errno, strerror_r(errno, err, sizeof(err)));
}
return rval;
}

View File

@ -1,4 +1,4 @@
add_library(hintfilter SHARED hintfilter.c hintparser.c)
set_target_properties(hintfilter PROPERTIES INSTALL_RPATH ${CMAKE_INSTALL_RPATH}:${MAXSCALE_LIBDIR} VERSION "1.0.0")
target_link_libraries(hintfilter maxscale-common)
install(TARGETS hintfilter DESTINATION ${MAXSCALE_LIBDIR})
install_module(hintfilter core)

View File

@ -4,7 +4,7 @@
* Use of this software is governed by the Business Source License included
* in the LICENSE.TXT file and at www.mariadb.com/bsl.
*
* Change Date: 2019-01-01
* 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
@ -12,6 +12,7 @@
*/
#include <stdio.h>
#include <filter.h>
#include <maxscale/alloc.h>
#include <modinfo.h>
#include <modutil.h>
#include <mysqlhint.h>
@ -105,7 +106,7 @@ createInstance(char **options, FILTER_PARAMETER **params)
{
HINT_INSTANCE *my_instance;
if ((my_instance = calloc(1, sizeof(HINT_INSTANCE))) != NULL)
if ((my_instance = MXS_CALLOC(1, sizeof(HINT_INSTANCE))) != NULL)
{
my_instance->sessions = 0;
}
@ -125,7 +126,7 @@ newSession(FILTER *instance, SESSION *session)
HINT_INSTANCE *my_instance = (HINT_INSTANCE *)instance;
HINT_SESSION *my_session;
if ((my_session = calloc(1, sizeof(HINT_SESSION))) != NULL)
if ((my_session = MXS_CALLOC(1, sizeof(HINT_SESSION))) != NULL)
{
my_session->query_len = 0;
my_session->request = NULL;
@ -177,7 +178,7 @@ closeSession(FILTER *instance, void *session)
static void
freeSession(FILTER *instance, void *session)
{
free(session);
MXS_FREE(session);
return;
}

View File

@ -4,7 +4,7 @@
* Use of this software is governed by the Business Source License included
* in the LICENSE.TXT file and at www.mariadb.com/bsl.
*
* Change Date: 2019-01-01
* 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
@ -19,6 +19,7 @@
#include <modinfo.h>
#include <modutil.h>
#include <mysqlhint.h>
#include <maxscale/alloc.h>
/**
* hintparser.c - Find any comment in the SQL packet and look for MAXSCALE
@ -83,9 +84,9 @@ void token_free(HINT_TOKEN* token)
{
if (token->value != NULL)
{
free(token->value);
MXS_FREE(token->value);
}
free(token);
MXS_FREE(token);
}
static const char* token_get_keyword(
@ -281,7 +282,7 @@ hint_parser(HINT_SESSION *session, GWBUF *request)
break;
case TOK_STRING:
state = HS_NAME;
lvalue = strdup(tok->value);
lvalue = MXS_STRDUP_A(tok->value);
break;
case TOK_STOP:
/* Action: pop active hint */
@ -452,7 +453,7 @@ hint_parser(HINT_SESSION *session, GWBUF *request)
/* We starting an already define set of named hints */
rval = lookup_named_hint(session, hintname);
hint_push(session, hint_dup(rval));
free(hintname);
MXS_FREE(hintname);
rval = NULL;
}
else if (hintname == NULL && rval == NULL)
@ -518,7 +519,7 @@ hint_next_token(GWBUF **buf, char **ptr)
int i, found;
HINT_TOKEN *tok;
if ((tok = (HINT_TOKEN *)malloc(sizeof(HINT_TOKEN))) == NULL)
if ((tok = (HINT_TOKEN *)MXS_MALLOC(sizeof(HINT_TOKEN))) == NULL)
{
return NULL;
}
@ -603,7 +604,7 @@ hint_next_token(GWBUF **buf, char **ptr)
if (found == 0)
{
tok->token = TOK_STRING;
tok->value = strdup(word);
tok->value = MXS_STRDUP_A(word);
}
return tok;
@ -629,7 +630,7 @@ hint_pop(HINT_SESSION *session)
ptr->hint = hint->next;
hint_free(hint);
}
free(ptr);
MXS_FREE(ptr);
}
}
@ -645,7 +646,7 @@ hint_push(HINT_SESSION *session, HINT *hint)
{
HINTSTACK *item;
if ((item = (HINTSTACK *)malloc(sizeof(HINTSTACK))) == NULL)
if ((item = (HINTSTACK *)MXS_MALLOC(sizeof(HINTSTACK))) == NULL)
{
return;
}
@ -689,7 +690,7 @@ create_named_hint(HINT_SESSION *session, char *name, HINT *hint)
{
NAMEDHINTS *block;
if ((block = (NAMEDHINTS *)malloc(sizeof(NAMEDHINTS))) == NULL)
if ((block = (NAMEDHINTS *)MXS_MALLOC(sizeof(NAMEDHINTS))) == NULL)
{
return;
}
@ -724,8 +725,8 @@ NAMEDHINTS* free_named_hint(
hint_free(named_hint->hints);
named_hint->hints = hint;
}
free(named_hint->name);
free(named_hint);
MXS_FREE(named_hint->name);
MXS_FREE(named_hint);
return next;
}
else
@ -758,7 +759,7 @@ HINTSTACK* free_hint_stack(
hint_free(hint_stack->hint);
hint_stack->hint = hint;
}
free(hint_stack);
MXS_FREE(hint_stack);
return next;
}
else

View File

@ -4,7 +4,7 @@
* Use of this software is governed by the Business Source License included
* in the LICENSE.TXT file and at www.mariadb.com/bsl.
*
* Change Date: 2019-01-01
* 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
@ -47,6 +47,7 @@
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
#include <maxscale/alloc.h>
MODULE_INFO info =
{
@ -173,7 +174,7 @@ createInstance(char **options, FILTER_PARAMETER **params)
LUA_INSTANCE *my_instance;
bool error = false;
if ((my_instance = (LUA_INSTANCE*) calloc(1, sizeof(LUA_INSTANCE))) == NULL)
if ((my_instance = (LUA_INSTANCE*) MXS_CALLOC(1, sizeof(LUA_INSTANCE))) == NULL)
{
return NULL;
}
@ -184,11 +185,11 @@ createInstance(char **options, FILTER_PARAMETER **params)
{
if (strcmp(params[i]->name, "global_script") == 0)
{
error = (my_instance->global_script = strdup(params[i]->value)) == NULL;
error = (my_instance->global_script = MXS_STRDUP(params[i]->value)) == NULL;
}
else if (strcmp(params[i]->name, "session_script") == 0)
{
error = (my_instance->session_script = strdup(params[i]->value)) == NULL;
error = (my_instance->session_script = MXS_STRDUP(params[i]->value)) == NULL;
}
else if (!filter_standard_parameter(params[i]->name))
{
@ -199,9 +200,9 @@ createInstance(char **options, FILTER_PARAMETER **params)
if (error)
{
free(my_instance->global_script);
free(my_instance->session_script);
free(my_instance);
MXS_FREE(my_instance->global_script);
MXS_FREE(my_instance->session_script);
MXS_FREE(my_instance);
return NULL;
}
@ -215,9 +216,9 @@ createInstance(char **options, FILTER_PARAMETER **params)
{
MXS_ERROR("luafilter: Failed to execute global script at '%s':%s.",
my_instance->global_script, lua_tostring(my_instance->global_lua_state, -1));
free(my_instance->global_script);
free(my_instance->session_script);
free(my_instance);
MXS_FREE(my_instance->global_script);
MXS_FREE(my_instance->session_script);
MXS_FREE(my_instance);
my_instance = NULL;
}
else if (my_instance->global_lua_state)
@ -234,7 +235,7 @@ createInstance(char **options, FILTER_PARAMETER **params)
else
{
MXS_ERROR("Unable to initialize new Lua state.");
free(my_instance);
MXS_FREE(my_instance);
my_instance = NULL;
}
}
@ -263,7 +264,7 @@ static void * newSession(FILTER *instance, SESSION *session)
LUA_SESSION *my_session;
LUA_INSTANCE *my_instance = (LUA_INSTANCE*) instance;
if ((my_session = (LUA_SESSION*) calloc(1, sizeof(LUA_SESSION))) == NULL)
if ((my_session = (LUA_SESSION*) MXS_CALLOC(1, sizeof(LUA_SESSION))) == NULL)
{
return NULL;
}
@ -282,7 +283,7 @@ static void * newSession(FILTER *instance, SESSION *session)
my_instance->session_script,
lua_tostring(my_session->lua_state, -1));
lua_close(my_session->lua_state);
free(my_session);
MXS_FREE(my_session);
my_session = NULL;
}
else
@ -367,7 +368,7 @@ static void freeSession(FILTER *instance, void *session)
{
LUA_SESSION *my_session = (LUA_SESSION *) session;
lua_close(my_session->lua_state);
free(my_session);
MXS_FREE(my_session);
}
/**
@ -526,7 +527,7 @@ static int routeQuery(FILTER *instance, void *session, GWBUF *queue)
spinlock_release(&my_instance->lock);
}
free(fullquery);
MXS_FREE(fullquery);
}
if (!route)

View File

@ -4,7 +4,7 @@
* Use of this software is governed by the Business Source License included
* in the LICENSE.TXT file and at www.mariadb.com/bsl.
*
* Change Date: 2019-01-01
* 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
@ -76,6 +76,7 @@
#include <spinlock.h>
#include <session.h>
#include <housekeeper.h>
#include <maxscale/alloc.h>
MODULE_INFO info =
{
@ -474,11 +475,10 @@ char** parse_optstr(char* str, char* tok, int* szstore)
size++;
}
arr = malloc(sizeof(char*)*size);
arr = MXS_MALLOC(sizeof(char*)*size);
if (arr == NULL)
{
MXS_ERROR("Cannot allocate enough memory.");
*szstore = 0;
return NULL;
}
@ -487,7 +487,7 @@ char** parse_optstr(char* str, char* tok, int* szstore)
tk = strtok_r(str, tok, &lasts);
while (tk && i < size)
{
arr[i++] = strdup(tk);
arr[i++] = MXS_STRDUP_A(tk);
tk = strtok_r(NULL, tok, &lasts);
}
return arr;
@ -510,17 +510,18 @@ createInstance(char **options, FILTER_PARAMETER **params)
char** arr = NULL;
char taskname[512];
if ((my_instance = calloc(1, sizeof(MQ_INSTANCE))))
if ((my_instance = MXS_CALLOC(1, sizeof(MQ_INSTANCE))))
{
spinlock_init(&my_instance->rconn_lock);
spinlock_init(&my_instance->msg_lock);
uid_gen = 0;
paramlist = malloc(sizeof(FILTER_PARAMETER*) * 64);
paramlist = MXS_MALLOC(sizeof(FILTER_PARAMETER*) * 64);
MXS_ABORT_IF_NULL(paramlist);
if ((my_instance->conn = amqp_new_connection()) == NULL)
{
free(paramlist);
free(my_instance);
MXS_FREE(paramlist);
MXS_FREE(my_instance);
return NULL;
}
my_instance->channel = 1;
@ -536,19 +537,19 @@ createInstance(char **options, FILTER_PARAMETER **params)
{
if (!strcmp(params[i]->name, "hostname"))
{
my_instance->hostname = strdup(params[i]->value);
my_instance->hostname = MXS_STRDUP_A(params[i]->value);
}
else if (!strcmp(params[i]->name, "username"))
{
my_instance->username = strdup(params[i]->value);
my_instance->username = MXS_STRDUP_A(params[i]->value);
}
else if (!strcmp(params[i]->name, "password"))
{
my_instance->password = strdup(params[i]->value);
my_instance->password = MXS_STRDUP_A(params[i]->value);
}
else if (!strcmp(params[i]->name, "vhost"))
{
my_instance->vhost = strdup(params[i]->value);
my_instance->vhost = MXS_STRDUP_A(params[i]->value);
}
else if (!strcmp(params[i]->name, "port"))
{
@ -556,35 +557,34 @@ createInstance(char **options, FILTER_PARAMETER **params)
}
else if (!strcmp(params[i]->name, "exchange"))
{
my_instance->exchange = strdup(params[i]->value);
my_instance->exchange = MXS_STRDUP_A(params[i]->value);
}
else if (!strcmp(params[i]->name, "key"))
{
my_instance->key = strdup(params[i]->value);
my_instance->key = MXS_STRDUP_A(params[i]->value);
}
else if (!strcmp(params[i]->name, "queue"))
{
my_instance->queue = strdup(params[i]->value);
my_instance->queue = MXS_STRDUP_A(params[i]->value);
}
else if (!strcmp(params[i]->name, "ssl_client_certificate"))
{
my_instance->ssl_client_cert = strdup(params[i]->value);
my_instance->ssl_client_cert = MXS_STRDUP_A(params[i]->value);
}
else if (!strcmp(params[i]->name, "ssl_client_key"))
{
my_instance->ssl_client_key = strdup(params[i]->value);
my_instance->ssl_client_key = MXS_STRDUP_A(params[i]->value);
}
else if (!strcmp(params[i]->name, "ssl_CA_cert"))
{
my_instance->ssl_CA_cert = strdup(params[i]->value);
my_instance->ssl_CA_cert = MXS_STRDUP_A(params[i]->value);
}
else if (!strcmp(params[i]->name, "exchange_type"))
{
my_instance->exchange_type = strdup(params[i]->value);
my_instance->exchange_type = MXS_STRDUP_A(params[i]->value);
}
else if (!strcmp(params[i]->name, "logging_trigger"))
{
@ -619,9 +619,9 @@ createInstance(char **options, FILTER_PARAMETER **params)
{
for (int x = 0; x < arrsize; x++)
{
free(arr[x]);
MXS_FREE(arr[x]);
}
free(arr);
MXS_FREE(arr);
arr = NULL;
}
arrsize = 0;
@ -634,9 +634,10 @@ createInstance(char **options, FILTER_PARAMETER **params)
if (paramcount < parammax)
{
paramlist[paramcount] = malloc(sizeof(FILTER_PARAMETER));
paramlist[paramcount]->name = strdup(params[i]->name);
paramlist[paramcount]->value = strdup(params[i]->value);
paramlist[paramcount] = MXS_MALLOC(sizeof(FILTER_PARAMETER));
MXS_ABORT_IF_NULL(paramlist[paramcount]);
paramlist[paramcount]->name = MXS_STRDUP_A(params[i]->name);
paramlist[paramcount]->value = MXS_STRDUP_A(params[i]->value);
paramcount++;
}
}
@ -645,7 +646,8 @@ createInstance(char **options, FILTER_PARAMETER **params)
if (my_instance->trgtype & TRG_SOURCE)
{
my_instance->src_trg = (SRC_TRIG*) malloc(sizeof(SRC_TRIG));
my_instance->src_trg = (SRC_TRIG*) MXS_MALLOC(sizeof(SRC_TRIG));
MXS_ABORT_IF_NULL(my_instance->src_trg);
my_instance->src_trg->user = NULL;
my_instance->src_trg->host = NULL;
my_instance->src_trg->usize = 0;
@ -656,7 +658,8 @@ createInstance(char **options, FILTER_PARAMETER **params)
if (my_instance->trgtype & TRG_SCHEMA)
{
my_instance->shm_trg = (SHM_TRIG*) malloc(sizeof(SHM_TRIG));
my_instance->shm_trg = (SHM_TRIG*) MXS_MALLOC(sizeof(SHM_TRIG));
MXS_ABORT_IF_NULL(my_instance->shm_trg);
my_instance->shm_trg->objects = NULL;
my_instance->shm_trg->size = 0;
@ -665,7 +668,8 @@ createInstance(char **options, FILTER_PARAMETER **params)
if (my_instance->trgtype & TRG_OBJECT)
{
my_instance->obj_trg = (OBJ_TRIG*) malloc(sizeof(OBJ_TRIG));
my_instance->obj_trg = (OBJ_TRIG*) MXS_MALLOC(sizeof(OBJ_TRIG));
MXS_ABORT_IF_NULL(my_instance->obj_trg);
my_instance->obj_trg->objects = NULL;
my_instance->obj_trg->size = 0;
@ -732,40 +736,40 @@ createInstance(char **options, FILTER_PARAMETER **params)
my_instance->strict_logging = false;
}
}
free(paramlist[i]->name);
free(paramlist[i]->value);
free(paramlist[i]);
MXS_FREE(paramlist[i]->name);
MXS_FREE(paramlist[i]->value);
MXS_FREE(paramlist[i]);
}
free(paramlist);
MXS_FREE(paramlist);
if (my_instance->hostname == NULL)
{
my_instance->hostname = strdup("localhost");
my_instance->hostname = MXS_STRDUP_A("localhost");
}
if (my_instance->username == NULL)
{
my_instance->username = strdup("guest");
my_instance->username = MXS_STRDUP_A("guest");
}
if (my_instance->password == NULL)
{
my_instance->password = strdup("guest");
my_instance->password = MXS_STRDUP_A("guest");
}
if (my_instance->vhost == NULL)
{
my_instance->vhost = strdup("/");
my_instance->vhost = MXS_STRDUP_A("/");
}
if (my_instance->exchange == NULL)
{
my_instance->exchange = strdup("default_exchange");
my_instance->exchange = MXS_STRDUP_A("default_exchange");
}
if (my_instance->key == NULL)
{
my_instance->key = strdup("key");
my_instance->key = MXS_STRDUP_A("key");
}
if (my_instance->exchange_type == NULL)
{
my_instance->exchange_type = strdup("direct");
my_instance->exchange_type = MXS_STRDUP_A("direct");
}
if (my_instance->ssl_client_cert != NULL &&
@ -794,9 +798,9 @@ createInstance(char **options, FILTER_PARAMETER **params)
{
for (int x = 0; x < arrsize; x++)
{
free(arr[x]);
MXS_FREE(arr[x]);
}
free(arr);
MXS_FREE(arr);
}
}
return (FILTER *) my_instance;
@ -910,9 +914,9 @@ void sendMessage(void* data)
if (err_num == AMQP_STATUS_OK)
{
/**Message was sent successfully*/
free(tmp->prop);
free(tmp->msg);
free(tmp);
MXS_FREE(tmp->prop);
MXS_FREE(tmp->msg);
MXS_FREE(tmp);
atomic_add(&instance->stats.n_sent, 1);
atomic_add(&instance->stats.n_queued, -1);
@ -948,7 +952,7 @@ void sendMessage(void* data)
void pushMessage(MQ_INSTANCE *instance, amqp_basic_properties_t* prop, char* msg)
{
mqmessage* newmsg = calloc(1, sizeof(mqmessage));
mqmessage* newmsg = MXS_CALLOC(1, sizeof(mqmessage));
if (newmsg)
{
newmsg->msg = msg;
@ -956,9 +960,8 @@ void pushMessage(MQ_INSTANCE *instance, amqp_basic_properties_t* prop, char* msg
}
else
{
MXS_ERROR("Cannot allocate enough memory.");
free(prop);
free(msg);
MXS_FREE(prop);
MXS_FREE(msg);
return;
}
@ -985,23 +988,36 @@ void pushMessage(MQ_INSTANCE *instance, amqp_basic_properties_t* prop, char* msg
static void *
newSession(FILTER *instance, SESSION *session)
{
MQ_SESSION *my_session;
MYSQL_session* sessauth;
MYSQL_session *sessauth = session->client_dcb->data;
char *db = sessauth->db;
if (db)
{
if (strnlen(db, 128) > 0)
{
db = MXS_STRDUP(db);
if (!db)
{
return NULL;
}
}
else
{
db = NULL;
}
}
if ((my_session = calloc(1, sizeof(MQ_SESSION))) != NULL)
MQ_SESSION *my_session;
if ((my_session = MXS_CALLOC(1, sizeof(MQ_SESSION))) != NULL)
{
my_session->was_query = false;
my_session->uid = NULL;
my_session->session = session;
sessauth = my_session->session->client_dcb->data;
if (sessauth->db && strnlen(sessauth->db, 128) > 0)
{
my_session->db = strdup(sessauth->db);
}
else
{
my_session->db = NULL;
}
my_session->db = db;
}
else
{
MXS_FREE(db);
}
return my_session;
@ -1028,9 +1044,9 @@ static void
freeSession(FILTER *instance, void *session)
{
MQ_SESSION *my_session = (MQ_SESSION *) session;
free(my_session->uid);
free(my_session->db);
free(my_session);
MXS_FREE(my_session->uid);
MXS_FREE(my_session->db);
MXS_FREE(my_session);
return;
}
@ -1117,10 +1133,11 @@ routeQuery(FILTER *instance, void *session, GWBUF *queue)
{
if (my_session->db)
{
free(my_session->db);
MXS_FREE(my_session->db);
}
plen = pktlen(queue->start);
my_session->db = calloc(plen, sizeof(char));
my_session->db = MXS_CALLOC(plen, sizeof(char));
MXS_ABORT_IF_NULL(my_session->db);
memcpy(my_session->db, queue->start + 5, plen - 1);
}
@ -1229,9 +1246,9 @@ routeQuery(FILTER *instance, void *session, GWBUF *queue)
{
all_remotes = false;
}
free(tblnames[z]);
MXS_FREE(tblnames[z]);
}
free(tblnames);
MXS_FREE(tblnames);
if (!schema_ok && !all_remotes && my_session->db && strlen(my_session->db) > 0)
{
@ -1305,9 +1322,9 @@ routeQuery(FILTER *instance, void *session, GWBUF *queue)
{
for (j = 0; j < dbcount; j++)
{
free(sesstbls[j]);
MXS_FREE(sesstbls[j]);
}
free(sesstbls);
MXS_FREE(sesstbls);
dbcount = 0;
}
@ -1344,17 +1361,12 @@ routeQuery(FILTER *instance, void *session, GWBUF *queue)
if (my_session->uid == NULL)
{
my_session->uid = calloc(33, sizeof(char));
my_session->uid = MXS_CALLOC(33, sizeof(char));
if (!my_session->uid)
{
MXS_ERROR("Out of memory.");
}
else
if (my_session->uid)
{
genkey(my_session->uid, 32);
}
}
if (queue->next != NULL)
@ -1367,7 +1379,7 @@ routeQuery(FILTER *instance, void *session, GWBUF *queue)
my_session->was_query = true;
if ((prop = malloc(sizeof(amqp_basic_properties_t))))
if ((prop = MXS_MALLOC(sizeof(amqp_basic_properties_t))))
{
prop->_flags = AMQP_BASIC_CONTENT_TYPE_FLAG |
AMQP_BASIC_DELIVERY_MODE_FLAG |
@ -1379,8 +1391,6 @@ routeQuery(FILTER *instance, void *session, GWBUF *queue)
prop->message_id = amqp_cstring_bytes("query");
}
if (success)
{
@ -1396,15 +1406,13 @@ routeQuery(FILTER *instance, void *session, GWBUF *queue)
sprintf(t_buf, "%lu|", (unsigned long) time(NULL));
int qlen = strnlen(canon_q, length) + strnlen(t_buf, 128);
if ((combined = malloc((qlen + 1) * sizeof(char))) == NULL)
{
MXS_ERROR("Out of memory");
}
combined = MXS_MALLOC((qlen + 1) * sizeof(char));
MXS_ABORT_IF_NULL(combined);
strcpy(combined, t_buf);
strncat(combined, canon_q, length);
pushMessage(my_instance, prop, combined);
free(canon_q);
MXS_FREE(canon_q);
}
}
@ -1494,7 +1502,7 @@ unsigned int consume_leitoi(unsigned char** c)
char* consume_lestr(unsigned char** c)
{
unsigned int slen = consume_leitoi(c);
char *str = calloc((slen + 1), sizeof(char));
char *str = MXS_CALLOC((slen + 1), sizeof(char));
if (str)
{
memcpy(str, *c, slen);
@ -1545,7 +1553,7 @@ static int clientReply(FILTER* instance, void *session, GWBUF *reply)
if (pkt_len > 0)
{
if ((prop = malloc(sizeof(amqp_basic_properties_t))))
if ((prop = MXS_MALLOC(sizeof(amqp_basic_properties_t))))
{
prop->_flags = AMQP_BASIC_CONTENT_TYPE_FLAG |
AMQP_BASIC_DELIVERY_MODE_FLAG |
@ -1556,10 +1564,9 @@ static int clientReply(FILTER* instance, void *session, GWBUF *reply)
prop->correlation_id = amqp_cstring_bytes(my_session->uid);
prop->message_id = amqp_cstring_bytes("reply");
}
if (!(combined = calloc(GWBUF_LENGTH(reply) + 256, sizeof(char))))
{
MXS_ERROR("Out of memory");
}
combined = MXS_CALLOC(GWBUF_LENGTH(reply) + 256, sizeof(char));
MXS_ABORT_IF_NULL(combined);
memset(t_buf, 0, 128);
sprintf(t_buf, "%lu|", (unsigned long) time(NULL));
@ -1627,13 +1634,14 @@ static int clientReply(FILTER* instance, void *session, GWBUF *reply)
char *tmp;
unsigned int col_cnt = consume_leitoi(&rset);
tmp = calloc(256, sizeof(char));
tmp = MXS_CALLOC(256, sizeof(char));
MXS_ABORT_IF_NULL(tmp);
sprintf(tmp, "Columns: %d", col_cnt);
memcpy(combined + offset, tmp, strnlen(tmp, 256));
offset += strnlen(tmp, 256);
memcpy(combined + offset, "\n", 1);
offset++;
free(tmp);
MXS_FREE(tmp);
packet_ok = 1;
was_last = 1;
@ -1649,7 +1657,7 @@ static int clientReply(FILTER* instance, void *session, GWBUF *reply)
/**Successful reply received and sent, releasing uid*/
free(my_session->uid);
MXS_FREE(my_session->uid);
my_session->uid = NULL;
}

View File

@ -4,7 +4,7 @@
* Use of this software is governed by the Business Source License included
* in the LICENSE.TXT file and at www.mariadb.com/bsl.
*
* Change Date: 2019-01-01
* 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
@ -12,6 +12,7 @@
*/
#include <stdio.h>
#include <maxscale/alloc.h>
#include <filter.h>
#include <modinfo.h>
#include <modutil.h>
@ -20,6 +21,7 @@
#include <string.h>
#include <regex.h>
#include <hint.h>
#include <maxscale/alloc.h>
/**
* @file namedserverfilter.c - a very simple regular expression based filter
@ -143,10 +145,9 @@ GetModuleObject()
static FILTER *
createInstance(char **options, FILTER_PARAMETER **params)
{
REGEXHINT_INSTANCE *my_instance;
int cflags = REG_ICASE;
REGEXHINT_INSTANCE *my_instance = (REGEXHINT_INSTANCE*)MXS_MALLOC(sizeof(REGEXHINT_INSTANCE));
if ((my_instance = malloc(sizeof(REGEXHINT_INSTANCE))) != NULL)
if (my_instance)
{
my_instance->match = NULL;
my_instance->server = NULL;
@ -158,19 +159,19 @@ createInstance(char **options, FILTER_PARAMETER **params)
{
if (!strcmp(params[i]->name, "match"))
{
my_instance->match = strdup(params[i]->value);
my_instance->match = MXS_STRDUP_A(params[i]->value);
}
else if (!strcmp(params[i]->name, "server"))
{
my_instance->server = strdup(params[i]->value);
my_instance->server = MXS_STRDUP_A(params[i]->value);
}
else if (!strcmp(params[i]->name, "source"))
{
my_instance->source = strdup(params[i]->value);
my_instance->source = MXS_STRDUP_A(params[i]->value);
}
else if (!strcmp(params[i]->name, "user"))
{
my_instance->user = strdup(params[i]->value);
my_instance->user = MXS_STRDUP_A(params[i]->value);
}
else if (!filter_standard_parameter(params[i]->name))
{
@ -180,6 +181,8 @@ createInstance(char **options, FILTER_PARAMETER **params)
}
}
int cflags = REG_ICASE;
if (options)
{
for (int i = 0; options[i]; i++)
@ -221,7 +224,7 @@ createInstance(char **options, FILTER_PARAMETER **params)
{
MXS_ERROR("namedserverfilter: Invalid regular expression '%s'.\n",
my_instance->match);
free(my_instance->match);
MXS_FREE(my_instance->match);
my_instance->match = NULL;
error = true;
}
@ -231,12 +234,12 @@ createInstance(char **options, FILTER_PARAMETER **params)
if (my_instance->match)
{
regfree(&my_instance->re);
free(my_instance->match);
MXS_FREE(my_instance->match);
}
free(my_instance->server);
free(my_instance->source);
free(my_instance->user);
free(my_instance);
MXS_FREE(my_instance->server);
MXS_FREE(my_instance->source);
MXS_FREE(my_instance->user);
MXS_FREE(my_instance);
my_instance = NULL;
}
@ -258,7 +261,7 @@ newSession(FILTER *instance, SESSION *session)
REGEXHINT_SESSION *my_session;
char *remote, *user;
if ((my_session = calloc(1, sizeof(REGEXHINT_SESSION))) != NULL)
if ((my_session = MXS_CALLOC(1, sizeof(REGEXHINT_SESSION))) != NULL)
{
my_session->n_diverted = 0;
my_session->n_undiverted = 0;
@ -303,7 +306,7 @@ closeSession(FILTER *instance, void *session)
static void
freeSession(FILTER *instance, void *session)
{
free(session);
MXS_FREE(session);
return;
}
@ -361,7 +364,7 @@ routeQuery(FILTER *instance, void *session, GWBUF *queue)
{
my_session->n_undiverted++;
}
free(sql);
MXS_FREE(sql);
}
}
return my_session->down.routeQuery(my_session->down.instance,

View File

@ -4,7 +4,7 @@
* Use of this software is governed by the Business Source License included
* in the LICENSE.TXT file and at www.mariadb.com/bsl.
*
* Change Date: 2019-01-01
* 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
@ -47,6 +47,7 @@
#include <regex.h>
#include <string.h>
#include <atomic.h>
#include <maxscale/alloc.h>
MODULE_INFO info =
{
@ -173,10 +174,9 @@ GetModuleObject()
static FILTER *
createInstance(char **options, FILTER_PARAMETER **params)
{
QLA_INSTANCE *my_instance;
int i;
QLA_INSTANCE *my_instance = (QLA_INSTANCE*) MXS_MALLOC(sizeof(QLA_INSTANCE));
if ((my_instance = malloc(sizeof(QLA_INSTANCE))) != NULL)
if (my_instance)
{
my_instance->source = NULL;
my_instance->userName = NULL;
@ -187,27 +187,27 @@ createInstance(char **options, FILTER_PARAMETER **params)
if (params)
{
for (i = 0; params[i]; i++)
for (int i = 0; params[i]; i++)
{
if (!strcmp(params[i]->name, "match"))
{
my_instance->match = strdup(params[i]->value);
my_instance->match = MXS_STRDUP_A(params[i]->value);
}
else if (!strcmp(params[i]->name, "exclude"))
{
my_instance->nomatch = strdup(params[i]->value);
my_instance->nomatch = MXS_STRDUP_A(params[i]->value);
}
else if (!strcmp(params[i]->name, "source"))
{
my_instance->source = strdup(params[i]->value);
my_instance->source = MXS_STRDUP_A(params[i]->value);
}
else if (!strcmp(params[i]->name, "user"))
{
my_instance->userName = strdup(params[i]->value);
my_instance->userName = MXS_STRDUP_A(params[i]->value);
}
else if (!strcmp(params[i]->name, "filebase"))
{
my_instance->filebase = strdup(params[i]->value);
my_instance->filebase = MXS_STRDUP_A(params[i]->value);
}
else if (!filter_standard_parameter(params[i]->name))
{
@ -222,7 +222,7 @@ createInstance(char **options, FILTER_PARAMETER **params)
if (options)
{
for (i = 0; options[i]; i++)
for (int i = 0; options[i]; i++)
{
if (!strcasecmp(options[i], "ignorecase"))
{
@ -258,7 +258,7 @@ createInstance(char **options, FILTER_PARAMETER **params)
MXS_ERROR("qlafilter: Invalid regular expression '%s'"
" for the 'match' parameter.\n",
my_instance->match);
free(my_instance->match);
MXS_FREE(my_instance->match);
my_instance->match = NULL;
error = true;
}
@ -268,7 +268,7 @@ createInstance(char **options, FILTER_PARAMETER **params)
MXS_ERROR("qlafilter: Invalid regular expression '%s'"
" for the 'nomatch' parameter.",
my_instance->nomatch);
free(my_instance->nomatch);
MXS_FREE(my_instance->nomatch);
my_instance->nomatch = NULL;
error = true;
}
@ -277,19 +277,19 @@ createInstance(char **options, FILTER_PARAMETER **params)
{
if (my_instance->match)
{
free(my_instance->match);
MXS_FREE(my_instance->match);
regfree(&my_instance->re);
}
if (my_instance->nomatch)
{
free(my_instance->nomatch);
MXS_FREE(my_instance->nomatch);
regfree(&my_instance->nore);
}
free(my_instance->filebase);
free(my_instance->source);
free(my_instance->userName);
free(my_instance);
MXS_FREE(my_instance->filebase);
MXS_FREE(my_instance->source);
MXS_FREE(my_instance->userName);
MXS_FREE(my_instance);
my_instance = NULL;
}
}
@ -312,16 +312,11 @@ newSession(FILTER *instance, SESSION *session)
QLA_SESSION *my_session;
char *remote, *userName;
if ((my_session = calloc(1, sizeof(QLA_SESSION))) != NULL)
if ((my_session = MXS_CALLOC(1, sizeof(QLA_SESSION))) != NULL)
{
if ((my_session->filename = (char *)malloc(strlen(my_instance->filebase) + 20)) == NULL)
if ((my_session->filename = (char *)MXS_MALLOC(strlen(my_instance->filebase) + 20)) == NULL)
{
char errbuf[STRERROR_BUFLEN];
MXS_ERROR("Memory allocation for qla filter "
"file name failed due to %d, %s.",
errno,
strerror_r(errno, errbuf, sizeof(errbuf)));
free(my_session);
MXS_FREE(my_session);
return NULL;
}
my_session->active = 1;
@ -359,8 +354,8 @@ newSession(FILTER *instance, SESSION *session)
"fileter failed due to %d, %s",
errno,
strerror_r(errno, errbuf, sizeof(errbuf)));
free(my_session->filename);
free(my_session);
MXS_FREE(my_session->filename);
MXS_FREE(my_session);
my_session = NULL;
}
}
@ -406,8 +401,8 @@ freeSession(FILTER *instance, void *session)
{
QLA_SESSION *my_session = (QLA_SESSION *) session;
free(my_session->filename);
free(session);
MXS_FREE(my_session->filename);
MXS_FREE(session);
return;
}
@ -467,7 +462,7 @@ routeQuery(FILTER *instance, void *session, GWBUF *queue)
fprintf(my_session->fp, "%s,%s@%s,%s\n", buffer, my_session->user,
my_session->remote, trim(squeeze_whitespace(ptr)));
}
free(ptr);
MXS_FREE(ptr);
}
}
/* Pass the query downstream */

View File

@ -4,7 +4,7 @@
* Use of this software is governed by the Business Source License included
* in the LICENSE.TXT file and at www.mariadb.com/bsl.
*
* Change Date: 2019-01-01
* 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
@ -21,6 +21,7 @@
#include <string.h>
#include <pcre2.h>
#include <atomic.h>
#include <maxscale/alloc.h>
#include "maxconfig.h"
/**
@ -159,11 +160,11 @@ void free_instance(REGEX_INSTANCE *instance)
pcre2_match_data_free(instance->match_data);
}
free(instance->match);
free(instance->replace);
free(instance->source);
free(instance->user);
free(instance);
MXS_FREE(instance->match);
MXS_FREE(instance->replace);
MXS_FREE(instance->source);
MXS_FREE(instance->user);
MXS_FREE(instance);
}
}
@ -185,7 +186,7 @@ createInstance(char **options, FILTER_PARAMETER **params)
char *logfile = NULL;
const char *errmsg;
if ((my_instance = calloc(1, sizeof(REGEX_INSTANCE))) != NULL)
if ((my_instance = MXS_CALLOC(1, sizeof(REGEX_INSTANCE))) != NULL)
{
my_instance->match = NULL;
my_instance->replace = NULL;
@ -194,19 +195,19 @@ createInstance(char **options, FILTER_PARAMETER **params)
{
if (!strcmp(params[i]->name, "match"))
{
my_instance->match = strdup(params[i]->value);
my_instance->match = MXS_STRDUP_A(params[i]->value);
}
else if (!strcmp(params[i]->name, "replace"))
{
my_instance->replace = strdup(params[i]->value);
my_instance->replace = MXS_STRDUP_A(params[i]->value);
}
else if (!strcmp(params[i]->name, "source"))
{
my_instance->source = strdup(params[i]->value);
my_instance->source = MXS_STRDUP_A(params[i]->value);
}
else if (!strcmp(params[i]->name, "user"))
{
my_instance->user = strdup(params[i]->value);
my_instance->user = MXS_STRDUP_A(params[i]->value);
}
else if (!strcmp(params[i]->name, "log_trace"))
{
@ -216,9 +217,9 @@ createInstance(char **options, FILTER_PARAMETER **params)
{
if (logfile)
{
free(logfile);
MXS_FREE(logfile);
}
logfile = strdup(params[i]->value);
logfile = MXS_STRDUP_A(params[i]->value);
}
else if (!filter_standard_parameter(params[i]->name))
{
@ -253,14 +254,14 @@ createInstance(char **options, FILTER_PARAMETER **params)
{
MXS_ERROR("regexfilter: Failed to open file '%s'.", logfile);
free_instance(my_instance);
free(logfile);
MXS_FREE(logfile);
return NULL;
}
fprintf(my_instance->logfile, "\nOpened regex filter log\n");
fflush(my_instance->logfile);
}
free(logfile);
MXS_FREE(logfile);
if (my_instance->match == NULL || my_instance->replace == NULL)
{
@ -309,7 +310,7 @@ newSession(FILTER *instance, SESSION *session)
REGEX_SESSION *my_session;
char *remote, *user;
if ((my_session = calloc(1, sizeof(REGEX_SESSION))) != NULL)
if ((my_session = MXS_CALLOC(1, sizeof(REGEX_SESSION))) != NULL)
{
my_session->no_change = 0;
my_session->replacements = 0;
@ -354,7 +355,7 @@ closeSession(FILTER *instance, void *session)
static void
freeSession(FILTER *instance, void *session)
{
free(session);
MXS_FREE(session);
return;
}
@ -408,7 +409,7 @@ routeQuery(FILTER *instance, void *session, GWBUF *queue)
spinlock_acquire(&my_session->lock);
log_match(my_instance, my_instance->match, sql, newsql);
spinlock_release(&my_session->lock);
free(newsql);
MXS_FREE(newsql);
my_session->replacements++;
}
else
@ -418,7 +419,7 @@ routeQuery(FILTER *instance, void *session, GWBUF *queue)
spinlock_release(&my_session->lock);
my_session->no_change++;
}
free(sql);
MXS_FREE(sql);
}
}
@ -485,7 +486,7 @@ regex_replace(const char *sql, pcre2_code *re, pcre2_match_data *match_data, con
if (pcre2_match(re, (PCRE2_SPTR) sql, PCRE2_ZERO_TERMINATED, 0, 0, match_data, NULL))
{
result_size = strlen(sql) + strlen(replace);
result = malloc(result_size);
result = MXS_MALLOC(result_size);
while (result &&
pcre2_substitute(re, (PCRE2_SPTR) sql, PCRE2_ZERO_TERMINATED, 0,
@ -494,9 +495,9 @@ regex_replace(const char *sql, pcre2_code *re, pcre2_match_data *match_data, con
(PCRE2_UCHAR*) result, (PCRE2_SIZE*) & result_size) == PCRE2_ERROR_NOMEMORY)
{
char *tmp;
if ((tmp = realloc(result, (result_size *= 1.5))) == NULL)
if ((tmp = MXS_REALLOC(result, (result_size *= 1.5))) == NULL)
{
free(result);
MXS_FREE(result);
result = NULL;
}
result = tmp;

View File

@ -4,7 +4,7 @@
* Use of this software is governed by the Business Source License included
* in the LICENSE.TXT file and at www.mariadb.com/bsl.
*
* Change Date: 2019-01-01
* 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
@ -58,6 +58,8 @@
#include <maxscale/poll.h>
#include <mysql_client_server_protocol.h>
#include <housekeeper.h>
#include <maxscale/alloc.h>
#include <listmanager.h>
#define MYSQL_COM_QUIT 0x01
#define MYSQL_COM_INITDB 0x02
@ -209,6 +211,8 @@ int route_single_query(TEE_INSTANCE* my_instance,
int reset_session_state(TEE_SESSION* my_session, GWBUF* buffer);
void create_orphan(SESSION* ses);
extern LIST_CONFIG SESSIONlist;
static void
orphan_free(void* data)
{
@ -293,8 +297,8 @@ orphan_free(void* data)
tmp->session->router_session);
tmp->session->state = SESSION_STATE_FREE;
free(tmp->session);
free(tmp);
list_free_entry(&SESSIONlist, (list_entry_t*)tmp->session);
MXS_FREE(tmp);
}
#ifdef SS_DEBUG
@ -358,7 +362,7 @@ createInstance(char **options, FILTER_PARAMETER **params)
TEE_INSTANCE *my_instance;
int i;
if ((my_instance = calloc(1, sizeof(TEE_INSTANCE))) != NULL)
if ((my_instance = MXS_CALLOC(1, sizeof(TEE_INSTANCE))) != NULL)
{
if (options)
{
@ -384,19 +388,19 @@ createInstance(char **options, FILTER_PARAMETER **params)
}
else if (!strcmp(params[i]->name, "match"))
{
my_instance->match = strdup(params[i]->value);
my_instance->match = MXS_STRDUP_A(params[i]->value);
}
else if (!strcmp(params[i]->name, "exclude"))
{
my_instance->nomatch = strdup(params[i]->value);
my_instance->nomatch = MXS_STRDUP_A(params[i]->value);
}
else if (!strcmp(params[i]->name, "source"))
{
my_instance->source = strdup(params[i]->value);
my_instance->source = MXS_STRDUP_A(params[i]->value);
}
else if (!strcmp(params[i]->name, "user"))
{
my_instance->userName = strdup(params[i]->value);
my_instance->userName = MXS_STRDUP_A(params[i]->value);
}
else if (!filter_standard_parameter(params[i]->name))
{
@ -434,9 +438,9 @@ createInstance(char **options, FILTER_PARAMETER **params)
if (my_instance->service == NULL)
{
free(my_instance->match);
free(my_instance->source);
free(my_instance);
MXS_FREE(my_instance->match);
MXS_FREE(my_instance->source);
MXS_FREE(my_instance);
return NULL;
}
@ -446,10 +450,10 @@ createInstance(char **options, FILTER_PARAMETER **params)
MXS_ERROR("tee: Invalid regular expression '%s'"
" for the match parameter.",
my_instance->match);
free(my_instance->match);
free(my_instance->nomatch);
free(my_instance->source);
free(my_instance);
MXS_FREE(my_instance->match);
MXS_FREE(my_instance->nomatch);
MXS_FREE(my_instance->source);
MXS_FREE(my_instance);
return NULL;
}
if (my_instance->nomatch &&
@ -461,11 +465,11 @@ createInstance(char **options, FILTER_PARAMETER **params)
if (my_instance->match)
{
regfree(&my_instance->re);
free(my_instance->match);
MXS_FREE(my_instance->match);
}
free(my_instance->nomatch);
free(my_instance->source);
free(my_instance);
MXS_FREE(my_instance->nomatch);
MXS_FREE(my_instance->source);
MXS_FREE(my_instance);
return NULL;
}
}
@ -496,7 +500,7 @@ newSession(FILTER *instance, SESSION *session)
goto retblock;
}
HASHTABLE* ht = hashtable_alloc(100, simple_str_hash, strcmp);
HASHTABLE* ht = hashtable_alloc(100, hashtable_item_strhash, hashtable_item_strcmp);
bool is_loop = detect_loops(my_instance, ht, session->service);
hashtable_free(ht);
@ -508,7 +512,7 @@ newSession(FILTER *instance, SESSION *session)
goto retblock;
}
if ((my_session = calloc(1, sizeof(TEE_SESSION))) != NULL)
if ((my_session = MXS_CALLOC(1, sizeof(TEE_SESSION))) != NULL)
{
my_session->active = 1;
my_session->residual = 0;
@ -597,7 +601,7 @@ newSession(FILTER *instance, SESSION *session)
filter_free(dummy);
closeSession(instance, (void*) my_session);
dcb_close(dcb);
free(my_session);
MXS_FREE(my_session);
MXS_ERROR("tee: Allocating memory for"
"dummy upstream failed."
" Terminating session.");
@ -608,7 +612,7 @@ newSession(FILTER *instance, SESSION *session)
ses->tail = *dummy_upstream;
MySQLProtocol* protocol = (MySQLProtocol*) session->client_dcb->protocol;
my_session->use_ok = protocol->client_capabilities & (1 << 6);
free(dummy_upstream);
MXS_FREE(dummy_upstream);
}
}
retblock:
@ -707,7 +711,7 @@ freeSession(FILTER *instance, void *session)
ses->router_session);
/** Free memory of branch client session */
ses->state = SESSION_STATE_FREE;
free(ses);
MXS_FREE(ses);
/** This indicates that branch session is not available anymore */
my_session->branch_session = NULL;
}
@ -724,7 +728,7 @@ freeSession(FILTER *instance, void *session)
{
gwbuf_free(my_session->tee_replybuf);
}
free(session);
MXS_FREE(session);
orphan_free(NULL);
@ -1248,7 +1252,7 @@ GWBUF* clone_query(TEE_INSTANCE* my_instance, TEE_SESSION* my_session, GWBUF* bu
clone = gwbuf_clone_all(buffer);
my_session->residual = residual;
}
free(ptr);
MXS_FREE(ptr);
}
else if (packet_is_required(buffer))
{
@ -1357,14 +1361,8 @@ int reset_session_state(TEE_SESSION* my_session, GWBUF* buffer)
void create_orphan(SESSION* ses)
{
orphan_session_t* orphan;
if ((orphan = malloc(sizeof(orphan_session_t))) == NULL)
{
MXS_ERROR("Failed to "
"allocate memory for orphan session struct, "
"child session might leak memory.");
}
else
orphan_session_t* orphan = MXS_MALLOC(sizeof(orphan_session_t));
if (orphan)
{
orphan->session = ses;
spinlock_acquire(&orphanLock);

View File

@ -1,26 +0,0 @@
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
add_executable(harness_ui harness_ui.c harness_common.c)
add_executable(harness harness_util.c harness_common.c)
target_link_libraries(harness_ui maxscale-common)
target_link_libraries(harness maxscale-common)
execute_process(COMMAND ${CMAKE_COMMAND} -E copy ${ERRMSG} ${CMAKE_CURRENT_BINARY_DIR})
execute_process(COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/harness.cnf ${CMAKE_CURRENT_BINARY_DIR})
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/testdriver.sh ${CMAKE_CURRENT_BINARY_DIR}/testdriver.sh @ONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/hintfilter/hint_testing.cnf ${CMAKE_CURRENT_BINARY_DIR}/hintfilter/hint_testing.cnf)
add_test(TestHintfilter testdriver.sh hintfilter/hint_testing.cnf hintfilter/hint_testing.input hintfilter/hint_testing.output hintfilter/hint_testing.expected)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/regexfilter/regextest.cnf ${CMAKE_CURRENT_BINARY_DIR}/regexfilter/regextest.cnf)
add_test(TestRegexfilter testdriver.sh regexfilter/regextest.cnf regexfilter/regextest.input regexfilter/regextest.output regexfilter/regextest.expected)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fwfilter/fwtest.cnf.in ${CMAKE_CURRENT_BINARY_DIR}/fwfilter/fwtest.cnf)
add_test(TestFwfilter1 testdriver.sh fwfilter/fwtest.cnf fwfilter/fwtest.input fwfilter/fwtest.output fwfilter/fwtest.expected)
add_test(TestFwfilter2 testdriver.sh fwfilter/fwtest.cnf fwfilter/fwtest2.input fwfilter/fwtest2.output fwfilter/fwtest2.expected)
add_test(TestTeeRecursion ${CMAKE_CURRENT_SOURCE_DIR}/tee_recursion.sh
${CMAKE_BINARY_DIR}
${CMAKE_SOURCE_DIR}
${TEST_USER}
${TEST_PASSWORD}
${TEST_HOST}
${TEST_PORT})

View File

@ -1,20 +0,0 @@
Filter Test Harness
For a more detailed description of the filter harness, either generate the documentation or read the harness.h file.
Running the program without arguments enters the interactive mode. Type 'help' for a list of all commands.
The default values for threads and sessions are stored in the 'harness.cnf' file
Mandatory parameters for the command line mode are -c and -i.
Parameters for the command line:
-h Display this information
-c Path to the MaxScale configuration file to parse for filters
-i Name of the input file for buffers
-o Name of the output file for results
-q Suppress printing to stdout
-t Number of threads
-s Number of sessions
-d Routing delay

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +0,0 @@
[Firewall]
type=filter
module=dbfwfilter
rules=@CMAKE_CURRENT_SOURCE_DIR@/rules

View File

@ -1,8 +0,0 @@
select id from t1;
select id from t1;
select id from t1;
select id from t1;
select id from t1;
select id from t1;
select id from t1;
select id from t1;

View File

@ -1,10 +0,0 @@
delete from t1;
select id from t1;
select id from t1;
select id from t1;
delete from t1;
select id from t1;
select id from t1;
select id from t1;
select id from t1;
select id from t1;

View File

@ -1,8 +0,0 @@
select id from t1;
select id from t1;
select id from t1;
select id from t1;
select id from t1;
select id from t1;
select id from t1;
select id from t1;

View File

@ -1,8 +0,0 @@
select id from t1;
select id from t1;
select id from t1;
select id from t1;
select id from t1;
select id from t1;
select id from t1;
select id from t1;

View File

@ -1,10 +0,0 @@
select id from t1;
select id from t1 union select name from t2;
select id from t1;
select id from t1;
select id from t1;
select id from t1;
select id from t1;
select id from t1 union select name from t2;
select id from t1;
select id from t1;

View File

@ -1,2 +0,0 @@
threads=2
sessions=4

View File

@ -1,371 +0,0 @@
#ifndef _FILTER_HARNESS_H
#define _FILTER_HARNESS_H
/*
* 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/bsl.
*
* Change Date: 2019-01-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.
*/
/**
* Test harness for independent testing of filters
*
* A test harness that feeds a GWBUF to a chain of filters and prints the results
* either into a file or to the standard output.
*
* The contents of the GWBUF and the filter parameters are either manually set through
* the command line or read from a file.
* @verbatim
* Options for the configuration file 'harness.cnf'':
*
* threads Number of threads to use when routing buffers
* sessions Number of sessions
*
* Options for the command line:
*
* -c Path to the MaxScale configuration file to parse for filters
* -i Name of the input file for buffers
* -o Name of the output file for results
* -q Suppress printing to stdout
* -s Number of sessions
* -t Number of threads
* -d Routing delay, in milliseconds
*
*
* Revision History
*
* Date Who Description
* 01/07/14 Markus Makela Initial implementation
*
* @endverbatim
*/
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <filter.h>
#include <buffer.h>
#include <modules.h>
#include <modutil.h>
#include <skygw_utils.h>
#include <log_manager.h>
#include <atomic.h>
#include <ini.h>
#include <hint.h>
#include <modutil.h>
#include <errno.h>
#include <mysql_client_server_protocol.h>
/**
* A single name-value pair and a link to the next item in the
* configuration.
*/
typedef struct CONFIG_ITEM_T
{
char* name;
char* value;
struct CONFIG_ITEM_T* next;
}CONFIG_ITEM;
/**
*A simplified version of a MaxScale configuration context used to load filters
* and their options.
*/
typedef struct CONFIG_T
{
char* section;
CONFIG_ITEM* item;
struct CONFIG_T* next;
}CONFIG;
/**
*A structure that holds all the necessary information to emulate a working
* filter environment.
*/
struct FILTERCHAIN_T
{
FILTER* filter; /**An instance of a particular filter*/
FILTER_OBJECT* instance; /**Dynamically loaded module*/
SESSION** session; /**A list of sessions*/
DOWNSTREAM** down; /** A list of next filters downstreams*/
UPSTREAM** up; /** A list of next filters upstreams*/
char* name; /**Module name*/
struct FILTERCHAIN_T* next;
};
typedef struct FILTERCHAIN_T FILTERCHAIN;
/**
* A container for all the filters, query buffers and user specified parameters
*/
typedef struct
{
int running;
int verbose; /**Whether to print to stdout*/
int infile; /**A file where the queries are loaded from*/
int expected;
int error;
char* mod_dir; /**Module directory absolute path*/
char* infile_name;
int outfile; /**A file where the output of the filters is logged*/
char* outfile_name;
FILTERCHAIN* head; /**The head of the filter chain*/
FILTERCHAIN* tail; /**The tail of the filter chain*/
GWBUF** buffer; /**Buffers that are fed to the filter chain*/
SESSION* session;
int buffer_count;
int session_count;
DOWNSTREAM dummyrouter; /**Dummy downstream router for data extraction*/
UPSTREAM dummyclient; /**Dummy downstream router for data extraction*/
CONFIG* conf; /**Configurations loaded from a file*/
pthread_mutex_t work_mtx; /**Mutex for buffer routing*/
int buff_ind; /**Index of first unrouted buffer*/
int sess_ind;/**Index of first unused session*/
int last_ind; /**Index of last used session*/
pthread_t* thrpool;
int thrcount; /**Number of active threads*/
int rt_delay; /**Delay each thread waits after routing a query, in milliseconds*/
}HARNESS_INSTANCE;
static HARNESS_INSTANCE instance;
/**
*A list of available actions.
*/
typedef enum
{
UNDEFINED,
RUNFILTERS,
LOAD_FILTER,
DELETE_FILTER,
LOAD_CONFIG,
SET_INFILE,
SET_OUTFILE,
THR_COUNT,
SESS_COUNT,
OK,
QUIT
} operation_t;
typedef enum
{
PACKET_OK,
PACKET_ERROR,
PACKET_RESULT_SET
} packet_t;
typedef packet_t PACKET;
/**
* Initialize the static instance.
*/
int harness_init(int argc,char** argv,HARNESS_INSTANCE** inst);
/**
* Frees all the query buffers
*/
void free_buffers();
/**
* Frees all the loaded filters
*/
void free_filters();
/**
* Converts the passed string into an operation
*
* @param tk The string to parse
* @return The operation to perform or UNDEFINED, if parsing failed
*/
operation_t user_input(char* tk);
/**
*Prints a list of available commands.
*/
void print_help();
/**
* Prints the current status of loaded filters and queries, number of threads
* and sessions and possible output files.
*/
void print_status();
/**
*Opens a file for reading and/or writing with adequate permissions.
*
* @param str Path to file
* @param write Non-zero for write permissions, zero for read only.
* @return The assigned file descriptor or -1 in case an error occurred
*/
int open_file(char* str, unsigned int write);
/**
* Reads filter parameters from the command line as name-value pairs.
*
*@param paramc The number of parameters read is assigned to this variable
*@return The newly allocated list of parameters with the last one being NULL
*/
FILTER_PARAMETER** read_params(int* paramc);
/**
* Dummy endpoint for the queries of the filter chain
*
* Prints and logs the contents of the GWBUF after it has passed through all the filters.
* The packet is handled as a COM_QUERY packet and the packet header is not printed.
*/
int routeQuery(void* instance, void* session, GWBUF* queue);
/**
* Dummy endpoint for the replies of the filter chain
*
* Prints and logs the contents of the GWBUF after it has passed through all the filters.
* The packet is handled as a OK packet with no message and the packet header is not printed.
*/
int clientReply(void* ins, void* session, GWBUF* queue);
/**
*Manual input if a query string
*
* Reads a single query from the standard input and inserts it into a GWBUF.
*/
void manual_query();
/**
*Loads the file pointed by @{instance.infile}
* @return Zero if successful, non-zero if an error occurred
*/
int load_query();
/**
* Handler for the INI file parser that builds a linked list
* of all the sections and their name-value pairs.
* @param user Current configuration.
* @param section Name of the section.
* @param name Name of the item.
* @param value Value of the item.
* @return Non-zero on success, zero in case parsing is finished.
* @see load_config()
*/
int handler(void* user, const char* section, const char* name,const char* value);
/**
* Removes all non-filter modules from the configuration
*
* @param conf A pointer to a configuration struct
* @return The stripped version of the configuration
* @see load_config()
*/
CONFIG* process_config(CONFIG* conf);
/**
* Loads the filter module and link it to the filter chain
*
* The downstream is set to point to the current head of the filter chain
*
* @param str Name of the filter module
* @return Pointer to the newly initialized FILTER_CHAIN element or NULL in case module loading failed
* @see load_filter()
*/
FILTERCHAIN* load_filter_module(char* str);
/**
* Loads a new instance of a filter and starts a new session.
* This function assumes that the filter module is already loaded.
* Passing NULL as the CONFIG parameter causes the parameters to be
* read from the command line one at a time.
*
* @param fc The FILTERCHAIN where the new instance and session are created
* @param cnf A configuration read from a file
* @return 1 on success, 0 in case an error occurred
* @see load_filter_module()
*/
int load_filter(FILTERCHAIN* fc, CONFIG* cnf);
/**
* Reads a MaxScale configuration (or any INI file using MaxScale notation) file and loads only the filter modules in it.
*
* @param fname Configuration file name
* @return Non-zero on success, zero in case an error occurred.
*/
int load_config(char* fname);
/**
* Initializes the indexes used while routing buffers and prints the progress
* of the routing process.
*/
void route_buffers();
/**
* Worker function for threads.
* Routes a query buffer if there are unrouted buffers left.
*
* @param thr_num ID number of the thread
*/
void work_buffer(void* thr_num);
/**
* Generates a fake packet used to emulate a response from the backend.
*
* Current implementation only works with PACKET_OK and the packet has no message.
* The caller is responsible for freeing the allocated memory by calling gwbuf_free().
* @param pkt The packet type
* @return The newly generated packet or NULL if an error occurred
*/
GWBUF* gen_packet(PACKET pkt);
/**
* Process the command line parameters and the harness configuration file.
*
* Reads the contents of the 'harness.cnf' file and command line parameters
* and parses them. Options are interpreted accoding to the following table.
* If no command line arguments are given, interactive mode is used.
*
* By default if no input file is given or no configuration file or specific
* filters are given, but other options are, the program exits with 0.
*
* Options for the configuration file 'harness.cnf'':
*
* threads Number of threads to use when routing buffers
* sessions Number of sessions
*
* Options for the command line:
*
* -h Display this information
* -c Path to the MaxScale configuration file to parse for filters
* -i Name of the input file for buffers
* -o Name of the output file for results
* -q Suppress printing to stdout
* -t Number of threads
* -s Number of sessions
* -d Routing delay
*
* @param argc Number of arguments
* @param argv List of argument strings
* @return 1 if successful, 0 if no input file, configuration file or specific
* filters are given, but other options are, or if an error occurs.
*/
int process_opts(int argc, char** argv);
/**
* Compares the contents of two files.
* This function resets the offsets of the file descriptors and leaves them in an
* undefined state.
* @param a The first file
* @param b The second file
* @return 0 if the files do not differ and 1 if they do or an error occurred.
*/
int compare_files(int a, int b);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,400 +0,0 @@
#include <harness.h>
int main(int argc, char** argv){
int i;
char buffer[256];
char* tk;
FILTERCHAIN* tmp_chn;
FILTERCHAIN* del_chn;
HARNESS_INSTANCE* hinstance;
if(harness_init(argc,argv,&hinstance)){
printf("Error: Initialization failed.\n");
MXS_ERROR("Initialization failed.\n");
mxs_log_finish();
return 1;
}
if(instance.verbose){
printf("\n\n\tFilter Test Harness\n\n");
}
while(instance.running){
printf("Harness> ");
memset(buffer,0,256);
fgets(buffer,256,stdin);
tk = strtok(buffer," \n");
switch(user_input(tk))
{
case RUNFILTERS:
if(instance.head->next == NULL){
printf("No filters loaded.\n");
break;
}
if(instance.buffer == NULL){
if(instance.infile<0){
manual_query();
}else{
load_query();
}
}
route_buffers();
break;
case LOAD_FILTER:
tk = strtok(NULL," \n");
tmp_chn = load_filter_module(tk);
if(!tmp_chn || !load_filter(tmp_chn,instance.conf)){
printf("Error creating filter instance.\n");
MXS_ERROR("Error creating filter instance.\n");
}else{
instance.head = tmp_chn;
}
break;
case DELETE_FILTER:
tk = strtok(NULL," \n\0");
tmp_chn = instance.head;
del_chn = instance.head;
if(tk){
if(strcmp(instance.head->name,tk) == 0){
instance.head = instance.head->next;
}else{
while(del_chn->next){
if(strcmp(del_chn->name,tk) == 0){
tmp_chn->next = del_chn->next;
break;
}else{
tmp_chn = del_chn;
del_chn = del_chn->next;
}
}
}
if(del_chn && del_chn->next){
printf("Deleted %s.\n",del_chn->name);
if(del_chn->instance){
del_chn->instance->freeSession(del_chn->filter,del_chn->session);
}
free(del_chn->filter);
free(del_chn->down);
free(del_chn->name);
free(del_chn);
}else{
printf("No matching filter found.\n");
}
}
break;
case LOAD_CONFIG:
tk = strtok(NULL," \n\0");
if(!load_config(tk)){
free_filters();
}
break;
case SET_INFILE:
tk = strtok(NULL," \n\0");
if(instance.infile >= 0){
close(instance.infile);
free(instance.infile_name);
}
if(tk!= NULL){
free_buffers();
instance.infile = open_file(tk,0);
if(instance.infile >= 0){
load_query();
instance.infile_name = strdup(tk);
if(instance.verbose){
printf("Loaded %d queries from file '%s'\n",instance.buffer_count,instance.infile_name);
}
}
}else{
instance.infile = -1;
printf("Queries are read from: command line\n");
}
break;
case SET_OUTFILE:
tk = strtok(NULL," \n\0");
if(instance.outfile >= 0){
close(instance.outfile);
free(instance.outfile_name);
}
if(tk!= NULL){
instance.outfile = open_file(tk,1);
if(instance.outfile >= 0){
instance.outfile_name = strdup(tk);
printf("Output is logged to: %s\n",tk);
}
}else{
instance.outfile = -1;
printf("Output logging disabled.\n");
}
break;
case SESS_COUNT:
tk = strtok(NULL," \n\0");
free_buffers();
free_filters();
instance.session_count = atoi(tk);
printf("Sessions set to: %d\n", instance.session_count);
break;
case THR_COUNT:
instance.running = 0;
pthread_mutex_unlock(&instance.work_mtx);
for(i = 0;i<instance.thrcount;i++){
pthread_join(instance.thrpool[i],NULL);
}
pthread_mutex_lock(&instance.work_mtx);
instance.running = 1;
tk = strtok(NULL," \n\0");
instance.thrcount = atoi(tk);
void* t_thr_pool;
if(!(t_thr_pool = realloc(instance.thrpool,instance.thrcount * sizeof(pthread_t)))){
printf("Error: Out of memory\n");
MXS_ERROR("Out of memory\n");
instance.running = 0;
break;
}
instance.thrpool = t_thr_pool;
intptr_t thr_num = 1;
for(i = 0;i<instance.thrcount;i++){
pthread_create(&instance.thrpool[i],
NULL,
(void*)work_buffer,
(void*)thr_num++);
}
printf("Threads set to: %d\n", instance.thrcount);
break;
case QUIT:
instance.running = 0;
pthread_mutex_unlock(&instance.work_mtx);
for(i = 0;i<instance.thrcount;i++){
pthread_join(instance.thrpool[i],NULL);
}
break;
case UNDEFINED:
printf("Command not found, enter \"help\" for a list of commands\n");
break;
default:
break;
}
}
if(instance.infile >= 0){
close(instance.infile);
}
if(instance.outfile >= 0){
close(instance.outfile);
}
free_buffers();
free_filters();
mxs_log_finish();
free(instance.head);
return 0;
}
operation_t user_input(char* tk)
{
if(tk){
char cmpbuff[256];
int tklen = strcspn(tk," \n\0");
memset(cmpbuff,0,256);
if(tklen > 0 && tklen < 256){
strncpy(cmpbuff,tk,tklen);
strcat(cmpbuff,"\0");
if(strcmp(tk,"run")==0 || strcmp(tk,"r")==0){
return RUNFILTERS;
}else if(strcmp(cmpbuff,"add")==0){
return LOAD_FILTER;
}else if(strcmp(cmpbuff,"delete")==0){
return DELETE_FILTER;
}else if(strcmp(cmpbuff,"clear")==0){
tk = strtok(NULL," \n\0");
if(tk && !strcmp(tk,"queries")){
free_buffers();
printf("Queries cleared.\n");
}else if(tk && !strcmp(tk,"filters")){
printf("Filters cleared.\n");
free_filters();
}else{
printf("All cleared.\n");
free_buffers();
free_filters();
}
return OK;
}else if(strcmp(cmpbuff,"config")==0){
return LOAD_CONFIG;
}else if(strcmp(cmpbuff,"in")==0){
return SET_INFILE;
}else if(strcmp(cmpbuff,"out")==0){
return SET_OUTFILE;
}else if(strcmp(cmpbuff,"exit")==0 || strcmp(cmpbuff,"quit")==0 || strcmp(cmpbuff,"q")==0){
return QUIT;
}else if(strcmp(cmpbuff,"help")==0){
print_help();
return OK;
}else if(strcmp(cmpbuff,"status")==0){
print_status();
return OK;
}else if(strcmp(cmpbuff,"quiet")==0){
instance.verbose = 0;
return OK;
}else if(strcmp(cmpbuff,"verbose")==0){
instance.verbose = 1;
return OK;
}else if(strcmp(cmpbuff,"sessions")==0){
return SESS_COUNT;
}else if(strcmp(cmpbuff,"threads")==0){
return THR_COUNT;
}
}
}
return UNDEFINED;
}
void print_help()
{
printf("\nFilter Test Harness\n\n"
"List of commands:\n %-32s%s\n %-32s%s\n %-32s%s\n %-32s%s\n %-32s%s\n "
"%-32s%s\n %-32s%s\n %-32s%s\n %-32s%s\n %-32s%s\n %-32s%s\n %-32s%s\n "
"%-32s%s\n %-32s%s\n"
,"help","Prints this help message."
,"run","Feeds the contents of the buffer to the filter chain."
,"add <filter name>","Loads a filter and appeds it to the end of the chain."
,"delete <filter name>","Deletes a filter."
,"status","Lists all loaded filters and queries"
,"clear","Clears the filter chain."
,"config <file name>","Loads filter configurations from a file."
,"in <file name>","Source file for the SQL statements."
,"out <file name>","Destination file for the SQL statements. Defaults to stdout if no parameters were passed."
,"threads <number>","Sets the amount of threads to use"
,"sessions <number>","How many sessions to create for each filter. This clears all loaded filters."
,"quiet","Print only error messages."
,"verbose","Print everything."
,"exit","Exit the program"
);
}
void manual_query()
{
char query[1024];
unsigned int qlen;
GWBUF** tmpbuf;
free_buffers();
printf("Enter query: ");
fgets(query,1024,stdin);
qlen = strnlen(query, 1024);
if((tmpbuf = malloc(sizeof(GWBUF*)))== NULL){
printf("Error: cannot allocate enough memory.\n");
MXS_ERROR("Cannot allocate enough memory.\n");
return;
}
instance.buffer = tmpbuf;
instance.buffer_count = 1;
instance.buffer[0] = gwbuf_alloc(qlen + 5);
gwbuf_set_type(instance.buffer[0],GWBUF_TYPE_MYSQL);
memcpy(instance.buffer[0]->sbuf->data + 5,query,qlen);
instance.buffer[0]->sbuf->data[0] = (qlen);
instance.buffer[0]->sbuf->data[1] = (qlen << 8);
instance.buffer[0]->sbuf->data[2] = (qlen << 16);
instance.buffer[0]->sbuf->data[3] = 0x00;
instance.buffer[0]->sbuf->data[4] = 0x03;
}
void print_status()
{
if(instance.head->filter){
printf("Filters currently loaded:\n\n");
FILTERCHAIN* hd = instance.head;
int i = 1;
while(hd->filter){
printf("%d: %s\n", i++, hd->name);
hd = hd->next;
}
}else{
printf("No filters loaded.\n");
}
printf("\n");
if(instance.buffer_count > 0){
printf("%d queries loaded.\n",instance.buffer_count);
}else{
printf("No queries loaded.\n");
}
printf("Using %d threads and %d sessions.\n",instance.thrcount,instance.session_count);
if(instance.infile_name){
printf("Input is read from %s.\n",instance.infile_name);
}
if(instance.outfile_name){
printf("Output is written to %s.\n",instance.outfile_name);
}
}

View File

@ -1,48 +0,0 @@
#include <my_config.h>
#include <mysql.h>
#include <harness.h>
int main(int argc,char** argv)
{
static char* server_options[] = {
"MariaDB Corporation MaxScale",
"--datadir=./",
"--language=./",
"--skip-innodb",
"--default-storage-engine=myisam",
NULL
};
const int num_elements = (sizeof(server_options) / sizeof(char *)) - 1;
static char* server_groups[] = {
"embedded",
"server",
"server",
NULL
};
HARNESS_INSTANCE* inst;
if(mysql_library_init(num_elements, server_options, server_groups)){
printf("Embedded server init failed.\n");
return 1;
}
if(harness_init(argc,argv,&inst) || inst->error){
printf("Error: Initialization failed.\n");
MXS_ERROR("Initialization failed.\n");
mxs_log_finish();
return 1;
}
route_buffers();
if(inst->expected > 0){
return compare_files(inst->outfile,inst->expected);
}
return 0;
}

View File

@ -1,3 +0,0 @@
[Hint]
type=filter
module=hintfilter

View File

@ -1,48 +0,0 @@
select @@server_id; -- maxscale begin route to master|HINT_ROUTE_TO_MASTER
select @@server_id;|HINT_ROUTE_TO_MASTER
select @@server_id; -- maxscale route to server server3|HINT_ROUTE_TO_NAMED_SERVER|server3
select @@server_id;|HINT_ROUTE_TO_MASTER
select @@server_id; -- maxscale end
select @@server_id; -- maxscale named1 prepare route to master
select @@server_id; -- maxscale named1 begin|HINT_ROUTE_TO_MASTER
select @@server_id;|HINT_ROUTE_TO_MASTER
select @@server_id; -- maxscale route to server server3|HINT_ROUTE_TO_NAMED_SERVER|server3
select @@server_id;|HINT_ROUTE_TO_MASTER
select @@server_id; -- maxscale end
select @@server_id; -- maxscale shorthand1 begin route to server server2|HINT_ROUTE_TO_NAMED_SERVER|server2
select @@server_id;|HINT_ROUTE_TO_NAMED_SERVER|server2
select @@server_id; -- maxscale route to server server3|HINT_ROUTE_TO_NAMED_SERVER|server3
select @@server_id;|HINT_ROUTE_TO_NAMED_SERVER|server2
select @@server_id; -- maxscale end
select @@server_id; # maxscale begin route to master|HINT_ROUTE_TO_MASTER
select @@server_id;|HINT_ROUTE_TO_MASTER
select @@server_id; # maxscale route to server server3|HINT_ROUTE_TO_NAMED_SERVER|server3
select @@server_id;|HINT_ROUTE_TO_MASTER
select @@server_id; # maxscale end
select @@server_id; # maxscale named2 prepare route to master
select @@server_id; # maxscale named2 begin|HINT_ROUTE_TO_MASTER
select @@server_id;|HINT_ROUTE_TO_MASTER
select @@server_id; # maxscale route to server server3|HINT_ROUTE_TO_NAMED_SERVER|server3
select @@server_id;|HINT_ROUTE_TO_MASTER
select @@server_id; # maxscale end
select @@server_id; # maxscale shorthand2 begin route to server server2|HINT_ROUTE_TO_NAMED_SERVER|server2
select @@server_id;|HINT_ROUTE_TO_NAMED_SERVER|server2
select @@server_id; # maxscale route to server server3|HINT_ROUTE_TO_NAMED_SERVER|server3
select @@server_id;|HINT_ROUTE_TO_NAMED_SERVER|server2
select @@server_id; # maxscale end
select @@server_id/* maxscale begin route to master */;|HINT_ROUTE_TO_MASTER
select @@server_id;|HINT_ROUTE_TO_MASTER
select @@server_id/* maxscale route to server server3 */;|HINT_ROUTE_TO_NAMED_SERVER|server3
select @@server_id;|HINT_ROUTE_TO_MASTER
select @@server_id/* maxscale end */;
select @@server_id/* maxscale named3 prepare route to master */;
select @@server_id/* maxscale named3 begin */;|HINT_ROUTE_TO_MASTER
select @@server_id;|HINT_ROUTE_TO_MASTER
select @@server_id/* maxscale route to server server3 */;|HINT_ROUTE_TO_NAMED_SERVER|server3
select @@server_id;|HINT_ROUTE_TO_MASTER
select @@server_id/* maxscale end */;
select @@server_id/* maxscale shorthand3 begin route to server server2 */; |HINT_ROUTE_TO_NAMED_SERVER|server2
select @@server_id;|HINT_ROUTE_TO_NAMED_SERVER|server2
select @@server_id/* maxscale route to server server3 */;|HINT_ROUTE_TO_NAMED_SERVER|server3
select @@server_id;|HINT_ROUTE_TO_NAMED_SERVER|server2
select @@server_id/* maxscale end */;

View File

@ -1,48 +0,0 @@
select @@server_id; -- maxscale begin route to master
select @@server_id;
select @@server_id; -- maxscale route to server server3
select @@server_id;
select @@server_id; -- maxscale end
select @@server_id; -- maxscale named1 prepare route to master
select @@server_id; -- maxscale named1 begin
select @@server_id;
select @@server_id; -- maxscale route to server server3
select @@server_id;
select @@server_id; -- maxscale end
select @@server_id; -- maxscale shorthand1 begin route to server server2
select @@server_id;
select @@server_id; -- maxscale route to server server3
select @@server_id;
select @@server_id; -- maxscale end
select @@server_id; # maxscale begin route to master
select @@server_id;
select @@server_id; # maxscale route to server server3
select @@server_id;
select @@server_id; # maxscale end
select @@server_id; # maxscale named2 prepare route to master
select @@server_id; # maxscale named2 begin
select @@server_id;
select @@server_id; # maxscale route to server server3
select @@server_id;
select @@server_id; # maxscale end
select @@server_id; # maxscale shorthand2 begin route to server server2
select @@server_id;
select @@server_id; # maxscale route to server server3
select @@server_id;
select @@server_id; # maxscale end
select @@server_id/* maxscale begin route to master */;
select @@server_id;
select @@server_id/* maxscale route to server server3 */;
select @@server_id;
select @@server_id/* maxscale end */;
select @@server_id/* maxscale named3 prepare route to master */;
select @@server_id/* maxscale named3 begin */;
select @@server_id;
select @@server_id/* maxscale route to server server3 */;
select @@server_id;
select @@server_id/* maxscale end */;
select @@server_id/* maxscale shorthand3 begin route to server server2 */;
select @@server_id;
select @@server_id/* maxscale route to server server3 */;
select @@server_id;
select @@server_id/* maxscale end */;

View File

@ -1,9 +0,0 @@
#! /bin/bash
./harness -q -i hint_testing.input -c hint_testing.cnf -o hint_testing.output -t 1 -s 1 -q &>/dev/null
diff hint_testing.expected hint_testing.output &>/dev/null
if [[ "$?" == "0" ]]
then
echo "PASSED"
else
echo "FAILED"
fi

View File

@ -1 +0,0 @@
SELECT * FROM test_table;

View File

@ -1,5 +0,0 @@
[Regex]
type=filter
module=regexfilter
match=wrong
replace=right

View File

@ -1,3 +0,0 @@
select * from mysql.right;
select right from test.table;
select * from test.table where name='right';

View File

@ -1,3 +0,0 @@
select * from mysql.wrong;
select wrong from test.table;
select * from test.table where name='wrong';

View File

@ -1,4 +0,0 @@
rule union_regex deny regex '.*union.*'
rule dont_delete_everything deny no_where_clause on_queries delete|update
rule no_wildcard deny wildcard
users %@% match any rules union_regex dont_delete_everything no_wildcard

View File

@ -1,86 +0,0 @@
#!/bin/bash
function execute_test()
{
RVAL=$(mysql --connect-timeout=5 -u $USER -p$PWD -h $HOST -P $PORT -e "select 1;"|grep -i error)
if [[ ! -e $MAXPID ]]
then
echo "Test failed: $MAXPID was not found."
return 1
fi
if [[ "$RVAL" != "" ]]
then
echo "Test failed: Query to backend didn't return an error."
return 1
fi
LAST_LOG=$(ls $BINDIR/ -1|grep error|sort|uniq|tail -n 1)
TEST_RESULT=$(cat $BINDIR/$LAST_LOG | grep -i recursive)
if [[ "$TEST_RESULT" != "" ]]
then
return 0
fi
echo "Test failed: Log file didn't mention tee recursion."
return 1
}
function reload_conf()
{
$BINDIR/bin/maxadmin --user=admin --password=mariadb reload config
if [[ $? -ne 0 ]]
then
echo "Test failed: maxadmin returned a non-zero value."
return 1
fi
return 0
}
if [[ $# -lt 6 ]]
then
echo "usage: $0 <build dir> <source dir>"
exit 1
fi
BINDIR=$1
SRCDIR=$2
USER=$3
PWD=$4
HOST=$5
PORT=$6
CONF=$BINDIR/etc/maxscale.cnf
OLDCONF=$BINDIR/etc/maxscale.cnf.old
MAXPID=$BINDIR/log/$(ls -1 $BINDIR/log|grep maxscale)
TEST1=$SRCDIR/server/modules/filter/test/tee_recursion1.cnf
TEST2=$SRCDIR/server/modules/filter/test/tee_recursion2.cnf
$BINDIR/bin/maxadmin --user=admin --password=mariadb flush logs
mv $CONF $OLDCONF
cp $TEST1 $CONF
reload_conf
execute_test
T1RVAL=$?
mv $CONF $CONF.test1
cp $TEST2 $CONF
reload_conf
execute_test
T2RVAL=$?
mv $CONF $CONF.test2
mv $OLDCONF $CONF
reload_conf
if [[ $T1RVAL -ne 0 ]]
then
echo "Test 1 failed."
exit 1
elif [[ $T2RVAL -ne 0 ]]
then
echo "Test 2 failed"
exit 1
else
echo "Test successful: log mentions recursive tee usage."
fi
exit 0

View File

@ -1,114 +0,0 @@
[maxscale]
threads=4
[MySQL Monitor]
type=monitor
module=mysqlmon
servers=server1,server2,server3,server4
user=maxuser
passwd=maxpwd
monitor_interval=10000
[RW Split Router]
type=service
router=readwritesplit
servers=server1,server2,server3,server4
user=maxuser
passwd=maxpwd
filters=recurse1
[RW Split Hint Router]
type=service
router=readwritesplit
servers=server1,server2,server3,server4
user=maxuser
passwd=maxpwd
filters=recurse2
[Read Connection Router]
type=service
router=readconnroute
router_options=master
servers=server1
user=maxuser
passwd=maxpwd
filters=recurse3
[recurse3]
type=filter
module=tee
service=RW Split Router
[recurse2]
type=filter
module=tee
service=Read Connection Router
[recurse1]
type=filter
module=tee
service=RW Split Hint Router
[Debug Interface]
type=service
router=debugcli
[CLI]
type=service
router=cli
[Read Connection Listener]
type=listener
service=Read Connection Router
protocol=MySQLClient
port=4008
[RW Split Listener]
type=listener
service=RW Split Router
protocol=MySQLClient
port=4006
[RW Split Hint Listener]
type=listener
service=RW Split Hint Router
protocol=MySQLClient
port=4009
[Debug Listener]
type=listener
service=Debug Interface
protocol=telnetd
port=4442
[CLI Listener]
type=listener
service=CLI
protocol=maxscaled
port=6603
[server1]
type=server
address=127.0.0.1
port=3000
protocol=MySQLBackend
[server2]
type=server
address=127.0.0.1
port=3001
protocol=MySQLBackend
[server3]
type=server
address=127.0.0.1
port=3002
protocol=MySQLBackend
[server4]
type=server
address=127.0.0.1
port=3003
protocol=MySQLBackend

View File

@ -1,112 +0,0 @@
[maxscale]
threads=4
[MySQL Monitor]
type=monitor
module=mysqlmon
servers=server1,server2,server3,server4
user=maxuser
passwd=maxpwd
monitor_interval=10000
[RW Split Router]
type=service
router=readwritesplit
servers=server1,server2,server3,server4
user=maxuser
passwd=maxpwd
filters=recurse1|recurse2
[RW Split Hint Router]
type=service
router=readwritesplit
servers=server1,server2,server3,server4
user=maxuser
passwd=maxpwd
[Read Connection Router]
type=service
router=readconnroute
router_options=master
servers=server1
user=maxuser
passwd=maxpwd
filters=recurse3
[recurse3]
type=filter
module=tee
service=RW Split Router
[recurse2]
type=filter
module=tee
service=Read Connection Router
[recurse1]
type=filter
module=tee
service=RW Split Hint Router
[Debug Interface]
type=service
router=debugcli
[CLI]
type=service
router=cli
[Read Connection Listener]
type=listener
service=Read Connection Router
protocol=MySQLClient
port=4008
[RW Split Listener]
type=listener
service=RW Split Router
protocol=MySQLClient
port=4006
[RW Split Hint Listener]
type=listener
service=RW Split Hint Router
protocol=MySQLClient
port=4009
[Debug Listener]
type=listener
service=Debug Interface
protocol=telnetd
port=4442
[CLI Listener]
type=listener
service=CLI
protocol=maxscaled
port=6603
[server1]
type=server
address=127.0.0.1
port=3000
protocol=MySQLBackend
[server2]
type=server
address=127.0.0.1
port=3001
protocol=MySQLBackend
[server3]
type=server
address=127.0.0.1
port=3002
protocol=MySQLBackend
[server4]
type=server
address=127.0.0.1
port=3003
protocol=MySQLBackend

View File

@ -1,11 +0,0 @@
#! /bin/bash
if [[ $# -lt 4 ]]
then
echo "Usage: $0 <config file> <input> <output> <expected>"
exit 1
fi
TESTDIR=@CMAKE_CURRENT_BINARY_DIR@
SRCDIR=@CMAKE_CURRENT_SOURCE_DIR@
$TESTDIR/harness -i $SRCDIR/$2 -o $TESTDIR/$3 -c $TESTDIR/$1 -t 1 -s 1 -e $SRCDIR/$4
exit $?

View File

@ -4,7 +4,7 @@
* Use of this software is governed by the Business Source License included
* in the LICENSE.TXT file and at www.mariadb.com/bsl.
*
* Change Date: 2019-01-01
* 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
@ -12,6 +12,7 @@
*/
#include <stdio.h>
#include <filter.h>
#include <maxscale/alloc.h>
#include <modinfo.h>
#include <modutil.h>
#include <atomic.h>
@ -128,7 +129,7 @@ createInstance(char **options, FILTER_PARAMETER **params)
{
TEST_INSTANCE *my_instance;
if ((my_instance = calloc(1, sizeof(TEST_INSTANCE))) != NULL)
if ((my_instance = MXS_CALLOC(1, sizeof(TEST_INSTANCE))) != NULL)
{
my_instance->sessions = 0;
}
@ -148,7 +149,7 @@ newSession(FILTER *instance, SESSION *session)
TEST_INSTANCE *my_instance = (TEST_INSTANCE *)instance;
TEST_SESSION *my_session;
if ((my_session = calloc(1, sizeof(TEST_SESSION))) != NULL)
if ((my_session = MXS_CALLOC(1, sizeof(TEST_SESSION))) != NULL)
{
atomic_add(&my_instance->sessions, 1);
my_session->count = 0;
@ -178,7 +179,7 @@ closeSession(FILTER *instance, void *session)
static void
freeSession(FILTER *instance, void *session)
{
free(session);
MXS_FREE(session);
return;
}

View File

@ -4,7 +4,7 @@
* Use of this software is governed by the Business Source License included
* in the LICENSE.TXT file and at www.mariadb.com/bsl.
*
* Change Date: 2019-01-01
* 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
@ -44,6 +44,7 @@
#include <sys/time.h>
#include <regex.h>
#include <atomic.h>
#include <maxscale/alloc.h>
MODULE_INFO info =
{
@ -186,10 +187,9 @@ GetModuleObject()
static FILTER *
createInstance(char **options, FILTER_PARAMETER **params)
{
int i;
TOPN_INSTANCE *my_instance;
TOPN_INSTANCE *my_instance = (TOPN_INSTANCE*)MXS_MALLOC(sizeof(TOPN_INSTANCE));
if ((my_instance = malloc(sizeof(TOPN_INSTANCE))) != NULL)
if (my_instance)
{
my_instance->topN = 10;
my_instance->match = NULL;
@ -199,7 +199,7 @@ createInstance(char **options, FILTER_PARAMETER **params)
my_instance->filebase = NULL;
bool error = false;
for (i = 0; params && params[i]; i++)
for (int i = 0; params && params[i]; i++)
{
if (!strcmp(params[i]->name, "count"))
{
@ -207,23 +207,23 @@ createInstance(char **options, FILTER_PARAMETER **params)
}
else if (!strcmp(params[i]->name, "filebase"))
{
my_instance->filebase = strdup(params[i]->value);
my_instance->filebase = MXS_STRDUP_A(params[i]->value);
}
else if (!strcmp(params[i]->name, "match"))
{
my_instance->match = strdup(params[i]->value);
my_instance->match = MXS_STRDUP_A(params[i]->value);
}
else if (!strcmp(params[i]->name, "exclude"))
{
my_instance->exclude = strdup(params[i]->value);
my_instance->exclude = MXS_STRDUP_A(params[i]->value);
}
else if (!strcmp(params[i]->name, "source"))
{
my_instance->source = strdup(params[i]->value);
my_instance->source = MXS_STRDUP_A(params[i]->value);
}
else if (!strcmp(params[i]->name, "user"))
{
my_instance->user = strdup(params[i]->value);
my_instance->user = MXS_STRDUP_A(params[i]->value);
}
else if (!filter_standard_parameter(params[i]->name))
{
@ -237,7 +237,7 @@ createInstance(char **options, FILTER_PARAMETER **params)
if (options)
{
for (i = 0; options[i]; i++)
for (int i = 0; options[i]; i++)
{
if (!strcasecmp(options[i], "ignorecase"))
{
@ -274,7 +274,7 @@ createInstance(char **options, FILTER_PARAMETER **params)
" for the 'match' parameter.",
my_instance->match);
regfree(&my_instance->re);
free(my_instance->match);
MXS_FREE(my_instance->match);
my_instance->match = NULL;
error = true;
}
@ -285,7 +285,7 @@ createInstance(char **options, FILTER_PARAMETER **params)
" for the 'nomatch' parameter.\n",
my_instance->exclude);
regfree(&my_instance->exre);
free(my_instance->exclude);
MXS_FREE(my_instance->exclude);
my_instance->exclude = NULL;
error = true;
}
@ -295,17 +295,17 @@ createInstance(char **options, FILTER_PARAMETER **params)
if (my_instance->exclude)
{
regfree(&my_instance->exre);
free(my_instance->exclude);
MXS_FREE(my_instance->exclude);
}
if (my_instance->match)
{
regfree(&my_instance->re);
free(my_instance->match);
MXS_FREE(my_instance->match);
}
free(my_instance->filebase);
free(my_instance->source);
free(my_instance->user);
free(my_instance);
MXS_FREE(my_instance->filebase);
MXS_FREE(my_instance->source);
MXS_FREE(my_instance->user);
MXS_FREE(my_instance);
my_instance = NULL;
}
}
@ -329,23 +329,24 @@ newSession(FILTER *instance, SESSION *session)
int i;
char *remote, *user;
if ((my_session = calloc(1, sizeof(TOPN_SESSION))) != NULL)
if ((my_session = MXS_CALLOC(1, sizeof(TOPN_SESSION))) != NULL)
{
if ((my_session->filename =
(char *) malloc(strlen(my_instance->filebase) + 20))
(char *) MXS_MALLOC(strlen(my_instance->filebase) + 20))
== NULL)
{
free(my_session);
MXS_FREE(my_session);
return NULL;
}
sprintf(my_session->filename, "%s.%d", my_instance->filebase,
my_instance->sessions);
atomic_add(&my_instance->sessions, 1);
my_session->top = (TOPNQ **) calloc(my_instance->topN + 1,
sizeof(TOPNQ *));
my_session->top = (TOPNQ **) MXS_CALLOC(my_instance->topN + 1, sizeof(TOPNQ *));
MXS_ABORT_IF_NULL(my_session->top);
for (i = 0; i < my_instance->topN; i++)
{
my_session->top[i] = (TOPNQ *) calloc(1, sizeof(TOPNQ));
my_session->top[i] = (TOPNQ *) MXS_CALLOC(1, sizeof(TOPNQ));
MXS_ABORT_IF_NULL(my_session->top[i]);
my_session->top[i]->sql = NULL;
}
my_session->n_statements = 0;
@ -354,7 +355,7 @@ newSession(FILTER *instance, SESSION *session)
my_session->current = NULL;
if ((remote = session_get_remote(session)) != NULL)
{
my_session->clientHost = strdup(remote);
my_session->clientHost = MXS_STRDUP_A(remote);
}
else
{
@ -362,7 +363,7 @@ newSession(FILTER *instance, SESSION *session)
}
if ((user = session_getUser(session)) != NULL)
{
my_session->userName = strdup(user);
my_session->userName = MXS_STRDUP_A(user);
}
else
{
@ -469,8 +470,8 @@ freeSession(FILTER *instance, void *session)
{
TOPN_SESSION *my_session = (TOPN_SESSION *) session;
free(my_session->filename);
free(session);
MXS_FREE(my_session->filename);
MXS_FREE(session);
return;
}
@ -539,14 +540,14 @@ routeQuery(FILTER *instance, void *session, GWBUF *queue)
my_session->n_statements++;
if (my_session->current)
{
free(my_session->current);
MXS_FREE(my_session->current);
}
gettimeofday(&my_session->start, NULL);
my_session->current = ptr;
}
else
{
free(ptr);
MXS_FREE(ptr);
}
}
}
@ -599,7 +600,7 @@ clientReply(FILTER *instance, void *session, GWBUF *reply)
(diff.tv_sec == my_session->top[my_instance->topN - 1]->duration.tv_sec &&
diff.tv_usec > my_session->top[my_instance->topN - 1]->duration.tv_usec)))
{
free(my_session->top[my_instance->topN - 1]->sql);
MXS_FREE(my_session->top[my_instance->topN - 1]->sql);
my_session->top[my_instance->topN - 1]->sql = my_session->current;
my_session->top[my_instance->topN - 1]->duration = diff;
inserted = 1;
@ -612,7 +613,7 @@ clientReply(FILTER *instance, void *session, GWBUF *reply)
}
else
{
free(my_session->current);
MXS_FREE(my_session->current);
}
my_session->current = NULL;
}