From d98dd6e15f88482d58067a93d94c2a53bbff54ce Mon Sep 17 00:00:00 2001 From: Markus Makela Date: Thu, 5 Mar 2015 11:14:12 +0200 Subject: [PATCH] Fixing errors caused by the merge with develop. --- server/core/modutil.c | 176 ------------------ server/include/modutil.h | 14 +- .../routing/schemarouter/schemarouter.c | 117 ++++++++++-- .../routing/schemarouter/shardrouter.c | 128 ++++++++++--- 4 files changed, 205 insertions(+), 230 deletions(-) diff --git a/server/core/modutil.c b/server/core/modutil.c index 5d6e4985f..db4563766 100644 --- a/server/core/modutil.c +++ b/server/core/modutil.c @@ -619,182 +619,6 @@ modutil_count_signal_packets(GWBUF *reply, int use_ok, int n_found) 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;icolumns;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;idata[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. * When event is notified the error message is processed as error reply and routed diff --git a/server/include/modutil.h b/server/include/modutil.h index b8e158c50..b91ccca65 100644 --- a/server/include/modutil.h +++ b/server/include/modutil.h @@ -41,17 +41,6 @@ #define PTR_IS_LOCAL_INFILE(b) (b[4] == 0xfb) #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_prepare(GWBUF *); extern int modutil_extract_SQL(GWBUF *, char **, int *); @@ -74,6 +63,5 @@ GWBUF *modutil_create_mysql_err_msg( const char *msg); int modutil_count_signal_packets(GWBUF*,int,int); -void resultset_free(RESULTSET* rset); -RESULTSET* modutil_get_rows(GWBUF*); + #endif diff --git a/server/modules/routing/schemarouter/schemarouter.c b/server/modules/routing/schemarouter/schemarouter.c index 1fcb94c0c..b1697e4e3 100644 --- a/server/modules/routing/schemarouter/schemarouter.c +++ b/server/modules/routing/schemarouter/schemarouter.c @@ -243,6 +243,69 @@ static int hashcmpfun( 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 * 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 rval = false; - RESULTSET* rset; - RSET_ROW* row; - + unsigned char* ptr; + if(PTR_IS_RESULTSET(((unsigned char*)buf->start)) && modutil_count_signal_packets(buf,0,0) == 2) { - rset = modutil_get_rows(buf); - if(rset && rset->columns == 1) + ptr = (unsigned char*)buf->start; + + if(ptr[4] != 1) { - row = rset->head; - - while(row) - { - if(hashtable_add(rses->dbhash,row->data[0],target)) - { - skygw_log_write(LOGFILE_TRACE,"schemarouter: <%s, %s>",target,row->data[0]); - } - - row = row->next; - } - resultset_free(rset); - rval = true; + /** Something else came back, discard and return with an error*/ + return false; } + + /** 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; + } + rval = true; + } return rval; diff --git a/server/modules/routing/schemarouter/shardrouter.c b/server/modules/routing/schemarouter/shardrouter.c index 3dbadcf0b..8345fd977 100644 --- a/server/modules/routing/schemarouter/shardrouter.c +++ b/server/modules/routing/schemarouter/shardrouter.c @@ -258,6 +258,69 @@ hashcmpfun( 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 * and associate these databases to the service that returned them. @@ -269,32 +332,51 @@ hashcmpfun( bool parse_mapping_response(ROUTER_CLIENT_SES* rses, char* target, GWBUF* buf) { - bool rval = false; - RESULTSET* rset; - RSET_ROW* row; + bool rval = false; + unsigned char* ptr; - if(PTR_IS_RESULTSET(((unsigned char*) buf->start)) && // TODO: update to handle larger response sets - modutil_count_signal_packets(buf, 0, 0) == 2) - { - rset = modutil_get_rows(buf); - if(rset && rset->columns == 1) - { - row = rset->head; + if(PTR_IS_RESULTSET(((unsigned char*)buf->start)) && + modutil_count_signal_packets(buf,0,0) == 2) + { + ptr = (char*)buf->start; - while(row) - { - if(hashtable_add(rses->dbhash, row->data[0], target)) - { - skygw_log_write(LOGFILE_TRACE,"shardrouter: <%s, %s>",target,row->data[0]); - } - row = row->next; - } - resultset_free(rset); - rval = true; - } - } + if(ptr[5] != 1) + { + /** Something else came back, discard and return with an error*/ + return false; + } - return rval; + /** 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,"shardrouter: <%s, %s>",target,data); + } + free(data); + } + ptr += packetlen; + } + rval = true; + + } + + return rval; } /**