dcb.c:dcb_clone: set same close function than in the original DCB so that routing session will become closed when client DCB is closed.
session.h:introduce a new state which indicates that SESSION structure can be freed next, SESSION_STATE_TO_BE_FREED. State is needed to separate the state before and after memory free. Memory is freed in different situation depending on whether the session is parent or child session. Child sessions are freed in their parent.
Also introduce a new member in SESSION struct, ses_is_child, to indicate whether SESSION has a parent session which is responsible for releasing the memory of it.

session.c:session_unlink_dcb:when last session reference is removed set SESSION->state=SESSION_STATE_TO_BE_FREED
session.c:session_free:only free the memory if session is not child session. If it is child, session is left to be freed by the parent (in tee filter's freeSession, for example).

tee.c:newSession:mark branch session to child.
tee.c:freeSession:if child session memory is ready to be freed, free it.

mysql_mon.c:monitorMain:when backend server's status changes so that it is not running anymore or doesn't have any of the states - master, slave, ndb, joined - call for each DCB the callback-function DCB_REASON_NOT_RESPONDING if specified. Earlier callbacks were called if there was any change in the state of the server being monitored.
This commit is contained in:
VilhoRaatikka
2014-12-22 16:24:07 +02:00
parent c33e17db31
commit 6b6ac2f95f
7 changed files with 82 additions and 36 deletions

View File

@ -321,7 +321,11 @@ DCB *clone;
clone->protocol = orig->protocol; clone->protocol = orig->protocol;
clone->func.write = dcb_null_write; clone->func.write = dcb_null_write;
#if 1
clone->func.close = orig->func.close;
#else
clone->func.close = dcb_null_close; clone->func.close = dcb_null_close;
#endif
clone->func.auth = dcb_null_auth; clone->func.auth = dcb_null_auth;
return clone; return clone;
@ -1254,20 +1258,20 @@ dcb_close(DCB *dcb)
if (rc == 0) if (rc == 0)
{ {
/** /**
* close protocol and router session * close protocol and router session
*/ */
if (dcb->func.close != NULL) if (dcb->func.close != NULL)
{ {
dcb->func.close(dcb); dcb->func.close(dcb);
} }
/** Call possible callback for this DCB in case of close */
dcb_call_callback(dcb, DCB_REASON_CLOSE); dcb_call_callback(dcb, DCB_REASON_CLOSE);
if (dcb->state == DCB_STATE_NOPOLLING) if (dcb->state == DCB_STATE_NOPOLLING)
{ {
dcb_add_to_zombieslist(dcb); dcb_add_to_zombieslist(dcb);
} }
} }
ss_dassert(dcb->state == DCB_STATE_NOPOLLING || ss_dassert(dcb->state == DCB_STATE_NOPOLLING ||
dcb->state == DCB_STATE_ZOMBIE); dcb->state == DCB_STATE_ZOMBIE);
} }
@ -1975,11 +1979,6 @@ dcb_call_callback(DCB *dcb, DCB_REASON reason)
{ {
DCB_CALLBACK *cb, *nextcb; DCB_CALLBACK *cb, *nextcb;
LOGIF(LD, (skygw_log_write(LOGFILE_DEBUG,
"%lu [dcb_call_callback] %s",
pthread_self(),
STRDCBREASON(reason))));
spinlock_acquire(&dcb->cb_lock); spinlock_acquire(&dcb->cb_lock);
cb = dcb->callbacks; cb = dcb->callbacks;
while (cb) while (cb)
@ -1988,6 +1987,12 @@ DCB_CALLBACK *cb, *nextcb;
{ {
nextcb = cb->next; nextcb = cb->next;
spinlock_release(&dcb->cb_lock); spinlock_release(&dcb->cb_lock);
LOGIF(LD, (skygw_log_write(LOGFILE_DEBUG,
"%lu [dcb_call_callback] %s",
pthread_self(),
STRDCBREASON(reason))));
cb->cb(dcb, reason, cb->userdata); cb->cb(dcb, reason, cb->userdata);
spinlock_acquire(&dcb->cb_lock); spinlock_acquire(&dcb->cb_lock);
cb = nextcb; cb = nextcb;

View File

@ -331,7 +331,7 @@ int session_unlink_dcb(
if (nlink == 0) if (nlink == 0)
{ {
session->state = SESSION_STATE_FREE; session->state = SESSION_STATE_TO_BE_FREED;
} }
if (dcb != NULL) if (dcb != NULL)
@ -388,11 +388,15 @@ bool session_free(
spinlock_release(&session_spin); spinlock_release(&session_spin);
atomic_add(&session->service->stats.n_current, -1); atomic_add(&session->service->stats.n_current, -1);
/* Free router_session and session */ /**
if (session->router_session) { * Free router_session and set it NULL
*/
if (session->router_session)
{
session->service->router->freeSession( session->service->router->freeSession(
session->service->router_instance, session->service->router_instance,
session->router_session); session->router_session);
session->router_session = NULL;
} }
if (session->n_filters) if (session->n_filters)
{ {
@ -422,7 +426,12 @@ bool session_free(
/** Disable trace and decrease trace logger counter */ /** Disable trace and decrease trace logger counter */
session_disable_log(session, LT); session_disable_log(session, LT);
free(session); /** If session doesn't have parent referencing to it, it can be freed */
if (!session->ses_is_child)
{
session->state = SESSION_STATE_FREE;
free(session);
}
succp = true; succp = true;
return_succp : return_succp :

View File

@ -61,6 +61,7 @@ typedef enum {
SESSION_STATE_STOPPING, /*< session and router are being closed */ SESSION_STATE_STOPPING, /*< session and router are being closed */
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_FREE /*< for all sessions */ SESSION_STATE_FREE /*< for all sessions */
} session_state_t; } session_state_t;
@ -124,6 +125,7 @@ typedef struct session {
UPSTREAM tail; /*< The tail of the filter chain */ UPSTREAM tail; /*< The tail of the filter chain */
struct session *next; /*< Linked list of all sessions */ struct session *next; /*< Linked list of all sessions */
int refcount; /*< Reference count on the session */ int refcount; /*< Reference count on the session */
bool ses_is_child; /*< this is a child session */
#if defined(SS_DEBUG) #if defined(SS_DEBUG)
skygw_chk_t ses_chk_tail; skygw_chk_t ses_chk_tail;
#endif #endif

View File

@ -326,7 +326,7 @@ char *remote, *userName;
{ {
my_session->active = 0; my_session->active = 0;
LOGIF(LE, (skygw_log_write( LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR, LOGFILE_ERROR,
"Warning : Tee filter is not active."))); "Warning : Tee filter is not active.")));
} }
@ -339,7 +339,7 @@ char *remote, *userName;
{ {
my_session->active = 0; my_session->active = 0;
LOGIF(LE, (skygw_log_write( LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR, LOGFILE_ERROR,
"Warning : Tee filter is not active."))); "Warning : Tee filter is not active.")));
} }
@ -354,7 +354,7 @@ char *remote, *userName;
freeSession(my_instance, (void *)my_session); freeSession(my_instance, (void *)my_session);
my_session = NULL; my_session = NULL;
LOGIF(LE, (skygw_log_write( LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR, LOGFILE_ERROR,
"Error : Creating client DCB for Tee " "Error : Creating client DCB for Tee "
"filter failed. Terminating session."))); "filter failed. Terminating session.")));
@ -366,13 +366,14 @@ char *remote, *userName;
dcb_close(dcb); dcb_close(dcb);
freeSession(my_instance, (void *)my_session); freeSession(my_instance, (void *)my_session);
my_session = NULL; my_session = NULL;
LOGIF(LE, (skygw_log_write( LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR, LOGFILE_ERROR,
"Error : Creating client session for Tee " "Error : Creating client session for Tee "
"filter failed. Terminating session."))); "filter failed. Terminating session.")));
goto retblock; goto retblock;
} }
ses->ses_is_child = true;
my_session->branch_session = ses; my_session->branch_session = ses;
my_session->branch_dcb = dcb; my_session->branch_dcb = dcb;
} }
@ -435,7 +436,13 @@ static void
freeSession(FILTER *instance, void *session) freeSession(FILTER *instance, void *session)
{ {
TEE_SESSION *my_session = (TEE_SESSION *)session; TEE_SESSION *my_session = (TEE_SESSION *)session;
SESSION* ses = my_session->branch_session;
if (ses != NULL && ses->state == SESSION_STATE_TO_BE_FREED)
{
ses->state = SESSION_STATE_FREE;
free(ses);
}
free(session); free(session);
return; return;
} }

View File

@ -680,8 +680,11 @@ int log_no_master = 1;
ptr->server->name, ptr->server->name,
ptr->server->port))); ptr->server->port)));
} }
if (!(SERVER_IS_RUNNING(ptr->server)) ||
dcb_call_foreach(DCB_REASON_NOT_RESPONDING); !(SERVER_IS_IN_CLUSTER(ptr->server)))
{
dcb_call_foreach(DCB_REASON_NOT_RESPONDING);
}
} }
if (mon_status_changed(ptr)) if (mon_status_changed(ptr))
@ -773,14 +776,18 @@ int log_no_master = 1;
ptr->server->status = ptr->pending_status; ptr->server->status = ptr->pending_status;
} }
} }
ptr = ptr->next; ptr = ptr->next;
} }
/* log master detection failure od first master becomes available after failure */ /* log master detection failure od first master becomes available after failure */
if (root_master && mon_status_changed(root_master) && !(root_master->server->status & SERVER_STALE_STATUS)) { if (root_master &&
mon_status_changed(root_master) &&
!(root_master->server->status & SERVER_STALE_STATUS))
{
if (root_master->pending_status & (SERVER_MASTER)) { if (root_master->pending_status & (SERVER_MASTER)) {
if (!(root_master->mon_prev_status & SERVER_STALE_STATUS) && !(root_master->server->status & SERVER_MAINT)) { if (!(root_master->mon_prev_status & SERVER_STALE_STATUS) &&
!(root_master->server->status & SERVER_MAINT))
{
LOGIF(LM, (skygw_log_write( LOGIF(LM, (skygw_log_write(
LOGFILE_MESSAGE, LOGFILE_MESSAGE,
"Info: A Master Server is now available: %s:%i", "Info: A Master Server is now available: %s:%i",
@ -796,7 +803,8 @@ int log_no_master = 1;
} }
log_no_master = 1; log_no_master = 1;
} else { } else {
if (!root_master && log_no_master) { if (!root_master && log_no_master)
{
LOGIF(LE, (skygw_log_write_flush( LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR, LOGFILE_ERROR,
"Error: No Master can be determined"))); "Error: No Master can be determined")));
@ -805,13 +813,21 @@ int log_no_master = 1;
} }
/* Do now the heartbeat replication set/get for MySQL Replication Consistency */ /* Do now the heartbeat replication set/get for MySQL Replication Consistency */
if (replication_heartbeat && root_master && (SERVER_IS_MASTER(root_master->server) || SERVER_IS_RELAY_SERVER(root_master->server))) { if (replication_heartbeat &&
root_master &&
(SERVER_IS_MASTER(root_master->server) ||
SERVER_IS_RELAY_SERVER(root_master->server)))
{
set_master_heartbeat(handle, root_master); set_master_heartbeat(handle, root_master);
ptr = handle->databases; ptr = handle->databases;
while (ptr) { while (ptr) {
if( (! SERVER_IN_MAINT(ptr->server)) && SERVER_IS_RUNNING(ptr->server)) if( (! SERVER_IN_MAINT(ptr->server)) && SERVER_IS_RUNNING(ptr->server))
{ {
if (ptr->server->node_id != root_master->server->node_id && (SERVER_IS_SLAVE(ptr->server) || SERVER_IS_RELAY_SERVER(ptr->server))) { if (ptr->server->node_id != root_master->server->node_id &&
(SERVER_IS_SLAVE(ptr->server) ||
SERVER_IS_RELAY_SERVER(ptr->server)))
{
set_slave_heartbeat(handle, ptr); set_slave_heartbeat(handle, ptr);
} }
} }

View File

@ -1510,7 +1510,14 @@ static GWBUF* process_response_data (
bool succp; bool succp;
srvcmd = protocol_get_srv_command(p, false); srvcmd = protocol_get_srv_command(p, false);
LOGIF(LD, (skygw_log_write(
LOGFILE_DEBUG,
"%lu [process_response_data] Read command %s for DCB %p fd %d.",
pthread_self(),
STRPACKETTYPE(srvcmd),
dcb,
dcb->fd)));
/** /**
* Read values from protocol structure, fails if values are * Read values from protocol structure, fails if values are
* uninitialized. * uninitialized.

View File

@ -391,7 +391,7 @@ ROUTER_OBJECT* GetModuleObject()
/** /**
* Refresh the instance by hte given parameter value. * Refresh the instance by the given parameter value.
* *
* @param router Router instance * @param router Router instance
* @param singleparam Parameter fo be reloaded * @param singleparam Parameter fo be reloaded
@ -4763,19 +4763,19 @@ static int router_handle_state_switch(
srv = bref->bref_backend->backend_server; srv = bref->bref_backend->backend_server;
LOGIF(LD, (skygw_log_write(LOGFILE_DEBUG,
"%lu [router_handle_state_switch] %s %s:%d in state %s",
pthread_self(),
STRDCBREASON(reason),
srv->name,
srv->port,
STRSRVSTATUS(srv))));
if (SERVER_IS_RUNNING(srv) && SERVER_IS_IN_CLUSTER(srv)) if (SERVER_IS_RUNNING(srv) && SERVER_IS_IN_CLUSTER(srv))
{ {
goto return_rc; goto return_rc;
} }
ses = dcb->session;
LOGIF(LD, (skygw_log_write(LOGFILE_DEBUG,
"%lu [router_handle_state_switch] %s %s:%d in state %s",
pthread_self(),
STRDCBREASON(reason),
srv->name,
srv->port,
STRSRVSTATUS(srv))));
ses = dcb->session;
CHK_SESSION(ses); CHK_SESSION(ses);
rses = (ROUTER_CLIENT_SES *)dcb->session->router_session; rses = (ROUTER_CLIENT_SES *)dcb->session->router_session;