From 09d20d105915450f8f7497662d26c8def54cf523 Mon Sep 17 00:00:00 2001 From: VilhoRaatikka Date: Fri, 13 Jun 2014 14:52:04 +0300 Subject: [PATCH] Modified dcb_call_foreach so that it doesn't hold spinlock (dcbspin) continuously because it caused deadlock when new slaves were tried to connect with. Fixed a few smallish things. --- server/core/dcb.c | 50 +++++++++++++++--- server/modules/protocol/mysql_backend.c | 51 ++++++++++++++++++- .../routing/readwritesplit/readwritesplit.c | 3 +- 3 files changed, 94 insertions(+), 10 deletions(-) diff --git a/server/core/dcb.c b/server/core/dcb.c index f19cfefb0..fe5b29590 100644 --- a/server/core/dcb.c +++ b/server/core/dcb.c @@ -83,6 +83,7 @@ static bool dcb_set_state_nomutex( const dcb_state_t new_state, dcb_state_t* old_state); static void dcb_call_callback(DCB *dcb, DCB_REASON reason); +static DCB* dcb_get_next (DCB* dcb); DCB* dcb_get_zombies(void) { @@ -1728,6 +1729,41 @@ int rval = 0; return rval; } +static DCB* dcb_get_next ( + DCB* dcb) +{ + DCB* p; + + spinlock_acquire(&dcbspin); + + p = allDCBs; + + if (dcb == NULL || p == NULL) + { + dcb = p; + + } + else + { + while (p != NULL && dcb != p) + { + p = p->next; + } + + if (p != NULL) + { + dcb = p->next; + } + else + { + dcb = NULL; + } + } + spinlock_release(&dcbspin); + + return dcb; +} + void dcb_call_foreach ( SERVER* srv, DCB_REASON reason) @@ -1742,16 +1778,16 @@ void dcb_call_foreach ( case DCB_REASON_NOT_RESPONDING: { DCB* dcb; + dcb = dcb_get_next(NULL); - spinlock_acquire(&dcbspin); - - dcb = allDCBs; - while (dcb) + while (dcb != NULL) { - dcb_call_callback(dcb, DCB_REASON_NOT_RESPONDING); - dcb = dcb->next; + if (dcb->state == DCB_STATE_POLLING) + { + dcb_call_callback(dcb, DCB_REASON_NOT_RESPONDING); + } + dcb = dcb_get_next(dcb); } - spinlock_release(&dcbspin); break; } diff --git a/server/modules/protocol/mysql_backend.c b/server/modules/protocol/mysql_backend.c index 932886a6e..588443c63 100644 --- a/server/modules/protocol/mysql_backend.c +++ b/server/modules/protocol/mysql_backend.c @@ -887,7 +887,56 @@ return_fd: static int gw_backend_hangup(DCB *dcb) { - /*< vraa : errorHandle */ + SESSION* session; + void* rsession; + ROUTER_OBJECT* router; + ROUTER* router_instance; + int rc = 0; + bool succp; + + CHK_DCB(dcb); + session = dcb->session; + CHK_SESSION(session); + rsession = session->router_session; + router = session->service->router; + router_instance = session->service->router_instance; + + mysql_send_custom_error( + dcb->session->client, + 1, + 0, + "Lost connection to backend server."); + + /** + * errorHandle : + * - sulje katkennut yhteys - miten? + * - etsi riittävä määrä servereitä + * - jos epäonnistui, sammuta sessio + * - jos onnistui, jatka + * + * Jos sammutetaan : + * - dcb_close - backend->func.close() + */ + + /*< vraa : errorHandle */ + /* + * + - lähetä virheviesti clientille jos odottaa + errorHandle : + - etsi riittävä määrä servereitä + - jos epäonnistui, sammuta sessio + - jos onnistui, jatka + */ + router->handleError(router_instance, + rsession, + "Lost connection to backend server", + dcb, + ERRACT_NEW_CONNECTION, + &succp); + + if (succp) { + dcb_close(dcb); + } return 1; } diff --git a/server/modules/routing/readwritesplit/readwritesplit.c b/server/modules/routing/readwritesplit/readwritesplit.c index b116bda69..f18f0ac18 100644 --- a/server/modules/routing/readwritesplit/readwritesplit.c +++ b/server/modules/routing/readwritesplit/readwritesplit.c @@ -813,7 +813,7 @@ static bool get_dcb( { backend_ref = rses->rses_master_ref; - if (BREF_IS_IN_USE((&backend_ref[i]))) + if (BREF_IS_IN_USE(backend_ref)) { *p_dcb = backend_ref->bref_dcb; succp = true; @@ -2765,7 +2765,6 @@ static int router_handle_state_switch( case DCB_REASON_NOT_RESPONDING: if (BREF_IS_WAITING_RESULT(bref)) { - printf("foo"); dcb->func.hangup(dcb); } break;