From 3870b81244c126c13f8dbfb896f01b33476d383b Mon Sep 17 00:00:00 2001 From: Markus Makela Date: Wed, 2 Nov 2016 19:55:36 +0200 Subject: [PATCH] Prevent unintentional reconnections to the master server If a master_failure_mode was set to error_on_write, a reconnection to the old master would happen after the following events: - Master server fails and the connection is closed - The master server recovers - A slave fails and the connection is closed - A replacement for the slave is searched If these events took place, the master would be taken back into use with an inconsistent session state. --- server/modules/include/readwritesplit.h | 4 ++-- .../modules/routing/readwritesplit/readwritesplit.c | 11 +++++++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/server/modules/include/readwritesplit.h b/server/modules/include/readwritesplit.h index 81d2d450a..c58136b7f 100644 --- a/server/modules/include/readwritesplit.h +++ b/server/modules/include/readwritesplit.h @@ -54,7 +54,7 @@ typedef enum bref_state BREF_WAITING_RESULT = 0x02, /*< for session commands only */ BREF_QUERY_ACTIVE = 0x04, /*< for other queries */ BREF_CLOSED = 0x08, - BREF_SESCMD_FAILED = 0x10 /*< Backend references that should be dropped */ + BREF_FATAL_FAILURE = 0x10 /*< Backend references that should be dropped */ } bref_state_t; #define BREF_IS_NOT_USED(s) ((s)->bref_state & ~BREF_IN_USE) @@ -62,7 +62,7 @@ typedef enum bref_state #define BREF_IS_WAITING_RESULT(s) ((s)->bref_num_result_wait > 0) #define BREF_IS_QUERY_ACTIVE(s) ((s)->bref_state & BREF_QUERY_ACTIVE) #define BREF_IS_CLOSED(s) ((s)->bref_state & BREF_CLOSED) -#define BREF_HAS_FAILED(s) ((s)->bref_state & BREF_SESCMD_FAILED) +#define BREF_HAS_FAILED(s) ((s)->bref_state & BREF_FATAL_FAILURE) typedef enum backend_type_t { diff --git a/server/modules/routing/readwritesplit/readwritesplit.c b/server/modules/routing/readwritesplit/readwritesplit.c index 61292c7e3..b13ff7155 100644 --- a/server/modules/routing/readwritesplit/readwritesplit.c +++ b/server/modules/routing/readwritesplit/readwritesplit.c @@ -3394,7 +3394,7 @@ static GWBUF *sescmd_cursor_process_replies(GWBUF *replybuf, bref_clear_state(bref, BREF_QUERY_ACTIVE); bref_clear_state(bref, BREF_IN_USE); bref_set_state(bref, BREF_CLOSED); - bref_set_state(bref, BREF_SESCMD_FAILED); + bref_set_state(bref, BREF_FATAL_FAILURE); if (bref->bref_dcb) { dcb_close(bref->bref_dcb); @@ -3435,7 +3435,7 @@ static GWBUF *sescmd_cursor_process_replies(GWBUF *replybuf, bref_clear_state(&ses->rses_backend_ref[i], BREF_QUERY_ACTIVE); bref_clear_state(&ses->rses_backend_ref[i], BREF_IN_USE); bref_set_state(&ses->rses_backend_ref[i], BREF_CLOSED); - bref_set_state(bref, BREF_SESCMD_FAILED); + bref_set_state(bref, BREF_FATAL_FAILURE); if (ses->rses_backend_ref[i].bref_dcb) { dcb_close(ses->rses_backend_ref[i].bref_dcb); @@ -4329,6 +4329,13 @@ static void handleError(ROUTER *instance, void *router_session, * case the safest thing to do is to close the client * connection. */ can_continue = true; + + if (bref) + { + /** Mark the master as failed so that it won't be + * taken into use if it comes back up. */ + bref_set_state(bref, BREF_FATAL_FAILURE); + } } else if (!srv->master_err_is_logged) {