Add result set buffering to MySQLBackend
The backend MySQL protocol module now supports a new routing capability which allows result sets to be gathered into one buffer before they are routed onward. This should not be used by modules that expect large result sets as the result set is buffered in memory. Adding a limit on how large of a result set could be buffered would allow relatively safe use of this routing capability without compromising the stability of the system.
This commit is contained in:
@ -287,7 +287,9 @@ typedef struct
|
||||
/** Defines for response codes */
|
||||
#define MYSQL_REPLY_ERR 0xff
|
||||
#define MYSQL_REPLY_OK 0x00
|
||||
#define MYSQL_REPLY_AUTHSWITCHREQUEST 0xfe
|
||||
#define MYSQL_REPLY_EOF 0xfe
|
||||
#define MYSQL_REPLY_LOCAL_INFILE 0xfb
|
||||
#define MYSQL_REPLY_AUTHSWITCHREQUEST 0xfe /**< Only sent during authentication */
|
||||
|
||||
static inline mysql_server_cmd_t MYSQL_GET_COMMAND(const uint8_t* header)
|
||||
{
|
||||
@ -399,4 +401,7 @@ int mxs_mysql_send_ok(DCB *dcb, int sequence, uint8_t affected_rows, const char*
|
||||
/** Check for OK packet */
|
||||
bool mxs_mysql_is_ok_packet(GWBUF *buffer);
|
||||
|
||||
/** Check for result set */
|
||||
bool mxs_mysql_is_result_set(GWBUF *buffer);
|
||||
|
||||
MXS_END_DECLS
|
||||
|
@ -40,6 +40,8 @@ typedef enum routing_capability
|
||||
RCAP_TYPE_STMT_OUTPUT = 0x0010, /* 0b0000000000010000 */
|
||||
/**< Each delivered buffer is contiguous; implies RCAP_TYPE_STMT_OUTPUT. */
|
||||
RCAP_TYPE_CONTIGUOUS_OUTPUT = 0x0030, /* 0b0000000000110000 */
|
||||
/** Result sets are delivered in one buffer; implies RCAP_TYPE_STMT_OUTPUT. */
|
||||
RCAP_TYPE_RESULTSET_OUTPUT = 0x0050, /* 0b0000000001110000 */
|
||||
|
||||
} routing_capability_t;
|
||||
|
||||
|
@ -787,6 +787,19 @@ gw_read_and_write(DCB *dcb)
|
||||
|
||||
read_buffer = tmp;
|
||||
|
||||
if (rcap_type_required(capabilities, RCAP_TYPE_RESULTSET_OUTPUT))
|
||||
{
|
||||
if (mxs_mysql_is_result_set(read_buffer))
|
||||
{
|
||||
int more = 0;
|
||||
if (modutil_count_signal_packets(read_buffer, 0, 0, &more) != 2)
|
||||
{
|
||||
dcb->dcb_readqueue = read_buffer;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rcap_type_required(capabilities, RCAP_TYPE_CONTIGUOUS_OUTPUT))
|
||||
{
|
||||
if ((tmp = gwbuf_make_contiguous(read_buffer)))
|
||||
@ -862,7 +875,8 @@ gw_read_and_write(DCB *dcb)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (rcap_type_required(capabilities, RCAP_TYPE_STMT_OUTPUT))
|
||||
else if (rcap_type_required(capabilities, RCAP_TYPE_STMT_OUTPUT) &&
|
||||
!rcap_type_required(capabilities, RCAP_TYPE_RESULTSET_OUTPUT))
|
||||
{
|
||||
stmt = modutil_get_next_MySQL_packet(&read_buffer);
|
||||
}
|
||||
|
@ -1559,3 +1559,31 @@ bool mxs_mysql_is_ok_packet(GWBUF *buffer)
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
bool mxs_mysql_is_result_set(GWBUF *buffer)
|
||||
{
|
||||
bool rval = false;
|
||||
uint8_t cmd;
|
||||
|
||||
if (gwbuf_copy_data(buffer, MYSQL_HEADER_LEN, 1, &cmd))
|
||||
{
|
||||
switch (cmd)
|
||||
{
|
||||
|
||||
case MYSQL_REPLY_OK:
|
||||
case MYSQL_REPLY_ERR:
|
||||
case MYSQL_REPLY_LOCAL_INFILE:
|
||||
case MYSQL_REPLY_EOF:
|
||||
/** Not a result set */
|
||||
break;
|
||||
default:
|
||||
if (gwbuf_copy_data(buffer, MYSQL_HEADER_LEN + 1, 1, &cmd) && cmd > 1)
|
||||
{
|
||||
rval = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
@ -1846,7 +1846,7 @@ static void rses_end_locked_router_action(ROUTER_SLAVE *rses)
|
||||
|
||||
static uint64_t getCapabilities(void)
|
||||
{
|
||||
return RCAP_TYPE_NO_RSESSION | RCAP_TYPE_CONTIGUOUS_OUTPUT;
|
||||
return RCAP_TYPE_NO_RSESSION | RCAP_TYPE_CONTIGUOUS_OUTPUT | RCAP_TYPE_RESULTSET_OUTPUT;
|
||||
}
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user