Merge branch '2.2' into develop
This commit is contained in:
@ -143,6 +143,17 @@ typedef struct mxs_upstream
|
|||||||
UPSTREAMFUNC clientReply;
|
UPSTREAMFUNC clientReply;
|
||||||
} MXS_UPSTREAM;
|
} MXS_UPSTREAM;
|
||||||
|
|
||||||
|
/* Specific reasons why a session was closed */
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
SESSION_CLOSE_NONE = 0, // No special reason
|
||||||
|
SESSION_CLOSE_TIMEOUT, // Connection timed out
|
||||||
|
SESSION_CLOSE_HANDLEERROR_FAILED, // Router returned an error from handleError
|
||||||
|
SESSION_CLOSE_ROUTING_FAILED, // Router closed DCB
|
||||||
|
SESSION_CLOSE_KILLED, // Killed by another connection
|
||||||
|
SESSION_CLOSE_TOO_MANY_CONNECTIONS, // Too many connections
|
||||||
|
} session_close_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler function for MaxScale specific session variables.
|
* Handler function for MaxScale specific session variables.
|
||||||
*
|
*
|
||||||
@ -215,6 +226,7 @@ typedef struct session
|
|||||||
} response; /*< Shortcircuited response */
|
} response; /*< Shortcircuited response */
|
||||||
SessionStmtQueue* last_statements; /*< The N last statements by the client */
|
SessionStmtQueue* last_statements; /*< The N last statements by the client */
|
||||||
DCBSet* dcb_set; /*< Set of associated backend DCBs */
|
DCBSet* dcb_set; /*< Set of associated backend DCBs */
|
||||||
|
session_close_t close_reason; /*< Reason why the session was closed */
|
||||||
skygw_chk_t ses_chk_tail;
|
skygw_chk_t ses_chk_tail;
|
||||||
} MXS_SESSION;
|
} MXS_SESSION;
|
||||||
|
|
||||||
@ -652,4 +664,14 @@ bool session_delay_routing(MXS_SESSION* session, MXS_DOWNSTREAM down, GWBUF* buf
|
|||||||
*/
|
*/
|
||||||
MXS_DOWNSTREAM router_as_downstream(MXS_SESSION* session);
|
MXS_DOWNSTREAM router_as_downstream(MXS_SESSION* session);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the reason why a session was closed
|
||||||
|
*
|
||||||
|
* @param session Session to inspect
|
||||||
|
*
|
||||||
|
* @return String representation of the reason why the session was closed. If
|
||||||
|
* the session was closed normally, an empty string is returned.
|
||||||
|
*/
|
||||||
|
const char* session_get_close_reason(const MXS_SESSION* session);
|
||||||
|
|
||||||
MXS_END_DECLS
|
MXS_END_DECLS
|
||||||
|
|||||||
@ -2479,6 +2479,7 @@ dcb_accept(DCB *dcb)
|
|||||||
{
|
{
|
||||||
client_dcb->func.connlimit(client_dcb, client_dcb->service->max_connections);
|
client_dcb->func.connlimit(client_dcb, client_dcb->service->max_connections);
|
||||||
}
|
}
|
||||||
|
dcb->session->close_reason = SESSION_CLOSE_TOO_MANY_CONNECTIONS;
|
||||||
dcb_close(client_dcb);
|
dcb_close(client_dcb);
|
||||||
client_dcb = NULL;
|
client_dcb = NULL;
|
||||||
}
|
}
|
||||||
@ -2887,6 +2888,7 @@ void dcb_process_idle_sessions(int thr)
|
|||||||
dcb->user ? dcb->user : "<unknown>",
|
dcb->user ? dcb->user : "<unknown>",
|
||||||
dcb->remote ? dcb->remote : "<unknown>",
|
dcb->remote ? dcb->remote : "<unknown>",
|
||||||
(float)idle / 10.f);
|
(float)idle / 10.f);
|
||||||
|
dcb->session->close_reason = SESSION_CLOSE_TIMEOUT;
|
||||||
poll_fake_hangup_event(dcb);
|
poll_fake_hangup_event(dcb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -130,6 +130,7 @@ static MXS_SESSION* session_alloc_body(SERVICE* service, DCB* client_dcb,
|
|||||||
session->client_dcb = client_dcb;
|
session->client_dcb = client_dcb;
|
||||||
session->stats.connect = time(0);
|
session->stats.connect = time(0);
|
||||||
session->qualifies_for_pooling = false;
|
session->qualifies_for_pooling = false;
|
||||||
|
session->close_reason = SESSION_CLOSE_NONE;
|
||||||
|
|
||||||
MXS_CONFIG *config = config_get_global_options();
|
MXS_CONFIG *config = config_get_global_options();
|
||||||
// If MaxScale is running in Oracle mode, then autocommit needs to
|
// If MaxScale is running in Oracle mode, then autocommit needs to
|
||||||
@ -1434,3 +1435,31 @@ MXS_DOWNSTREAM router_as_downstream(MXS_SESSION* session)
|
|||||||
head.routeQuery = (DOWNSTREAMFUNC)session->service->router->routeQuery;
|
head.routeQuery = (DOWNSTREAMFUNC)session->service->router->routeQuery;
|
||||||
return head;
|
return head;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* session_get_close_reason(const MXS_SESSION* session)
|
||||||
|
{
|
||||||
|
switch (session->close_reason)
|
||||||
|
{
|
||||||
|
case SESSION_CLOSE_NONE:
|
||||||
|
return "";
|
||||||
|
|
||||||
|
case SESSION_CLOSE_TIMEOUT:
|
||||||
|
return "Timed out by MaxScale";
|
||||||
|
|
||||||
|
case SESSION_CLOSE_HANDLEERROR_FAILED:
|
||||||
|
return "Router could not recover from connection errors";
|
||||||
|
|
||||||
|
case SESSION_CLOSE_ROUTING_FAILED:
|
||||||
|
return "Router could not route query";
|
||||||
|
|
||||||
|
case SESSION_CLOSE_KILLED:
|
||||||
|
return "Killed by another connection";
|
||||||
|
|
||||||
|
case SESSION_CLOSE_TOO_MANY_CONNECTIONS:
|
||||||
|
return "Too many connections";
|
||||||
|
|
||||||
|
default:
|
||||||
|
ss_dassert(!true);
|
||||||
|
return "Internal error";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -601,6 +601,7 @@ static void do_handle_error(DCB *dcb, mxs_error_action_t action, const char *err
|
|||||||
*/
|
*/
|
||||||
if (!succp)
|
if (!succp)
|
||||||
{
|
{
|
||||||
|
session->close_reason = SESSION_CLOSE_HANDLEERROR_FAILED;
|
||||||
poll_fake_hangup_event(session->client_dcb);
|
poll_fake_hangup_event(session->client_dcb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1193,12 +1193,14 @@ gw_read_finish_processing(DCB *dcb, GWBUF *read_buffer, uint64_t capabilities)
|
|||||||
if (return_code != 0)
|
if (return_code != 0)
|
||||||
{
|
{
|
||||||
/** Routing failed, close the client connection */
|
/** Routing failed, close the client connection */
|
||||||
|
dcb->session->close_reason = SESSION_CLOSE_ROUTING_FAILED;
|
||||||
dcb_close(dcb);
|
dcb_close(dcb);
|
||||||
MXS_ERROR("Routing the query failed. Session will be closed.");
|
MXS_ERROR("Routing the query failed. Session will be closed.");
|
||||||
}
|
}
|
||||||
else if (proto->current_command == MXS_COM_QUIT)
|
else if (proto->current_command == MXS_COM_QUIT)
|
||||||
{
|
{
|
||||||
/** Close router session which causes closing of backends */
|
/** Close router session which causes closing of backends */
|
||||||
|
ss_info_dassert(session_valid_for_pool(dcb->session), "Session should qualify for pooling");
|
||||||
dcb_close(dcb);
|
dcb_close(dcb);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1527,7 +1529,15 @@ static int gw_client_hangup_event(DCB *dcb)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The client did not send a COM_QUIT packet
|
// The client did not send a COM_QUIT packet
|
||||||
modutil_send_mysql_err_packet(dcb, 0, 0, 1927, "08S01", "Connection killed by MaxScale");
|
std::string errmsg{"Connection killed by MaxScale"};
|
||||||
|
std::string extra{session_get_close_reason(dcb->session)};
|
||||||
|
|
||||||
|
if (!extra.empty())
|
||||||
|
{
|
||||||
|
errmsg += ": " + extra;
|
||||||
|
}
|
||||||
|
|
||||||
|
modutil_send_mysql_err_packet(dcb, 0, 0, 1927, "08S01", errmsg.c_str());
|
||||||
}
|
}
|
||||||
dcb_close(dcb);
|
dcb_close(dcb);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1726,6 +1726,7 @@ static bool kill_func(DCB *dcb, void *data)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// DCB is not yet connected, send a hangup to forcibly close it
|
// DCB is not yet connected, send a hangup to forcibly close it
|
||||||
|
dcb->session->close_reason = SESSION_CLOSE_KILLED;
|
||||||
poll_fake_hangup_event(*it);
|
poll_fake_hangup_event(*it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user