RWSplit router handles query processing errors that happened in router by sending parse error reply to client. routeQuery fails only when backend has failed.
This commit is contained in:
VilhoRaatikka
2015-01-17 22:40:52 +02:00
parent d362ed227f
commit 6d2b38d4b6
6 changed files with 106 additions and 36 deletions

View File

@ -32,6 +32,19 @@
#include <string.h>
#include <mysql_client_server_protocol.h>
#include <modutil.h>
/** Defined in log_manager.cc */
extern int lm_enabled_logfiles_bitmask;
extern size_t log_ses_count[];
extern __thread log_info_t tls_log_info;
static void modutil_reply_routing_error(
DCB* backend_dcb,
int error,
char* state,
char* errstr);
/**
* Check if a GWBUF structure is a MySQL COM_QUERY packet
*
@ -327,7 +340,7 @@ GWBUF *modutil_create_mysql_err_msg(
const char *msg)
{
uint8_t *outbuf = NULL;
uint32_t mysql_payload_size = 0;
uint32_t mysql_payload_size = 0;
uint8_t mysql_packet_header[4];
uint8_t *mysql_payload = NULL;
uint8_t field_count = 0;
@ -528,7 +541,7 @@ modutil_count_signal_packets(GWBUF *reply, int use_ok, int n_found)
unsigned char* ptr = (unsigned char*) reply->start;
unsigned char* end = (unsigned char*) reply->end;
unsigned char* prev = ptr;
int pktlen, eof = 0, err = 0, found = n_found;
int pktlen, eof = 0, err = 0;
int errlen = 0, eoflen = 0;
int iserr = 0, iseof = 0;
while(ptr < end)
@ -583,3 +596,57 @@ modutil_count_signal_packets(GWBUF *reply, int use_ok, int n_found)
return(eof + err);
}
/**
* 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
* upstream to client.
*
* @param backend_dcb DCB where event is added
* @param errstr Plain-text string error
*/
void modutil_reply_parse_error(
DCB* backend_dcb,
char* errstr)
{
CHK_DCB(backend_dcb);
modutil_reply_routing_error(backend_dcb, 1064, "42000", errstr);
}
/**
* Create error message and EPOLLIN event to event queue of the backend DCB.
* When event is notified the message is processed as error reply and routed
* upstream to client.
*
* @param backend_dcb DCB where event is added
* @param error SQL error number
* @param state SQL state
* @param errstr Plain-text string error
*/
static void modutil_reply_routing_error(
DCB* backend_dcb,
int error,
char* state,
char* errstr)
{
GWBUF* buf;
CHK_DCB(backend_dcb);
buf = modutil_create_mysql_err_msg(1, 0, error, state, errstr);
free(errstr);
if (buf == NULL)
{
LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
"Error : Creating buffer for error message failed.")));
return;
}
/** Set flags that help router to identify session commands reply */
gwbuf_set_type(buf, GWBUF_TYPE_MYSQL);
gwbuf_set_type(buf, GWBUF_TYPE_SESCMD_RESPONSE);
gwbuf_set_type(buf, GWBUF_TYPE_RESPONSE_END);
/** Create an incoming event for backend DCB */
poll_add_epollin_event_to_dcb(backend_dcb, buf);
return;
}