Merge branch 'develop' into MAX-324
Conflicts: query_classifier/query_classifier.cc
This commit is contained in:
@ -3079,7 +3079,7 @@ static int find_last_seqno(
|
|||||||
|
|
||||||
for (i=0, p=parts; p->sp_string != NULL; i++, p=p->sp_next)
|
for (i=0, p=parts; p->sp_string != NULL; i++, p=p->sp_next)
|
||||||
{
|
{
|
||||||
if (snstr != NULL && i == seqnoidx && strnlen(snstr,NAME_MAX) < NAME_MAX)
|
if (snstr != NULL && i == seqnoidx)
|
||||||
{
|
{
|
||||||
strncat(filename, snstr, NAME_MAX - 1); /*< add sequence number */
|
strncat(filename, snstr, NAME_MAX - 1); /*< add sequence number */
|
||||||
}
|
}
|
||||||
|
@ -1210,7 +1210,124 @@ bool is_drop_table_query(GWBUF* querybuf)
|
|||||||
lex->sql_command == SQLCOM_DROP_TABLE);
|
lex->sql_command == SQLCOM_DROP_TABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void add_str(char** buf, int* buflen, int* bufsize, char* str)
|
||||||
|
{
|
||||||
|
int isize = strlen(str) + 1;
|
||||||
|
if(*buf == NULL || isize + *buflen >= *bufsize)
|
||||||
|
{
|
||||||
|
char *tmp = (char*)calloc((*bufsize) * 2 + isize, sizeof(char));
|
||||||
|
if(tmp){
|
||||||
|
memcpy(tmp,*buf,*bufsize);
|
||||||
|
if(*buf){
|
||||||
|
free(*buf);
|
||||||
|
}
|
||||||
|
*buf = tmp;
|
||||||
|
*bufsize = (*bufsize) * 2 + isize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(*buflen > 0){
|
||||||
|
strcat(*buf," ");
|
||||||
|
}
|
||||||
|
strcat(*buf,str);
|
||||||
|
*buflen += isize;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Returns all the fields that the query affects.
|
||||||
|
* @param buf Buffer to parse
|
||||||
|
* @return Pointer to newly allocated string or NULL if nothing was found
|
||||||
|
*/
|
||||||
|
char* skygw_get_affected_fields(GWBUF* buf)
|
||||||
|
{
|
||||||
|
LEX* lex;
|
||||||
|
int buffsz = 0,bufflen = 0;
|
||||||
|
char* where = NULL;
|
||||||
|
Item* item;
|
||||||
|
Item::Type itype;
|
||||||
|
|
||||||
|
if(!query_is_parsed(buf)){
|
||||||
|
parse_query(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
if((lex = get_lex(buf)) == NULL){
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
lex->current_select = lex->all_selects_list;
|
||||||
|
|
||||||
|
while(lex->current_select)
|
||||||
|
{
|
||||||
|
|
||||||
|
List_iterator<Item> ilist(lex->current_select->item_list);
|
||||||
|
item = (Item*)ilist.next();
|
||||||
|
for (item; item != NULL; item=(Item*)ilist.next())
|
||||||
|
{
|
||||||
|
|
||||||
|
itype = item->type();
|
||||||
|
if(item->name && itype == Item::FIELD_ITEM){
|
||||||
|
add_str(&where,&buffsz,&bufflen,item->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(lex->current_select->where){
|
||||||
|
for (item=lex->current_select->where; item != NULL; item=item->next)
|
||||||
|
{
|
||||||
|
|
||||||
|
itype = item->type();
|
||||||
|
if(item->name && itype == Item::FIELD_ITEM){
|
||||||
|
add_str(&where,&buffsz,&bufflen,item->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(lex->current_select->having){
|
||||||
|
for (item=lex->current_select->having; item != NULL; item=item->next)
|
||||||
|
{
|
||||||
|
|
||||||
|
itype = item->type();
|
||||||
|
if(item->name && itype == Item::FIELD_ITEM){
|
||||||
|
add_str(&where,&buffsz,&bufflen,item->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lex->current_select = lex->current_select->next_select_in_list();
|
||||||
|
}
|
||||||
|
return where;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool skygw_query_has_clause(GWBUF* buf)
|
||||||
|
{
|
||||||
|
LEX* lex;
|
||||||
|
SELECT_LEX* current;
|
||||||
|
bool clause = false;
|
||||||
|
|
||||||
|
if(!query_is_parsed(buf)){
|
||||||
|
parse_query(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
if((lex = get_lex(buf)) == NULL){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
current = lex->all_selects_list;
|
||||||
|
|
||||||
|
while(current)
|
||||||
|
{
|
||||||
|
if(current->where || current->having){
|
||||||
|
clause = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
current = current->next_select_in_list();
|
||||||
|
}
|
||||||
|
return clause;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
* Replace user-provided literals with question marks. Return a copy of the
|
* Replace user-provided literals with question marks. Return a copy of the
|
||||||
* querystr with replacements.
|
* querystr with replacements.
|
||||||
*
|
*
|
||||||
@ -1425,7 +1542,7 @@ static void parsing_info_set_plain_str(
|
|||||||
* @return string representing the query type value
|
* @return string representing the query type value
|
||||||
*/
|
*/
|
||||||
char* skygw_get_qtype_str(
|
char* skygw_get_qtype_str(
|
||||||
skygw_query_type_t qtype)
|
skygw_query_type_t qtype)
|
||||||
{
|
{
|
||||||
int t1 = (int)qtype;
|
int t1 = (int)qtype;
|
||||||
int t2 = 1;
|
int t2 = 1;
|
||||||
@ -1437,27 +1554,27 @@ char* skygw_get_qtype_str(
|
|||||||
* t1 is completely cleared.
|
* t1 is completely cleared.
|
||||||
*/
|
*/
|
||||||
while (t1 != 0)
|
while (t1 != 0)
|
||||||
{
|
{
|
||||||
if (t1&t2)
|
if (t1&t2)
|
||||||
{
|
{
|
||||||
t = (skygw_query_type_t)t2;
|
t = (skygw_query_type_t)t2;
|
||||||
|
|
||||||
if (qtype_str == NULL)
|
if (qtype_str == NULL)
|
||||||
{
|
{
|
||||||
qtype_str = strdup(STRQTYPE(t));
|
qtype_str = strdup(STRQTYPE(t));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
size_t len = strlen(STRQTYPE(t));
|
size_t len = strlen(STRQTYPE(t));
|
||||||
/** reallocate space for delimiter, new string and termination */
|
/** reallocate space for delimiter, new string and termination */
|
||||||
qtype_str = (char *)realloc(qtype_str, strlen(qtype_str)+1+len+1);
|
qtype_str = (char *)realloc(qtype_str, strlen(qtype_str)+1+len+1);
|
||||||
snprintf(qtype_str+strlen(qtype_str), 1+len+1, "|%s", STRQTYPE(t));
|
snprintf(qtype_str+strlen(qtype_str), 1+len+1, "|%s", STRQTYPE(t));
|
||||||
}
|
}
|
||||||
/** Remove found value from t1 */
|
/** Remove found value from t1 */
|
||||||
t1 &= ~t2;
|
t1 &= ~t2;
|
||||||
|
}
|
||||||
|
t2 <<= 1;
|
||||||
}
|
}
|
||||||
t2 <<= 1;
|
|
||||||
}
|
|
||||||
return qtype_str;
|
return qtype_str;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1516,3 +1633,50 @@ retblock:
|
|||||||
*size = i;
|
*size = i;
|
||||||
return databases;
|
return databases;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
skygw_query_op_t query_classifier_get_operation(GWBUF* querybuf)
|
||||||
|
{
|
||||||
|
LEX* lex = get_lex(querybuf);
|
||||||
|
skygw_query_op_t operation;
|
||||||
|
if(lex){
|
||||||
|
switch(lex->sql_command){
|
||||||
|
case SQLCOM_SELECT:
|
||||||
|
operation = QUERY_OP_SELECT;
|
||||||
|
break;
|
||||||
|
case SQLCOM_CREATE_TABLE:
|
||||||
|
operation = QUERY_OP_CREATE_TABLE;
|
||||||
|
break;
|
||||||
|
case SQLCOM_CREATE_INDEX:
|
||||||
|
operation = QUERY_OP_CREATE_INDEX;
|
||||||
|
break;
|
||||||
|
case SQLCOM_ALTER_TABLE:
|
||||||
|
operation = QUERY_OP_ALTER_TABLE;
|
||||||
|
break;
|
||||||
|
case SQLCOM_UPDATE:
|
||||||
|
operation = QUERY_OP_UPDATE;
|
||||||
|
break;
|
||||||
|
case SQLCOM_INSERT:
|
||||||
|
operation = QUERY_OP_INSERT;
|
||||||
|
break;
|
||||||
|
case SQLCOM_INSERT_SELECT:
|
||||||
|
operation = QUERY_OP_INSERT_SELECT;
|
||||||
|
break;
|
||||||
|
case SQLCOM_DELETE:
|
||||||
|
operation = QUERY_OP_DELETE;
|
||||||
|
break;
|
||||||
|
case SQLCOM_TRUNCATE:
|
||||||
|
operation = QUERY_OP_TRUNCATE;
|
||||||
|
break;
|
||||||
|
case SQLCOM_DROP_TABLE:
|
||||||
|
operation = QUERY_OP_DROP_TABLE;
|
||||||
|
break;
|
||||||
|
case SQLCOM_DROP_INDEX:
|
||||||
|
operation = QUERY_OP_DROP_INDEX;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
operation = QUERY_OP_UNDEFINED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return operation;
|
||||||
|
}
|
||||||
|
@ -60,6 +60,20 @@ typedef enum {
|
|||||||
QUERY_TYPE_SHOW_TABLES = 0x400000 /*< Show list of tables */
|
QUERY_TYPE_SHOW_TABLES = 0x400000 /*< Show list of tables */
|
||||||
} skygw_query_type_t;
|
} skygw_query_type_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
QUERY_OP_UNDEFINED = 0,
|
||||||
|
QUERY_OP_SELECT = 1,
|
||||||
|
QUERY_OP_UPDATE = (1 << 1),
|
||||||
|
QUERY_OP_INSERT = (1 << 2),
|
||||||
|
QUERY_OP_DELETE = (1 << 3),
|
||||||
|
QUERY_OP_INSERT_SELECT = (1 << 4),
|
||||||
|
QUERY_OP_TRUNCATE = (1 << 5),
|
||||||
|
QUERY_OP_ALTER_TABLE = (1 << 6),
|
||||||
|
QUERY_OP_CREATE_TABLE = (1 << 7),
|
||||||
|
QUERY_OP_CREATE_INDEX = (1 << 8),
|
||||||
|
QUERY_OP_DROP_TABLE = (1 << 9),
|
||||||
|
QUERY_OP_DROP_INDEX = (1 << 10)
|
||||||
|
}skygw_query_op_t;
|
||||||
|
|
||||||
typedef struct parsing_info_st {
|
typedef struct parsing_info_st {
|
||||||
#if defined(SS_DEBUG)
|
#if defined(SS_DEBUG)
|
||||||
@ -81,7 +95,7 @@ typedef struct parsing_info_st {
|
|||||||
* classify the query.
|
* classify the query.
|
||||||
*/
|
*/
|
||||||
skygw_query_type_t query_classifier_get_type(GWBUF* querybuf);
|
skygw_query_type_t query_classifier_get_type(GWBUF* querybuf);
|
||||||
|
skygw_query_op_t query_classifier_get_operation(GWBUF* querybuf);
|
||||||
/** Free THD context and close MYSQL */
|
/** Free THD context and close MYSQL */
|
||||||
#if defined(NOT_USED)
|
#if defined(NOT_USED)
|
||||||
char* skygw_query_classifier_get_stmtname(GWBUF* buf);
|
char* skygw_query_classifier_get_stmtname(GWBUF* buf);
|
||||||
@ -95,8 +109,9 @@ bool parse_query (GWBUF* querybuf);
|
|||||||
parsing_info_t* parsing_info_init(void (*donefun)(void *));
|
parsing_info_t* parsing_info_init(void (*donefun)(void *));
|
||||||
void parsing_info_done(void* ptr);
|
void parsing_info_done(void* ptr);
|
||||||
bool query_is_parsed(GWBUF* buf);
|
bool query_is_parsed(GWBUF* buf);
|
||||||
|
bool skygw_query_has_clause(GWBUF* buf);
|
||||||
char* skygw_get_qtype_str(skygw_query_type_t qtype);
|
char* skygw_get_qtype_str(skygw_query_type_t qtype);
|
||||||
|
char* skygw_get_affected_fields(GWBUF* buf);
|
||||||
|
|
||||||
EXTERN_C_BLOCK_END
|
EXTERN_C_BLOCK_END
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
#include <buffer.h>
|
#include <buffer.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <mysql_client_server_protocol.h>
|
#include <mysql_client_server_protocol.h>
|
||||||
|
#include <modutil.h>
|
||||||
/**
|
/**
|
||||||
* Check if a GWBUF structure is a MySQL COM_QUERY packet
|
* Check if a GWBUF structure is a MySQL COM_QUERY packet
|
||||||
*
|
*
|
||||||
@ -493,3 +493,39 @@ GWBUF* modutil_get_next_MySQL_packet(
|
|||||||
return_packetbuf:
|
return_packetbuf:
|
||||||
return packetbuf;
|
return packetbuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Count the number of EOF, OK or ERR packets in the buffer.
|
||||||
|
* @param reply Buffer to use
|
||||||
|
* @param use_ok Whether the DEPRECATE_EOF flag is set
|
||||||
|
* @param n_found If there were previous packets found
|
||||||
|
* @return Number of EOF packets
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
modutil_count_signal_packets(GWBUF *reply,int use_ok, int n_found)
|
||||||
|
{
|
||||||
|
unsigned char* ptr = (unsigned char*) reply->start;
|
||||||
|
unsigned char* end = (unsigned char*) reply->end;
|
||||||
|
int pktlen,pkt = 0;
|
||||||
|
|
||||||
|
while(ptr < end)
|
||||||
|
{
|
||||||
|
pktlen = gw_mysql_get_byte3(ptr) + 4;
|
||||||
|
|
||||||
|
if(PTR_IS_ERR(ptr) || (PTR_IS_EOF(ptr) && !use_ok) || (use_ok && PTR_IS_OK(ptr)))
|
||||||
|
{
|
||||||
|
if(n_found)
|
||||||
|
{
|
||||||
|
if(ptr + pktlen >= end)
|
||||||
|
pkt++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pkt++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ptr += pktlen;
|
||||||
|
}
|
||||||
|
return pkt;
|
||||||
|
}
|
||||||
|
@ -34,6 +34,12 @@
|
|||||||
#include <buffer.h>
|
#include <buffer.h>
|
||||||
#include <dcb.h>
|
#include <dcb.h>
|
||||||
|
|
||||||
|
#define PTR_IS_RESULTSET(b) (b[0] == 0x01 && b[1] == 0x0 && b[2] == 0x0 && b[3] == 0x01)
|
||||||
|
#define PTR_IS_EOF(b) (b[0] == 0x05 && b[1] == 0x0 && b[2] == 0x0 && b[4] == 0xfe)
|
||||||
|
#define PTR_IS_OK(b) (b[4] == 0x00)
|
||||||
|
#define PTR_IS_ERR(b) (b[4] == 0xff)
|
||||||
|
#define PTR_IS_LOCAL_INFILE(b) (b[4] == 0xfb)
|
||||||
|
|
||||||
extern int modutil_is_SQL(GWBUF *);
|
extern int modutil_is_SQL(GWBUF *);
|
||||||
extern int modutil_extract_SQL(GWBUF *, char **, int *);
|
extern int modutil_extract_SQL(GWBUF *, char **, int *);
|
||||||
extern int modutil_MySQL_Query(GWBUF *, char **, int *, int *);
|
extern int modutil_MySQL_Query(GWBUF *, char **, int *, int *);
|
||||||
@ -44,7 +50,6 @@ extern int modutil_send_mysql_err_packet(DCB *, int, int, int, const char *, con
|
|||||||
GWBUF* modutil_get_next_MySQL_packet(GWBUF** p_readbuf);
|
GWBUF* modutil_get_next_MySQL_packet(GWBUF** p_readbuf);
|
||||||
int modutil_MySQL_query_len(GWBUF* buf, int* nbytes_missing);
|
int modutil_MySQL_query_len(GWBUF* buf, int* nbytes_missing);
|
||||||
|
|
||||||
|
|
||||||
GWBUF *modutil_create_mysql_err_msg(
|
GWBUF *modutil_create_mysql_err_msg(
|
||||||
int packet_number,
|
int packet_number,
|
||||||
int affected_rows,
|
int affected_rows,
|
||||||
@ -52,4 +57,5 @@ GWBUF *modutil_create_mysql_err_msg(
|
|||||||
const char *statemsg,
|
const char *statemsg,
|
||||||
const char *msg);
|
const char *msg);
|
||||||
|
|
||||||
|
int modutil_count_signal_packets(GWBUF*,int,int);
|
||||||
#endif
|
#endif
|
||||||
|
@ -24,8 +24,13 @@ add_library(topfilter SHARED topfilter.c)
|
|||||||
target_link_libraries(topfilter log_manager utils)
|
target_link_libraries(topfilter log_manager utils)
|
||||||
install(TARGETS topfilter DESTINATION modules)
|
install(TARGETS topfilter DESTINATION modules)
|
||||||
|
|
||||||
|
add_library(fwfilter SHARED fwfilter.c)
|
||||||
|
target_link_libraries(fwfilter log_manager utils query_classifier)
|
||||||
|
install(TARGETS fwfilter DESTINATION modules)
|
||||||
|
|
||||||
|
|
||||||
add_subdirectory(hint)
|
add_subdirectory(hint)
|
||||||
|
|
||||||
if(BUILD_TESTS)
|
if(BUILD_TESTS)
|
||||||
add_subdirectory(test)
|
add_subdirectory(test)
|
||||||
endif()
|
endif()
|
||||||
|
1639
server/modules/filter/fwfilter.c
Normal file
1639
server/modules/filter/fwfilter.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -16,6 +16,9 @@
|
|||||||
* Copyright MariaDB Corporation Ab 2014
|
* Copyright MariaDB Corporation Ab 2014
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "spinlock.h"
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file tee.c A filter that splits the processing pipeline in two
|
* @file tee.c A filter that splits the processing pipeline in two
|
||||||
* @verbatim
|
* @verbatim
|
||||||
@ -78,9 +81,6 @@
|
|||||||
#define PARENT 0
|
#define PARENT 0
|
||||||
#define CHILD 1
|
#define CHILD 1
|
||||||
|
|
||||||
#define PTR_IS_RESULTSET(b) (b[0] == 0x01 && b[1] == 0x0 && b[2] == 0x0 && b[3] == 0x01)
|
|
||||||
#define PTR_IS_EOF(b) (b[4] == 0xfe)
|
|
||||||
|
|
||||||
static unsigned char required_packets[] = {
|
static unsigned char required_packets[] = {
|
||||||
MYSQL_COM_QUIT,
|
MYSQL_COM_QUIT,
|
||||||
MYSQL_COM_INITDB,
|
MYSQL_COM_INITDB,
|
||||||
@ -160,6 +160,9 @@ typedef struct {
|
|||||||
|
|
||||||
FILTER_DEF* dummy_filterdef;
|
FILTER_DEF* dummy_filterdef;
|
||||||
int active; /* filter is active? */
|
int active; /* filter is active? */
|
||||||
|
bool use_ok;
|
||||||
|
bool multipacket;
|
||||||
|
unsigned char command;
|
||||||
bool waiting[2]; /* if the client is waiting for a reply */
|
bool waiting[2]; /* if the client is waiting for a reply */
|
||||||
int eof[2];
|
int eof[2];
|
||||||
int replies[2]; /* Number of queries received */
|
int replies[2]; /* Number of queries received */
|
||||||
@ -220,6 +223,8 @@ orphan_free(void* data)
|
|||||||
{
|
{
|
||||||
if(ptr->session->state == SESSION_STATE_TO_BE_FREED)
|
if(ptr->session->state == SESSION_STATE_TO_BE_FREED)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
if(ptr == allOrphans)
|
if(ptr == allOrphans)
|
||||||
{
|
{
|
||||||
tmp = ptr;
|
tmp = ptr;
|
||||||
@ -236,6 +241,17 @@ orphan_free(void* data)
|
|||||||
tmp = ptr;
|
tmp = ptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The session has been unlinked from all the DCBs and it is ready to be freed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if(ptr->session->state == SESSION_STATE_STOPPING &&
|
||||||
|
ptr->session->refcount == 0 && ptr->session->client == NULL)
|
||||||
|
{
|
||||||
|
ptr->session->state = SESSION_STATE_TO_BE_FREED;
|
||||||
}
|
}
|
||||||
#ifdef SS_DEBUG
|
#ifdef SS_DEBUG
|
||||||
else if(ptr->session->state == SESSION_STATE_STOPPING)
|
else if(ptr->session->state == SESSION_STATE_STOPPING)
|
||||||
@ -577,6 +593,9 @@ char *remote, *userName;
|
|||||||
my_session->branch_session = ses;
|
my_session->branch_session = ses;
|
||||||
my_session->branch_dcb = dcb;
|
my_session->branch_dcb = dcb;
|
||||||
my_session->dummy_filterdef = dummy;
|
my_session->dummy_filterdef = dummy;
|
||||||
|
|
||||||
|
MySQLProtocol* protocol = (MySQLProtocol*)session->client->protocol;
|
||||||
|
my_session->use_ok = protocol->client_capabilities & (1 << 6);
|
||||||
free(dummy_upstream);
|
free(dummy_upstream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -640,15 +659,16 @@ freeSession(FILTER *instance, void *session)
|
|||||||
{
|
{
|
||||||
TEE_SESSION *my_session = (TEE_SESSION *)session;
|
TEE_SESSION *my_session = (TEE_SESSION *)session;
|
||||||
SESSION* ses = my_session->branch_session;
|
SESSION* ses = my_session->branch_session;
|
||||||
|
session_state_t state;
|
||||||
if (ses != NULL)
|
if (ses != NULL)
|
||||||
{
|
{
|
||||||
if (ses->state == SESSION_STATE_ROUTER_READY)
|
state = ses->state;
|
||||||
|
|
||||||
|
if (state == SESSION_STATE_ROUTER_READY)
|
||||||
{
|
{
|
||||||
session_free(ses);
|
session_free(ses);
|
||||||
}
|
}
|
||||||
|
else if (state == SESSION_STATE_TO_BE_FREED)
|
||||||
if (ses->state == SESSION_STATE_TO_BE_FREED)
|
|
||||||
{
|
{
|
||||||
/** Free branch router session */
|
/** Free branch router session */
|
||||||
ses->service->router->freeSession(
|
ses->service->router->freeSession(
|
||||||
@ -660,7 +680,7 @@ SESSION* ses = my_session->branch_session;
|
|||||||
/** This indicates that branch session is not available anymore */
|
/** This indicates that branch session is not available anymore */
|
||||||
my_session->branch_session = NULL;
|
my_session->branch_session = NULL;
|
||||||
}
|
}
|
||||||
else if(ses->state == SESSION_STATE_STOPPING)
|
else if(state == SESSION_STATE_STOPPING)
|
||||||
{
|
{
|
||||||
orphan_session_t* orphan;
|
orphan_session_t* orphan;
|
||||||
if((orphan = malloc(sizeof(orphan_session_t))) == NULL)
|
if((orphan = malloc(sizeof(orphan_session_t))) == NULL)
|
||||||
@ -675,17 +695,14 @@ SESSION* ses = my_session->branch_session;
|
|||||||
allOrphans = orphan;
|
allOrphans = orphan;
|
||||||
spinlock_release(&orphanLock);
|
spinlock_release(&orphanLock);
|
||||||
}
|
}
|
||||||
if(ses->refcount == 0)
|
|
||||||
{
|
|
||||||
ss_dassert(ses->refcount == 0 && ses->client == NULL);
|
|
||||||
ses->state = SESSION_STATE_TO_BE_FREED;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (my_session->dummy_filterdef)
|
if (my_session->dummy_filterdef)
|
||||||
{
|
{
|
||||||
filter_free(my_session->dummy_filterdef);
|
filter_free(my_session->dummy_filterdef);
|
||||||
}
|
}
|
||||||
|
if(my_session->tee_replybuf)
|
||||||
|
gwbuf_free(my_session->tee_replybuf);
|
||||||
free(session);
|
free(session);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -746,7 +763,7 @@ TEE_SESSION *my_session = (TEE_SESSION *)session;
|
|||||||
char *ptr;
|
char *ptr;
|
||||||
int length, rval, residual = 0;
|
int length, rval, residual = 0;
|
||||||
GWBUF *clone = NULL;
|
GWBUF *clone = NULL;
|
||||||
|
unsigned char command = *((unsigned char*)queue->start + 4);
|
||||||
if (my_session->branch_session &&
|
if (my_session->branch_session &&
|
||||||
my_session->branch_session->state == SESSION_STATE_ROUTER_READY)
|
my_session->branch_session->state == SESSION_STATE_ROUTER_READY)
|
||||||
{
|
{
|
||||||
@ -787,10 +804,24 @@ GWBUF *clone = NULL;
|
|||||||
|
|
||||||
ss_dassert(my_session->tee_replybuf == NULL);
|
ss_dassert(my_session->tee_replybuf == NULL);
|
||||||
|
|
||||||
|
switch(command)
|
||||||
|
{
|
||||||
|
case 0x03:
|
||||||
|
case 0x16:
|
||||||
|
case 0x17:
|
||||||
|
case 0x04:
|
||||||
|
case 0x0a:
|
||||||
|
my_session->multipacket = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
my_session->multipacket = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
memset(my_session->replies,0,2*sizeof(int));
|
memset(my_session->replies,0,2*sizeof(int));
|
||||||
memset(my_session->eof,0,2*sizeof(int));
|
memset(my_session->eof,0,2*sizeof(int));
|
||||||
memset(my_session->waiting,0,2*sizeof(bool));
|
memset(my_session->waiting,1,2*sizeof(bool));
|
||||||
|
my_session->command = command;
|
||||||
rval = my_session->down.routeQuery(my_session->down.instance,
|
rval = my_session->down.routeQuery(my_session->down.instance,
|
||||||
my_session->down.session,
|
my_session->down.session,
|
||||||
queue);
|
queue);
|
||||||
@ -827,39 +858,6 @@ GWBUF *clone = NULL;
|
|||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Scans the GWBUF for EOF packets. If two packets for this session have been found
|
|
||||||
* from either the parent or the child branch, mark the response set from that branch as over.
|
|
||||||
* @param session The Tee filter session
|
|
||||||
* @param branch Parent or child branch
|
|
||||||
* @param reply Buffer to scan
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
scan_resultset(TEE_SESSION *session, int branch, GWBUF *reply)
|
|
||||||
{
|
|
||||||
unsigned char* ptr = (unsigned char*) reply->start;
|
|
||||||
unsigned char* end = (unsigned char*) reply->end;
|
|
||||||
int pktlen = 0;
|
|
||||||
|
|
||||||
while(ptr < end)
|
|
||||||
{
|
|
||||||
pktlen = gw_mysql_get_byte3(ptr) + 4;
|
|
||||||
if(PTR_IS_EOF(ptr))
|
|
||||||
{
|
|
||||||
session->eof[branch]++;
|
|
||||||
|
|
||||||
if(session->eof[branch] == 2)
|
|
||||||
{
|
|
||||||
session->waiting[branch] = false;
|
|
||||||
session->eof[branch] = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ptr += pktlen;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The clientReply entry point. This is passed the response buffer
|
* The clientReply entry point. This is passed the response buffer
|
||||||
* to which the filter should be applied. Once processed the
|
* to which the filter should be applied. Once processed the
|
||||||
@ -873,28 +871,49 @@ scan_resultset(TEE_SESSION *session, int branch, GWBUF *reply)
|
|||||||
static int
|
static int
|
||||||
clientReply (FILTER* instance, void *session, GWBUF *reply)
|
clientReply (FILTER* instance, void *session, GWBUF *reply)
|
||||||
{
|
{
|
||||||
int rc, branch;
|
int rc, branch, eof;
|
||||||
TEE_SESSION *my_session = (TEE_SESSION *) session;
|
TEE_SESSION *my_session = (TEE_SESSION *) session;
|
||||||
|
|
||||||
spinlock_acquire(&my_session->tee_lock);
|
spinlock_acquire(&my_session->tee_lock);
|
||||||
|
|
||||||
ss_dassert(my_session->active);
|
ss_dassert(my_session->active);
|
||||||
|
|
||||||
branch = instance == NULL ? CHILD : PARENT;
|
branch = instance == NULL ? CHILD : PARENT;
|
||||||
unsigned char *ptr = (unsigned char*)reply->start;
|
unsigned char *ptr = (unsigned char*)reply->start;
|
||||||
|
|
||||||
if(my_session->replies[branch] == 0)
|
if(my_session->replies[branch] == 0)
|
||||||
{
|
{
|
||||||
if(PTR_IS_RESULTSET(ptr))
|
/* Reply is in a single packet if it is an OK, ERR or LOCAL_INFILE packet.
|
||||||
|
* Otherwise the reply is a result set and the amount of packets is unknown.
|
||||||
|
*/
|
||||||
|
if(PTR_IS_ERR(ptr) || PTR_IS_LOCAL_INFILE(ptr) ||
|
||||||
|
PTR_IS_OK(ptr) || !my_session->multipacket )
|
||||||
{
|
{
|
||||||
my_session->waiting[branch] = true;
|
my_session->waiting[branch] = false;
|
||||||
my_session->eof[branch] = 0;
|
|
||||||
}
|
}
|
||||||
|
#ifdef SS_DEBUG
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ss_dassert(PTR_IS_RESULTSET(ptr));
|
||||||
|
skygw_log_write_flush(LOGFILE_DEBUG,"tee.c: Waiting for a result set from %s session.",branch == PARENT?"parent":"child");
|
||||||
|
}
|
||||||
|
ss_dassert(PTR_IS_ERR(ptr) || PTR_IS_LOCAL_INFILE(ptr)||
|
||||||
|
PTR_IS_OK(ptr) || my_session->waiting[branch] ||
|
||||||
|
!my_session->multipacket);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if(my_session->waiting[branch])
|
if(my_session->waiting[branch])
|
||||||
{
|
{
|
||||||
scan_resultset(my_session,branch,reply);
|
|
||||||
|
eof = modutil_count_signal_packets(reply,my_session->use_ok,my_session->eof[branch] > 0);
|
||||||
|
my_session->eof[branch] += eof;
|
||||||
|
if(my_session->eof[branch] >= 2 ||
|
||||||
|
(my_session->command == 0x04 && my_session->eof[branch] > 0))
|
||||||
|
{
|
||||||
|
ss_dassert(my_session->eof[branch] < 3)
|
||||||
|
my_session->waiting[branch] = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(branch == PARENT)
|
if(branch == PARENT)
|
||||||
@ -913,7 +932,19 @@ clientReply (FILTER* instance, void *session, GWBUF *reply)
|
|||||||
(my_session->branch_session == NULL ||
|
(my_session->branch_session == NULL ||
|
||||||
my_session->waiting[PARENT] ||
|
my_session->waiting[PARENT] ||
|
||||||
(!my_session->waiting[CHILD] && !my_session->waiting[PARENT])))
|
(!my_session->waiting[CHILD] && !my_session->waiting[PARENT])))
|
||||||
{
|
{
|
||||||
|
#ifdef SS_DEBUG
|
||||||
|
skygw_log_write_flush(LOGFILE_DEBUG, "tee.c: Routing buffer '%p' parent(waiting [%s] replies [%d] eof[%d])"
|
||||||
|
" child(waiting [%s] replies[%d] eof [%d])",
|
||||||
|
my_session->tee_replybuf,
|
||||||
|
my_session->waiting[PARENT] ? "true":"false",
|
||||||
|
my_session->replies[PARENT],
|
||||||
|
my_session->eof[PARENT],
|
||||||
|
my_session->waiting[CHILD]?"true":"false",
|
||||||
|
my_session->replies[CHILD],
|
||||||
|
my_session->eof[CHILD]);
|
||||||
|
#endif
|
||||||
|
|
||||||
rc = my_session->up.clientReply (
|
rc = my_session->up.clientReply (
|
||||||
my_session->up.instance,
|
my_session->up.instance,
|
||||||
my_session->up.session,
|
my_session->up.session,
|
||||||
|
@ -11,9 +11,17 @@ add_executable(harness harness_util.c harness_common.c ${CORE})
|
|||||||
target_link_libraries(harness_ui fullcore log_manager utils)
|
target_link_libraries(harness_ui fullcore log_manager utils)
|
||||||
target_link_libraries(harness fullcore)
|
target_link_libraries(harness fullcore)
|
||||||
execute_process(COMMAND ${CMAKE_COMMAND} -E copy ${ERRMSG} ${CMAKE_CURRENT_BINARY_DIR})
|
execute_process(COMMAND ${CMAKE_COMMAND} -E copy ${ERRMSG} ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
add_test(TestHintfilter /bin/sh -c "MAXSCALE_HOME=\"${CMAKE_BINARY_DIR}\" ${CMAKE_CURRENT_BINARY_DIR}/harness -i ${CMAKE_CURRENT_SOURCE_DIR}/hint_testing.input -o ${CMAKE_CURRENT_BINARY_DIR}/hint_testing.output -c ${CMAKE_CURRENT_SOURCE_DIR}/hint_testing.cnf -t 1 -s 1 -e ${CMAKE_CURRENT_SOURCE_DIR}/hint_testing.expected")
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/testdriver.sh ${CMAKE_CURRENT_BINARY_DIR}/testdriver.sh @ONLY)
|
||||||
|
|
||||||
add_test(TestRegexfilter /bin/sh -c "MAXSCALE_HOME=\"${CMAKE_BINARY_DIR}\" ${CMAKE_CURRENT_BINARY_DIR}/harness -i ${CMAKE_CURRENT_SOURCE_DIR}/regextest.input -o ${CMAKE_CURRENT_BINARY_DIR}/regextest.output -c ${CMAKE_CURRENT_SOURCE_DIR}/regextest.cnf -t 1 -s 1 -e ${CMAKE_CURRENT_SOURCE_DIR}/regextest.expected")
|
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
|
add_test(TestTeeRecursion ${CMAKE_CURRENT_SOURCE_DIR}/tee_recursion.sh
|
||||||
${CMAKE_BINARY_DIR}
|
${CMAKE_BINARY_DIR}
|
||||||
@ -22,3 +30,7 @@ add_test(TestTeeRecursion ${CMAKE_CURRENT_SOURCE_DIR}/tee_recursion.sh
|
|||||||
${TEST_PASSWORD}
|
${TEST_PASSWORD}
|
||||||
${TEST_HOST}
|
${TEST_HOST}
|
||||||
${TEST_PORT})
|
${TEST_PORT})
|
||||||
|
|
||||||
|
set_tests_properties(TestHintfilter TestRegexfilter TestFwfilter1 TestFwfilter2 TestTeeRecursion
|
||||||
|
PROPERTIES
|
||||||
|
ENVIRONMENT MAXSCALE_HOME=${CMAKE_BINARY_DIR}/)
|
||||||
|
4
server/modules/filter/test/fwfilter/fwtest.cnf.in
Executable file
4
server/modules/filter/test/fwfilter/fwtest.cnf.in
Executable file
@ -0,0 +1,4 @@
|
|||||||
|
[Firewall]
|
||||||
|
type=filter
|
||||||
|
module=fwfilter
|
||||||
|
rules=@CMAKE_CURRENT_SOURCE_DIR@/rules
|
8
server/modules/filter/test/fwfilter/fwtest.expected
Executable file
8
server/modules/filter/test/fwfilter/fwtest.expected
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
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;
|
10
server/modules/filter/test/fwfilter/fwtest.input
Executable file
10
server/modules/filter/test/fwfilter/fwtest.input
Executable file
@ -0,0 +1,10 @@
|
|||||||
|
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;
|
8
server/modules/filter/test/fwfilter/fwtest.output
Executable file
8
server/modules/filter/test/fwfilter/fwtest.output
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
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;
|
8
server/modules/filter/test/fwfilter/fwtest2.expected
Executable file
8
server/modules/filter/test/fwfilter/fwtest2.expected
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
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;
|
10
server/modules/filter/test/fwfilter/fwtest2.input
Executable file
10
server/modules/filter/test/fwfilter/fwtest2.input
Executable file
@ -0,0 +1,10 @@
|
|||||||
|
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;
|
@ -10,7 +10,7 @@ int dcbfun(struct dcb* dcb, GWBUF * buffer)
|
|||||||
int harness_init(int argc, char** argv, HARNESS_INSTANCE** inst){
|
int harness_init(int argc, char** argv, HARNESS_INSTANCE** inst){
|
||||||
|
|
||||||
|
|
||||||
int i = 0;
|
int i = 0,rval = 0;
|
||||||
MYSQL_session* mysqlsess;
|
MYSQL_session* mysqlsess;
|
||||||
DCB* dcb;
|
DCB* dcb;
|
||||||
char cwd[1024];
|
char cwd[1024];
|
||||||
@ -60,7 +60,7 @@ int harness_init(int argc, char** argv, HARNESS_INSTANCE** inst){
|
|||||||
skygw_logmanager_init( 3, optstr);
|
skygw_logmanager_init( 3, optstr);
|
||||||
free(optstr);
|
free(optstr);
|
||||||
|
|
||||||
process_opts(argc,argv);
|
rval = process_opts(argc,argv);
|
||||||
|
|
||||||
if(!(instance.thrpool = malloc(instance.thrcount * sizeof(pthread_t)))){
|
if(!(instance.thrpool = malloc(instance.thrcount * sizeof(pthread_t)))){
|
||||||
printf("Error: Out of memory\n");
|
printf("Error: Out of memory\n");
|
||||||
@ -72,10 +72,10 @@ int harness_init(int argc, char** argv, HARNESS_INSTANCE** inst){
|
|||||||
pthread_mutex_lock(&instance.work_mtx);
|
pthread_mutex_lock(&instance.work_mtx);
|
||||||
size_t thr_num = 1;
|
size_t thr_num = 1;
|
||||||
for(i = 0;i<instance.thrcount;i++){
|
for(i = 0;i<instance.thrcount;i++){
|
||||||
pthread_create(&instance.thrpool[i],NULL,(void*)work_buffer,(void*)thr_num++);
|
rval |= pthread_create(&instance.thrpool[i],NULL,(void*)work_buffer,(void*)thr_num++);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
void free_filters()
|
void free_filters()
|
||||||
@ -543,10 +543,14 @@ int load_config( char* fname)
|
|||||||
{
|
{
|
||||||
CONFIG* iter;
|
CONFIG* iter;
|
||||||
CONFIG_ITEM* item;
|
CONFIG_ITEM* item;
|
||||||
int config_ok = 1;
|
int config_ok = 1,inirval;
|
||||||
free_filters();
|
free_filters();
|
||||||
if(ini_parse(fname,handler,instance.conf) < 0){
|
if((inirval = ini_parse(fname,handler,instance.conf)) < 0){
|
||||||
printf("Error parsing configuration file!\n");
|
printf("Error parsing configuration file!\n");
|
||||||
|
if(inirval == -1)
|
||||||
|
printf("Inih file open error.\n");
|
||||||
|
else if(inirval == -2)
|
||||||
|
printf("inih memory error.\n");
|
||||||
skygw_log_write(LOGFILE_ERROR,"Error parsing configuration file!\n");
|
skygw_log_write(LOGFILE_ERROR,"Error parsing configuration file!\n");
|
||||||
config_ok = 0;
|
config_ok = 0;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
@ -991,7 +995,7 @@ GWBUF* gen_packet(PACKET pkt)
|
|||||||
int process_opts(int argc, char** argv)
|
int process_opts(int argc, char** argv)
|
||||||
{
|
{
|
||||||
int fd, buffsize = 1024;
|
int fd, buffsize = 1024;
|
||||||
int rd,rdsz, rval = 0;
|
int rd,rdsz, rval = 0,error;
|
||||||
size_t fsize;
|
size_t fsize;
|
||||||
char *buff = calloc(buffsize,sizeof(char)), *tok = NULL;
|
char *buff = calloc(buffsize,sizeof(char)), *tok = NULL;
|
||||||
|
|
||||||
@ -1071,6 +1075,7 @@ int process_opts(int argc, char** argv)
|
|||||||
free(conf_name);
|
free(conf_name);
|
||||||
}
|
}
|
||||||
conf_name = strdup(optarg);
|
conf_name = strdup(optarg);
|
||||||
|
printf("Configuration: %s\n",optarg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'q':
|
case 'q':
|
||||||
@ -1079,12 +1084,12 @@ int process_opts(int argc, char** argv)
|
|||||||
|
|
||||||
case 's':
|
case 's':
|
||||||
instance.session_count = atoi(optarg);
|
instance.session_count = atoi(optarg);
|
||||||
printf("Sessions: %i ",instance.session_count);
|
printf("Sessions: %i\n",instance.session_count);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 't':
|
case 't':
|
||||||
instance.thrcount = atoi(optarg);
|
instance.thrcount = atoi(optarg);
|
||||||
printf("Threads: %i ",instance.thrcount);
|
printf("Threads: %i\n",instance.thrcount);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'd':
|
case 'd':
|
||||||
@ -1121,7 +1126,7 @@ int process_opts(int argc, char** argv)
|
|||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
if(conf_name && load_config(conf_name)){
|
if(conf_name && (error = load_config(conf_name))){
|
||||||
load_query();
|
load_query();
|
||||||
}else{
|
}else{
|
||||||
instance.running = 0;
|
instance.running = 0;
|
||||||
@ -1129,6 +1134,11 @@ int process_opts(int argc, char** argv)
|
|||||||
free(conf_name);
|
free(conf_name);
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
|
if(!error)
|
||||||
|
{
|
||||||
|
rval = 1;
|
||||||
|
}
|
||||||
|
|
||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +41,8 @@ int main(int argc,char** argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
route_buffers();
|
route_buffers();
|
||||||
if(inst->expected){
|
|
||||||
|
if(inst->expected > 0){
|
||||||
return compare_files(inst->outfile,inst->expected);
|
return compare_files(inst->outfile,inst->expected);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
4
server/modules/filter/test/rules
Normal file
4
server/modules/filter/test/rules
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
rule union_regex deny regex '.*union.*'
|
||||||
|
rule dont_delete_everything deny no_where_clause on_operations delete|update
|
||||||
|
rule no_wildcard deny wildcard
|
||||||
|
users %@% match any rules union_regex dont_delete_everything no_wildcard
|
11
server/modules/filter/test/testdriver.sh
Executable file
11
server/modules/filter/test/testdriver.sh
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
#! /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 $?
|
@ -1494,12 +1494,17 @@ retblock:
|
|||||||
* and lengths have been noticed and counted.
|
* and lengths have been noticed and counted.
|
||||||
* Session commands need to be marked so that they can be handled properly in
|
* Session commands need to be marked so that they can be handled properly in
|
||||||
* the router's clientReply.
|
* the router's clientReply.
|
||||||
* Return the pointer to outbuf.
|
*
|
||||||
|
* @param dcb Backend's DCB where data was read from
|
||||||
|
* @param readbuf GWBUF where data was read to
|
||||||
|
* @param nbytes_to_process Number of bytes that has been read and need to be processed
|
||||||
|
*
|
||||||
|
* @return GWBUF which includes complete MySQL packet
|
||||||
*/
|
*/
|
||||||
static GWBUF* process_response_data (
|
static GWBUF* process_response_data (
|
||||||
DCB* dcb,
|
DCB* dcb,
|
||||||
GWBUF* readbuf,
|
GWBUF* readbuf,
|
||||||
int nbytes_to_process) /*< number of new bytes read */
|
int nbytes_to_process)
|
||||||
{
|
{
|
||||||
int npackets_left = 0; /*< response's packet count */
|
int npackets_left = 0; /*< response's packet count */
|
||||||
ssize_t nbytes_left = 0; /*< nbytes to be read for the packet */
|
ssize_t nbytes_left = 0; /*< nbytes to be read for the packet */
|
||||||
|
Reference in New Issue
Block a user