Additional spinlock in random_jkiss. Initial attempt at implementing dummy sessions to provide total consistency - used in mysql_client in relation to authentication - a single static dummy session is used and linked from the client dcb when authentication is not yet complete.

This commit is contained in:
counterpoint
2015-08-28 15:30:06 +01:00
parent 0d62f52812
commit 9c5f622481
7 changed files with 71 additions and 9 deletions

View File

@ -346,9 +346,12 @@ dcb_final_free(DCB *dcb)
local_session->client = NULL; local_session->client = NULL;
spinlock_release(&local_session->ses_lock); spinlock_release(&local_session->ses_lock);
} }
if (SESSION_STATE_DUMMY != local_session->state)
{
session_free(local_session); session_free(local_session);
} }
} }
}
if (dcb->protocol && (!DCB_IS_CLONE(dcb))) if (dcb->protocol && (!DCB_IS_CLONE(dcb)))
free(dcb->protocol); free(dcb->protocol);

View File

@ -117,11 +117,13 @@ static void
random_init_jkiss(void) random_init_jkiss(void)
{ {
int newrand, i; int newrand, i;
spinlock_acquire(&random_jkiss_spinlock);
if ((newrand = random_jkiss_devrand()) != 0) x = newrand; if ((newrand = random_jkiss_devrand()) != 0) x = newrand;
if ((newrand = random_jkiss_devrand()) != 0) y = newrand; if ((newrand = random_jkiss_devrand()) != 0) y = newrand;
if ((newrand = random_jkiss_devrand()) != 0) z = newrand; if ((newrand = random_jkiss_devrand()) != 0) z = newrand;
if ((newrand = random_jkiss_devrand()) != 0) if ((newrand = random_jkiss_devrand()) != 0)
c = newrand % 698769068 + 1; /* Should be less than 698769069 */ c = newrand % 698769068 + 1; /* Should be less than 698769069 */
spinlock_release(&random_jkiss_spinlock);
/* "Warm up" our random number generator */ /* "Warm up" our random number generator */
for (i = 0; i < 100; i++) random_jkiss(); for (i = 0; i < 100; i++) random_jkiss();

View File

@ -56,6 +56,7 @@ static size_t session_id;
static SPINLOCK session_spin = SPINLOCK_INIT; static SPINLOCK session_spin = SPINLOCK_INIT;
static SESSION *allSessions = NULL; static SESSION *allSessions = NULL;
static struct session session_dummy_struct;
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);
@ -212,6 +213,48 @@ session_alloc(SERVICE *service, DCB *client_dcb)
return session; return session;
} }
/**
* Allocate a dummy session so that DCBs can always have sessions.
*
* Only one dummy session exists, it is statically declared
*
* @param client_dcb The client side DCB
* @return The dummy created session
*/
SESSION *
session_alloc_dummy(DCB *client_dcb)
{
SESSION *session;
session = &session_dummy_struct;
#if defined(SS_DEBUG)
session->ses_chk_top = CHK_NUM_SESSION;
session->ses_chk_tail = CHK_NUM_SESSION;
#endif
session->ses_is_child = false;
spinlock_init(&session->ses_lock);
session->service = NULL;
session->client = NULL;
session->n_filters = 0;
memset(&session->stats, 0, sizeof(SESSION_STATS));
session->stats.connect = 0;
session->state = SESSION_STATE_DUMMY;
/*<
* Associate the session to the client DCB and set the reference count on
* the session to indicate that there is a single reference to the
* session. There is no need to protect this or use atomic add as the
* session has not been made available to the other threads at this
* point.
*/
session->data = NULL;
session->refcount = 1;
session->ses_id = 0;
session->next = NULL;
client_dcb->session = session;
return session;
}
/** /**
* Enable specified logging for the current session and increase logger * Enable specified logging for the current session and increase logger
* counter. * counter.
@ -323,6 +366,10 @@ session_simple_free(SESSION *session, DCB *dcb)
} }
if (session) if (session)
{ {
if (SESSION_STATE_DUMMY == session->state)
{
return;
}
if (session && session->router_session) if (session && session->router_session)
{ {
session->service->router->freeSession( session->service->router->freeSession(
@ -344,6 +391,10 @@ session_simple_free(SESSION *session, DCB *dcb)
bool bool
session_free(SESSION *session) session_free(SESSION *session)
{ {
if (session && SESSION_STATE_DUMMY == session->state)
{
return true;
}
CHK_SESSION(session); CHK_SESSION(session);
/* /*
@ -711,6 +762,8 @@ session_state(int state)
{ {
case SESSION_STATE_ALLOC: case SESSION_STATE_ALLOC:
return "Session Allocated"; return "Session Allocated";
case SESSION_STATE_DUMMY:
return "Dummy Session";
case SESSION_STATE_READY: case SESSION_STATE_READY:
return "Session Ready"; return "Session Ready";
case SESSION_STATE_ROUTER_READY: case SESSION_STATE_ROUTER_READY:

View File

@ -64,7 +64,8 @@ typedef enum {
SESSION_STATE_LISTENER, /*< for listener session */ SESSION_STATE_LISTENER, /*< for listener session */
SESSION_STATE_LISTENER_STOPPED, /*< for listener session */ SESSION_STATE_LISTENER_STOPPED, /*< for listener session */
SESSION_STATE_TO_BE_FREED, /*< ready to be freed as soon as there are no references */ SESSION_STATE_TO_BE_FREED, /*< ready to be freed as soon as there are no references */
SESSION_STATE_FREE /*< for all sessions */ SESSION_STATE_FREE, /*< for all sessions */
SESSION_STATE_DUMMY /*< dummy session for consistency */
} session_state_t; } session_state_t;
/** /**
@ -162,6 +163,7 @@ typedef struct session {
SESSION *get_all_sessions(); SESSION *get_all_sessions();
SESSION *session_alloc(struct service *, struct dcb *); SESSION *session_alloc(struct service *, struct dcb *);
SESSION *session_alloc_dummy(struct dcb *);
bool session_free(SESSION *); bool session_free(SESSION *);
int session_isvalid(SESSION *); int session_isvalid(SESSION *);
int session_reply(void *inst, void *session, GWBUF *data); int session_reply(void *inst, void *session, GWBUF *data);

View File

@ -140,7 +140,7 @@ static MYSQL_session* gw_get_shared_session_auth_info(
spinlock_acquire(&dcb->session->ses_lock); spinlock_acquire(&dcb->session->ses_lock);
if (dcb->session->state != SESSION_STATE_ALLOC) { if (dcb->session->state != SESSION_STATE_ALLOC && dcb->session->state != SESSION_STATE_DUMMY) {
auth_info = dcb->session->data; auth_info = dcb->session->data;
} else { } else {
LOGIF(LE, (skygw_log_write_flush( LOGIF(LE, (skygw_log_write_flush(

View File

@ -912,7 +912,7 @@ int gw_read_client_event(
if (session != NULL) if (session != NULL)
{ {
CHK_SESSION(session); CHK_SESSION(session);
ss_dassert(session->state != SESSION_STATE_ALLOC); ss_dassert(session->state != SESSION_STATE_ALLOC && session->state != SESSION_STATE_DUMMY);
protocol->protocol_auth_state = MYSQL_IDLE; protocol->protocol_auth_state = MYSQL_IDLE;
/** /**
@ -1012,7 +1012,7 @@ int gw_read_client_event(
if (session != NULL) if (session != NULL)
{ {
CHK_SESSION(session); CHK_SESSION(session);
ss_dassert(session->state != SESSION_STATE_ALLOC); ss_dassert(session->state != SESSION_STATE_ALLOC && session->state != SESSION_STATE_DUMMY);
protocol->protocol_auth_state = MYSQL_IDLE; protocol->protocol_auth_state = MYSQL_IDLE;
/** /**
@ -1643,6 +1643,7 @@ int gw_MySQLAccept(DCB *listener)
} }
client_dcb->service = listener->session->service; client_dcb->service = listener->session->service;
client_dcb->session = session_alloc_dummy(client_dcb);
client_dcb->fd = c_sock; client_dcb->fd = c_sock;
// get client address // get client address

View File

@ -210,6 +210,7 @@ typedef enum skygw_chk_t {
((s) == DCB_STATE_UNDEFINED ? "DCB_STATE_UNDEFINED" : "DCB_STATE_UNKNOWN"))))))) ((s) == DCB_STATE_UNDEFINED ? "DCB_STATE_UNDEFINED" : "DCB_STATE_UNKNOWN")))))))
#define STRSESSIONSTATE(s) ((s) == SESSION_STATE_ALLOC ? "SESSION_STATE_ALLOC" : \ #define STRSESSIONSTATE(s) ((s) == SESSION_STATE_ALLOC ? "SESSION_STATE_ALLOC" : \
((s) == SESSION_STATE_DUMMY ? "SESSION_STATE_DUMMY" : \
((s) == SESSION_STATE_READY ? "SESSION_STATE_READY" : \ ((s) == SESSION_STATE_READY ? "SESSION_STATE_READY" : \
((s) == SESSION_STATE_LISTENER ? "SESSION_STATE_LISTENER" : \ ((s) == SESSION_STATE_LISTENER ? "SESSION_STATE_LISTENER" : \
((s) == SESSION_STATE_LISTENER_STOPPED ? "SESSION_STATE_LISTENER_STOPPED" : \ ((s) == SESSION_STATE_LISTENER_STOPPED ? "SESSION_STATE_LISTENER_STOPPED" : \