From b7402bcad58cfcc78beb3f7119aa556b87d985d1 Mon Sep 17 00:00:00 2001 From: antirez Date: Wed, 5 Feb 2014 13:10:03 +0100 Subject: [PATCH] Cluster: force AUTH ACK on manual failover. When a slave requests masters vote for a manual failover, the REQUEST_AUTH message is flagged in a special way in order to force the masters to give the authorization even if the master is not marked as failing. --- src/cluster.c | 12 ++++++++++-- src/cluster.h | 2 ++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/cluster.c b/src/cluster.c index 604110f68..faa0eebc0 100644 --- a/src/cluster.c +++ b/src/cluster.c @@ -1896,6 +1896,10 @@ void clusterRequestFailoverAuth(void) { uint32_t totlen; clusterBuildMessageHdr(hdr,CLUSTERMSG_TYPE_FAILOVER_AUTH_REQUEST); + /* If this is a manual failover, set the CLUSTERMSG_FLAG0_FORCEACK bit + * in the header to communicate the nodes receiving the message that + * they should authorized the failover even if the master is working. */ + if (server.cluster->mf_end) hdr->mflags[0] |= CLUSTERMSG_FLAG0_FORCEACK; totlen = sizeof(clusterMsg)-sizeof(union clusterMsgData); hdr->totlen = htonl(totlen); clusterBroadcastMessage(buf,totlen); @@ -1933,6 +1937,7 @@ void clusterSendFailoverAuthIfNeeded(clusterNode *node, clusterMsg *request) { uint64_t requestCurrentEpoch = ntohu64(request->currentEpoch); uint64_t requestConfigEpoch = ntohu64(request->configEpoch); unsigned char *claimed_slots = request->myslots; + int force_ack = request->mflags[0] & CLUSTERMSG_FLAG0_FORCEACK; int j; /* IF we are not a master serving at least 1 slot, we don't have the @@ -1947,8 +1952,11 @@ void clusterSendFailoverAuthIfNeeded(clusterNode *node, clusterMsg *request) { /* I already voted for this epoch? Return ASAP. */ if (server.cluster->last_vote_epoch == server.cluster->currentEpoch) return; - /* Node must be a slave and its master down. */ - if (nodeIsMaster(node) || master == NULL || !nodeFailed(master)) return; + /* Node must be a slave and its master down. + * The master can be non failing if the request is flagged + * with CLUSTERMSG_FLAG0_FORCEACK (manual failover). */ + if (nodeIsMaster(node) || master == NULL || + (!nodeFailed(master) && !force_ack)) return; /* We did not voted for a slave about this master for two * times the node timeout. This is not strictly needed for correctness diff --git a/src/cluster.h b/src/cluster.h index 52edbf780..cbda08987 100644 --- a/src/cluster.h +++ b/src/cluster.h @@ -220,6 +220,8 @@ typedef struct { /* Message flags better specify the packet content or are used to * provide some information about the node state. */ #define CLUSTERMSG_FLAG0_PAUSED (1<<0) /* Master paused for manual failover. */ +#define CLUSTERMSG_FLAG0_FORCEACK (1<<1) /* Give ACK to AUTH_REQUEST even if + master is up. */ /* ---------------------- API exported outside cluster.c -------------------- */ clusterNode *getNodeByQuery(redisClient *c, struct redisCommand *cmd, robj **argv, int argc, int *hashslot, int *ask);