Bugzilla #455, MaxScale crashed due missing buffer type information in multi-buffer responses.
This commit is contained in:
@ -317,12 +317,23 @@ gwbuf_trim(GWBUF *buf, unsigned int n_bytes)
|
|||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set given type to all buffers on the list.
|
||||||
|
* *
|
||||||
|
* @param buf The shared buffer
|
||||||
|
* @param type Type to be added
|
||||||
|
*/
|
||||||
void gwbuf_set_type(
|
void gwbuf_set_type(
|
||||||
GWBUF* buf,
|
GWBUF* buf,
|
||||||
gwbuf_type_t type)
|
gwbuf_type_t type)
|
||||||
{
|
{
|
||||||
CHK_GWBUF(buf);
|
/** Set type consistenly to all buffers on the list */
|
||||||
buf->gwbuf_type |= type;
|
while (buf != NULL)
|
||||||
|
{
|
||||||
|
CHK_GWBUF(buf);
|
||||||
|
buf->gwbuf_type |= type;
|
||||||
|
buf=buf->next;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -97,10 +97,13 @@ typedef struct router_object {
|
|||||||
*/
|
*/
|
||||||
#define ROUTER_VERSION { 1, 0, 0 }
|
#define ROUTER_VERSION { 1, 0, 0 }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Router capability type. Indicates what kind of input router accepts.
|
||||||
|
*/
|
||||||
typedef enum router_capability_t {
|
typedef enum router_capability_t {
|
||||||
RCAP_TYPE_UNDEFINED = 0,
|
RCAP_TYPE_UNDEFINED = 0x00,
|
||||||
RCAP_TYPE_STMT_INPUT = (1 << 0),
|
RCAP_TYPE_STMT_INPUT = 0x01, /*< statement per buffer */
|
||||||
RCAP_TYPE_PACKET_INPUT = (1 << 1)
|
RCAP_TYPE_PACKET_INPUT = 0x02 /*< data as it was read from DCB */
|
||||||
} router_capability_t;
|
} router_capability_t;
|
||||||
|
|
||||||
|
|
||||||
|
@ -253,27 +253,30 @@ typedef struct server_command_st {
|
|||||||
struct server_command_st* scom_next;
|
struct server_command_st* scom_next;
|
||||||
} server_command_t;
|
} server_command_t;
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* MySQL Protocol specific state data
|
* MySQL Protocol specific state data.
|
||||||
|
*
|
||||||
|
* Protocol carries information from client side to backend side, such as
|
||||||
|
* MySQL session command information and history of earlier session commands.
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
#if defined(SS_DEBUG)
|
#if defined(SS_DEBUG)
|
||||||
skygw_chk_t protocol_chk_top;
|
skygw_chk_t protocol_chk_top;
|
||||||
#endif
|
#endif
|
||||||
int fd; /*< The socket descriptor */
|
int fd; /*< The socket descriptor */
|
||||||
struct dcb *owner_dcb; /*< The DCB of the socket
|
struct dcb *owner_dcb; /*< The DCB of the socket
|
||||||
* we are running on */
|
* we are running on */
|
||||||
SPINLOCK protocol_lock;
|
SPINLOCK protocol_lock;
|
||||||
server_command_t protocol_command; /*< list of active commands */
|
server_command_t protocol_command; /*< session command list */
|
||||||
server_command_t* protocol_cmd_history; /*< command history list */
|
server_command_t* protocol_cmd_history; /*< session command history */
|
||||||
mysql_auth_state_t protocol_auth_state; /*< Authentication status */
|
mysql_auth_state_t protocol_auth_state; /*< Authentication status */
|
||||||
uint8_t scramble[MYSQL_SCRAMBLE_LEN]; /*< server scramble,
|
uint8_t scramble[MYSQL_SCRAMBLE_LEN]; /*< server scramble,
|
||||||
* created or received */
|
* created or received */
|
||||||
uint32_t server_capabilities; /*< server capabilities,
|
uint32_t server_capabilities; /*< server capabilities,
|
||||||
* created or received */
|
* created or received */
|
||||||
uint32_t client_capabilities; /*< client capabilities,
|
uint32_t client_capabilities; /*< client capabilities,
|
||||||
* created or received */
|
* created or received */
|
||||||
unsigned long tid; /*< MySQL Thread ID, in
|
unsigned long tid; /*< MySQL Thread ID, in
|
||||||
* handshake */
|
* handshake */
|
||||||
#if defined(SS_DEBUG)
|
#if defined(SS_DEBUG)
|
||||||
skygw_chk_t protocol_chk_tail;
|
skygw_chk_t protocol_chk_tail;
|
||||||
|
@ -167,7 +167,7 @@ static int gw_read_backend_event(DCB *dcb) {
|
|||||||
|
|
||||||
backend_protocol = (MySQLProtocol *) dcb->protocol;
|
backend_protocol = (MySQLProtocol *) dcb->protocol;
|
||||||
CHK_PROTOCOL(backend_protocol);
|
CHK_PROTOCOL(backend_protocol);
|
||||||
#if 1
|
|
||||||
LOGIF(LD, (skygw_log_write(
|
LOGIF(LD, (skygw_log_write(
|
||||||
LOGFILE_DEBUG,
|
LOGFILE_DEBUG,
|
||||||
"%lu [gw_read_backend_event] Read dcb %p fd %d protocol "
|
"%lu [gw_read_backend_event] Read dcb %p fd %d protocol "
|
||||||
@ -177,7 +177,6 @@ static int gw_read_backend_event(DCB *dcb) {
|
|||||||
dcb->fd,
|
dcb->fd,
|
||||||
backend_protocol->protocol_auth_state,
|
backend_protocol->protocol_auth_state,
|
||||||
STRPROTOCOLSTATE(backend_protocol->protocol_auth_state))));
|
STRPROTOCOLSTATE(backend_protocol->protocol_auth_state))));
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* backend is connected:
|
/* backend is connected:
|
||||||
@ -420,13 +419,13 @@ static int gw_read_backend_event(DCB *dcb) {
|
|||||||
|
|
||||||
/* reading MySQL command output from backend and writing to the client */
|
/* reading MySQL command output from backend and writing to the client */
|
||||||
{
|
{
|
||||||
GWBUF *read_buffer = NULL;
|
GWBUF *read_buffer = NULL;
|
||||||
ROUTER_OBJECT *router = NULL;
|
ROUTER_OBJECT *router = NULL;
|
||||||
ROUTER *router_instance = NULL;
|
ROUTER *router_instance = NULL;
|
||||||
void *rsession = NULL;
|
void *rsession = NULL;
|
||||||
SESSION *session = dcb->session;
|
SESSION *session = dcb->session;
|
||||||
int nbytes_read = 0;
|
int nbytes_read = 0;
|
||||||
|
|
||||||
CHK_SESSION(session);
|
CHK_SESSION(session);
|
||||||
router = session->service->router;
|
router = session->service->router;
|
||||||
router_instance = session->service->router_instance;
|
router_instance = session->service->router_instance;
|
||||||
@ -1226,7 +1225,7 @@ static GWBUF* process_response_data (
|
|||||||
|
|
||||||
/** Get command which was stored in gw_MySQLWrite_backend */
|
/** Get command which was stored in gw_MySQLWrite_backend */
|
||||||
p = DCB_PROTOCOL(dcb, MySQLProtocol);
|
p = DCB_PROTOCOL(dcb, MySQLProtocol);
|
||||||
CHK_PROTOCOL(p);
|
CHK_PROTOCOL(p);
|
||||||
|
|
||||||
/** All buffers processed here are sescmd responses */
|
/** All buffers processed here are sescmd responses */
|
||||||
gwbuf_set_type(readbuf, GWBUF_TYPE_SESCMD_RESPONSE);
|
gwbuf_set_type(readbuf, GWBUF_TYPE_SESCMD_RESPONSE);
|
||||||
|
@ -666,10 +666,11 @@ int gw_read_client_event(
|
|||||||
case MYSQL_IDLE:
|
case MYSQL_IDLE:
|
||||||
{
|
{
|
||||||
uint8_t cap = 0;
|
uint8_t cap = 0;
|
||||||
uint8_t *ptr_buff = NULL;
|
uint8_t* payload = NULL;
|
||||||
int mysql_command = -1;
|
|
||||||
bool stmt_input; /*< router input type */
|
bool stmt_input; /*< router input type */
|
||||||
|
|
||||||
|
ss_dassert(nbytes_read >= 5);
|
||||||
|
|
||||||
session = dcb->session;
|
session = dcb->session;
|
||||||
ss_dassert( session!= NULL);
|
ss_dassert( session!= NULL);
|
||||||
|
|
||||||
@ -685,13 +686,7 @@ int gw_read_client_event(
|
|||||||
|
|
||||||
/* Now, we are assuming in the first buffer there is
|
/* Now, we are assuming in the first buffer there is
|
||||||
* the information form mysql command */
|
* the information form mysql command */
|
||||||
ptr_buff = GWBUF_DATA(read_buffer);
|
payload = GWBUF_DATA(read_buffer);
|
||||||
|
|
||||||
/* get mysql commang at fifth byte */
|
|
||||||
if (ptr_buff) {
|
|
||||||
ss_dassert(nbytes_read >= 5);
|
|
||||||
mysql_command = ptr_buff[4];
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* Without rsession there is no access to backend.
|
* Without rsession there is no access to backend.
|
||||||
* COM_QUIT : close client dcb
|
* COM_QUIT : close client dcb
|
||||||
@ -700,7 +695,7 @@ int gw_read_client_event(
|
|||||||
if(rsession == NULL)
|
if(rsession == NULL)
|
||||||
{
|
{
|
||||||
/** COM_QUIT */
|
/** COM_QUIT */
|
||||||
if (mysql_command == '\x01')
|
if (MYSQL_IS_COM_QUIT(payload))
|
||||||
{
|
{
|
||||||
LOGIF(LD, (skygw_log_write_flush(
|
LOGIF(LD, (skygw_log_write_flush(
|
||||||
LOGFILE_DEBUG,
|
LOGFILE_DEBUG,
|
||||||
@ -767,7 +762,7 @@ int gw_read_client_event(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Route COM_QUIT to backend */
|
/** Route COM_QUIT to backend */
|
||||||
if (mysql_command == '\x01')
|
if (MYSQL_IS_COM_QUIT(payload))
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Sends COM_QUIT packets since buffer is already
|
* Sends COM_QUIT packets since buffer is already
|
||||||
@ -1394,11 +1389,25 @@ static int route_by_statement(SESSION *session, GWBUF *readbuf)
|
|||||||
{
|
{
|
||||||
int rc = -1;
|
int rc = -1;
|
||||||
GWBUF* packetbuf;
|
GWBUF* packetbuf;
|
||||||
|
#if defined(SS_DEBUG)
|
||||||
|
gwbuf_type_t prevtype;
|
||||||
|
GWBUF* tmpbuf;
|
||||||
|
|
||||||
|
tmpbuf = readbuf;
|
||||||
|
while (tmpbuf != NULL)
|
||||||
|
{
|
||||||
|
ss_dassert(GWBUF_IS_TYPE_MYSQL(tmpbuf));
|
||||||
|
tmpbuf=tmpbuf->next;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
ss_dassert(GWBUF_IS_TYPE_MYSQL(readbuf));
|
||||||
|
|
||||||
packetbuf = gw_MySQL_get_next_packet(&readbuf);
|
packetbuf = gw_MySQL_get_next_packet(&readbuf);
|
||||||
|
|
||||||
|
ss_dassert(GWBUF_IS_TYPE_MYSQL(packetbuf));
|
||||||
|
|
||||||
if (packetbuf != NULL)
|
if (packetbuf != NULL)
|
||||||
{
|
{
|
||||||
CHK_GWBUF(packetbuf);
|
CHK_GWBUF(packetbuf);
|
||||||
|
@ -738,9 +738,9 @@ static void* newSession(
|
|||||||
client_rses->rses_master_ref = master_ref;
|
client_rses->rses_master_ref = master_ref;
|
||||||
/* assert with master_host */
|
/* assert with master_host */
|
||||||
ss_dassert(master_ref && (master_ref->bref_backend->backend_server && SERVER_MASTER));
|
ss_dassert(master_ref && (master_ref->bref_backend->backend_server && SERVER_MASTER));
|
||||||
|
client_rses->rses_capabilities = RCAP_TYPE_STMT_INPUT;
|
||||||
client_rses->rses_backend_ref = backend_ref;
|
client_rses->rses_backend_ref = backend_ref;
|
||||||
client_rses->rses_nbackends = router_nservers; /*< # of backend servers */
|
client_rses->rses_nbackends = router_nservers; /*< # of backend servers */
|
||||||
client_rses->rses_capabilities = RCAP_TYPE_STMT_INPUT;
|
|
||||||
router->stats.n_sessions += 1;
|
router->stats.n_sessions += 1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1052,6 +1052,9 @@ static int routeQuery(
|
|||||||
{
|
{
|
||||||
rses_is_closed = true;
|
rses_is_closed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ss_dassert(!GWBUF_IS_TYPE_UNDEFINED(querybuf));
|
||||||
|
|
||||||
packet = GWBUF_DATA(querybuf);
|
packet = GWBUF_DATA(querybuf);
|
||||||
packet_type = packet[4];
|
packet_type = packet[4];
|
||||||
|
|
||||||
@ -1564,10 +1567,6 @@ static void clientReply (
|
|||||||
*/
|
*/
|
||||||
writebuf = sescmd_cursor_process_replies(writebuf, bref);
|
writebuf = sescmd_cursor_process_replies(writebuf, bref);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
ss_dassert(false);
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* If response will be sent to client, decrease waiter count.
|
* If response will be sent to client, decrease waiter count.
|
||||||
* This applies to session commands only. Counter decrement
|
* This applies to session commands only. Counter decrement
|
||||||
@ -1818,11 +1817,11 @@ static bool select_connect_backend_servers(
|
|||||||
{
|
{
|
||||||
LOGIF(LD, (skygw_log_write(
|
LOGIF(LD, (skygw_log_write(
|
||||||
LOGFILE_DEBUG,
|
LOGFILE_DEBUG,
|
||||||
"%lu [select_connect_backend_servers] Didn't find master ",
|
"%lu [select_connect_backend_servers] Session %p doesn't "
|
||||||
"for session %p rses %p.",
|
"currently have a master chosen. Proceeding to master "
|
||||||
|
"selection.",
|
||||||
pthread_self(),
|
pthread_self(),
|
||||||
session,
|
session)));
|
||||||
backend_ref)));
|
|
||||||
|
|
||||||
master_found = false;
|
master_found = false;
|
||||||
master_connected = false;
|
master_connected = false;
|
||||||
@ -2004,7 +2003,8 @@ static bool select_connect_backend_servers(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* take the master_host for master */
|
/* take the master_host for master */
|
||||||
else if (master_host && (b->backend_server == master_host->backend_server))
|
else if (master_host &&
|
||||||
|
(b->backend_server == master_host->backend_server))
|
||||||
{
|
{
|
||||||
*p_master_ref = &backend_ref[i];
|
*p_master_ref = &backend_ref[i];
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user