Fixed queries being routed when the session is already closing.

This commit is contained in:
Markus Makela
2015-07-07 13:15:23 +03:00
parent c2e51f2e98
commit fb09cbf100
5 changed files with 89 additions and 77 deletions

View File

@ -197,6 +197,7 @@ GWBUF *rval;
rval->gwbuf_info = buf->gwbuf_info; rval->gwbuf_info = buf->gwbuf_info;
rval->gwbuf_bufobj = buf->gwbuf_bufobj; rval->gwbuf_bufobj = buf->gwbuf_bufobj;
rval->tail = rval; rval->tail = rval;
rval->next = NULL;
CHK_GWBUF(rval); CHK_GWBUF(rval);
return rval; return rval;
} }

View File

@ -1080,7 +1080,7 @@ gw_backend_hangup(DCB *dcb)
len = sizeof(error); len = sizeof(error);
if (getsockopt(dcb->fd, SOL_SOCKET, SO_ERROR, &error, (socklen_t *)&len) == 0) if (getsockopt(dcb->fd, SOL_SOCKET, SO_ERROR, &error, (socklen_t *)&len) == 0)
{ {
if (error != 0) if (error != 0 && ses_state != SESSION_STATE_STOPPING)
{ {
strerror_r(error, buf, 100); strerror_r(error, buf, 100);
LOGIF(LE, (skygw_log_write_flush( LOGIF(LE, (skygw_log_write_flush(
@ -1094,9 +1094,12 @@ gw_backend_hangup(DCB *dcb)
goto retblock; goto retblock;
} }
#if defined(SS_DEBUG) #if defined(SS_DEBUG)
LOGIF(LE, (skygw_log_write_flush( if(ses_state != SESSION_STATE_STOPPING)
LOGFILE_ERROR, {
"Backend hangup error handling."))); LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
"Backend hangup error handling.")));
}
#endif #endif
router->handleError(router_instance, router->handleError(router_instance,

View File

@ -1092,6 +1092,7 @@ int gw_read_client_event(
case MYSQL_IDLE: case MYSQL_IDLE:
{ {
uint8_t* payload = NULL; uint8_t* payload = NULL;
session_state_t ses_state;
session = dcb->session; session = dcb->session;
ss_dassert(session!= NULL); ss_dassert(session!= NULL);
@ -1100,93 +1101,106 @@ int gw_read_client_event(
{ {
CHK_SESSION(session); CHK_SESSION(session);
} }
spinlock_acquire(&session->ses_lock);
ses_state = session->state;
spinlock_release(&session->ses_lock);
/* 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 */
payload = GWBUF_DATA(read_buffer); payload = GWBUF_DATA(read_buffer);
/** Route COM_QUIT to backend */ if(ses_state == SESSION_STATE_ROUTER_READY)
if (MYSQL_IS_COM_QUIT(payload)) {
{ /** Route COM_QUIT to backend */
if (MYSQL_IS_COM_QUIT(payload))
{
/** /**
* Sends COM_QUIT packets since buffer is already * Sends COM_QUIT packets since buffer is already
* created. A BREF_CLOSED flag is set so dcb_close won't * created. A BREF_CLOSED flag is set so dcb_close won't
* send redundant COM_QUIT. * send redundant COM_QUIT.
*/ */
SESSION_ROUTE_QUERY(session, read_buffer); SESSION_ROUTE_QUERY(session, read_buffer);
/** /**
* Close router session which causes closing of backends. * Close router session which causes closing of backends.
*/ */
dcb_close(dcb); dcb_close(dcb);
} }
else else
{ {
/** Reset error handler when routing of the new query begins */ /** Reset error handler when routing of the new query begins */
router->handleError(NULL, NULL, NULL, dcb, ERRACT_RESET, NULL); router->handleError(NULL, NULL, NULL, dcb, ERRACT_RESET, NULL);
if (stmt_input) if (stmt_input)
{ {
/** /**
* Feed each statement completely and separately * Feed each statement completely and separately
* to router. * to router.
*/ */
rc = route_by_statement(session, &read_buffer); rc = route_by_statement(session, &read_buffer);
if (read_buffer != NULL) if (read_buffer != NULL)
{ {
/** add incomplete mysql packet to read queue */ /** add incomplete mysql packet to read queue */
dcb->dcb_readqueue = gwbuf_append(dcb->dcb_readqueue, read_buffer); dcb->dcb_readqueue = gwbuf_append(dcb->dcb_readqueue, read_buffer);
} }
} }
else else
{ {
/** Feed whole packet to router */ /** Feed whole packet to router */
rc = SESSION_ROUTE_QUERY(session, read_buffer); rc = SESSION_ROUTE_QUERY(session, read_buffer);
} }
/** Routing succeed */ /** Routing succeed */
if (rc) if (rc)
{ {
rc = 0; /**< here '0' means success */ rc = 0; /**< here '0' means success */
} }
else else
{ {
bool succp; bool succp;
GWBUF* errbuf; GWBUF* errbuf;
/** /**
* Create error to be sent to client if session * Create error to be sent to client if session
* can't be continued. * can't be continued.
*/ */
errbuf = mysql_create_custom_error( errbuf = mysql_create_custom_error(
1, 1,
0, 0,
"Routing failed. Session is closed."); "Routing failed. Session is closed.");
/** /**
* Ensure that there are enough backends * Ensure that there are enough backends
* available. * available.
*/ */
router->handleError( router->handleError(
router_instance, router_instance,
session->router_session, session->router_session,
errbuf, errbuf,
dcb, dcb,
ERRACT_NEW_CONNECTION, ERRACT_NEW_CONNECTION,
&succp); &succp);
gwbuf_free(errbuf); gwbuf_free(errbuf);
/** /**
* If there are not enough backends close * If there are not enough backends close
* session * session
*/ */
if (!succp) if (!succp)
{ {
LOGIF(LE, (skygw_log_write_flush( LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR, LOGFILE_ERROR,
"Error : Routing the query failed. " "Error : Routing the query failed. "
"Session will be closed."))); "Session will be closed.")));
dcb_close(dcb); dcb_close(dcb);
} }
} }
} }
}
else
{
skygw_log_write_flush(LT,"Session received a query in state %s",
STRSESSIONSTATE(ses_state));
while((read_buffer = GWBUF_CONSUME_ALL(read_buffer)) != NULL);
goto return_rc;
}
goto return_rc; goto return_rc;
} /* MYSQL_IDLE */ } /* MYSQL_IDLE */
break; break;

View File

@ -723,16 +723,10 @@ routeQuery(ROUTER *instance, void *router_session, GWBUF *queue)
SERVER_IS_DOWN(router_cli_ses->backend->server)) SERVER_IS_DOWN(router_cli_ses->backend->server))
{ {
LOGIF(LT, (skygw_log_write( LOGIF(LT, (skygw_log_write(
LOGFILE_TRACE, LOGFILE_TRACE|LOGFILE_ERROR,
"Error : Failed to route MySQL command %d to backend " "Error : Failed to route MySQL command %d to backend "
"server.", "server.%s",
mysql_command))); mysql_command,rses_is_closed ? " Session is closed." : "")));
skygw_log_write(
LOGFILE_ERROR,
"Error : Failed to route MySQL command %d to backend "
"server %s.",
mysql_command,
router_cli_ses->backend->server->unique_name);
rc = 0; rc = 0;
goto return_rc; goto return_rc;

View File

@ -3915,7 +3915,7 @@ static GWBUF* sescmd_cursor_clone_querybuf(
} }
ss_dassert(scur->scmd_cur_cmd != NULL); ss_dassert(scur->scmd_cur_cmd != NULL);
buf = gwbuf_clone(scur->scmd_cur_cmd->my_sescmd_buf); buf = gwbuf_clone_all(scur->scmd_cur_cmd->my_sescmd_buf);
CHK_GWBUF(buf); CHK_GWBUF(buf);
return buf; return buf;