From 179e54d2a9c6545d6f102bf9a3f9506175639743 Mon Sep 17 00:00:00 2001 From: antirez Date: Thu, 29 Mar 2012 09:24:02 +0200 Subject: [PATCH] Fix for slaves chains. Force resync of slaves (simply disconnecting them) when SLAVEOF turns a master into a slave. --- src/networking.c | 29 +++++++++++++++-------------- src/redis.h | 1 + src/replication.c | 1 + 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/networking.c b/src/networking.c index 937f8402..406d1cde 100644 --- a/src/networking.c +++ b/src/networking.c @@ -547,6 +547,16 @@ static void freeClientArgv(redisClient *c) { 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) { listNode *ln; @@ -605,21 +615,12 @@ void freeClient(redisClient *c) { server.master = NULL; server.repl_state = REDIS_REPL_CONNECT; server.repl_down_since = server.unixtime; - /* Since we lost the connection with the master, we should also - * close the connection with all our slaves if we have any, so - * 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 lost connection with our master, force our slaves to resync + * with us as well to load the new data set. * - * We do this only if server.masterhost != NULL. If it is NULL this - * means the user called SLAVEOF NO ONE and we are freeing our - * link with the master, so no need to close link with slaves. */ - if (server.masterhost != NULL) { - while (listLength(server.slaves)) { - ln = listFirst(server.slaves); - freeClient((redisClient*)ln->value); - } - } + * If server.masterhost is NULL te user called SLAVEOF NO ONE so + * slave resync is not needed. */ + if (server.masterhost != NULL) disconnectSlaves(); } /* If this client was scheduled for async freeing we need to remove it diff --git a/src/redis.h b/src/redis.h index 41e24557..5a3d1a9c 100644 --- a/src/redis.h +++ b/src/redis.h @@ -869,6 +869,7 @@ void asyncCloseClientOnOutputBufferLimitReached(redisClient *c); int getClientLimitClassByName(char *name); char *getClientLimitClassName(int class); void flushSlavesOutputBuffers(void); +void disconnectSlaves(void); #ifdef __GNUC__ void addReplyErrorFormat(redisClient *c, const char *fmt, ...) diff --git a/src/replication.c b/src/replication.c index 170bee73..c99be32a 100644 --- a/src/replication.c +++ b/src/replication.c @@ -541,6 +541,7 @@ void slaveofCommand(redisClient *c) { server.masterhost = sdsdup(c->argv[1]->ptr); server.masterport = port; if (server.master) freeClient(server.master); + disconnectSlaves(); /* Force our slaves to resync with us as well. */ if (server.repl_state == REDIS_REPL_TRANSFER) replicationAbortSyncTransfer(); server.repl_state = REDIS_REPL_CONNECT; -- 2.45.2