if (!strncmp(reply,"+CONTINUE",9)) { /* Check the new replication ID advertised by the master. If it * changed, we need to set the new ID as primary ID, and set * secondary ID as the old master ID up to the current offset, so * that our sub-slaves will be able to PSYNC with us after a * disconnection. */ char *start = reply+10; char *end = reply+9; while(end[0] != '\r' && end[0] != '\n' && end[0] != '\0') end++; if (end-start == CONFIG_RUN_ID_SIZE) { char new[CONFIG_RUN_ID_SIZE+1]; memcpy(new,start,CONFIG_RUN_ID_SIZE); new[CONFIG_RUN_ID_SIZE] = '\0';
if (strcmp(new,server.cached_master->replid)) { /* Master ID changed. */ serverLog(LL_WARNING,"Master replication ID changed to %s",new);
/* Set the old ID as our ID2, up to the current offset+1. */ memcpy(server.replid2,server.cached_master->replid, sizeof(server.replid2)); server.second_replid_offset = server.master_repl_offset+1;
/* Update the cached master ID and our own primary ID to the * new one. */ memcpy(server.replid,new,sizeof(server.replid)); memcpy(server.cached_master->replid,new,sizeof(server.replid));
/* Disconnect all the sub-slaves: they need to be notified. */ disconnectSlaves(); } } ... }
/* Check if this is a failover request to a replica with the same replid and * become a master if so. */ if (c->argc > 3 && !strcasecmp(c->argv[0]->ptr,"psync") && !strcasecmp(c->argv[3]->ptr,"failover")) { serverLog(LL_WARNING, "Failover request received for replid %s.", (unsignedchar *)c->argv[1]->ptr); if (!server.masterhost) { addReplyError(c, "PSYNC FAILOVER can't be sent to a master."); return; }
if (!strcasecmp(c->argv[1]->ptr,server.replid)) { replicationUnsetMaster(); sds client = catClientInfoString(sdsempty(),c); serverLog(LL_NOTICE, "MASTER MODE enabled (failover request from '%s')",client); sdsfree(client); } else { addReplyError(c, "PSYNC FAILOVER replid must match my replid."); return; } }
/* Cancel replication, setting the instance as a master itself. */ voidreplicationUnsetMaster(void) { if (server.masterhost == NULL) return; /* Nothing to do. */ ... /* Clear masterhost first, since the freeClient calls * replicationHandleMasterDisconnection which can attempt to re-connect. */ sdsfree(server.masterhost); server.masterhost = NULL; if (server.master) freeClient(server.master); replicationDiscardCachedMaster(); cancelReplicationHandshake(0); /* When a slave is turned into a master, the current replication ID * (that was inherited from the master at synchronization time) is * used as secondary ID up to the current offset, and a new replication * ID is created to continue with a new replication history. */ shiftReplicationId(); /* Disconnecting all the slaves is required: we need to inform slaves * of the replication ID change (see shiftReplicationId() call). However * the slaves will be able to partially resync with us, so it will be * a very fast reconnection. */ disconnectSlaves(); server.repl_state = REPL_STATE_NONE; ... }