MXS-2196: Split session startup into two parts

The session allocation now has two distinct parts: the initialization of
the session itself and the creation of the router and filter
sessions. This allows sessions to be allocated the moment a client DCB is
created instead of only after the authentication is complete. With this
change, the need for the dummy session is removed.
This commit is contained in:
Markus Mäkelä
2018-12-03 08:45:00 +02:00
parent 13769a0e8c
commit 180e150ba1
2 changed files with 65 additions and 80 deletions

View File

@ -303,6 +303,19 @@ MXS_SESSION* session_alloc(SERVICE*, DCB*);
*/
MXS_SESSION* session_alloc_with_id(SERVICE*, DCB*, uint64_t);
/**
* Start the session
*
* Called after the session is initialized and authentication is complete. This creates the router and filter
* sessions.
*
* @param session Session to start
* @param service The service where the session is started
*
* @return True if session was started successfully
*/
bool session_start(MXS_SESSION* session, SERVICE* service);
MXS_SESSION* session_set_dummy(DCB*);
static inline bool session_is_dummy(MXS_SESSION* session)

View File

@ -158,26 +158,27 @@ static MXS_SESSION* session_alloc_body(SERVICE* service,
memset(&session->response, 0, sizeof(session->response));
session->close_reason = SESSION_CLOSE_NONE;
/*
* Only create a router session if we are not the listening DCB or an
* internal DCB. Creating a router session may create a connection to
* a backend server, depending upon the router module implementation
* and should be avoided for a listener session.
*
* Router session creation may create other DCBs that link to the
* session.
*/
if (client_dcb->state != DCB_STATE_LISTENING
&& client_dcb->dcb_role != DCB_ROLE_INTERNAL)
if (client_dcb->dcb_role != DCB_ROLE_INTERNAL && !session_start(session, service))
{
// The session will be freed when the client DCB is freed
session = nullptr;
}
return session;
}
bool session_start(MXS_SESSION* session, SERVICE* service)
{
session->router_session = service->router->newSession(service->router_instance, session);
if (session->router_session == NULL)
{
session->state = SESSION_STATE_TO_BE_FREED;
MXS_ERROR("Failed to create new router session for service '%s'. "
"See previous errors for more details.",
service->name);
"See previous errors for more details.", service->name);
return false;
}
/*
* Pending filter chain being setup set the head of the chain to
* be the router. As filters are inserted the current head will
@ -202,52 +203,23 @@ static MXS_SESSION* session_alloc_body(SERVICE* service,
session->tail.session = (MXS_FILTER_SESSION*)session;
session->tail.clientReply = session_reply;
if (SESSION_STATE_TO_BE_FREED != session->state
&& !session_setup_filters(session))
if (!session_setup_filters(session))
{
session->state = SESSION_STATE_TO_BE_FREED;
MXS_ERROR("Setting up filters failed. "
"Terminating session %s.",
service->name);
}
MXS_ERROR("Setting up filters failed. Terminating session %s.", session->service->name);
return false;
}
if (SESSION_STATE_TO_BE_FREED != session->state)
{
session->state = SESSION_STATE_ROUTER_READY;
if (session->client_dcb->user == NULL)
{
MXS_INFO("Started session [%" PRIu64 "] for %s service ",
session->ses_id,
service->name);
}
else
{
MXS_INFO("Started %s client session [%" PRIu64 "] for '%s' from %s",
service->name,
session->ses_id,
session->client_dcb->user,
session->client_dcb->remote);
}
}
else
{
MXS_INFO("Start %s client session [%" PRIu64 "] for '%s' from %s failed, will be "
"closed as soon as all related DCBs have been closed.",
service->name,
session->ses_id,
session->client_dcb->user,
session->client_dcb->remote);
}
mxb::atomic::add(&service->stats.n_sessions, 1, mxb::atomic::RELAXED);
mxb::atomic::add(&service->stats.n_current, 1, mxb::atomic::RELAXED);
// Store the session in the client DCB even if the session creation fails.
// It will be freed later on when the DCB is closed.
client_dcb->session = session;
MXS_INFO("Started %s client session [%" PRIu64 "] for '%s' from %s",
service->name, session->ses_id,
session->client_dcb->user ? session->client_dcb->user : "<no user>",
session->client_dcb->remote);
return (session->state == SESSION_STATE_TO_BE_FREED) ? NULL : session;
return true;
}
/**