HELP subcommand, continued (#5531)

* man-like consistent long formatting
* Uppercases commands, subcommands and options
* Adds 'HELP' to HELP for all
* Lexicographical order
* Uses value notation and other .md likeness
* Moves const char *help to top
* Keeps it under 80 chars
* Misc help typos, consistent conjuctioning (i.e return and not returns)
* Uses addReplySubcommandSyntaxError(c) all over

Signed-off-by: Itamar Haber <itamar@redislabs.com>
This commit is contained in:
Itamar Haber 2021-01-04 17:02:57 +02:00 committed by GitHub
parent 10f94b0ab1
commit 9dcdc7e79a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 363 additions and 188 deletions

View File

@ -174,15 +174,15 @@ sds ACLHashPassword(unsigned char *cleartext, size_t len) {
return sdsnewlen(hex,HASH_PASSWORD_LEN);
}
/* Given a hash and the hash length, returns C_OK if it is a valid password
/* Given a hash and the hash length, returns C_OK if it is a valid password
* hash, or C_ERR otherwise. */
int ACLCheckPasswordHash(unsigned char *hash, int hashlen) {
if (hashlen != HASH_PASSWORD_LEN) {
return C_ERR;
return C_ERR;
}
/* Password hashes can only be characters that represent
* hexadecimal values, which are numbers and lowercase
* hexadecimal values, which are numbers and lowercase
* characters 'a' through 'f'. */
for(int i = 0; i < HASH_PASSWORD_LEN; i++) {
char c = hash[i];
@ -2184,18 +2184,30 @@ void aclCommand(client *c) {
}
} else if (c->argc == 2 && !strcasecmp(sub,"help")) {
const char *help[] = {
"LOAD -- Reload users from the ACL file.",
"SAVE -- Save the current config to the ACL file.",
"LIST -- Show user details in config file format.",
"USERS -- List all the registered usernames.",
"SETUSER <username> [attribs ...] -- Create or modify a user.",
"GETUSER <username> -- Get the user details.",
"DELUSER <username> [...] -- Delete a list of users.",
"CAT -- List available categories.",
"CAT <category> -- List commands inside category.",
"GENPASS [<bits>] -- Generate a secure user password.",
"WHOAMI -- Return the current connection username.",
"LOG [<count> | RESET] -- Show the ACL log entries.",
"CAT [<category>]",
" List all commands that belong to <category>, or all command categories",
" when no category is specified.",
"DELUSER <username> [<username> ...]",
" Delete a list of users.",
"GETUSER <username>",
" Get the user's details.",
"GENPASS [<bits>]",
" Generate a secure 256-bit user password. The optional `bits` argument can",
" be used to specify a different size.",
"LIST",
" Show users details in config file format.",
"LOAD",
" Reload users from the ACL file.",
"LOG [<count> | RESET]",
" Show the ACL log entries.",
"SAVE",
" Save the current config to the ACL file.",
"SETUSER <username> <attribute> [<attribute> ...]",
" Create or modify a user with the specified attributes.",
"USERS",
" List all the registered usernames.",
"WHOAMI",
" Return the current connection username.",
NULL
};
addReplyHelp(c,help);

View File

@ -4357,28 +4357,49 @@ void clusterCommand(client *c) {
if (c->argc == 2 && !strcasecmp(c->argv[1]->ptr,"help")) {
const char *help[] = {
"ADDSLOTS <slot> [slot ...] -- Assign slots to current node.",
"BUMPEPOCH -- Advance the cluster config epoch.",
"COUNT-failure-reports <node-id> -- Return number of failure reports for <node-id>.",
"COUNTKEYSINSLOT <slot> - Return the number of keys in <slot>.",
"DELSLOTS <slot> [slot ...] -- Delete slots information from current node.",
"FAILOVER [force|takeover] -- Promote current replica node to being a master.",
"FORGET <node-id> -- Remove a node from the cluster.",
"GETKEYSINSLOT <slot> <count> -- Return key names stored by current node in a slot.",
"FLUSHSLOTS -- Delete current node own slots information.",
"INFO - Return information about the cluster.",
"KEYSLOT <key> -- Return the hash slot for <key>.",
"MEET <ip> <port> [bus-port] -- Connect nodes into a working cluster.",
"MYID -- Return the node id.",
"NODES -- Return cluster configuration seen by node. Output format:",
" <id> <ip:port> <flags> <master> <pings> <pongs> <epoch> <link> <slot> ... <slot>",
"REPLICATE <node-id> -- Configure current node as replica to <node-id>.",
"RESET [hard|soft] -- Reset current node (default: soft).",
"SET-config-epoch <epoch> - Set config epoch of current node.",
"SETSLOT <slot> (importing|migrating|stable|node <node-id>) -- Set slot state.",
"REPLICAS <node-id> -- Return <node-id> replicas.",
"SAVECONFIG - Force saving cluster configuration on disk.",
"SLOTS -- Return information about slots range mappings. Each range is made of:",
"ADDSLOTS <slot> [<slot> ...]",
" Assign slots to current node.",
"BUMPEPOCH",
" Advance the cluster config epoch.",
"COUNT-FAILURE-REPORTS <node-id>",
" Return number of failure reports for <node-id>.",
"COUNTKEYSINSLOT <slot>",
" Return the number of keys in <slot>.",
"DELSLOTS <slot> [<slot> ...]",
" Delete slots information from current node.",
"FAILOVER [FORCE|TAKEOVER]",
" Promote current replica node to being a master.",
"FORGET <node-id>",
" Remove a node from the cluster.",
"GETKEYSINSLOT <slot> <count>",
" Return key names stored by current node in a slot.",
"FLUSHSLOTS",
" Delete current node own slots information.",
"INFO",
" Return information about the cluster.",
"KEYSLOT <key>",
" Return the hash slot for <key>.",
"MEET <ip> <port> [<bus-port>]",
" Connect nodes into a working cluster.",
"MYID",
" Return the node id.",
"NODES",
" Return cluster configuration seen by node. Output format:",
" <id> <ip:port> <flags> <master> <pings> <pongs> <epoch> <link> <slot> ...",
"REPLICATE <node-id>",
" Configure current node as replica to <node-id>.",
"RESET [HARD|SOFT]",
" Reset current node (default: soft).",
"SET-CONFIG-EPOCH <epoch>",
" Set config epoch of current node.",
"SETSLOT <slot> (IMPORTING|MIGRATING|STABLE|NODE <node-id>)",
" Set slot state.",
"REPLICAS <node-id>",
" Return <node-id> replicas.",
"SAVECONFIG",
" Force saving cluster configuration on disk.",
"SLOTS",
" Return information about slots range mappings. Each range is made of:",
" start, end, master and replicas IP addresses, ports and ids",
NULL
};

View File

@ -2546,12 +2546,17 @@ void configCommand(client *c) {
if (c->argc == 2 && !strcasecmp(c->argv[1]->ptr,"help")) {
const char *help[] = {
"GET <pattern> -- Return parameters matching the glob-like <pattern> and their values.",
"SET <parameter> <value> -- Set parameter to value.",
"RESETSTAT -- Reset statistics reported by INFO.",
"REWRITE -- Rewrite the configuration file.",
"GET <pattern>",
" Return parameters matching the glob-like <pattern> and their values.",
"SET <directive> <value>",
" Set the configuration <directive> to <value>.",
"RESETSTAT",
" Reset statistics reported by the INFO command.",
"REWRITE",
" Rewrite the configuration file.",
NULL
};
addReplyHelp(c, help);
} else if (!strcasecmp(c->argv[1]->ptr,"set") && c->argc == 4) {
configSetCommand(c);

View File

@ -381,39 +381,88 @@ void mallctl_string(client *c, robj **argv, int argc) {
void debugCommand(client *c) {
if (c->argc == 2 && !strcasecmp(c->argv[1]->ptr,"help")) {
const char *help[] = {
"ASSERT -- Crash by assertion failed.",
"CHANGE-REPL-ID -- Change the replication IDs of the instance. Dangerous, should be used only for testing the replication subsystem.",
"CRASH-AND-RECOVER <milliseconds> -- Hard crash and restart after <milliseconds> delay.",
"DIGEST -- Output a hex signature representing the current DB content.",
"DIGEST-VALUE <key-1> ... <key-N>-- Output a hex signature of the values of all the specified keys.",
"DEBUG PROTOCOL [string|integer|double|bignum|null|array|set|map|attrib|push|verbatim|true|false]",
"ERROR <string> -- Return a Redis protocol error with <string> as message. Useful for clients unit tests to simulate Redis errors.",
"LOG <message> -- write message to the server log.",
"LEAK <string> -- Create a memory leak of the input string.",
"HTSTATS <dbid> -- Return hash table statistics of the specified Redis database.",
"HTSTATS-KEY <key> -- Like htstats but for the hash table stored as key's value.",
"LOADAOF -- Flush the AOF buffers on disk and reload the AOF in memory.",
"LUA-ALWAYS-REPLICATE-COMMANDS <0|1> -- Setting it to 1 makes Lua replication defaulting to replicating single commands, without the script having to enable effects replication.",
"OBJECT <key> -- Show low level info about key and associated value.",
"OOM -- Crash the server simulating an out-of-memory error.",
"PANIC -- Crash the server simulating a panic.",
"POPULATE <count> [prefix] [size] -- Create <count> string keys named key:<num>. If a prefix is specified is used instead of the 'key' prefix.",
"RELOAD [MERGE] [NOFLUSH] [NOSAVE] -- Save the RDB on disk and reload it back in memory. By default it will save the RDB file and load it back. With the NOFLUSH option the current database is not removed before loading the new one, but conflicts in keys will kill the server with an exception. When MERGE is used, conflicting keys will be loaded (the key in the loaded RDB file will win). When NOSAVE is used, the server will not save the current dataset in the RDB file before loading. Use DEBUG RELOAD NOSAVE when you want just to load the RDB file you placed in the Redis working directory in order to replace the current dataset in memory. Use DEBUG RELOAD NOSAVE NOFLUSH MERGE when you want to add what is in the current RDB file placed in the Redis current directory, with the current memory content. Use DEBUG RELOAD when you want to verify Redis is able to persist the current dataset in the RDB file, flush the memory content, and load it back.",
"RESTART -- Graceful restart: save config, db, restart.",
"SDSLEN <key> -- Show low level SDS string info representing key and value.",
"SEGFAULT -- Crash the server with sigsegv.",
"SET-ACTIVE-EXPIRE <0|1> -- Setting it to 0 disables expiring keys in background when they are not accessed (otherwise the Redis behavior). Setting it to 1 reenables back the default.",
"SET-SKIP-CHECKSUM-VALIDATION <0|1> -- Enables or disables checksum checks for rdb or RESTORE payload.",
"AOF-FLUSH-SLEEP <microsec> -- Server will sleep before flushing the AOF, this is used for testing",
"SLEEP <seconds> -- Stop the server for <seconds>. Decimals allowed.",
"STRUCTSIZE -- Return the size of different Redis core C structures.",
"ZIPLIST <key> -- Show low level info about the ziplist encoding.",
"STRINGMATCH-TEST -- Run a fuzz tester against the stringmatchlen() function.",
"CONFIG-REWRITE-FORCE-ALL -- Like CONFIG REWRITE but writes all configuration options, including keywords not listed in original configuration file or default values.",
"AOF-FLUSH-SLEEP <microsec>",
" Server will sleep before flushing the AOF, this is used for testing.",
"ASSERT",
" Crash by assertion failed.",
"CHANGE-REPL-ID"
" Change the replication IDs of the instance.",
" Dangerous: should be used only for testing the replication subsystem.",
"CONFIG-REWRITE-FORCE-ALL",
" Like CONFIG REWRITE but writes all configuration options, including",
" keywords not listed in original configuration file or default values.",
"CRASH-AND-RECOVER <milliseconds>",
" Hard crash and restart after a <milliseconds> delay.",
"DIGEST",
" Output a hex signature representing the current DB content.",
"DIGEST-VALUE <key> [<key> ...]",
" Output a hex signature of the values of all the specified keys.",
"ERROR <string>",
" Return a Redis protocol error with <string> as message. Useful for clients",
" unit tests to simulate Redis errors.",
"LOG <message>",
" Write <message> to the server log.",
"HTSTATS <dbid>",
" Return hash table statistics of the specified Redis database.",
"HTSTATS-KEY <key>",
" Like HTSTATS but for the hash table stored at <key>'s value.",
"LOADAOF",
" Flush the AOF buffers on disk and reload the AOF in memory.",
"LUA-ALWAYS-REPLICATE-COMMANDS <0|1>",
" Setting it to 1 makes Lua replication defaulting to replicating single",
" commands, without the script having to enable effects replication.",
#ifdef USE_JEMALLOC
"MALLCTL <key> [<val>] -- Get or set a malloc tunning integer.",
"MALLCTL-STR <key> [<val>] -- Get or set a malloc tunning string.",
"MALLCTL <key> [<val>]",
" Get or set a malloc tuning integer.",
"MALLCTL-STR <key> [<val>]",
" Get or set a malloc tuning string.",
#endif
"OBJECT <key>",
" Show low level info about `key` and associated value.",
"OOM",
" Crash the server simulating an out-of-memory error.",
"PANIC",
" Crash the server simulating a panic.",
"POPULATE <count> [<prefix>] [<size>]",
" Create <count> string keys named key:<num>. If <prefix> is specified then",
" it is used instead of the 'key' prefix.",
"DEBUG PROTOCOL <type>",
" Reply with a test value of the specified type. <type> can be: string,",
" integer, double, bignum, null, array, set, map, attrib, push, verbatim,",
" true, false.",
"RELOAD [option ...]",
" Save the RDB on disk and reload it back to memory. Valid <option> values:",
" * MERGE: conflicting keys will be loaded from RDB.",
" * NOFLUSH: the existing database will not be removed before load, but",
" conflicting keys will generate an exception and kill the server."
" * NOSAVE: the database will be loaded from an existing RDB file.",
" Examples:",
" * DEBUG RELOAD: verify that the server is able to persist, flsuh and reload",
" the database.",
" * DEBUG RELOAD NOSAVE: replace the current database with the contents of an",
" existing RDB file.",
" * DEBUG RELOAD NOSAVE NOFLUSH MERGE: add the contents of an existing RDB",
" file to the database.",
"RESTART",
" Graceful restart: save config, db, restart.",
"SDSLEN <key>",
" Show low level SDS string info representing `key` and value.",
"SEGFAULT",
" Crash the server with sigsegv.",
"SET-ACTIVE-EXPIRE <0|1>",
" Setting it to 0 disables expiring keys in background when they are not",
" accessed (otherwise the Redis behavior). Setting it to 1 reenables back the",
" default.",
"SET-SKIP-CHECKSUM-VALIDATION <0|1>",
" Enables or disables checksum checks for RDB files and RESTORE's payload.",
"SLEEP <seconds>",
" Stop the server for <seconds>. Decimals allowed.",
"STRINGMATCH-TEST",
" Run a fuzz tester against the stringmatchlen() function.",
"STRUCTSIZE",
" Return the size of different Redis core C structures.",
"ZIPLIST <key>",
" Show low level info about the ziplist encoding of <key>.",
NULL
};
addReplyHelp(c, help);

View File

@ -584,16 +584,6 @@ sds latencyCommandGenSparkeline(char *event, struct latencyTimeSeries *ts) {
* LATENCY RESET: reset data of a specified event or all the data if no event provided.
*/
void latencyCommand(client *c) {
const char *help[] = {
"DOCTOR -- Returns a human readable latency analysis report.",
"GRAPH <event> -- Returns an ASCII latency graph for the event class.",
"HISTORY <event> -- Returns time-latency samples for the event class.",
"LATEST -- Returns the latest latency samples for all events.",
"RESET [event ...] -- Resets latency data of one or more event classes.",
" (default: reset all data for all event classes)",
"HELP -- Prints this help.",
NULL
};
struct latencyTimeSeries *ts;
if (!strcasecmp(c->argv[1]->ptr,"history") && c->argc == 3) {
@ -639,6 +629,20 @@ NULL
addReplyLongLong(c,resets);
}
} else if (!strcasecmp(c->argv[1]->ptr,"help") && c->argc == 2) {
const char *help[] = {
"DOCTOR",
" Return a human readable latency analysis report.",
"GRAPH <event>",
" Return an ASCII latency graph for the <event> class.",
"HISTORY <event>",
" Return time-latency samples for the <event> class.",
"LATEST",
" Return the latest latency samples for all events.",
"RESET [<event> ...]",
" Reset latency data of one or more <event> classes.",
" (default: reset all data for all event classes)",
NULL
};
addReplyHelp(c, help);
} else {
addReplySubcommandSyntaxError(c);

View File

@ -7936,14 +7936,21 @@ sds genModulesInfoString(sds info) {
/* Redis MODULE command.
*
* MODULE LOAD <path> [args...] */
* MODULE LIST
* MODULE LOAD <path> [args...]
* MODULE UNLOAD <name>
*/
void moduleCommand(client *c) {
char *subcmd = c->argv[1]->ptr;
if (c->argc == 2 && !strcasecmp(subcmd,"help")) {
const char *help[] = {
"LIST -- Return a list of loaded modules.",
"LOAD <path> [arg ...] -- Load a module library from <path>.",
"UNLOAD <name> -- Unload a module.",
"LIST",
" Return a list of loaded modules.",
"LOAD <path> [<arg> ...]",
" Load a module library from <path>, passing to it any optional arguments.",
"UNLOAD <name>",
" Unload a module.",
NULL
};
addReplyHelp(c, help);

View File

@ -855,12 +855,16 @@ void addReplyHelp(client *c, const char **help) {
sdstoupper(cmd);
addReplyStatusFormat(c,
"%s <subcommand> arg arg ... arg. Subcommands are:",cmd);
"%s <subcommand> [<arg> [value] [opt] ...]. Subcommands are:",cmd);
sdsfree(cmd);
while (help[blen]) addReplyStatus(c,help[blen++]);
blen++; /* Account for the header line(s). */
addReplyStatus(c,"HELP");
addReplyStatus(c," Prints this help.");
blen += 1; /* Account for the header. */
blen += 2; /* Account for the footer. */
setDeferredArrayLen(c,blenp,blen);
}
@ -2387,27 +2391,45 @@ void clientCommand(client *c) {
if (c->argc == 2 && !strcasecmp(c->argv[1]->ptr,"help")) {
const char *help[] = {
"ID -- Return the ID of the current connection.",
"INFO -- Return information about the current client connection.",
"GETNAME -- Return the name of the current connection.",
"KILL <ip:port> -- Kill connection made from <ip:port>.",
"KILL <option> <value> [option value ...] -- Kill connections. Options are:",
" ADDR <ip:port> -- Kill connection made from <ip:port>",
" LADDR <ip:port> -- Kill connection made to <ip:port>",
" TYPE (normal|master|replica|pubsub) -- Kill connections by type.",
" USER <username> -- Kill connections authenticated with such user.",
" SKIPME (yes|no) -- Skip killing current connection (default: yes).",
"LIST [options ...] -- Return information about client connections. Options:",
" TYPE (normal|master|replica|pubsub) -- Return clients of specified type.",
" ID id [id ...] -- Return clients of specified IDs only.",
"PAUSE <timeout> -- Suspend all Redis clients for <timeout> milliseconds.",
"REPLY (on|off|skip) -- Control the replies sent to the current connection.",
"SETNAME <name> -- Assign the name <name> to the current connection.",
"UNBLOCK <clientid> [TIMEOUT|ERROR] -- Unblock the specified blocked client.",
"TRACKING (on|off) [REDIRECT <id>] [BCAST] [PREFIX first] [PREFIX second] [OPTIN] [OPTOUT] [NOLOOP]... -- Enable client keys tracking for client side caching.",
"CACHING (yes|no) -- Enable/Disable tracking of the keys for next command in OPTIN/OPTOUT mode.",
"GETREDIR -- Return the client ID we are redirecting to when tracking is enabled.",
"TRACKINGINFO -- Return information about current client's tracking status.",
"CACHING (YES|NO)",
" Enable/disable tracking of the keys for next command in OPTIN/OPTOUT modes.",
"GETREDIR",
" Return the client ID we are redirecting to when tracking is enabled.",
"GETNAME",
" Return the name of the current connection.",
"ID",
" Return the ID of the current connection.",
"INFO",
" Return information about the current client connection.",
"KILL <ip:port>",
" Kill connection made from <ip:port>.",
"KILL <option> <value> [<option> <value> [...]]",
" Kill connections. Options are:",
" * ADDR <ip:port>",
" Kill connection made from <ip:port>",
" * TYPE (normal|master|replica|pubsub)",
" Kill connections by type.",
" * USER <username>",
" Kill connections authenticated by <username>.",
" * SKIPME (YES|NO)",
" Skip killing current connection (default: yes).",
"LIST [options ...]",
" Return information about client connections. Options:",
" * TYPE (NORMAL|MASTER|REPLICA|PUBSUB)",
" Return clients of specified type.",
"PAUSE <timeout>",
" Suspend all clients for <timout> milliseconds.",
"REPLY (ON|OFF|SKIP)",
" Control the replies sent to the current connection.",
"SETNAME <name>",
" Assign the name <name> to the current connection.",
"UNBLOCK <clientid> [TIMEOUT|ERROR]",
" Unblock the specified blocked client.",
"TRACKING (ON|OFF) [REDIRECT <id>] [BCAST] [PREFIX <prefix> [...]]",
" [OPTIN] [OPTOUT]",
" Control server assisted client side caching.",
"TRACKINGINFO",
" Report tracking status for the current connection.",
NULL
};
addReplyHelp(c, help);
@ -2836,7 +2858,7 @@ NULL
addReplyArrayLen(c,0);
}
} else {
addReplyErrorFormat(c, "Unknown subcommand or wrong number of arguments for '%s'. Try CLIENT HELP", (char*)c->argv[1]->ptr);
addReplySubcommandSyntaxError(c);
}
}

View File

@ -1035,7 +1035,7 @@ struct redisMemOverhead *getMemoryOverheadData(void) {
mem += dictSize(server.repl_scriptcache_dict) * sizeof(dictEntry) +
dictSlots(server.repl_scriptcache_dict) * sizeof(dictEntry*);
if (listLength(server.repl_scriptcache_fifo) > 0) {
mem += listLength(server.repl_scriptcache_fifo) * (sizeof(listNode) +
mem += listLength(server.repl_scriptcache_fifo) * (sizeof(listNode) +
sdsZmallocSize(listNodeValue(listFirst(server.repl_scriptcache_fifo))));
}
mh->lua_caches = mem;
@ -1256,10 +1256,18 @@ void objectCommand(client *c) {
if (c->argc == 2 && !strcasecmp(c->argv[1]->ptr,"help")) {
const char *help[] = {
"ENCODING <key> -- Return the kind of internal representation used in order to store the value associated with a key.",
"FREQ <key> -- Return the access frequency index of the key. The returned integer is proportional to the logarithm of the recent access frequency of the key.",
"IDLETIME <key> -- Return the idle time of the key, that is the approximated number of seconds elapsed since the last access to the key.",
"REFCOUNT <key> -- Return the number of references of the value associated with the specified key.",
"ENCODING <key>",
" Return the kind of internal representation used in order to store the value",
" associated with a <key>.",
"FREQ <key>",
" Return the access frequency index of the <key>. The returned integer is",
" proportional to the logarithm of the recent access frequency of the key.",
"IDLETIME <key>",
" Return the idle time of the <key>, that is the approximated number of",
" seconds elapsed since the last access to the key.",
"REFCOUNT <key>",
" Return the number of references of the value associated with the specified",
" <key>.",
NULL
};
addReplyHelp(c, help);
@ -1303,11 +1311,17 @@ NULL
void memoryCommand(client *c) {
if (!strcasecmp(c->argv[1]->ptr,"help") && c->argc == 2) {
const char *help[] = {
"DOCTOR - Return memory problems reports.",
"MALLOC-STATS -- Return internal statistics report from the memory allocator.",
"PURGE -- Attempt to purge dirty pages for reclamation by the allocator.",
"STATS -- Return information about the memory usage of the server.",
"USAGE <key> [SAMPLES <count>] -- Return memory in bytes used by <key> and its value. Nested values are sampled up to <count> times (default: 5).",
"DOCTOR",
" Return memory problems reports.",
"MALLOC-STATS"
" Return internal statistics report from the memory allocator.",
"PURGE",
" Attempt to purge dirty pages for reclamation by the allocator.",
"STATS",
" Return information about the memory usage of the server.",
"USAGE <key> [SAMPLES <count>]",
" Return memory in bytes used by <key> and its value. Nested values are",
" sampled up to <count> times (default: 5).",
NULL
};
addReplyHelp(c, help);
@ -1452,6 +1466,6 @@ NULL
else
addReplyError(c, "Error purging dirty pages");
} else {
addReplyErrorFormat(c, "Unknown subcommand or wrong number of arguments for '%s'. Try MEMORY HELP", (char*)c->argv[1]->ptr);
addReplySubcommandSyntaxError(c);
}
}

View File

@ -455,9 +455,13 @@ void publishCommand(client *c) {
void pubsubCommand(client *c) {
if (c->argc == 2 && !strcasecmp(c->argv[1]->ptr,"help")) {
const char *help[] = {
"CHANNELS [<pattern>] -- Return the currently active channels matching a pattern (default: all).",
"NUMPAT -- Return number of subscriptions to patterns.",
"NUMSUB [channel-1 .. channel-N] -- Returns the number of subscribers for the specified channels (excluding patterns, default: none).",
"CHANNELS [<pattern>]",
" Return the currently active channels matching a <pattern> (default: '*').",
"NUMPAT",
" Return number of subscriptions to patterns.",
"NUMSUB [<channel> ...]",
" Return the number of subscribers for the specified channels, excluding",
" pattern subscriptions(default: no channels).",
NULL
};
addReplyHelp(c, help);

View File

@ -691,11 +691,11 @@ int luaRedisGenericCommand(lua_State *lua, int raise_error) {
if (getNodeByQuery(c,c->cmd,c->argv,c->argc,NULL,&error_code) !=
server.cluster->myself)
{
if (error_code == CLUSTER_REDIR_DOWN_RO_STATE) {
if (error_code == CLUSTER_REDIR_DOWN_RO_STATE) {
luaPushError(lua,
"Lua script attempted to execute a write command while the "
"cluster is down and readonly");
} else if (error_code == CLUSTER_REDIR_DOWN_STATE) {
} else if (error_code == CLUSTER_REDIR_DOWN_STATE) {
luaPushError(lua,
"Lua script attempted to execute a command while the "
"cluster is down");
@ -1707,11 +1707,16 @@ void evalShaCommand(client *c) {
void scriptCommand(client *c) {
if (c->argc == 2 && !strcasecmp(c->argv[1]->ptr,"help")) {
const char *help[] = {
"DEBUG (yes|sync|no) -- Set the debug mode for subsequent scripts executed.",
"EXISTS <sha1> [<sha1> ...] -- Return information about the existence of the scripts in the script cache.",
"FLUSH -- Flush the Lua scripts cache. Very dangerous on replicas.",
"KILL -- Kill the currently executing Lua script.",
"LOAD <script> -- Load a script into the scripts cache, without executing it.",
"DEBUG (YES|SYNC|NO)",
" Set the debug mode for subsequent scripts executed.",
"EXISTS <sha1> [<sha1> ...]",
" Return information about the existence of the scripts in the script cache.",
"FLUSH",
" Flush the Lua scripts cache. Very dangerous on replicas.",
"KILL",
" Kill the currently executing Lua script.",
"LOAD <script>",
" Load a script into the scripts cache without executing it.",
NULL
};
addReplyHelp(c, help);
@ -1762,7 +1767,7 @@ NULL
addReply(c,shared.ok);
c->flags |= CLIENT_LUA_DEBUG_SYNC;
} else {
addReplyError(c,"Use SCRIPT DEBUG yes/sync/no");
addReplyError(c,"Use SCRIPT DEBUG YES/SYNC/NO");
return;
}
} else {

View File

@ -3090,25 +3090,45 @@ int sentinelIsQuorumReachable(sentinelRedisInstance *master, int *usableptr) {
void sentinelCommand(client *c) {
if (c->argc == 2 && !strcasecmp(c->argv[1]->ptr,"help")) {
const char *help[] = {
"MASTERS -- Show a list of monitored masters and their state.",
"MASTER <master-name> -- Show the state and info of the specified master.",
"REPLICAS <master-name> -- Show a list of replicas for this master and their state.",
"SENTINELS <master-name> -- Show a list of Sentinel instances for this master and their state.",
"MYID -- Show Current Sentinel Id",
"IS-MASTER-DOWN-BY-ADDR <ip> <port> <current-epoch> <runid> -- Check if the master specified by ip:port is down from current Sentinel's point of view.",
"GET-MASTER-ADDR-BY-NAME <master-name> -- Return the ip and port number of the master with that name.",
"RESET <pattern> -- Reset masters for specific master name matching this pattern.",
"FAILOVER <master-name> -- Manually failover a master node without asking for agreement from other Sentinels",
"PENDING-SCRIPTS -- Get pending scripts information.",
"MONITOR <name> <ip> <port> <quorum> -- Start monitoring a new master with the specified name, ip, port and quorum.",
"FLUSHCONFIG -- Force Sentinel to rewrite its configuration on disk, including the current Sentinel state.",
"REMOVE <master-name> -- Remove master from Sentinel's monitor list.",
"CKQUORUM <master-name> -- Check if the current Sentinel configuration is able to reach the quorum needed to failover a master "
"and the majority needed to authorize the failover.",
"SET <master-name> <option> <value> -- Set configuration paramters for certain masters.",
"INFO-CACHE <master-name> -- Return last cached INFO output from masters and all its replicas.",
"SIMULATE-FAILURE (crash-after-election|crash-after-promotion|help) -- Simulate a Sentinel crash.",
"HELP -- Prints this help.",
"CKQUORUM <master-name>",
" Check if the current Sentinel configuration is able to reach the quorum",
" needed to failover a master and the majority needed to authorize the",
" failover.",
"GET-MASTER-ADDR-BY-NAME <master-name>",
" Return the ip and port number of the master with that name.",
"FAILOVER <master-name>",
" Manually failover a master node without asking for agreement from other",
" Sentinels",
"FLUSHCONFIG",
" Force Sentinel to rewrite its configuration on disk, including the current",
" Sentinel state.",
"INFO-CACHE <master-name>",
" Return last cached INFO output from masters and all its replicas.",
"IS-MASTER-DOWN-BY-ADDR <ip> <port> <current-epoch> <runid>",
" Check if the master specified by ip:port is down from current Sentinel's",
" point of view.",
"MASTER <master-name>",
" Show the state and info of the specified master.",
"MASTERS",
" Show a list of monitored masters and their state.",
"MONITOR <name> <ip> <port> <quorum>",
" Start monitoring a new master with the specified name, ip, port and quorum.",
"MYID",
" Return the ID of the Sentinel instance.",
"PENDING-SCRIPTS",
" Get pending scripts information.",
"REMOVE <master-name>",
" Remove master from Sentinel's monitor list.",
"REPLICAS <master-name>",
" Show a list of replicas for this master and their state.",
"RESET <pattern>",
" Reset masters for specific master name matching this pattern.",
"SENTINELS <master-name>",
" Show a list of Sentinel instances for this master and their state.",
"SET <master-name> <option> <value>",
" Set configuration paramters for certain masters.",
"SIMULATE-FAILURE (CRASH-AFTER-ELECTION|CRASH-AFTER-PROMOTION|HELP)",
" Simulate a Sentinel crash.",
NULL
};
addReplyHelp(c, help);

View File

@ -2233,6 +2233,7 @@ void whileBlockedCron() {
activeDefragCycle();
server.blocked_last_cron += hz_ms;
/* Increment cronloop so that run_with_period works. */
server.cronloops++;
}
@ -4248,10 +4249,14 @@ void commandCommand(client *c) {
if (c->argc == 2 && !strcasecmp(c->argv[1]->ptr,"help")) {
const char *help[] = {
"(no subcommand) -- Return details about all Redis commands.",
"COUNT -- Return the total number of commands in this Redis server.",
"GETKEYS <full-command> -- Return the keys from a full Redis command.",
"INFO [command-name ...] -- Return details about multiple Redis commands.",
"(no subcommand)",
" Return details about all Redis commands.",
"COUNT",
" Return the total number of commands in this Redis server.",
"GETKEYS <full-command>",
" Return the keys from a full Redis command.",
"INFO [<command-name> ...]",
" Return details about multiple Redis commands.",
NULL
};
addReplyHelp(c, help);
@ -5365,7 +5370,7 @@ void loadDataFromDisk(void) {
void redisOutOfMemoryHandler(size_t allocation_size) {
serverLog(LL_WARNING,"Out Of Memory allocating %zu bytes!",
allocation_size);
serverPanic("Redis aborting for OUT OF MEMORY. Allocating %zu bytes!",
serverPanic("Redis aborting for OUT OF MEMORY. Allocating %zu bytes!",
allocation_size);
}

View File

@ -142,11 +142,15 @@ void slowlogReset(void) {
void slowlogCommand(client *c) {
if (c->argc == 2 && !strcasecmp(c->argv[1]->ptr,"help")) {
const char *help[] = {
"GET [count] -- Return top entries from the slowlog (default: 10)."
" Entries are made of:",
" id, timestamp, time in microseconds, arguments array, client IP and port, client name",
"LEN -- Return the length of the slowlog.",
"RESET -- Reset the slowlog.",
"GET [<count>]",
" Return top <count> entries from the slowlog (default: 10). Entries are",
" made of:",
" id, timestamp, time in microseconds, arguments array, client IP and port,",
" client name",
"LEN",
" Return the length of the slowlog.",
"RESET",
" Reset the slowlog.",
NULL
};
addReplyHelp(c, help);

View File

@ -1981,19 +1981,9 @@ uint64_t streamDelConsumer(streamCG *cg, sds name) {
/* XGROUP CREATE <key> <groupname> <id or $> [MKSTREAM]
* XGROUP SETID <key> <groupname> <id or $>
* XGROUP DESTROY <key> <groupname>
* CREATECONSUMER <key> <groupname> <consumer>
* XGROUP CREATECONSUMER <key> <groupname> <consumer>
* XGROUP DELCONSUMER <key> <groupname> <consumername> */
void xgroupCommand(client *c) {
const char *help[] = {
"CREATE <key> <groupname> <id or $> [opt] -- Create a new consumer group.",
" option MKSTREAM: create the empty stream if it does not exist.",
"SETID <key> <groupname> <id or $> -- Set the current group ID.",
"DESTROY <key> <groupname> -- Remove the specified group.",
"CREATECONSUMER <key> <groupname> <consumer> -- Create new consumer in the specified group.",
"DELCONSUMER <key> <groupname> <consumer> -- Remove the specified consumer.",
"HELP -- Prints this help.",
NULL
};
stream *s = NULL;
sds grpname = NULL;
streamCG *cg = NULL;
@ -2047,7 +2037,24 @@ NULL
}
/* Dispatch the different subcommands. */
if (!strcasecmp(opt,"CREATE") && (c->argc == 5 || c->argc == 6)) {
if (c->argc == 2 && !strcasecmp(opt,"HELP")) {
const char *help[] = {
"CREATE <key> <groupname> <id|$> [option]",
" Create a new consumer group. Options are:",
" * MKSTREAM",
" Create the empty stream if it does not exist.",
"CREATECONSUMER <key> <groupname> <consumer>",
" Create a new consumer in the specified group.",
"DELCONSUMER <key> <groupname> <consumer>",
" Remove the specified consumer.",
"DESTROY <key> <groupname>"
" Remove the specified group.",
"SETID <key> <groupname> <id|$>",
" Set the current group ID.",
NULL
};
addReplyHelp(c, help);
} else if (!strcasecmp(opt,"CREATE") && (c->argc == 5 || c->argc == 6)) {
streamID id;
if (!strcmp(c->argv[4]->ptr,"$")) {
if (s) {
@ -2119,8 +2126,6 @@ NULL
server.dirty++;
notifyKeyspaceEvent(NOTIFY_STREAM,"xgroup-delconsumer",
c->argv[2],c->db->id);
} else if (c->argc == 2 && !strcasecmp(opt,"HELP")) {
addReplyHelp(c, help);
} else {
addReplySubcommandSyntaxError(c);
}
@ -2971,27 +2976,25 @@ void xinfoReplyWithStreamInfo(client *c, stream *s) {
* XINFO STREAM <key> [FULL [COUNT <count>]]
* XINFO HELP. */
void xinfoCommand(client *c) {
const char *help[] = {
"CONSUMERS <key> <groupname> -- Show consumer groups of group <groupname>.",
"GROUPS <key> -- Show the stream consumer groups.",
"STREAM <key> [FULL [COUNT <count>]] -- Show information about the stream.",
" FULL will return the full state of the stream,",
" including all entries, groups, consumers and PELs.",
" It's possible to show only the first stream/PEL entries",
" by using the COUNT modifier (Default is 10)",
"HELP -- Print this help.",
NULL
};
stream *s = NULL;
char *opt;
robj *key;
/* HELP is special. Handle it ASAP. */
if (!strcasecmp(c->argv[1]->ptr,"HELP")) {
const char *help[] = {
"CONSUMERS <key> <groupname>",
" Show consumers of <groupname>.",
"GROUPS <key>",
" Show the stream consumer groups.",
"STREAM <key> [FULL [COUNT <count>]",
" Show information about the stream.",
NULL
};
addReplyHelp(c, help);
return;
} else if (c->argc < 3) {
addReplyError(c,"syntax error, try 'XINFO HELP'");
addReplySubcommandSyntaxError(c);
return;
}