In dcb.c:dcb_close DCB is removed either before or after the call dcb->func.close. Since mysql backend protocol sends COM_QUIT and thus, writes to backend DCB, it is kept in DCB_STATE_POLLING until the write is completed.

dcb.h: define ERRHAND temporarily since changes are still behind that macro
Defined two error handling actions in router.h: ERRACT_NEW_COMMECTION and ERRACT_REPLY_CLIENT.
Failed database is logged at expanding frequence to error and to message log due changes in mysql_mon.c. Added two new members in MONITOR_SERVERS: mon_err_count, and mon_prev_status so that each backend can be treated individually.

Error handling: if mysql_backend.c:dcb_read fails, router's handleError is called instead of closing session.
	If mysql_client.c:SESSION_ROUTE_QUERY fails router's handleError is called instead of sending error to client.

	readwritesplit.c:select_connect_backend_servers is modified so that in can be called during active router session. When called, it attempts to find one master and maximum number of configured slaves in correct state if necessary.
	When handleError needs to replace failed unit it now calls select_connect_backend_servers.
This commit is contained in:
VilhoRaatikka
2014-06-08 19:36:12 +03:00
parent 916b763685
commit 889bdd4f8c
8 changed files with 298 additions and 121 deletions

View File

@ -804,7 +804,6 @@ int gw_read_client_event(DCB* dcb) {
dcb_close(dcb);
#else
SESSION_ROUTE_QUERY(session, read_buffer);
// router->routeQuery(router_instance, rsession, read_buffer);
LOGIF(LD, (skygw_log_write_flush(
LOGFILE_DEBUG,
"%lu [gw_read_client_event] Routed COM_QUIT to "
@ -824,6 +823,7 @@ int gw_read_client_event(DCB* dcb) {
* to router.
*/
rc = route_by_statement(session, read_buffer);
if (read_buffer != NULL)
{
/** add incomplete mysql packet to read queue */
@ -840,7 +840,7 @@ int gw_read_client_event(DCB* dcb) {
if (rc == 1) {
rc = 0; /**< here '0' means success */
} else {
#if defined(ERRHANDLE2)
#if defined(ERRHANDLE)
bool succp;
LOGIF(LE, (skygw_log_write_flush(
@ -848,40 +848,28 @@ int gw_read_client_event(DCB* dcb) {
"Error : Routing the query failed. "
"Reselecting backends.")));
/**
* Decide whether close router and its
* connections or just send an error to client
*/
router->handleError(router_instance,
rsession,
"Query routing failed. "
"Query execution aborted. "
"Reselecting backend.",
NULL,
ERRACT_RELECT_BACKENDS,
rsession,
"Write to backend failed.",
dcb,
ERRACT_NEW_CONNECTION,
&succp);
if (!succp)
{
router->handleError(router_instance,
rsession,
"Connection to "
"backend lost.",
NULL,
ERRACT_CLOSE_RSES,
NULL);
LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
"Error : Reselecting backend "
"servers failed.")));
dcb_close(dcb);
}
else
{
LOGIF(LT, (skygw_log_write_flush(
LOGFILE_TRACE,
"Reselected backend servers.")));
}
LOGIF(LT, (skygw_log_write_flush(
LOGFILE_TRACE,
"Reselected backend servers.")));
#else
mysql_send_custom_error(dcb,
1,