From 55513cc99866ae7125ed786451a7dc37ee5a28d3 Mon Sep 17 00:00:00 2001 From: Markus Makela Date: Sun, 22 Mar 2015 07:44:14 +0200 Subject: [PATCH] Improved modutil_get_complete_packets to only allocate a single buffer. --- server/core/modutil.c | 42 +++++++++++++++++++++++-- server/modules/protocol/mysql_backend.c | 25 +++++++++++++++ 2 files changed, 64 insertions(+), 3 deletions(-) diff --git a/server/core/modutil.c b/server/core/modutil.c index 6362d70a0..f4a0a4e4e 100644 --- a/server/core/modutil.c +++ b/server/core/modutil.c @@ -537,12 +537,48 @@ return_packetbuf: */ GWBUF* modutil_get_complete_packets(GWBUF** p_readbuf) { - GWBUF *buff = NULL, *packet = NULL; + GWBUF *buff = NULL, *packet; + uint8_t *ptr,*end; + unsigned int len,total = 0; + + if(p_readbuf == NULL || (*p_readbuf) == NULL || + gwbuf_length(*p_readbuf) < 3) + return NULL; + + packet = *p_readbuf; + ptr = (uint8_t*)packet->start; + end = (uint8_t*)packet->end; + len = gw_mysql_get_byte3(ptr) + 4; - while((packet = modutil_get_next_MySQL_packet(p_readbuf)) != NULL) + if(ptr + len >= end) + return NULL; + + while(ptr + len < end) { - buff = gwbuf_append(buff,packet); + ptr += len; + total += len; + len = gw_mysql_get_byte3(ptr) + 4; } + + /** Full packets only, return original */ + if(total == gwbuf_length(packet)) + return packet; + + /** The next packet is a partial, split into complete and partial packets */ + total -= len; + + if(buff = gwbuf_alloc(total)) + { + skygw_log_write(LOGFILE_ERROR, + "Error: Failed to allocate new buffer " + " of %d bytes while splitting buffer" + " into complete packets.", + total); + return NULL; + } + + memcpy(buff->start,packet->start,total); + gwbuf_consume(*p_readbuf,total); return buff; } diff --git a/server/modules/protocol/mysql_backend.c b/server/modules/protocol/mysql_backend.c index 2096f937d..7fff6871f 100644 --- a/server/modules/protocol/mysql_backend.c +++ b/server/modules/protocol/mysql_backend.c @@ -493,6 +493,31 @@ static int gw_read_backend_event(DCB *dcb) { ss_dassert(read_buffer != NULL || dcb->dcb_readqueue != NULL); } + read_buffer = gwbuf_append(read_buffer,dcb->dcb_readqueue); + nbytes_read = gwbuf_length(read_buffer); + + if (nbytes_read < 3) + { + dcb->dcb_readqueue = gwbuf_append(dcb->dcb_readqueue, read_buffer); + rc = 0; + goto return_rc; + } + + { + GWBUF *tmp = modutil_get_complete_packets(&read_buffer); + + if(tmp == NULL) + { + dcb->dcb_readqueue = gwbuf_append(dcb->dcb_readqueue, read_buffer); + rc = 0; + goto return_rc; + + } + + dcb->dcb_readqueue = read_buffer; + read_buffer = tmp; + } + /** * If protocol has session command set, concatenate whole * response into one buffer.