Fix for slaves chains. Force resync of slaves (simply disconnecting them) when SLAVEOF turns a master into a slave.

This commit is contained in:
antirez
2012-03-29 09:24:02 +02:00
parent 9a5cbf9f7e
commit 6938960b66
3 changed files with 17 additions and 14 deletions

View File

@ -491,6 +491,16 @@ static void freeClientArgv(redisClient *c) {
c->cmd = NULL; c->cmd = NULL;
} }
/* Close all the slaves connections. This is useful in chained replication
* when we resync with our own master and want to force all our slaves to
* resync with us as well. */
void disconnectSlaves(void) {
while (listLength(server.slaves)) {
listNode *ln = listFirst(server.slaves);
freeClient((redisClient*)ln->value);
}
}
void freeClient(redisClient *c) { void freeClient(redisClient *c) {
listNode *ln; listNode *ln;
@ -568,21 +578,12 @@ void freeClient(redisClient *c) {
server.master = NULL; server.master = NULL;
server.replstate = REDIS_REPL_CONNECT; server.replstate = REDIS_REPL_CONNECT;
server.repl_down_since = time(NULL); server.repl_down_since = time(NULL);
/* Since we lost the connection with the master, we should also /* We lost connection with our master, force our slaves to resync
* close the connection with all our slaves if we have any, so * with us as well to load the new data set.
* when we'll resync with the master the other slaves will sync again
* with us as well. Note that also when the slave is not connected
* to the master it will keep refusing connections by other slaves.
* *
* We do this only if server.masterhost != NULL. If it is NULL this * If server.masterhost is NULL the user called SLAVEOF NO ONE so
* means the user called SLAVEOF NO ONE and we are freeing our * slave resync is not needed. */
* link with the master, so no need to close link with slaves. */ if (server.masterhost != NULL) disconnectSlaves();
if (server.masterhost != NULL) {
while (listLength(server.slaves)) {
ln = listFirst(server.slaves);
freeClient((redisClient*)ln->value);
}
}
} }
/* Release memory */ /* Release memory */
zfree(c->argv); zfree(c->argv);

View File

@ -718,6 +718,7 @@ sds getAllClientsInfoString(void);
void rewriteClientCommandVector(redisClient *c, int argc, ...); void rewriteClientCommandVector(redisClient *c, int argc, ...);
unsigned long getClientOutputBufferMemoryUsage(redisClient *c); unsigned long getClientOutputBufferMemoryUsage(redisClient *c);
void flushSlavesOutputBuffers(void); void flushSlavesOutputBuffers(void);
void disconnectSlaves(void);
#ifdef __GNUC__ #ifdef __GNUC__
void addReplyErrorFormat(redisClient *c, const char *fmt, ...) void addReplyErrorFormat(redisClient *c, const char *fmt, ...)

View File

@ -507,6 +507,7 @@ void slaveofCommand(redisClient *c) {
server.masterhost = sdsdup(c->argv[1]->ptr); server.masterhost = sdsdup(c->argv[1]->ptr);
server.masterport = atoi(c->argv[2]->ptr); server.masterport = atoi(c->argv[2]->ptr);
if (server.master) freeClient(server.master); if (server.master) freeClient(server.master);
disconnectSlaves(); /* Force our slaves to resync with us as well. */
if (server.replstate == REDIS_REPL_TRANSFER) if (server.replstate == REDIS_REPL_TRANSFER)
replicationAbortSyncTransfer(); replicationAbortSyncTransfer();
server.replstate = REDIS_REPL_CONNECT; server.replstate = REDIS_REPL_CONNECT;