提交 183458f7 编写于 作者: M Matt Stancliff 提交者: antirez

Cluster: Add COMMANDS command

COMMANDS returns a nested multibulk reply for each
command in the command table.  The reply for each
command contains:
  - command name
  - arity
  - array of command flags
  - start key position
  - end key position
  - key offset step
  - optional: if the keys are not deterministic and
    Redis uses an internal key evaluation function,
    the 6th field appears and is defined as a status
    reply of: REQUIRES ARGUMENT PARSING

Cluster clients need to know where the keys are in each
command to implement proper routing to cluster nodes.

Redis commands can have multiple keys, keys at offset steps, or other
issues where you can't always assume the first element after
the command name is the cluster routing key.

Using the information exposed by COMMANDS, client implementations
can have live, accurate key extraction details for all commands.

Also implements COMMANDS INFO [commands...] to return only a
specific set of commands instead of all 160+ commands live in Redis.
上级 1f0c0df4
......@@ -273,6 +273,7 @@ struct redisCommand redisCommandTable[] = {
{"bitcount",bitcountCommand,-2,"r",0,NULL,1,1,1,0,0},
{"bitpos",bitposCommand,-3,"r",0,NULL,1,1,1,0,0},
{"wait",waitCommand,3,"rs",0,NULL,0,0,0,0,0},
{"commands",commandsCommand,0,"rlt",0,NULL,0,0,0,0,0},
{"pfselftest",pfselftestCommand,1,"r",0,NULL,0,0,0,0,0},
{"pfadd",pfaddCommand,-2,"wm",0,NULL,1,1,1,0,0},
{"pfcount",pfcountCommand,-2,"w",0,NULL,1,1,1,0,0},
......@@ -2401,6 +2402,73 @@ void timeCommand(redisClient *c) {
addReplyBulkLongLong(c,tv.tv_usec);
}
static int replyCmdFlag(redisClient *c,
struct redisCommand *cmd, int f, char *reply) {
if (cmd->flags & f) {
addReplyStatus(c, reply);
return 1;
}
return 0;
}
static void replyCmd(redisClient *c, struct redisCommand *cmd) {
if (!cmd) {
addReply(c, shared.nullbulk);
} else {
/* We are adding: command name, arg count, flags, first, last, offset */
addReplyMultiBulkLen(c, 6);
addReplyBulkCString(c, cmd->name);
addReplyLongLong(c, cmd->arity);
int flagcount = 0;
void *flaglen = addDeferredMultiBulkLength(c);
flagcount += replyCmdFlag(c,cmd,REDIS_CMD_WRITE, "write");
flagcount += replyCmdFlag(c,cmd,REDIS_CMD_READONLY, "readonly");
flagcount += replyCmdFlag(c,cmd,REDIS_CMD_DENYOOM, "denyoom");
flagcount += replyCmdFlag(c,cmd,REDIS_CMD_ADMIN, "admin");
flagcount += replyCmdFlag(c,cmd,REDIS_CMD_PUBSUB, "pubsub");
flagcount += replyCmdFlag(c,cmd,REDIS_CMD_NOSCRIPT, "noscript");
flagcount += replyCmdFlag(c,cmd,REDIS_CMD_RANDOM, "random");
flagcount += replyCmdFlag(c,cmd,REDIS_CMD_SORT_FOR_SCRIPT,"scriptsort");
flagcount += replyCmdFlag(c,cmd,REDIS_CMD_LOADING, "loading");
flagcount += replyCmdFlag(c,cmd,REDIS_CMD_STALE, "stale");
flagcount += replyCmdFlag(c,cmd,REDIS_CMD_SKIP_MONITOR, "skipmonitor");
flagcount += replyCmdFlag(c,cmd,REDIS_CMD_ASKING, "asking");
if (cmd->getkeys_proc) {
addReplyStatus(c, "movablekeys");
flagcount += 1;
}
setDeferredMultiBulkLength(c, flaglen, flagcount);
addReplyLongLong(c, cmd->firstkey);
addReplyLongLong(c, cmd->lastkey);
addReplyLongLong(c, cmd->keystep);
}
}
void commandsCommand(redisClient *c) {
dictIterator *di;
dictEntry *de;
if (c->argc > 2 && !strcasecmp(c->argv[1]->ptr, "info")) {
int i;
addReplyMultiBulkLen(c, c->argc-2);
for (i = 2; i < c->argc; i++) {
replyCmd(c, dictFetchValue(server.commands, c->argv[i]->ptr));
}
} else if (c->argc > 2) {
addReplyError(c, "Unknown subcommand.");
return;
} else {
addReplyMultiBulkLen(c, dictSize(server.commands));
di = dictGetIterator(server.commands);
while ((de = dictNext(di)) != NULL) {
replyCmd(c, dictGetVal(de));
}
dictReleaseIterator(di);
}
}
/* Convert an amount of bytes into a human readable string in the form
* of 100B, 2G, 100M, 4K, and so forth. */
void bytesToHuman(char *s, unsigned long long n) {
......
......@@ -1327,6 +1327,7 @@ uint64_t redisBuildId(void);
void authCommand(redisClient *c);
void pingCommand(redisClient *c);
void echoCommand(redisClient *c);
void commandsCommand(redisClient *c);
void setCommand(redisClient *c);
void setnxCommand(redisClient *c);
void setexCommand(redisClient *c);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册