MXS-2710: Move client_count handling inside Session

By incrementing the counters when the session is created, we know that the
counter will always be decremented correctly. This does cause the listener
session to be counted as an actual session but this is already present in
the statistics calculations and is something we have to live with in 2.3
This change also makes it possible to overshoot the connection count
limitation as the session creation is delayed until authentication
fails. Both of these problems are fixed in 2.4.
This commit is contained in:
Markus Mäkelä 2020-01-02 13:50:23 +02:00
parent aa83bc24ae
commit 6306519e5e
No known key found for this signature in database
GPG Key ID: 72D48FCE664F7B19
4 changed files with 18 additions and 27 deletions

View File

@ -2533,11 +2533,6 @@ DCB* dcb_accept(DCB* dcb)
}
}
if (client_dcb)
{
mxb::atomic::add(&client_dcb->service->client_count, 1);
}
return client_dcb;
}

View File

@ -361,18 +361,7 @@ private:
static void session_free(MXS_SESSION* session)
{
MXS_INFO("Stopped %s client session [%" PRIu64 "]", session->service->name, session->ses_id);
Service* service = static_cast<Service*>(session->service);
session_final_free(session);
bool should_destroy = !mxb::atomic::load(&service->active);
if (mxb::atomic::add(&service->client_count, -1) == 1 && should_destroy)
{
// Destroy the service in the main routing worker thread
mxs::RoutingWorker* main_worker = mxs::RoutingWorker::get(mxs::RoutingWorker::MAIN);
main_worker->execute(std::unique_ptr<ServiceDestroyTask>(new ServiceDestroyTask(service)),
Worker::EXECUTE_AUTO);
}
}
static void session_final_free(MXS_SESSION* ses)
@ -1264,6 +1253,7 @@ Session::Session(SERVICE* service)
mxb::atomic::add(&service->stats.n_current, 1, mxb::atomic::RELAXED);
mxb_assert(service->stats.n_current >= 0);
mxb::atomic::add(&service->client_count, 1, mxb::atomic::RELAXED);
}
Session::~Session()
@ -1281,6 +1271,17 @@ Session::~Session()
mxb::atomic::add(&service->stats.n_current, -1, mxb::atomic::RELAXED);
mxb_assert(service->stats.n_current >= 0);
bool should_destroy = !mxb::atomic::load(&service->active);
if (mxb::atomic::add(&service->client_count, -1) == 1 && should_destroy)
{
// Destroy the service in the main routing worker thread
mxs::RoutingWorker* main_worker = mxs::RoutingWorker::get(mxs::RoutingWorker::MAIN);
main_worker->execute(
std::unique_ptr<ServiceDestroyTask>(new ServiceDestroyTask(static_cast<Service*>(service))),
Worker::EXECUTE_AUTO);
}
}
namespace

View File

@ -44,6 +44,9 @@ Session::Session(Client* pClient)
m_client_dcb.data = &m_mysql_session;
service = &dummy_service;
// This prevents the destruction of the dummy service
service->active = true;
}
Session::~Session()

View File

@ -740,20 +740,12 @@ static void check_packet(DCB* dcb, GWBUF* buf, int bytes)
*/
static int gw_read_do_authentication(DCB* dcb, GWBUF* read_buffer, int nbytes_read)
{
// If this function fails and dcb is closed, the service client count must be decremented manually.
// After authentication, the session closing code decrements the count.
auto decrement_and_close = [](DCB* dcb)
{
mxb::atomic::add(&dcb->service->client_count, -1);
dcb_close(dcb);
};
MXB_AT_DEBUG(check_packet(dcb, read_buffer, nbytes_read));
/** Allocate the shared session structure */
if (dcb->data == NULL && (dcb->data = mysql_session_alloc()) == NULL)
{
decrement_and_close(dcb);
dcb_close(dcb);
return 1;
}
@ -820,7 +812,7 @@ static int gw_read_do_authentication(DCB* dcb, GWBUF* read_buffer, int nbytes_re
MYSQL_session* ses = (MYSQL_session*)dcb->data;
if ((dcb->user = MXS_STRDUP(ses->user)) == NULL)
{
decrement_and_close(dcb);
dcb_close(dcb);
gwbuf_free(read_buffer);
return 0;
}
@ -873,7 +865,7 @@ static int gw_read_do_authentication(DCB* dcb, GWBUF* read_buffer, int nbytes_re
/**
* Close DCB and which will release MYSQL_session
*/
decrement_and_close(dcb);
dcb_close(dcb);
}
/* One way or another, the buffer is now fully processed */
gwbuf_free(read_buffer);