diff --git a/src/cluster.c b/src/cluster.c index d16427428..ccb230c91 100644 --- a/src/cluster.c +++ b/src/cluster.c @@ -1657,6 +1657,19 @@ void dumpCommand(redisClient *c) { return; } +/* The ASKING command is required after a -ASK redirection. + * The client should issue ASKING before to actualy send the command to + * the target instance. See the Redis Cluster specification for more + * information. */ +void askingCommand(redisClient *c) { + if (server.cluster_enabled == 0) { + addReplyError(c,"This instance has cluster support disabled"); + return; + } + c->flags |= REDIS_ASKING; + addReply(c,shared.ok); +} + /* ----------------------------------------------------------------------------- * Cluster functions related to serving / redirecting clients * -------------------------------------------------------------------------- */ @@ -1750,9 +1763,12 @@ clusterNode *getNodeByQuery(redisClient *c, struct redisCommand *cmd, robj **arg } /* Handle the case in which we are receiving this hash slot from * another instance, so we'll accept the query even if in the table - * it is assigned to a different node. */ - if (server.cluster.importing_slots_from[slot] != NULL) + * it is assigned to a different node, but only if the client + * issued an ASKING command before. */ + if (server.cluster.importing_slots_from[slot] != NULL && + c->flags & REDIS_ASKING) { return server.cluster.myself; + } /* It's not a -ASK case. Base case: just return the right node. */ return n; } diff --git a/src/networking.c b/src/networking.c index f14b4ef8c..7ed5c6fcf 100644 --- a/src/networking.c +++ b/src/networking.c @@ -625,6 +625,8 @@ void resetClient(redisClient *c) { c->reqtype = 0; c->multibulklen = 0; c->bulklen = -1; + /* We clear the ASKING flag as well if we are not inside a MULTI. */ + if (!(c->flags & REDIS_MULTI)) c->flags &= (~REDIS_ASKING); } void closeTimedoutClients(void) { diff --git a/src/redis.c b/src/redis.c index dd693f6c3..6f52ada2d 100644 --- a/src/redis.c +++ b/src/redis.c @@ -209,6 +209,7 @@ struct redisCommand redisCommandTable[] = { {"cluster",clusterCommand,-2,"ar",0,NULL,0,0,0,0,0}, {"restore",restoreCommand,4,"awm",0,NULL,1,1,1,0,0}, {"migrate",migrateCommand,6,"aw",0,NULL,0,0,0,0,0}, + {"asking",askingCommand,1,"r",0,NULL,0,0,0,0,0}, {"dump",dumpCommand,2,"ar",0,NULL,0,0,0,0,0}, {"object",objectCommand,-2,"r",0,NULL,0,0,0,0,0}, {"client",clientCommand,-2,"ar",0,NULL,0,0,0,0,0}, diff --git a/src/redis.h b/src/redis.h index af08145e6..0f0587e44 100644 --- a/src/redis.h +++ b/src/redis.h @@ -133,6 +133,7 @@ #define REDIS_UNBLOCKED 256 /* This client was unblocked and is stored in server.unblocked_clients */ #define REDIS_LUA_CLIENT 512 /* This is a non connected client used by Lua */ +#define REDIS_ASKING 1024 /* Client issued the ASKING command */ /* Client request types */ #define REDIS_REQ_INLINE 1 @@ -1121,6 +1122,7 @@ void unwatchCommand(redisClient *c); void clusterCommand(redisClient *c); void restoreCommand(redisClient *c); void migrateCommand(redisClient *c); +void askingCommand(redisClient *c); void dumpCommand(redisClient *c); void objectCommand(redisClient *c); void clientCommand(redisClient *c);