Commit 778b2210 authored by antirez's avatar antirez
Browse files

slave with attached slaves now close the conection to all the slaves when the...

slave with attached slaves now close the conection to all the slaves when the connection to the master is lost. Now a slave without a connected link to the master will refuse SYNC from other slaves. Enhanced the replication error reporting. All this will fix Issue 156
parent e452436a
...@@ -255,7 +255,8 @@ void freeClient(redisClient *c) { ...@@ -255,7 +255,8 @@ void freeClient(redisClient *c) {
server.vm_blocked_clients--; server.vm_blocked_clients--;
} }
listRelease(c->io_keys); listRelease(c->io_keys);
/* Master/slave cleanup */ /* Master/slave cleanup.
* Case 1: we lost the connection with a slave. */
if (c->flags & REDIS_SLAVE) { if (c->flags & REDIS_SLAVE) {
if (c->replstate == REDIS_REPL_SEND_BULK && c->repldbfd != -1) if (c->replstate == REDIS_REPL_SEND_BULK && c->repldbfd != -1)
close(c->repldbfd); close(c->repldbfd);
...@@ -264,9 +265,20 @@ void freeClient(redisClient *c) { ...@@ -264,9 +265,20 @@ void freeClient(redisClient *c) {
redisAssert(ln != NULL); redisAssert(ln != NULL);
listDelNode(l,ln); listDelNode(l,ln);
} }
/* Case 2: we lost the connection with the master. */
if (c->flags & REDIS_MASTER) { if (c->flags & REDIS_MASTER) {
server.master = NULL; server.master = NULL;
server.replstate = REDIS_REPL_CONNECT; server.replstate = REDIS_REPL_CONNECT;
/* 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. */
while (listLength(server.slaves)) {
ln = listFirst(server.slaves);
freeClient((redisClient*)ln->value);
}
} }
/* Release memory */ /* Release memory */
zfree(c->argv); zfree(c->argv);
......
...@@ -176,6 +176,13 @@ void syncCommand(redisClient *c) { ...@@ -176,6 +176,13 @@ void syncCommand(redisClient *c) {
/* ignore SYNC if aleady slave or in monitor mode */ /* ignore SYNC if aleady slave or in monitor mode */
if (c->flags & REDIS_SLAVE) return; if (c->flags & REDIS_SLAVE) return;
/* Refuse SYNC requests if we are a slave but the link with our master
* is not ok... */
if (server.masterhost && server.replstate != REDIS_REPL_CONNECTED) {
addReplySds(c,sdsnew("-ERR Can't SYNC while not connected with my master\r\n"));
return;
}
/* SYNC can't be issued when the server has pending data to send to /* SYNC can't be issued when the server has pending data to send to
* the client about already issued commands. We need a fresh reply * the client about already issued commands. We need a fresh reply
* buffer registering the differences between the BGSAVE and the current * buffer registering the differences between the BGSAVE and the current
...@@ -392,7 +399,12 @@ int syncWithMaster(void) { ...@@ -392,7 +399,12 @@ int syncWithMaster(void) {
strerror(errno)); strerror(errno));
return REDIS_ERR; return REDIS_ERR;
} }
if (buf[0] != '$') { if (buf[0] == '-') {
close(fd);
redisLog(REDIS_WARNING,"MASTER aborted replication with an error: %s",
buf+1);
return REDIS_ERR;
} else if (buf[0] != '$') {
close(fd); close(fd);
redisLog(REDIS_WARNING,"Bad protocol from MASTER, the first byte is not '$', are you sure the host and port are right?"); redisLog(REDIS_WARNING,"Bad protocol from MASTER, the first byte is not '$', are you sure the host and port are right?");
return REDIS_ERR; return REDIS_ERR;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment