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.
This commit is contained in:
Markus Makela
2016-11-02 19:55:36 +02:00
parent 572d466fad
commit 3870b81244
2 changed files with 11 additions and 4 deletions

View File

@ -54,7 +54,7 @@ typedef enum bref_state
BREF_WAITING_RESULT = 0x02, /*< for session commands only */ BREF_WAITING_RESULT = 0x02, /*< for session commands only */
BREF_QUERY_ACTIVE = 0x04, /*< for other queries */ BREF_QUERY_ACTIVE = 0x04, /*< for other queries */
BREF_CLOSED = 0x08, 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; } bref_state_t;
#define BREF_IS_NOT_USED(s) ((s)->bref_state & ~BREF_IN_USE) #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_WAITING_RESULT(s) ((s)->bref_num_result_wait > 0)
#define BREF_IS_QUERY_ACTIVE(s) ((s)->bref_state & BREF_QUERY_ACTIVE) #define BREF_IS_QUERY_ACTIVE(s) ((s)->bref_state & BREF_QUERY_ACTIVE)
#define BREF_IS_CLOSED(s) ((s)->bref_state & BREF_CLOSED) #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 typedef enum backend_type_t
{ {

View File

@ -3394,7 +3394,7 @@ static GWBUF *sescmd_cursor_process_replies(GWBUF *replybuf,
bref_clear_state(bref, BREF_QUERY_ACTIVE); bref_clear_state(bref, BREF_QUERY_ACTIVE);
bref_clear_state(bref, BREF_IN_USE); bref_clear_state(bref, BREF_IN_USE);
bref_set_state(bref, BREF_CLOSED); bref_set_state(bref, BREF_CLOSED);
bref_set_state(bref, BREF_SESCMD_FAILED); bref_set_state(bref, BREF_FATAL_FAILURE);
if (bref->bref_dcb) if (bref->bref_dcb)
{ {
dcb_close(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_QUERY_ACTIVE);
bref_clear_state(&ses->rses_backend_ref[i], BREF_IN_USE); bref_clear_state(&ses->rses_backend_ref[i], BREF_IN_USE);
bref_set_state(&ses->rses_backend_ref[i], BREF_CLOSED); 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) if (ses->rses_backend_ref[i].bref_dcb)
{ {
dcb_close(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 * case the safest thing to do is to close the client
* connection. */ * connection. */
can_continue = true; 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) else if (!srv->master_err_is_logged)
{ {