Fixing errors caused by the merge with develop.
This commit is contained in:
@ -619,182 +619,6 @@ modutil_count_signal_packets(GWBUF *reply, int use_ok, int n_found)
|
|||||||
return(eof + err);
|
return(eof + err);
|
||||||
}
|
}
|
||||||
|
|
||||||
void resultset_free(RESULTSET* rset)
|
|
||||||
{
|
|
||||||
RSET_ROW *row,*tmp;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
row = rset->head;
|
|
||||||
|
|
||||||
while(row)
|
|
||||||
{
|
|
||||||
tmp = row;
|
|
||||||
row = row->next;
|
|
||||||
for(i = 0;i<rset->columns;i++)
|
|
||||||
{
|
|
||||||
free(tmp->data[i]);
|
|
||||||
}
|
|
||||||
free(tmp);
|
|
||||||
}
|
|
||||||
free(rset);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
char* get_lenenc_str(void* data, int* len)
|
|
||||||
{
|
|
||||||
unsigned char* ptr = data;
|
|
||||||
char* rval;
|
|
||||||
long size, offset;
|
|
||||||
|
|
||||||
if(data == NULL || len == NULL)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(*ptr < 251)
|
|
||||||
{
|
|
||||||
size = *ptr;
|
|
||||||
offset = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
switch(*(ptr))
|
|
||||||
{
|
|
||||||
case 0xfb:
|
|
||||||
*len = 1;
|
|
||||||
return NULL;
|
|
||||||
case 0xfc:
|
|
||||||
size = *(ptr + 1) + (*(ptr + 2) << 8);
|
|
||||||
offset = 2;
|
|
||||||
break;
|
|
||||||
case 0xfd:
|
|
||||||
size = *ptr + (*(ptr + 2) << 8) + (*(ptr + 3) << 16);
|
|
||||||
offset = 3;
|
|
||||||
break;
|
|
||||||
case 0xfe:
|
|
||||||
size = *ptr + ((*(ptr + 2) << 8)) + (*(ptr + 3) << 16) +
|
|
||||||
(*(ptr + 4) << 24) + (*(ptr + 5) << 32) + (*(ptr + 6) << 40) +
|
|
||||||
(*(ptr + 7) << 48) + (*(ptr + 8) << 56);
|
|
||||||
offset = 8;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rval = malloc(sizeof(char)*(size+1));
|
|
||||||
if(rval)
|
|
||||||
{
|
|
||||||
memcpy(rval,ptr + offset,size);
|
|
||||||
memset(rval + size,0,1);
|
|
||||||
|
|
||||||
}
|
|
||||||
*len = size + offset;
|
|
||||||
return rval;
|
|
||||||
}
|
|
||||||
|
|
||||||
RESULTSET*
|
|
||||||
modutil_get_rows(GWBUF* buffer)
|
|
||||||
{
|
|
||||||
RESULTSET* result;
|
|
||||||
RSET_ROW* row;
|
|
||||||
int columns,plen,slen,i,offset;
|
|
||||||
unsigned char *ptr,*end;
|
|
||||||
|
|
||||||
if(buffer == NULL)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ptr = (unsigned char*) buffer->start;
|
|
||||||
end = (unsigned char*) buffer->end;
|
|
||||||
|
|
||||||
if(!PTR_IS_RESULTSET(ptr))
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
columns = *(ptr + 4);
|
|
||||||
|
|
||||||
if((result = calloc(1, sizeof(RESULTSET))) == NULL)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
result->columns = columns;
|
|
||||||
|
|
||||||
while(ptr < end)
|
|
||||||
{
|
|
||||||
plen = MYSQL_GET_PACKET_LEN(ptr) + 4;
|
|
||||||
if(PTR_IS_EOF(ptr))
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ptr += plen;
|
|
||||||
}
|
|
||||||
|
|
||||||
ptr += plen;
|
|
||||||
|
|
||||||
while(ptr < end)
|
|
||||||
{
|
|
||||||
|
|
||||||
plen = MYSQL_GET_PACKET_LEN(ptr) + 4;
|
|
||||||
|
|
||||||
if(PTR_IS_EOF(ptr) || PTR_IS_ERR(ptr))
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* The final EOF/ERR packet was found so the result set is parsed.
|
|
||||||
*/
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ptr + plen > end)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* There is a partial packet in the buffer and this is not a complete
|
|
||||||
* result set. This is considered as an error and will cause the
|
|
||||||
* deallocation of the resultset.
|
|
||||||
*/
|
|
||||||
|
|
||||||
resultset_free(result);
|
|
||||||
result = NULL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if((row = calloc(1,sizeof(RSET_ROW))) == NULL)
|
|
||||||
{
|
|
||||||
resultset_free(result);
|
|
||||||
result = NULL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if((row->data = malloc(sizeof(char*)*columns)) == NULL)
|
|
||||||
{
|
|
||||||
free(row);
|
|
||||||
resultset_free(result);
|
|
||||||
result = NULL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
offset = 4;
|
|
||||||
|
|
||||||
for(i = 0;i<columns;i++)
|
|
||||||
{
|
|
||||||
row->data[i] = get_lenenc_str(ptr + offset,&slen);
|
|
||||||
offset += slen;
|
|
||||||
}
|
|
||||||
|
|
||||||
row->next = result->head;
|
|
||||||
result->rows++;
|
|
||||||
result->head = row;
|
|
||||||
|
|
||||||
ptr += plen;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* Create parse error and EPOLLIN event to event queue of the backend DCB.
|
* Create parse error and EPOLLIN event to event queue of the backend DCB.
|
||||||
* When event is notified the error message is processed as error reply and routed
|
* When event is notified the error message is processed as error reply and routed
|
||||||
|
@ -41,17 +41,6 @@
|
|||||||
#define PTR_IS_LOCAL_INFILE(b) (b[4] == 0xfb)
|
#define PTR_IS_LOCAL_INFILE(b) (b[4] == 0xfb)
|
||||||
#define IS_FULL_RESPONSE(buf) (modutil_count_signal_packets(buf,0,0) == 2)
|
#define IS_FULL_RESPONSE(buf) (modutil_count_signal_packets(buf,0,0) == 2)
|
||||||
|
|
||||||
typedef struct rset_row_t{
|
|
||||||
char** data;
|
|
||||||
struct rset_row_t* next;
|
|
||||||
} RSET_ROW;
|
|
||||||
|
|
||||||
typedef struct rset_t{
|
|
||||||
int rows;
|
|
||||||
int columns;
|
|
||||||
RSET_ROW* head;
|
|
||||||
}RESULTSET;
|
|
||||||
|
|
||||||
extern int modutil_is_SQL(GWBUF *);
|
extern int modutil_is_SQL(GWBUF *);
|
||||||
extern int modutil_is_SQL_prepare(GWBUF *);
|
extern int modutil_is_SQL_prepare(GWBUF *);
|
||||||
extern int modutil_extract_SQL(GWBUF *, char **, int *);
|
extern int modutil_extract_SQL(GWBUF *, char **, int *);
|
||||||
@ -74,6 +63,5 @@ GWBUF *modutil_create_mysql_err_msg(
|
|||||||
const char *msg);
|
const char *msg);
|
||||||
|
|
||||||
int modutil_count_signal_packets(GWBUF*,int,int);
|
int modutil_count_signal_packets(GWBUF*,int,int);
|
||||||
void resultset_free(RESULTSET* rset);
|
|
||||||
RESULTSET* modutil_get_rows(GWBUF*);
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -243,6 +243,69 @@ static int hashcmpfun(
|
|||||||
return strcmp(i1,i2);
|
return strcmp(i1,i2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a length encoded string into a C string.
|
||||||
|
* @param data Pointer to the first byte of the string
|
||||||
|
* @param len Pointer to an integer where the length of the string will be stored. On errors this will be set to -1.
|
||||||
|
* @return Pointer to the newly allocated string or NULL if the value is NULL or an error occurred
|
||||||
|
*/
|
||||||
|
char* get_lenenc_str(void* data, int* len)
|
||||||
|
{
|
||||||
|
unsigned char* ptr = (unsigned char*)data;
|
||||||
|
char* rval;
|
||||||
|
long size, offset;
|
||||||
|
|
||||||
|
if(data == NULL || len == NULL)
|
||||||
|
{
|
||||||
|
*len = -1;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(*ptr < 251)
|
||||||
|
{
|
||||||
|
size = *ptr;
|
||||||
|
offset = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch(*(ptr))
|
||||||
|
{
|
||||||
|
case 0xfb:
|
||||||
|
*len = 1;
|
||||||
|
return NULL;
|
||||||
|
case 0xfc:
|
||||||
|
size = *(ptr + 1) + (*(ptr + 2) << 8);
|
||||||
|
offset = 2;
|
||||||
|
break;
|
||||||
|
case 0xfd:
|
||||||
|
size = *ptr + (*(ptr + 2) << 8) + (*(ptr + 3) << 16);
|
||||||
|
offset = 3;
|
||||||
|
break;
|
||||||
|
case 0xfe:
|
||||||
|
size = *ptr + ((*(ptr + 2) << 8)) + (*(ptr + 3) << 16) +
|
||||||
|
(*(ptr + 4) << 24) + (*(ptr + 5) << 32) + (*(ptr + 6) << 40) +
|
||||||
|
(*(ptr + 7) << 48) + (*(ptr + 8) << 56);
|
||||||
|
offset = 8;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rval = malloc(sizeof(char)*(size+1));
|
||||||
|
if(rval)
|
||||||
|
{
|
||||||
|
memcpy(rval,ptr + offset,size);
|
||||||
|
memset(rval + size,0,1);
|
||||||
|
|
||||||
|
}
|
||||||
|
*len = size + offset;
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses a response set to a SHOW DATABASES query and inserts them into the
|
* 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
|
* router client session's database hashtable. The name of the database is used
|
||||||
@ -256,29 +319,47 @@ static int hashcmpfun(
|
|||||||
bool parse_showdb_response(ROUTER_CLIENT_SES* rses, char* target, GWBUF* buf)
|
bool parse_showdb_response(ROUTER_CLIENT_SES* rses, char* target, GWBUF* buf)
|
||||||
{
|
{
|
||||||
bool rval = false;
|
bool rval = false;
|
||||||
RESULTSET* rset;
|
unsigned char* ptr;
|
||||||
RSET_ROW* row;
|
|
||||||
|
|
||||||
if(PTR_IS_RESULTSET(((unsigned char*)buf->start)) &&
|
if(PTR_IS_RESULTSET(((unsigned char*)buf->start)) &&
|
||||||
modutil_count_signal_packets(buf,0,0) == 2)
|
modutil_count_signal_packets(buf,0,0) == 2)
|
||||||
{
|
{
|
||||||
rset = modutil_get_rows(buf);
|
ptr = (unsigned char*)buf->start;
|
||||||
if(rset && rset->columns == 1)
|
|
||||||
{
|
|
||||||
row = rset->head;
|
|
||||||
|
|
||||||
while(row)
|
if(ptr[4] != 1)
|
||||||
{
|
{
|
||||||
if(hashtable_add(rses->dbhash,row->data[0],target))
|
/** Something else came back, discard and return with an error*/
|
||||||
{
|
return false;
|
||||||
skygw_log_write(LOGFILE_TRACE,"schemarouter: <%s, %s>",target,row->data[0]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
row = row->next;
|
/** Skip column definitions */
|
||||||
|
while(!PTR_IS_EOF(ptr))
|
||||||
|
{
|
||||||
|
ptr += gw_mysql_get_byte3(ptr) + 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Skip first EOF packet */
|
||||||
|
ptr += gw_mysql_get_byte3(ptr) + 4;
|
||||||
|
|
||||||
|
while(!PTR_IS_EOF(ptr))
|
||||||
|
{
|
||||||
|
int payloadlen = gw_mysql_get_byte3(ptr);
|
||||||
|
int packetlen = payloadlen + 4;
|
||||||
|
int len = 0;
|
||||||
|
char* data = get_lenenc_str(ptr+4,&len);
|
||||||
|
|
||||||
|
if(data)
|
||||||
|
{
|
||||||
|
if(hashtable_add(rses->dbhash,data,target))
|
||||||
|
{
|
||||||
|
skygw_log_write(LOGFILE_TRACE,"schemarouter: <%s, %s>",target,data);
|
||||||
|
}
|
||||||
|
free(data);
|
||||||
|
}
|
||||||
|
ptr += packetlen;
|
||||||
}
|
}
|
||||||
resultset_free(rset);
|
|
||||||
rval = true;
|
rval = true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return rval;
|
return rval;
|
||||||
|
@ -258,6 +258,69 @@ hashcmpfun(
|
|||||||
return strcmp(i1, i2);
|
return strcmp(i1, i2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a length encoded string into a C string.
|
||||||
|
* @param data Pointer to the first byte of the string
|
||||||
|
* @param len Pointer to an integer where the length of the string will be stored. On errors this will be set to -1.
|
||||||
|
* @return Pointer to the newly allocated string or NULL if the value is NULL or an error occurred
|
||||||
|
*/
|
||||||
|
char* get_lenenc_str(void* data, int* len)
|
||||||
|
{
|
||||||
|
unsigned char* ptr = (unsigned char*)data;
|
||||||
|
char* rval;
|
||||||
|
long size, offset;
|
||||||
|
|
||||||
|
if(data == NULL || len == NULL)
|
||||||
|
{
|
||||||
|
*len = -1;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(*ptr < 251)
|
||||||
|
{
|
||||||
|
size = *ptr;
|
||||||
|
offset = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch(*(ptr))
|
||||||
|
{
|
||||||
|
case 0xfb:
|
||||||
|
*len = 1;
|
||||||
|
return NULL;
|
||||||
|
case 0xfc:
|
||||||
|
size = *(ptr + 1) + (*(ptr + 2) << 8);
|
||||||
|
offset = 2;
|
||||||
|
break;
|
||||||
|
case 0xfd:
|
||||||
|
size = *ptr + (*(ptr + 2) << 8) + (*(ptr + 3) << 16);
|
||||||
|
offset = 3;
|
||||||
|
break;
|
||||||
|
case 0xfe:
|
||||||
|
size = *ptr + ((*(ptr + 2) << 8)) + (*(ptr + 3) << 16) +
|
||||||
|
(*(ptr + 4) << 24) + (*(ptr + 5) << 32) + (*(ptr + 6) << 40) +
|
||||||
|
(*(ptr + 7) << 48) + (*(ptr + 8) << 56);
|
||||||
|
offset = 8;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rval = malloc(sizeof(char)*(size+1));
|
||||||
|
if(rval)
|
||||||
|
{
|
||||||
|
memcpy(rval,ptr + offset,size);
|
||||||
|
memset(rval + size,0,1);
|
||||||
|
|
||||||
|
}
|
||||||
|
*len = size + offset;
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle the result returned from a SHOW DATABASES query. Parse the result set
|
* Handle the result returned from a SHOW DATABASES query. Parse the result set
|
||||||
* and associate these databases to the service that returned them.
|
* and associate these databases to the service that returned them.
|
||||||
@ -270,28 +333,47 @@ bool
|
|||||||
parse_mapping_response(ROUTER_CLIENT_SES* rses, char* target, GWBUF* buf)
|
parse_mapping_response(ROUTER_CLIENT_SES* rses, char* target, GWBUF* buf)
|
||||||
{
|
{
|
||||||
bool rval = false;
|
bool rval = false;
|
||||||
RESULTSET* rset;
|
unsigned char* ptr;
|
||||||
RSET_ROW* row;
|
|
||||||
|
|
||||||
if(PTR_IS_RESULTSET(((unsigned char*) buf->start)) && // TODO: update to handle larger response sets
|
if(PTR_IS_RESULTSET(((unsigned char*)buf->start)) &&
|
||||||
modutil_count_signal_packets(buf, 0, 0) == 2)
|
modutil_count_signal_packets(buf,0,0) == 2)
|
||||||
{
|
{
|
||||||
rset = modutil_get_rows(buf);
|
ptr = (char*)buf->start;
|
||||||
if(rset && rset->columns == 1)
|
|
||||||
{
|
|
||||||
row = rset->head;
|
|
||||||
|
|
||||||
while(row)
|
if(ptr[5] != 1)
|
||||||
{
|
{
|
||||||
if(hashtable_add(rses->dbhash, row->data[0], target))
|
/** Something else came back, discard and return with an error*/
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Skip column definitions */
|
||||||
|
while(!PTR_IS_EOF(ptr))
|
||||||
{
|
{
|
||||||
skygw_log_write(LOGFILE_TRACE,"shardrouter: <%s, %s>",target,row->data[0]);
|
ptr += gw_mysql_get_byte3(ptr) + 4;
|
||||||
}
|
}
|
||||||
row = row->next;
|
|
||||||
|
/** Skip first EOF packet */
|
||||||
|
ptr += gw_mysql_get_byte3(ptr) + 4;
|
||||||
|
|
||||||
|
while(!PTR_IS_EOF(ptr))
|
||||||
|
{
|
||||||
|
int payloadlen = gw_mysql_get_byte3(ptr);
|
||||||
|
int packetlen = payloadlen + 4;
|
||||||
|
int len = 0;
|
||||||
|
char* data = get_lenenc_str(ptr+4,&len);
|
||||||
|
|
||||||
|
if(data)
|
||||||
|
{
|
||||||
|
if(hashtable_add(rses->dbhash,data,target))
|
||||||
|
{
|
||||||
|
skygw_log_write(LOGFILE_TRACE,"shardrouter: <%s, %s>",target,data);
|
||||||
|
}
|
||||||
|
free(data);
|
||||||
|
}
|
||||||
|
ptr += packetlen;
|
||||||
}
|
}
|
||||||
resultset_free(rset);
|
|
||||||
rval = true;
|
rval = true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return rval;
|
return rval;
|
||||||
|
Reference in New Issue
Block a user