Merge branch 'develop' into MAX-324
Conflicts: server/include/modutil.h
This commit is contained in:
@ -253,7 +253,9 @@ char* admin_remove_user(
|
||||
/**
|
||||
* Open passwd file and remove user from the file.
|
||||
*/
|
||||
if ((home = getenv("MAXSCALE_HOME")) != NULL && strlen(home) < 1024) {
|
||||
if ((home = getenv("MAXSCALE_HOME")) != NULL &&
|
||||
strnlen(home,PATH_MAX) < PATH_MAX &&
|
||||
strnlen(home,PATH_MAX) > 0) {
|
||||
sprintf(fname, "%s/etc/passwd", home);
|
||||
sprintf(fname_tmp, "%s/etc/passwd_tmp", home);
|
||||
} else {
|
||||
|
@ -558,7 +558,7 @@ GWBUF* modutil_get_complete_packets(GWBUF** p_readbuf)
|
||||
* @return Number of EOF packets
|
||||
*/
|
||||
int
|
||||
modutil_count_signal_packets(GWBUF *reply, int use_ok, int n_found)
|
||||
modutil_count_signal_packets(GWBUF *reply, int use_ok, int n_found, int* more)
|
||||
{
|
||||
unsigned char* ptr = (unsigned char*) reply->start;
|
||||
unsigned char* end = (unsigned char*) reply->end;
|
||||
@ -566,6 +566,7 @@ modutil_count_signal_packets(GWBUF *reply, int use_ok, int n_found)
|
||||
int pktlen, eof = 0, err = 0;
|
||||
int errlen = 0, eoflen = 0;
|
||||
int iserr = 0, iseof = 0;
|
||||
bool moreresults = false;
|
||||
while(ptr < end)
|
||||
{
|
||||
|
||||
@ -585,8 +586,9 @@ modutil_count_signal_packets(GWBUF *reply, int use_ok, int n_found)
|
||||
}
|
||||
}
|
||||
|
||||
if((ptr + pktlen) > end)
|
||||
if((ptr + pktlen) > end || (eof + n_found) >= 2)
|
||||
{
|
||||
moreresults = PTR_EOF_MORE_RESULTS(ptr);
|
||||
ptr = prev;
|
||||
break;
|
||||
}
|
||||
@ -616,6 +618,8 @@ modutil_count_signal_packets(GWBUF *reply, int use_ok, int n_found)
|
||||
}
|
||||
}
|
||||
|
||||
*more = moreresults;
|
||||
|
||||
return(eof + err);
|
||||
}
|
||||
|
||||
@ -693,3 +697,97 @@ static void modutil_reply_routing_error(
|
||||
poll_add_epollin_event_to_dcb(backend_dcb, buf);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the first occurrence of a character in a string. This function ignores
|
||||
* escaped characters and all characters that are enclosed in single or double quotes.
|
||||
* @param ptr Pointer to area of memory to inspect
|
||||
* @param c Character to search for
|
||||
* @param len Size of the memory area
|
||||
* @return Pointer to the first non-escaped, non-quoted occurrence of the character.
|
||||
* If the character is not found, NULL is returned.
|
||||
*/
|
||||
void* strnchr_esc(char* ptr,char c, int len)
|
||||
{
|
||||
char* p = (char*)ptr;
|
||||
char* start = p;
|
||||
bool quoted = false, escaped = false;
|
||||
char qc;
|
||||
|
||||
while(p < start + len)
|
||||
{
|
||||
if(escaped)
|
||||
{
|
||||
escaped = false;
|
||||
}
|
||||
else if(*p == '\\')
|
||||
{
|
||||
escaped = true;
|
||||
}
|
||||
else if((*p == '\'' || *p == '"') && !quoted)
|
||||
{
|
||||
quoted = true;
|
||||
qc = *p;
|
||||
}
|
||||
else if(quoted && *p == qc)
|
||||
{
|
||||
quoted = false;
|
||||
}
|
||||
else if(*p == c && !escaped && !quoted)
|
||||
{
|
||||
return p;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a COM_QUERY packet from a string.
|
||||
* @param query Query to create.
|
||||
* @return Pointer to GWBUF with the query or NULL if an error occurred.
|
||||
*/
|
||||
GWBUF* modutil_create_query(char* query)
|
||||
{
|
||||
if(query == NULL)
|
||||
return NULL;
|
||||
|
||||
GWBUF* rval = gwbuf_alloc(strlen(query) + 5);
|
||||
int pktlen = strlen(query) + 1;
|
||||
unsigned char* ptr;
|
||||
|
||||
if(rval)
|
||||
{
|
||||
ptr = (unsigned char*)rval->start;
|
||||
*ptr++ = (pktlen);
|
||||
*ptr++ = (pktlen)>>8;
|
||||
*ptr++ = (pktlen)>>16;
|
||||
*ptr++ = 0x0;
|
||||
*ptr++ = 0x03;
|
||||
memcpy(ptr,query,strlen(query));
|
||||
gwbuf_set_type(rval,GWBUF_TYPE_MYSQL);
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Count the number of statements in a query.
|
||||
* @param buffer Buffer to analyze.
|
||||
* @return Number of statements.
|
||||
*/
|
||||
int modutil_count_statements(GWBUF* buffer)
|
||||
{
|
||||
char* ptr = ((char*)(buffer)->start + 5);
|
||||
char* end = ((char*)(buffer)->end);
|
||||
int num = 1;
|
||||
|
||||
while((ptr = strnchr_esc(ptr,';', end - ptr)))
|
||||
{
|
||||
num++;
|
||||
ptr++;
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
@ -73,18 +73,19 @@ resultset_free(RESULTSET *resultset)
|
||||
{
|
||||
RESULT_COLUMN *col;
|
||||
|
||||
if (resultset)
|
||||
return;
|
||||
col = resultset->column;
|
||||
while (col)
|
||||
if (resultset != NULL)
|
||||
{
|
||||
RESULT_COLUMN *next;
|
||||
col = resultset->column;
|
||||
while (col)
|
||||
{
|
||||
RESULT_COLUMN *next;
|
||||
|
||||
next = col->next;
|
||||
resultset_column_free(col);
|
||||
col = next;
|
||||
}
|
||||
free(resultset);
|
||||
}
|
||||
free(resultset);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -42,6 +42,7 @@ static bool success = false;
|
||||
int hup(DCB* dcb)
|
||||
{
|
||||
success = true;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -108,7 +109,8 @@ hkinit();
|
||||
skygw_log_sync_all();
|
||||
ss_info_dassert(0 != result, "Stop should succeed");
|
||||
|
||||
dcb = dcb_alloc(DCB_ROLE_REQUEST_HANDLER);
|
||||
if((dcb = dcb_alloc(DCB_ROLE_REQUEST_HANDLER)) == NULL)
|
||||
return 1;
|
||||
ss_info_dassert(dcb != NULL, "DCB allocation failed");
|
||||
|
||||
session = session_alloc(service,dcb);
|
||||
|
@ -33,6 +33,7 @@
|
||||
*/
|
||||
#include <buffer.h>
|
||||
#include <dcb.h>
|
||||
#include <string.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)
|
||||
@ -40,6 +41,8 @@
|
||||
#define PTR_IS_ERR(b) (b[4] == 0xff)
|
||||
#define PTR_IS_LOCAL_INFILE(b) (b[4] == 0xfb)
|
||||
#define IS_FULL_RESPONSE(buf) (modutil_count_signal_packets(buf,0,0) == 2)
|
||||
#define PTR_EOF_MORE_RESULTS(b) ((PTR_IS_EOF(b) && ptr[7] & 0x08))
|
||||
|
||||
|
||||
extern int modutil_is_SQL(GWBUF *);
|
||||
extern int modutil_is_SQL_prepare(GWBUF *);
|
||||
@ -54,6 +57,8 @@ GWBUF* modutil_get_complete_packets(GWBUF** p_readbuf);
|
||||
int modutil_MySQL_query_len(GWBUF* buf, int* nbytes_missing);
|
||||
void modutil_reply_parse_error(DCB* backend_dcb, char* errstr, uint32_t flags);
|
||||
void modutil_reply_auth_error(DCB* backend_dcb, char* errstr, uint32_t flags);
|
||||
int modutil_count_statements(GWBUF* buffer);
|
||||
GWBUF* modutil_create_query(char* query);
|
||||
|
||||
GWBUF *modutil_create_mysql_err_msg(
|
||||
int packet_number,
|
||||
@ -62,6 +67,5 @@ GWBUF *modutil_create_mysql_err_msg(
|
||||
const char *statemsg,
|
||||
const char *msg);
|
||||
|
||||
int modutil_count_signal_packets(GWBUF*,int,int);
|
||||
|
||||
int modutil_count_signal_packets(GWBUF*,int,int,int*);
|
||||
#endif
|
||||
|
@ -34,9 +34,9 @@ add_library(namedserverfilter SHARED namedserverfilter.c)
|
||||
target_link_libraries(namedserverfilter log_manager utils)
|
||||
install(TARGETS namedserverfilter DESTINATION modules)
|
||||
|
||||
add_library(lagfilter SHARED lagfilter.c)
|
||||
target_link_libraries(lagfilter log_manager utils query_classifier)
|
||||
install(TARGETS lagfilter DESTINATION modules)
|
||||
add_library(slavelag SHARED slavelag.c)
|
||||
target_link_libraries(slavelag log_manager utils query_classifier)
|
||||
install(TARGETS slavelag DESTINATION modules)
|
||||
|
||||
|
||||
add_subdirectory(hint)
|
||||
|
@ -1558,6 +1558,7 @@ bool check_match_any(FW_INSTANCE* my_instance, FW_SESSION* my_session, GWBUF *qu
|
||||
}
|
||||
|
||||
qlen = gw_mysql_get_byte3(memptr);
|
||||
qlen = qlen < 0xffffff ? qlen : 0xffffff;
|
||||
fullquery = malloc((qlen) * sizeof(char));
|
||||
memcpy(fullquery,memptr + 5,qlen - 1);
|
||||
memset(fullquery + qlen - 1,0,1);
|
||||
@ -1612,6 +1613,7 @@ bool check_match_all(FW_INSTANCE* my_instance, FW_SESSION* my_session, GWBUF *qu
|
||||
}
|
||||
|
||||
qlen = gw_mysql_get_byte3(memptr);
|
||||
qlen = qlen < 0xffffff ? qlen : 0xffffff;
|
||||
fullquery = malloc((qlen) * sizeof(char));
|
||||
memcpy(fullquery,memptr + 5,qlen - 1);
|
||||
memset(fullquery + qlen - 1,0,1);
|
||||
|
@ -32,7 +32,7 @@ extern size_t log_ses_count[];
|
||||
extern __thread log_info_t tls_log_info;
|
||||
|
||||
/**
|
||||
* @file lagfilter.c - a very simple filter designed to send queries to the
|
||||
* @file slavelag.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,8 +42,11 @@ extern __thread log_info_t tls_log_info;
|
||||
* is executed:
|
||||
*
|
||||
* count=<number of queries> Queries to route to master after data modification.
|
||||
* time=<time period> Seconds to wait before queries are routed to slaves.
|
||||
* time=<time period> Seconds to wait before queries are routed to slaves.
|
||||
* match=<regex> Regex for matching
|
||||
* ignore=<regex> Regex for ignoring
|
||||
*
|
||||
* The filter also has two options: @c case, which makes the regex case-sensitive, and @c ignorecase, which does the opposite.
|
||||
* Date Who Description
|
||||
* 03/03/2015 Markus Mäkelä Written for demonstrative purposes
|
||||
* @endverbatim
|
||||
@ -333,20 +336,20 @@ time_t now = time(NULL);
|
||||
|
||||
if(query_classifier_get_operation(queue) & (QUERY_OP_DELETE|QUERY_OP_INSERT|QUERY_OP_UPDATE))
|
||||
{
|
||||
sql = modutil_get_SQL(queue);
|
||||
|
||||
if(my_instance->nomatch == NULL||(my_instance->nomatch && regexec(&my_instance->nore,sql,0,NULL,0) != 0))
|
||||
if((sql = modutil_get_SQL(queue)) != NULL)
|
||||
{
|
||||
if(my_instance->match == NULL||
|
||||
(my_instance->match && regexec(&my_instance->re,sql,0,NULL,0) == 0))
|
||||
if(my_instance->nomatch == NULL||(my_instance->nomatch && regexec(&my_instance->nore,sql,0,NULL,0) != 0))
|
||||
{
|
||||
my_session->hints_left = my_instance->count;
|
||||
my_session->last_modification = now;
|
||||
my_instance->stats.n_modified++;
|
||||
if(my_instance->match == NULL||
|
||||
(my_instance->match && regexec(&my_instance->re,sql,0,NULL,0) == 0))
|
||||
{
|
||||
my_session->hints_left = my_instance->count;
|
||||
my_session->last_modification = now;
|
||||
my_instance->stats.n_modified++;
|
||||
}
|
||||
}
|
||||
free(sql);
|
||||
}
|
||||
|
||||
free(sql);
|
||||
}
|
||||
else if(my_session->hints_left > 0)
|
||||
{
|
@ -63,7 +63,6 @@
|
||||
#include <mysql_client_server_protocol.h>
|
||||
#include <housekeeper.h>
|
||||
|
||||
|
||||
#define MYSQL_COM_QUIT 0x01
|
||||
#define MYSQL_COM_INITDB 0x02
|
||||
#define MYSQL_COM_FIELD_LIST 0x04
|
||||
@ -73,6 +72,7 @@
|
||||
#define MYSQL_COM_STMT_SEND_LONG_DATA 0x18
|
||||
#define MYSQL_COM_STMT_CLOSE 0x19
|
||||
#define MYSQL_COM_STMT_RESET 0x1a
|
||||
#define MYSQL_COM_CONNECT 0x1b
|
||||
|
||||
#define REPLY_TIMEOUT_SECOND 5
|
||||
#define REPLY_TIMEOUT_MILLISECOND 1
|
||||
@ -93,6 +93,7 @@ static unsigned char required_packets[] = {
|
||||
MYSQL_COM_STMT_SEND_LONG_DATA,
|
||||
MYSQL_COM_STMT_CLOSE,
|
||||
MYSQL_COM_STMT_RESET,
|
||||
MYSQL_COM_CONNECT,
|
||||
0 };
|
||||
|
||||
/** Defined in log_manager.cc */
|
||||
@ -163,20 +164,28 @@ typedef struct {
|
||||
FILTER_DEF* dummy_filterdef;
|
||||
int active; /* filter is active? */
|
||||
bool use_ok;
|
||||
int client_multistatement;
|
||||
bool multipacket[2];
|
||||
unsigned char command;
|
||||
bool waiting[2]; /* if the client is waiting for a reply */
|
||||
int eof[2];
|
||||
int replies[2]; /* Number of queries received */
|
||||
int reply_packets[2]; /* Number of OK, ERR, LOCAL_INFILE_REQUEST or RESULT_SET packets received */
|
||||
DCB *branch_dcb; /* Client DCB for "branch" service */
|
||||
SESSION *branch_session;/* The branch service session */
|
||||
TEE_INSTANCE *instance;
|
||||
int n_duped; /* Number of duplicated queries */
|
||||
int n_rejected; /* Number of rejected queries */
|
||||
int residual; /* Any outstanding SQL text */
|
||||
GWBUF* tee_replybuf; /* Buffer for reply */
|
||||
GWBUF* tee_partials[2];
|
||||
GWBUF* querybuf;
|
||||
SPINLOCK tee_lock;
|
||||
DCB* client_dcb;
|
||||
int statements; /*< Number of statements in the query,
|
||||
* used to identify and track multi-statement
|
||||
* queries and that both the parent and the child
|
||||
* branch are in sync. */
|
||||
#ifdef SS_DEBUG
|
||||
long d_id;
|
||||
#endif
|
||||
@ -184,7 +193,8 @@ typedef struct {
|
||||
|
||||
typedef struct orphan_session_tt
|
||||
{
|
||||
SESSION* session;
|
||||
SESSION* session; /*< The child branch session whose parent was freed before
|
||||
* the child session was in a suitable state. */
|
||||
struct orphan_session_tt* next;
|
||||
}orphan_session_t;
|
||||
|
||||
@ -198,6 +208,7 @@ static orphan_session_t* allOrphans = NULL;
|
||||
static SPINLOCK orphanLock;
|
||||
static int packet_is_required(GWBUF *queue);
|
||||
static int detect_loops(TEE_INSTANCE *instance, HASHTABLE* ht, SERVICE* session);
|
||||
int internal_route(DCB* dcb);
|
||||
|
||||
static int hkfn(
|
||||
void* key)
|
||||
@ -498,7 +509,12 @@ char *remote, *userName;
|
||||
{
|
||||
my_session->active = 1;
|
||||
my_session->residual = 0;
|
||||
my_session->statements = 0;
|
||||
my_session->tee_replybuf = NULL;
|
||||
my_session->client_dcb = session->client;
|
||||
my_session->instance = my_instance;
|
||||
my_session->client_multistatement = false;
|
||||
|
||||
spinlock_init(&my_session->tee_lock);
|
||||
if (my_instance->source &&
|
||||
(remote = session_get_remote(session)) != NULL)
|
||||
@ -544,7 +560,7 @@ char *remote, *userName;
|
||||
|
||||
goto retblock;
|
||||
}
|
||||
|
||||
|
||||
if((dummy = filter_alloc("tee_dummy","tee_dummy")) == NULL)
|
||||
{
|
||||
dcb_close(dcb);
|
||||
@ -641,6 +657,7 @@ skygw_log_write(LOGFILE_TRACE,"Tee close: %d", atomic_add(&debug_seq,1));
|
||||
#endif
|
||||
if (my_session->active)
|
||||
{
|
||||
|
||||
if ((bsession = my_session->branch_session) != NULL)
|
||||
{
|
||||
CHK_SESSION(bsession);
|
||||
@ -675,7 +692,8 @@ skygw_log_write(LOGFILE_TRACE,"Tee close: %d", atomic_add(&debug_seq,1));
|
||||
}
|
||||
}
|
||||
|
||||
my_session->active = 0;
|
||||
|
||||
my_session->active = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -800,11 +818,14 @@ char *ptr;
|
||||
int length, rval, residual = 0;
|
||||
GWBUF *clone = NULL;
|
||||
unsigned char command = *((unsigned char*)queue->start + 4);
|
||||
|
||||
#ifdef SS_DEBUG
|
||||
skygw_log_write(LOGFILE_TRACE,"Tee routeQuery: %d : %s",
|
||||
atomic_add(&debug_seq,1),
|
||||
((char*)queue->start + 5));
|
||||
#endif
|
||||
|
||||
|
||||
spinlock_acquire(&my_session->tee_lock);
|
||||
|
||||
if(!my_session->active)
|
||||
@ -858,6 +879,8 @@ if(!my_session->active)
|
||||
|
||||
switch(command)
|
||||
{
|
||||
case 0x1b:
|
||||
my_session->client_multistatement = *((unsigned char*) queue->start + 5);
|
||||
case 0x03:
|
||||
case 0x16:
|
||||
case 0x17:
|
||||
@ -871,8 +894,10 @@ if(!my_session->active)
|
||||
}
|
||||
|
||||
memset(my_session->replies,0,2*sizeof(int));
|
||||
memset(my_session->reply_packets,0,2*sizeof(int));
|
||||
memset(my_session->eof,0,2*sizeof(int));
|
||||
memset(my_session->waiting,1,2*sizeof(bool));
|
||||
my_session->statements = modutil_count_statements(queue);
|
||||
my_session->command = command;
|
||||
#ifdef SS_DEBUG
|
||||
spinlock_acquire(&debug_lock);
|
||||
@ -938,6 +963,73 @@ if(!my_session->active)
|
||||
return rval;
|
||||
}
|
||||
|
||||
int count_replies(GWBUF* buffer)
|
||||
{
|
||||
unsigned char* ptr = (unsigned char*)buffer->start;
|
||||
unsigned char* end = (unsigned char*) buffer->end;
|
||||
int pktlen, eof = 0;
|
||||
int replies = 0;
|
||||
while(ptr < end)
|
||||
{
|
||||
pktlen = MYSQL_GET_PACKET_LEN(ptr) + 4;
|
||||
if(PTR_IS_OK(ptr) || PTR_IS_ERR(ptr) || PTR_IS_LOCAL_INFILE(ptr))
|
||||
{
|
||||
replies++;
|
||||
ptr += pktlen;
|
||||
}
|
||||
else
|
||||
{
|
||||
while(ptr < end && eof < 2)
|
||||
{
|
||||
pktlen = MYSQL_GET_PACKET_LEN(ptr) + 4;
|
||||
if(PTR_IS_EOF(ptr) || PTR_IS_ERR(ptr)) eof++;
|
||||
ptr += pktlen;
|
||||
}
|
||||
if(eof == 2) replies++;
|
||||
eof = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return replies;
|
||||
}
|
||||
|
||||
int lenenc_length(uint8_t* ptr)
|
||||
{
|
||||
char val = *ptr;
|
||||
if(val < 251)
|
||||
return 1;
|
||||
else if(val == 0xfc)
|
||||
return 3;
|
||||
else if(val == 0xfd)
|
||||
return 4;
|
||||
else
|
||||
return 9;
|
||||
}
|
||||
|
||||
uint16_t get_response_flags(uint8_t* datastart, bool ok_packet)
|
||||
{
|
||||
uint8_t* ptr = datastart;
|
||||
uint16_t rval = 0;
|
||||
int pktlen = gw_mysql_get_byte3(ptr);
|
||||
|
||||
ptr += 4;
|
||||
|
||||
if(ok_packet)
|
||||
{
|
||||
ptr += lenenc_length(ptr);
|
||||
ptr += lenenc_length(ptr);
|
||||
memcpy(&rval,ptr,sizeof(uint8_t)*2);
|
||||
}
|
||||
else
|
||||
{
|
||||
/** This is an EOF packet*/
|
||||
ptr += 2;
|
||||
memcpy(&rval,ptr,sizeof(uint8_t)*2);
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
/**
|
||||
* The clientReply entry point. This is passed the response buffer
|
||||
* to which the filter should be applied. Once processed the
|
||||
@ -956,7 +1048,9 @@ clientReply (FILTER* instance, void *session, GWBUF *reply)
|
||||
bool route = false,mpkt;
|
||||
GWBUF *complete = NULL;
|
||||
unsigned char *ptr;
|
||||
uint16_t flags = 0;
|
||||
int min_eof = my_session->command != 0x04 ? 2 : 1;
|
||||
int more_results = 0;
|
||||
#ifdef SS_DEBUG
|
||||
ptr = (unsigned char*) reply->start;
|
||||
skygw_log_write(LOGFILE_TRACE,"Tee clientReply [%s] [%s] [%s]: %d",
|
||||
@ -1008,26 +1102,28 @@ clientReply (FILTER* instance, void *session, GWBUF *reply)
|
||||
{
|
||||
my_session->waiting[branch] = false;
|
||||
my_session->multipacket[branch] = false;
|
||||
if(PTR_IS_OK(ptr))
|
||||
{
|
||||
flags = get_response_flags(ptr,true);
|
||||
more_results = (flags & 0x08) && my_session->client_multistatement;
|
||||
}
|
||||
}
|
||||
#ifdef SS_DEBUG
|
||||
else
|
||||
{
|
||||
ss_dassert(PTR_IS_RESULTSET(ptr));
|
||||
skygw_log_write_flush(LOGFILE_DEBUG,"tee.c: [%d] Waiting for a result set from %s session.",
|
||||
my_session->d_id,
|
||||
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])
|
||||
{
|
||||
|
||||
eof = modutil_count_signal_packets(complete,my_session->use_ok,my_session->eof[branch] > 0);
|
||||
eof = modutil_count_signal_packets(complete,my_session->use_ok,my_session->eof[branch] > 0,&more_results);
|
||||
more_results &= my_session->client_multistatement;
|
||||
my_session->eof[branch] += eof;
|
||||
|
||||
if(my_session->eof[branch] >= min_eof)
|
||||
{
|
||||
#ifdef SS_DEBUG
|
||||
@ -1035,27 +1131,27 @@ clientReply (FILTER* instance, void *session, GWBUF *reply)
|
||||
my_session->d_id,
|
||||
branch == PARENT?"parent":"child");
|
||||
#endif
|
||||
ss_dassert(my_session->eof[branch] < 3)
|
||||
my_session->waiting[branch] = false;
|
||||
my_session->waiting[branch] = more_results;
|
||||
if(more_results)
|
||||
{
|
||||
my_session->eof[branch] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(branch == PARENT)
|
||||
{
|
||||
//ss_dassert(my_session->tee_replybuf == NULL);
|
||||
my_session->tee_replybuf = gwbuf_append(my_session->tee_replybuf,complete);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(complete)
|
||||
gwbuf_free(complete);
|
||||
gwbuf_free(complete);
|
||||
}
|
||||
|
||||
my_session->replies[branch]++;
|
||||
rc = 1;
|
||||
mpkt = my_session->multipacket[PARENT] || my_session->multipacket[CHILD];
|
||||
|
||||
|
||||
|
||||
if(my_session->tee_replybuf != NULL)
|
||||
{
|
||||
@ -1074,16 +1170,10 @@ clientReply (FILTER* instance, void *session, GWBUF *reply)
|
||||
if(my_session->waiting[PARENT])
|
||||
{
|
||||
route = true;
|
||||
#ifdef SS_DEBUG
|
||||
ss_dassert(my_session->replies[PARENT] < 2 ||
|
||||
modutil_count_signal_packets(my_session->tee_replybuf,
|
||||
my_session->use_ok,
|
||||
my_session->eof[PARENT]) == 0);
|
||||
skygw_log_write_flush(LOGFILE_DEBUG,"tee.c:[%d] Routing partial response set.",my_session->d_id);
|
||||
#endif
|
||||
|
||||
}
|
||||
else if(my_session->eof[PARENT] == min_eof &&
|
||||
my_session->eof[CHILD] == min_eof)
|
||||
else if(my_session->eof[PARENT] >= min_eof &&
|
||||
my_session->eof[CHILD] >= min_eof)
|
||||
{
|
||||
route = true;
|
||||
#ifdef SS_DEBUG
|
||||
@ -1098,7 +1188,7 @@ clientReply (FILTER* instance, void *session, GWBUF *reply)
|
||||
skygw_log_write_flush(LOGFILE_DEBUG,"tee.c:[%d] Routing single packet response.",my_session->d_id);
|
||||
#endif
|
||||
route = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(route)
|
||||
@ -1236,3 +1326,13 @@ int detect_loops(TEE_INSTANCE *instance,HASHTABLE* ht, SERVICE* service)
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int internal_route(DCB* dcb)
|
||||
{
|
||||
GWBUF* buffer = dcb->dcb_readqueue;
|
||||
|
||||
/** This was set in the newSession function*/
|
||||
TEE_SESSION* session = dcb->data;
|
||||
|
||||
return routeQuery((FILTER*)session->instance,session,buffer);
|
||||
}
|
@ -71,7 +71,7 @@ static void blr_log_header(logfile_id_t file, char *msg, uint8_t *ptr);
|
||||
int
|
||||
blr_file_init(ROUTER_INSTANCE *router)
|
||||
{
|
||||
char *ptr, path[1024], filename[1050];
|
||||
char *ptr, path[1025], filename[1051];
|
||||
int file_found, n = 1;
|
||||
int root_len, i;
|
||||
DIR *dirp;
|
||||
@ -80,12 +80,12 @@ struct dirent *dp;
|
||||
if (router->binlogdir == NULL)
|
||||
{
|
||||
strcpy(path, "/usr/local/skysql/MaxScale");
|
||||
if ((ptr = getenv("MAXSCALE_HOME")) != NULL)
|
||||
if ((ptr = getenv("MAXSCALE_HOME")) != NULL && strnlen(ptr,1025) < 1025)
|
||||
{
|
||||
strcpy(path, ptr);
|
||||
strncpy(path, ptr,PATH_MAX);
|
||||
}
|
||||
strcat(path, "/");
|
||||
strcat(path, router->service->name);
|
||||
strncat(path, "/",1024);
|
||||
strncat(path, router->service->name,1024);
|
||||
|
||||
if (access(path, R_OK) == -1)
|
||||
mkdir(path, 0777);
|
||||
@ -196,7 +196,7 @@ unsigned char magic[] = BINLOG_MAGIC;
|
||||
fsync(fd);
|
||||
close(router->binlog_fd);
|
||||
spinlock_acquire(&router->binlog_lock);
|
||||
strcpy(router->binlog_name, file);
|
||||
strncpy(router->binlog_name, file,BINLOG_FNAMELEN);
|
||||
router->binlog_position = 4; /* Initial position after the magic number */
|
||||
spinlock_release(&router->binlog_lock);
|
||||
router->binlog_fd = fd;
|
||||
@ -230,7 +230,7 @@ int fd;
|
||||
fsync(fd);
|
||||
close(router->binlog_fd);
|
||||
spinlock_acquire(&router->binlog_lock);
|
||||
strcpy(router->binlog_name, file);
|
||||
strncpy(router->binlog_name, file,BINLOG_FNAMELEN);
|
||||
router->binlog_position = lseek(fd, 0L, SEEK_END);
|
||||
spinlock_release(&router->binlog_lock);
|
||||
router->binlog_fd = fd;
|
||||
@ -290,7 +290,7 @@ blr_file_flush(ROUTER_INSTANCE *router)
|
||||
BLFILE *
|
||||
blr_open_binlog(ROUTER_INSTANCE *router, char *binlog)
|
||||
{
|
||||
char path[1024];
|
||||
char path[1025];
|
||||
BLFILE *file;
|
||||
|
||||
spinlock_acquire(&router->fileslock);
|
||||
@ -310,14 +310,14 @@ BLFILE *file;
|
||||
spinlock_release(&router->fileslock);
|
||||
return NULL;
|
||||
}
|
||||
strcpy(file->binlogname, binlog);
|
||||
strncpy(file->binlogname, binlog,BINLOG_FNAMELEN+1);
|
||||
file->refcnt = 1;
|
||||
file->cache = 0;
|
||||
spinlock_init(&file->lock);
|
||||
|
||||
strcpy(path, router->binlogdir);
|
||||
strcat(path, "/");
|
||||
strcat(path, binlog);
|
||||
strncpy(path, router->binlogdir,1024);
|
||||
strncat(path, "/",1024);
|
||||
strncat(path, binlog,1024);
|
||||
|
||||
if ((file->fd = open(path, O_RDONLY, 0666)) == -1)
|
||||
{
|
||||
@ -630,7 +630,7 @@ struct stat statb;
|
||||
void
|
||||
blr_cache_response(ROUTER_INSTANCE *router, char *response, GWBUF *buf)
|
||||
{
|
||||
char path[4096], *ptr;
|
||||
char path[4097], *ptr;
|
||||
int fd;
|
||||
|
||||
strcpy(path, "/usr/local/skysql/MaxScale");
|
||||
|
@ -1228,8 +1228,8 @@ MYSQL_session *auth_info;
|
||||
|
||||
if ((auth_info = calloc(1, sizeof(MYSQL_session))) == NULL)
|
||||
return NULL;
|
||||
strcpy(auth_info->user, username);
|
||||
strcpy(auth_info->db, database);
|
||||
strncpy(auth_info->user, username,MYSQL_USER_MAXLEN+1);
|
||||
strncpy(auth_info->db, database,MYSQL_DATABASE_MAXLEN+1);
|
||||
gw_sha1_str((const uint8_t *)password, strlen(password), auth_info->client_sha1);
|
||||
|
||||
return auth_info;
|
||||
|
@ -385,7 +385,9 @@ char *sql;
|
||||
if (modutil_MySQL_Query(queue, &sql, &len, &residual))
|
||||
{
|
||||
sql = strndup(sql, len);
|
||||
return maxinfo_execute_query(instance, session, sql);
|
||||
int rc = maxinfo_execute_query(instance, session, sql);
|
||||
free(sql);
|
||||
return rc;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -85,6 +85,7 @@ int len;
|
||||
return;
|
||||
sprintf(msg, "%s in query '%s'", desc, sql);
|
||||
maxinfo_send_error(dcb, 1149, msg);
|
||||
free(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -112,7 +113,7 @@ int len;
|
||||
data[4] = 0xff; // Error indicator
|
||||
data[5] = errcode & 0xff; // Error Code
|
||||
data[6] = (errcode >> 8) & 0xff; // Error Code
|
||||
strncpy((char *)&data[7], "#42000", 6);
|
||||
strncpy((char *)&data[13], msg, strlen(msg)); // Error Message
|
||||
memcpy(&data[7], "#42000", 6);
|
||||
memcpy(&data[13], msg, strlen(msg)); // Error Message
|
||||
dcb->func.write(dcb, pkt);
|
||||
}
|
||||
|
@ -735,7 +735,7 @@ exec_select(DCB *dcb, MAXINFO_TREE *tree)
|
||||
static int
|
||||
maxinfo_pattern_match(char *pattern, char *str)
|
||||
{
|
||||
int anchor, len, trailing;
|
||||
int anchor = 0, len, trailing;
|
||||
char *fixed;
|
||||
extern char *strcasestr();
|
||||
|
||||
|
@ -100,6 +100,7 @@ MAXINFO_TREE *col, *table;
|
||||
}
|
||||
}
|
||||
// Malformed show
|
||||
free(text);
|
||||
free_tree(tree);
|
||||
*parse_error = PARSE_MALFORMED_SHOW;
|
||||
return NULL;
|
||||
@ -136,31 +137,35 @@ parse_column_list(char **ptr)
|
||||
int token, lookahead;
|
||||
char *text, *text2;
|
||||
MAXINFO_TREE *tree = NULL;
|
||||
|
||||
MAXINFO_TREE * rval = NULL;
|
||||
*ptr = fetch_token(*ptr, &token, &text);
|
||||
*ptr = fetch_token(*ptr, &lookahead, &text2);
|
||||
switch (token)
|
||||
{
|
||||
case LT_STRING:
|
||||
free(text2);
|
||||
switch (lookahead)
|
||||
{
|
||||
case LT_COMMA:
|
||||
return make_tree_node(MAXOP_COLUMNS, text, NULL,
|
||||
rval = make_tree_node(MAXOP_COLUMNS, text, NULL,
|
||||
parse_column_list(ptr));
|
||||
case LT_FROM:
|
||||
return make_tree_node(MAXOP_COLUMNS, text, NULL,
|
||||
rval = make_tree_node(MAXOP_COLUMNS, text, NULL,
|
||||
NULL);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case LT_STAR:
|
||||
free(text);
|
||||
free(text2);
|
||||
if (lookahead != LT_FROM)
|
||||
return make_tree_node(MAXOP_ALL_COLUMNS, NULL, NULL,
|
||||
rval = make_tree_node(MAXOP_ALL_COLUMNS, NULL, NULL,
|
||||
NULL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
free(text);
|
||||
free(text2);
|
||||
return rval;
|
||||
}
|
||||
|
||||
|
||||
@ -180,6 +185,7 @@ MAXINFO_TREE *tree = NULL;
|
||||
*ptr = fetch_token(*ptr, &token, &text);
|
||||
if (token == LT_STRING)
|
||||
return make_tree_node(MAXOP_TABLE, text, NULL, NULL);
|
||||
free(text);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -305,7 +305,7 @@ char* get_lenenc_str(void* data, int* len)
|
||||
* Parses a response set to a SHOW DATABASES query and inserts them into the
|
||||
* router client session's database hashtable. The name of the database is used
|
||||
* as the key and the unique name of the server is the value. The function
|
||||
* currently supports only result sets that span a single GWBUF.
|
||||
* currently supports only result sets that span a single SQL packet.
|
||||
* @param rses Router client session
|
||||
* @param target Target server where the database is
|
||||
* @param buf GWBUF containing the result set
|
||||
@ -315,9 +315,9 @@ bool parse_showdb_response(ROUTER_CLIENT_SES* rses, char* target, GWBUF* buf)
|
||||
{
|
||||
bool rval = false;
|
||||
unsigned char* ptr;
|
||||
|
||||
int more = 0;
|
||||
if(PTR_IS_RESULTSET(((unsigned char*)buf->start)) &&
|
||||
modutil_count_signal_packets(buf,0,0) == 2)
|
||||
modutil_count_signal_packets(buf,0,0,&more) == 2)
|
||||
{
|
||||
ptr = (unsigned char*)buf->start;
|
||||
|
||||
|
@ -334,9 +334,10 @@ parse_mapping_response(ROUTER_CLIENT_SES* rses, char* target, GWBUF* buf)
|
||||
{
|
||||
bool rval = false;
|
||||
unsigned char* ptr;
|
||||
int more = 0;
|
||||
|
||||
if(PTR_IS_RESULTSET(((unsigned char*)buf->start)) &&
|
||||
modutil_count_signal_packets(buf,0,0) == 2)
|
||||
modutil_count_signal_packets(buf,0,0,&more) == 2)
|
||||
{
|
||||
ptr = (char*)buf->start;
|
||||
|
||||
@ -2988,4 +2989,4 @@ reply_error:
|
||||
}
|
||||
retblock:
|
||||
return succp;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user