dcb.c
dcb_final_free: Router session is not closed anymore when dcb is closed. Router session is shared among all dcbs and is closed and freed with session. dcb_connect: dcb's state must be switched fro DCB_STATE_ALLOC to DCB_STATE_DISCONNECTED before dcb_final_free can be called for it. dcb_close: poll_remove_dcb encapsulates dcb's state transition in the same way as poll_add_dcb. Removed state modification from dcb_close. Read return value of poll_remove_dcb and log accordingly. dcb_set state: remove dassert if dcb_set_state_nomutex returned false. False can be returned indicating that intented change didn't occur but the end state, for example, may be acceptable. Failures in state transitions are asserted in dcb_Set_state_nomutex. poll.c poll_add_dcb: dcb state is now set here to either DCB_STATE_LISTENING or to DCB_STATE_POLLING according to dcb's role. Failures in state setting and in epoll_ctl are detected, logged and handled. poll_remove_dcb: Failures in state setting and epoll_ctl are detected, logged, and handled. mysql_client_server_protocol.h Removed macros MYSQL_FAILED_AUTHENTICATION & MYSQL_SUCCESFUL_AUTHENTICATION as they were not necessary and used with constant values 0 and 1 depending on the case. Renamed variable 'conn' to 'protocol' in cases where it meant protocol. mysql_backend.c gw_read_backend_event: In case when there was nothing to read or read failed, backend dcb is closed because situation is assumed to be such that backend server closed its side of the socket. Removed macros MYSQL_FAILED/SUCCESFUL_AUTHENTICATION gw_create_backend_connection: Assigned protocol with fd which is connected to backend. backend_write_delayqueue: In case where dcb_write fails to write anything, close backend dcb to avoid it getting hanging. mysql_client.c gw_read_client_event: Read return value of routeQuery and if it isn't == 1, call mysql_send_custom_error with client dcb and set client's protocol state to MYSQL_IDLE instead of MYSQL_ROUTING. gw_MySQLAccept: Static reply counter was erroneously used as a criteria for jumping to return point where return value was constantly 'success' (=0). Replaced static reply counter with private. Fixed return value in different cases. mysql_common.c gw_receive_backend_auth: Changed to return boolean values indicating of success or failue. Used integers which were assigned to macroed values on the caller side. Added length check before accessing buffer. readconnroute.c Cut too long lines and removed statements with side effects. skygw_debug.h Added macro STRPROTOCOLSTATE(s) to produce string representation of a given protocol state.
This commit is contained in:
@ -576,7 +576,7 @@ int gw_read_client_event(DCB* dcb) {
|
||||
//write to client mysql AUTH_OK packet, packet n. is 2
|
||||
// start a new session, and connect to backends
|
||||
session = session_alloc(dcb->service, dcb);
|
||||
|
||||
|
||||
if (session != NULL) {
|
||||
CHK_SESSION(session);
|
||||
ss_dassert(session->state != SESSION_STATE_ALLOC);
|
||||
@ -667,6 +667,14 @@ int gw_read_client_event(DCB* dcb) {
|
||||
* fprintf(stderr, "COM_QUIT received with
|
||||
* no connected backends from %i\n", dcb->fd);
|
||||
*/
|
||||
skygw_log_write_flush(
|
||||
LOGFILE_DEBUG,
|
||||
"%lu [gw_read_client_event] Client read "
|
||||
"COM_QUIT and rsession == NULL. Closing "
|
||||
"client dcb %p.",
|
||||
pthread_self(),
|
||||
dcb);
|
||||
|
||||
(dcb->func).close(dcb);
|
||||
} else {
|
||||
/* Send a custom error as MySQL command reply */
|
||||
@ -683,6 +691,12 @@ int gw_read_client_event(DCB* dcb) {
|
||||
/* We can route the query */
|
||||
/* COM_QUIT handling */
|
||||
if (mysql_command == '\x01') {
|
||||
skygw_log_write_flush(
|
||||
LOGFILE_DEBUG,
|
||||
"%lu [gw_read_client_event] Before routeQuery. "
|
||||
"dcb %p.",
|
||||
pthread_self(),
|
||||
dcb);
|
||||
/**
|
||||
* fprintf(stderr, "COM_QUIT received from %i and
|
||||
* passed to backed\n", dcb->fd);
|
||||
@ -690,6 +704,13 @@ int gw_read_client_event(DCB* dcb) {
|
||||
* fprintf(stderr, "<<< Routing the COM_QUIT ...\n");
|
||||
*/
|
||||
router->routeQuery(router_instance, rsession, queue);
|
||||
skygw_log_write_flush(
|
||||
LOGFILE_DEBUG,
|
||||
"%lu [gw_read_client_event] After routeQuery. "
|
||||
"dcb %p.",
|
||||
pthread_self(),
|
||||
dcb);
|
||||
|
||||
/* close client connection */
|
||||
(dcb->func).close(dcb);
|
||||
rc = 1;
|
||||
@ -701,10 +722,18 @@ int gw_read_client_event(DCB* dcb) {
|
||||
|
||||
/* writing in the backend buffer queue, via routeQuery */
|
||||
//fprintf(stderr, "<<< Routing the Query ...\n");
|
||||
router->routeQuery(router_instance,
|
||||
rsession,
|
||||
queue);
|
||||
protocol->state = MYSQL_WAITING_RESULT;
|
||||
rc = router->routeQuery(router_instance, rsession, queue);
|
||||
|
||||
if (rc == 1) {
|
||||
protocol->state = MYSQL_WAITING_RESULT;
|
||||
} else {
|
||||
mysql_send_custom_error(dcb,
|
||||
1,
|
||||
0,
|
||||
"Connection to backend lost.");
|
||||
protocol->state = MYSQL_IDLE;
|
||||
goto return_rc;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@ -715,6 +744,14 @@ int gw_read_client_event(DCB* dcb) {
|
||||
rc = 0;
|
||||
|
||||
return_rc:
|
||||
#if defined(SS_DEBUG)
|
||||
if (dcb->state == DCB_STATE_POLLING ||
|
||||
dcb->state == DCB_STATE_NOPOLLING ||
|
||||
dcb->state == DCB_STATE_ZOMBIE)
|
||||
{
|
||||
CHK_PROTOCOL(protocol);
|
||||
}
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -766,6 +803,14 @@ int gw_write_client_event(DCB *dcb)
|
||||
}
|
||||
|
||||
return_1:
|
||||
#if defined(SS_DEBUG)
|
||||
if (dcb->state == DCB_STATE_POLLING ||
|
||||
dcb->state == DCB_STATE_NOPOLLING ||
|
||||
dcb->state == DCB_STATE_ZOMBIE)
|
||||
{
|
||||
CHK_PROTOCOL(protocol);
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -867,20 +912,36 @@ int gw_MySQLListener(
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @node (write brief function description here)
|
||||
*
|
||||
* Parameters:
|
||||
* @param listener - <usage>
|
||||
* <description>
|
||||
*
|
||||
* @return 0 in success, 1 in failure
|
||||
*
|
||||
*
|
||||
* @details (write detailed description here)
|
||||
*
|
||||
*/
|
||||
int gw_MySQLAccept(DCB *listener)
|
||||
{
|
||||
{
|
||||
int rc = 0;
|
||||
DCB *client_dcb;
|
||||
MySQLProtocol *protocol;
|
||||
int c_sock;
|
||||
struct sockaddr_in local;
|
||||
socklen_t addrlen = sizeof(struct sockaddr_in);
|
||||
int sendbuf = GW_BACKEND_SO_SNDBUF;
|
||||
socklen_t optlen = sizeof(sendbuf);
|
||||
int eno = 0;
|
||||
int i = 0;
|
||||
|
||||
CHK_DCB(listener);
|
||||
fprintf(stderr, "MySQL Listener socket is: %i\n", listener->fd);
|
||||
|
||||
while (1) {
|
||||
int c_sock;
|
||||
struct sockaddr_in local;
|
||||
socklen_t addrlen = sizeof(struct sockaddr_in);
|
||||
DCB *client_dcb;
|
||||
MySQLProtocol *protocol;
|
||||
int sendbuf = GW_BACKEND_SO_SNDBUF;
|
||||
socklen_t optlen = sizeof(sendbuf);
|
||||
int eno = 0;
|
||||
static int i;
|
||||
|
||||
retry_accept:
|
||||
// new connection from client
|
||||
@ -895,6 +956,7 @@ int gw_MySQLAccept(DCB *listener)
|
||||
if (eno == EAGAIN ||
|
||||
eno == EWOULDBLOCK)
|
||||
{
|
||||
rc = 1;
|
||||
/* We have processed all incoming connections. */
|
||||
break;
|
||||
}
|
||||
@ -915,7 +977,8 @@ int gw_MySQLAccept(DCB *listener)
|
||||
if (i<10) {
|
||||
goto retry_accept;
|
||||
}
|
||||
goto return_to_poll;
|
||||
rc = 1;
|
||||
goto return_rc;
|
||||
}
|
||||
else if (eno == EMFILE)
|
||||
{
|
||||
@ -934,7 +997,8 @@ int gw_MySQLAccept(DCB *listener)
|
||||
if (i<10) {
|
||||
goto retry_accept;
|
||||
}
|
||||
goto return_to_poll;
|
||||
rc = 1;
|
||||
goto return_rc;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -982,12 +1046,16 @@ int gw_MySQLAccept(DCB *listener)
|
||||
ss_dassert(protocol != NULL);
|
||||
|
||||
if (protocol == NULL) {
|
||||
/** delete client_dcb */
|
||||
dcb_close(client_dcb);
|
||||
|
||||
skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"%lu [gw_MySQLAccept] Failed to create "
|
||||
"protocol object for client connection.",
|
||||
pthread_self());
|
||||
return 1;
|
||||
rc = 1;
|
||||
goto return_rc;
|
||||
}
|
||||
client_dcb->protocol = protocol;
|
||||
// assign function poiters to "func" field
|
||||
@ -1005,6 +1073,9 @@ int gw_MySQLAccept(DCB *listener)
|
||||
*/
|
||||
if (poll_add_dcb(client_dcb) == -1)
|
||||
{
|
||||
/** delete client_dcb */
|
||||
dcb_close(client_dcb);
|
||||
|
||||
/** Previous state is recovered in poll_add_dcb. */
|
||||
skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
@ -1013,7 +1084,8 @@ int gw_MySQLAccept(DCB *listener)
|
||||
pthread_self(),
|
||||
client_dcb,
|
||||
client_dcb->fd);
|
||||
return 1;
|
||||
rc = 1;
|
||||
goto return_rc;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1026,8 +1098,15 @@ int gw_MySQLAccept(DCB *listener)
|
||||
client_dcb->fd);
|
||||
}
|
||||
} /**< while 1 */
|
||||
return_to_poll:
|
||||
return 0;
|
||||
#if defined(SS_DEBUG)
|
||||
if (rc == 0) {
|
||||
CHK_DCB(client_dcb);
|
||||
protocol = (MySQLProtocol *)client_dcb->protocol;
|
||||
CHK_PROTOCOL(protocol);
|
||||
}
|
||||
#endif
|
||||
return_rc:
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1036,16 +1115,34 @@ static int gw_error_client_event(DCB *dcb) {
|
||||
/**
|
||||
* should this be removed if we don't want to execute it ?
|
||||
*
|
||||
//fprintf(stderr, "#### Handle error function gw_error_client_event, for [%i] is [%s]\n", dcb->fd, gw_dcb_state2string(dcb->state));
|
||||
//fprintf(stderr, "#### Handle error function gw_error_client_event, for [%i] is [%s]\n", dcb->fd, gw_state2string(dcb->state));
|
||||
//dcb_close(dcb);
|
||||
*/
|
||||
|
||||
#if defined(SS_DEBUG)
|
||||
MySQLProtocol* protocol = (MySQLProtocol *)dcb->protocol;
|
||||
if (dcb->state == DCB_STATE_POLLING ||
|
||||
dcb->state == DCB_STATE_NOPOLLING ||
|
||||
dcb->state == DCB_STATE_ZOMBIE)
|
||||
{
|
||||
CHK_PROTOCOL(protocol);
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
gw_client_close(DCB *dcb)
|
||||
{
|
||||
#if defined(SS_DEBUG)
|
||||
MySQLProtocol* protocol = (MySQLProtocol *)dcb->protocol;
|
||||
if (dcb->state == DCB_STATE_POLLING ||
|
||||
dcb->state == DCB_STATE_NOPOLLING ||
|
||||
dcb->state == DCB_STATE_ZOMBIE)
|
||||
{
|
||||
CHK_PROTOCOL(protocol);
|
||||
}
|
||||
#endif
|
||||
|
||||
dcb_close(dcb);
|
||||
return 1;
|
||||
}
|
||||
@ -1061,6 +1158,15 @@ gw_client_close(DCB *dcb)
|
||||
static int
|
||||
gw_client_hangup_event(DCB *dcb)
|
||||
{
|
||||
#if defined(SS_DEBUG)
|
||||
MySQLProtocol* protocol = (MySQLProtocol *)dcb->protocol;
|
||||
if (dcb->state == DCB_STATE_POLLING ||
|
||||
dcb->state == DCB_STATE_NOPOLLING ||
|
||||
dcb->state == DCB_STATE_ZOMBIE)
|
||||
{
|
||||
CHK_PROTOCOL(protocol);
|
||||
}
|
||||
#endif
|
||||
dcb_close(dcb);
|
||||
return 1;
|
||||
}
|
||||
|
Reference in New Issue
Block a user