Adapt session timeout checks to a per thread model
Each thread will now check their own list of DCBs for timed out sessions.
This commit is contained in:
@ -377,6 +377,8 @@ int dcb_accept_SSL(DCB* dcb);
|
|||||||
int dcb_connect_SSL(DCB* dcb);
|
int dcb_connect_SSL(DCB* dcb);
|
||||||
int dcb_listen(DCB *listener, const char *config, const char *protocol_name);
|
int dcb_listen(DCB *listener, const char *config, const char *protocol_name);
|
||||||
void dcb_append_readqueue(DCB *dcb, GWBUF *buffer);
|
void dcb_append_readqueue(DCB *dcb, GWBUF *buffer);
|
||||||
|
void dcb_enable_session_timeouts();
|
||||||
|
void dcb_process_idle_sessions(int thr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DCB flags values
|
* DCB flags values
|
||||||
|
@ -185,13 +185,6 @@ typedef struct session
|
|||||||
.stats = SESSION_STATS_INIT, .head = DOWNSTREAM_INIT, .tail = UPSTREAM_INIT, \
|
.stats = SESSION_STATS_INIT, .head = DOWNSTREAM_INIT, .tail = UPSTREAM_INIT, \
|
||||||
.state = SESSION_STATE_ALLOC, .ses_chk_tail = CHK_NUM_SESSION}
|
.state = SESSION_STATE_ALLOC, .ses_chk_tail = CHK_NUM_SESSION}
|
||||||
|
|
||||||
/** Whether to do session timeout checks */
|
|
||||||
extern bool check_timeouts;
|
|
||||||
|
|
||||||
/** When the next timeout check is done. This is compared to hkheartbeat in
|
|
||||||
* hk_heartbeat.h */
|
|
||||||
extern long next_timeout_check;
|
|
||||||
|
|
||||||
#define SESSION_PROTOCOL(x, type) DCB_PROTOCOL((x)->client_dcb, type)
|
#define SESSION_PROTOCOL(x, type) DCB_PROTOCOL((x)->client_dcb, type)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -231,8 +224,6 @@ SESSION* get_session_by_router_ses(void* rses);
|
|||||||
void session_enable_log_priority(SESSION* ses, int priority);
|
void session_enable_log_priority(SESSION* ses, int priority);
|
||||||
void session_disable_log_priority(SESSION* ses, int priority);
|
void session_disable_log_priority(SESSION* ses, int priority);
|
||||||
RESULTSET *sessionGetList(SESSIONLISTFILTER);
|
RESULTSET *sessionGetList(SESSIONLISTFILTER);
|
||||||
void process_idle_sessions();
|
|
||||||
void enable_session_timeouts();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the transaction state of the session.
|
* Get the transaction state of the session.
|
||||||
|
@ -92,6 +92,7 @@
|
|||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
#include <maxscale/alloc.h>
|
#include <maxscale/alloc.h>
|
||||||
#include <maxscale/utils.h>
|
#include <maxscale/utils.h>
|
||||||
|
#include <maxscale/platform.h>
|
||||||
|
|
||||||
/* The list of all DCBs */
|
/* The list of all DCBs */
|
||||||
static LIST_CONFIG DCBlist =
|
static LIST_CONFIG DCBlist =
|
||||||
@ -107,6 +108,10 @@ static int *nzombies;
|
|||||||
static int maxzombies = 0;
|
static int maxzombies = 0;
|
||||||
static SPINLOCK zombiespin = SPINLOCK_INIT;
|
static SPINLOCK zombiespin = SPINLOCK_INIT;
|
||||||
|
|
||||||
|
/** Variables for session timeout checks */
|
||||||
|
bool check_timeouts = false;
|
||||||
|
thread_local long next_timeout_check = 0;
|
||||||
|
|
||||||
void dcb_global_init()
|
void dcb_global_init()
|
||||||
{
|
{
|
||||||
int nthreads = config_threadcount();
|
int nthreads = config_threadcount();
|
||||||
@ -3479,3 +3484,41 @@ static void dcb_remove_from_list(DCB *dcb)
|
|||||||
|
|
||||||
spinlock_release(&all_dcbs_lock[dcb->owner]);
|
spinlock_release(&all_dcbs_lock[dcb->owner]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable the timing out of idle connections.
|
||||||
|
*/
|
||||||
|
void dcb_enable_session_timeouts()
|
||||||
|
{
|
||||||
|
check_timeouts = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close sessions that have been idle for too long.
|
||||||
|
*
|
||||||
|
* If the time since a session last sent data is greater than the set value in the
|
||||||
|
* service, it is disconnected. The connection timeout is disabled by default.
|
||||||
|
*/
|
||||||
|
void dcb_process_idle_sessions(int thr)
|
||||||
|
{
|
||||||
|
if (check_timeouts && hkheartbeat >= next_timeout_check)
|
||||||
|
{
|
||||||
|
/** Because the resolution of the timeout is one second, we only need to
|
||||||
|
* check for it once per second. One heartbeat is 100 milliseconds. */
|
||||||
|
next_timeout_check = hkheartbeat + 10;
|
||||||
|
|
||||||
|
for (DCB *dcb = all_dcbs[thr]; dcb; dcb = dcb->memdata.next)
|
||||||
|
{
|
||||||
|
if (dcb->dcb_role == DCB_ROLE_CLIENT_HANDLER)
|
||||||
|
{
|
||||||
|
SESSION *session = dcb->session;
|
||||||
|
|
||||||
|
if (session->service && session->client_dcb && session->client_dcb->state == DCB_STATE_POLLING &&
|
||||||
|
hkheartbeat - session->client_dcb->last_read > session->service->conn_idle_timeout * 10)
|
||||||
|
{
|
||||||
|
poll_fake_hangup_event(dcb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -752,10 +752,7 @@ poll_waitevents(void *arg)
|
|||||||
MXS_FREE(tmp);
|
MXS_FREE(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_timeouts && hkheartbeat >= next_timeout_check)
|
dcb_process_idle_sessions(thread_id);
|
||||||
{
|
|
||||||
process_idle_sessions();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (thread_data)
|
if (thread_data)
|
||||||
{
|
{
|
||||||
|
@ -1052,7 +1052,7 @@ serviceSetTimeout(SERVICE *service, int val)
|
|||||||
* configured with a idle timeout. */
|
* configured with a idle timeout. */
|
||||||
if ((service->conn_idle_timeout = val))
|
if ((service->conn_idle_timeout = val))
|
||||||
{
|
{
|
||||||
enable_session_timeouts();
|
dcb_enable_session_timeouts();
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -56,14 +56,6 @@ static int session_id;
|
|||||||
|
|
||||||
static struct session session_dummy_struct;
|
static struct session session_dummy_struct;
|
||||||
|
|
||||||
/**
|
|
||||||
* These two are declared in session.h
|
|
||||||
*/
|
|
||||||
bool check_timeouts = false;
|
|
||||||
long next_timeout_check = 0;
|
|
||||||
|
|
||||||
static SPINLOCK timeout_lock = SPINLOCK_INIT;
|
|
||||||
|
|
||||||
static void session_initialize(void *session);
|
static void session_initialize(void *session);
|
||||||
static int session_setup_filters(SESSION *session);
|
static int session_setup_filters(SESSION *session);
|
||||||
static void session_simple_free(SESSION *session, DCB *dcb);
|
static void session_simple_free(SESSION *session, DCB *dcb);
|
||||||
@ -894,50 +886,6 @@ session_getUser(SESSION *session)
|
|||||||
return (session && session->client_dcb) ? session->client_dcb->user : NULL;
|
return (session && session->client_dcb) ? session->client_dcb->user : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Enable the timing out of idle connections.
|
|
||||||
*
|
|
||||||
* This will prevent unnecessary acquisitions of the session spinlock if no
|
|
||||||
* service is configured with a session idle timeout.
|
|
||||||
*/
|
|
||||||
void enable_session_timeouts()
|
|
||||||
{
|
|
||||||
check_timeouts = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Close sessions that have been idle for too long.
|
|
||||||
*
|
|
||||||
* If the time since a session last sent data is greater than the set value in the
|
|
||||||
* service, it is disconnected. The connection timeout is disabled by default.
|
|
||||||
*/
|
|
||||||
void process_idle_sessions()
|
|
||||||
{
|
|
||||||
if (spinlock_acquire_nowait(&timeout_lock))
|
|
||||||
{
|
|
||||||
if (hkheartbeat >= next_timeout_check)
|
|
||||||
{
|
|
||||||
list_entry_t *current = list_start_iteration(&SESSIONlist);
|
|
||||||
/** Because the resolution of the timeout is one second, we only need to
|
|
||||||
* check for it once per second. One heartbeat is 100 milliseconds. */
|
|
||||||
next_timeout_check = hkheartbeat + 10;
|
|
||||||
while (current)
|
|
||||||
{
|
|
||||||
SESSION *all_session = (SESSION *)current;
|
|
||||||
|
|
||||||
if (all_session->service && all_session->client_dcb && all_session->client_dcb->state == DCB_STATE_POLLING &&
|
|
||||||
hkheartbeat - all_session->client_dcb->last_read > all_session->service->conn_idle_timeout * 10)
|
|
||||||
{
|
|
||||||
poll_fake_hangup_event(all_session->client_dcb);
|
|
||||||
}
|
|
||||||
|
|
||||||
current = list_iterate(&SESSIONlist, current);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
spinlock_release(&timeout_lock);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback structure for the session list extraction
|
* Callback structure for the session list extraction
|
||||||
*/
|
*/
|
||||||
|
Reference in New Issue
Block a user