tee.c:routeQuery cloned partial MySQL packets to be routed to child router. Problems were due to the use of gwbuf_clone and modutil_MySQL_query which clone/examine only the first buffer from the buffer list which composes GWBUF.
modutil.c: Added function modutil_MySQL_query_len which calculates MySQL packet length and the missing bytecount
This commit is contained in:
VilhoRaatikka 2015-01-02 18:32:57 +02:00
parent 48f443782e
commit 6228be4284
8 changed files with 88 additions and 19 deletions

View File

@ -201,6 +201,36 @@ GWBUF *rval;
return rval;
}
/**
* Clone whole GWBUF list instead of single buffer.
*
* @param buf head of the list to be cloned till the tail of it
*
* @return head of the cloned list or NULL if the list was empty.
*/
GWBUF* gwbuf_clone_all(
GWBUF* buf)
{
GWBUF* rval;
GWBUF* clonebuf;
if (buf == NULL)
{
return NULL;
}
/** Store the head of the list to rval. */
clonebuf = gwbuf_clone(buf);
rval = clonebuf;
while (buf->next)
{
buf = buf->next;
clonebuf->next = gwbuf_clone(buf);
clonebuf = clonebuf->next;
}
return rval;
}
GWBUF *gwbuf_clone_portion(
GWBUF *buf,

View File

@ -121,6 +121,41 @@ unsigned char *ptr;
return 1;
}
/**
* Calculate the length of MySQL packet and how much is missing from the GWBUF
* passed as parameter.
*
* This routine assumes that there is only one MySQL packet in the buffer.
*
* @param buf buffer list including the query, may consist of
* multiple buffers
* @param nbytes_missing pointer to missing bytecount
*
* @return the length of MySQL packet and writes missing bytecount to
* nbytes_missing.
*/
int modutil_MySQL_query_len(
GWBUF* buf,
int* nbytes_missing)
{
int len;
int buflen;
uint8_t data;
if (!modutil_is_SQL(buf))
{
len = 0;
goto retblock;
}
len = MYSQL_GET_PACKET_LEN((uint8_t *)GWBUF_DATA(buf));
*nbytes_missing = len-1;
buflen = gwbuf_length(buf);
*nbytes_missing -= buflen-5;
retblock:
return len;
}
/**
@ -178,7 +213,7 @@ GWBUF *addition;
/**
* Extract the SQL from a COM_QUERY packet and return in a NULL terminated buffer.
* The buffer shoudl be freed by the caller when it is no longer required.
* The buffer should be freed by the caller when it is no longer required.
*
* If the packet is not a COM_QUERY packet then the function will return NULL
*

View File

@ -184,6 +184,7 @@ extern GWBUF *gwbuf_rtrim(GWBUF *head, unsigned int length);
extern unsigned int gwbuf_length(GWBUF *head);
extern GWBUF *gwbuf_clone_portion(GWBUF *head, size_t offset, size_t len);
extern GWBUF *gwbuf_clone_transform(GWBUF *head, gwbuf_type_t type);
extern GWBUF *gwbuf_clone_all(GWBUF* head);
extern void gwbuf_set_type(GWBUF *head, gwbuf_type_t type);
extern int gwbuf_add_property(GWBUF *buf, char *name, char *value);
extern char *gwbuf_get_property(GWBUF *buf, char *name);
@ -195,7 +196,6 @@ void gwbuf_add_buffer_object(GWBUF* buf,
void* data,
void (*donefun_fp)(void *));
void* gwbuf_get_buffer_object_data(GWBUF* buf, bufobj_id_t id);
EXTERN_C_BLOCK_END

View File

@ -42,6 +42,8 @@ extern GWBUF *modutil_replace_SQL(GWBUF *, char *);
extern char *modutil_get_query(GWBUF* buf);
extern int modutil_send_mysql_err_packet(DCB *, int, int, int, const char *, const char *);
GWBUF* modutil_get_next_MySQL_packet(GWBUF** p_readbuf);
int modutil_MySQL_query_len(GWBUF* buf, int* nbytes_missing);
GWBUF *modutil_create_mysql_err_msg(
int packet_number,

View File

@ -737,12 +737,12 @@ char *ptr;
int length, rval, residual = 0;
GWBUF *clone = NULL;
if (my_session->branch_session && my_session->branch_session->state == SESSION_STATE_ROUTER_READY)
if (my_session->branch_session &&
my_session->branch_session->state == SESSION_STATE_ROUTER_READY)
{
if (my_session->residual)
{
clone = gwbuf_clone(queue);
clone = gwbuf_clone_all(queue);
if (my_session->residual < GWBUF_LENGTH(clone))
{
@ -764,22 +764,22 @@ GWBUF *clone = NULL;
{
char *dummy;
modutil_MySQL_Query(queue, &dummy, &length, &residual);
clone = gwbuf_clone(queue);
length = modutil_MySQL_query_len(queue, &residual);
clone = gwbuf_clone_all(queue);
my_session->residual = residual;
}
free(ptr);
}
else if (packet_is_required(queue))
{
clone = gwbuf_clone(queue);
clone = gwbuf_clone_all(queue);
}
}
}
/* Pass the query downstream */
rval = my_session->down.routeQuery(my_session->down.instance,
my_session->down.session,
queue);
rval = my_session->down.routeQuery(
my_session->down.instance,
my_session->down.session,
queue);
if (clone)
{
my_session->n_duped++;

View File

@ -668,8 +668,8 @@ int gw_read_client_event(
"%lu [gw_read_client_event] session "
"creation failed. fd %d, "
"state = MYSQL_AUTH_FAILED.",
protocol->owner_dcb->fd,
pthread_self())));
pthread_self(),
protocol->owner_dcb->fd)));
/** Send ERR 1045 to client */
mysql_send_auth_error(

View File

@ -1637,7 +1637,9 @@ mysql_send_auth_error (
* Buffer contains at least one of the following:
* complete [complete] [partial] mysql packet
*
* return pointer to gwbuf containing a complete packet or
* @param p_readbuf Address of read buffer pointer
*
* @return pointer to gwbuf containing a complete packet or
* NULL if no complete packet was found.
*/
GWBUF* gw_MySQL_get_next_packet(

View File

@ -410,12 +410,12 @@ BACKEND *master_host = NULL;
LOGIF(LD, (skygw_log_write(
LOGFILE_DEBUG,
"%lu [newSession] Examine server in port %d with "
"%d connections. Status is %d, "
"%d connections. Status is %s, "
"inst->bitvalue is %d",
pthread_self(),
inst->servers[i]->server->port,
inst->servers[i]->current_connection_count,
inst->servers[i]->server->status,
STRSRVSTATUS(inst->servers[i]->server),
inst->bitmask)));
}
@ -971,7 +971,7 @@ static int handle_state_switch(DCB* dcb,DCB_REASON reason, void * routersession)
SESSION* session = dcb->session;
ROUTER_CLIENT_SES* rses = (ROUTER_CLIENT_SES*)routersession;
SERVICE* service = session->service;
ROUTER* router = service->router;
ROUTER* router = (ROUTER *)service->router;
switch(reason)
{