diff --git a/src/sentinel.c b/src/sentinel.c index f4f3164c73f3adce824c3b23f77778f8d46a4a6c..7f81443bbf2dffd0448368e037f2a8b9368ed805 100644 --- a/src/sentinel.c +++ b/src/sentinel.c @@ -3239,21 +3239,53 @@ int sentinelSendSlaveOf(sentinelRedisInstance *ri, char *host, int port) { ll2string(portstr,sizeof(portstr),port); + /* If host is NULL we send SLAVEOF NO ONE that will turn the instance + * into a master. */ if (host == NULL) { host = "NO"; memcpy(portstr,"ONE",4); } + /* In order to send SLAVEOF in a safe way, we send a transaction performing + * the following tasks: + * 1) Reconfigure the instance according to the specified host/port params. + * 2) Rewrite the configuraiton. + * 3) Disconnect all clients (but this one sending the commnad) in order + * to trigger the ask-master-on-reconnection protocol for connected + * clients. + * + * Note that we don't check the replies returned by commands, since we + * will observe instead the effects in the next INFO output. */ + retval = redisAsyncCommand(ri->cc, + sentinelDiscardReplyCallback, NULL, "MULTI"); + if (retval == REDIS_ERR) return retval; + ri->pending_commands++; + retval = redisAsyncCommand(ri->cc, sentinelDiscardReplyCallback, NULL, "SLAVEOF %s %s", host, portstr); if (retval == REDIS_ERR) return retval; + ri->pending_commands++; + retval = redisAsyncCommand(ri->cc, + sentinelDiscardReplyCallback, NULL, "CONFIG REWRITE"); + if (retval == REDIS_ERR) return retval; ri->pending_commands++; - if (redisAsyncCommand(ri->cc, - sentinelDiscardReplyCallback, NULL, "CONFIG REWRITE") == REDIS_OK) - { - ri->pending_commands++; - } + + /* CLIENT KILL TYPE is only supported starting from Redis 2.8.12, + * however sending it to an instance not understanding this command is not + * an issue because CLIENT is variadic command, so Redis will not + * recognized as a syntax error, and the transaction will not fail (but + * only the unsupported command will fail). */ + retval = redisAsyncCommand(ri->cc, + sentinelDiscardReplyCallback, NULL, "CLIENT KILL TYPE normal"); + if (retval == REDIS_ERR) return retval; + ri->pending_commands++; + + retval = redisAsyncCommand(ri->cc, + sentinelDiscardReplyCallback, NULL, "EXEC"); + if (retval == REDIS_ERR) return retval; + ri->pending_commands++; + return REDIS_OK; }