From 3447062d5e02cf14fd3d7765fa39a65de15f8c15 Mon Sep 17 00:00:00 2001 From: Chris Lamb Date: Fri, 16 Jan 2015 09:03:00 +0000 Subject: [PATCH 001/989] Make some defaults explicit in the sentinel.conf for package maintainers This may look a little pointless (and it is a complete no-op change here) but as package maintainers need to modify these lines to actually daemonize (etc. etc) but it's far preferable if the diff is restricted to actually changing just that bit, not adding docs, etc. The less diff the better, in general. Signed-off-by: Chris Lamb --- sentinel.conf | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/sentinel.conf b/sentinel.conf index 39d1044e2..d627b8536 100644 --- a/sentinel.conf +++ b/sentinel.conf @@ -4,6 +4,31 @@ # The port that this sentinel instance will run on port 26379 +# By default Redis Sentinel does not run as a daemon. Use 'yes' if you need it. +# Note that Redis will write a pid file in /var/run/redis-sentinel.pid when +# daemonized. +daemonize no + +# When running daemonized, Redis Sentinel writes a pid file in +# /var/run/redis-sentinel.pid by default. You can specify a custom pid file +# location here. +pidfile /var/run/redis-sentinel.pid + +# By default Redis Sentinel listens for connections from all the network +# interfaces available on the server. It is possible to listen to just one or +# multiple interfaces using the "bind" configuration directive, followed by one +# or more IP addresses. +# +# Examples: +# +# bind 192.168.1.100 10.0.0.1 +# bind 127.0.0.1 + +# Specify the log file name. Also the empty string can be used to force +# Sentinel to log on the standard output. Note that if you use standard +# output for logging but daemonize, logs will be sent to /dev/null +logfile "" + # sentinel announce-ip # sentinel announce-port # From eaeba1b2c85812c6b16a8ef50bf889d72804db09 Mon Sep 17 00:00:00 2001 From: Chris Lamb Date: Wed, 4 Feb 2015 18:29:22 +0000 Subject: [PATCH 002/989] Tidy grammar in CONFIG SET maxmemory warning. Signed-off-by: Chris Lamb --- src/config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config.c b/src/config.c index 8255a56b7..f0a019517 100644 --- a/src/config.c +++ b/src/config.c @@ -648,7 +648,7 @@ void configSetCommand(redisClient *c) { server.maxmemory = ll; if (server.maxmemory) { if (server.maxmemory < zmalloc_used_memory()) { - redisLog(REDIS_WARNING,"WARNING: the new maxmemory value set via CONFIG SET is smaller than the current memory usage. This will result in keys eviction and/or inability to accept new write commands depending on the maxmemory-policy."); + redisLog(REDIS_WARNING,"WARNING: the new maxmemory value set via CONFIG SET is smaller than the current memory usage. This will result in key eviction and/or the inability to accept new write commands depending on the maxmemory-policy."); } freeMemoryIfNeeded(); } From eca0187370c14aa2c126fe07e5310e44c2780a95 Mon Sep 17 00:00:00 2001 From: James Rouzier Date: Sat, 19 Sep 2015 14:01:10 -0400 Subject: [PATCH 003/989] If the unit of a timeout is seconds treat it a float --- src/blocked.c | 15 +++++++++++---- tests/unit/type/list.tcl | 7 +++++-- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/blocked.c b/src/blocked.c index d22872548..fc7106395 100644 --- a/src/blocked.c +++ b/src/blocked.c @@ -75,10 +75,18 @@ * is zero. */ int getTimeoutFromObjectOrReply(client *c, robj *object, mstime_t *timeout, int unit) { long long tval; + long double ftval; - if (getLongLongFromObjectOrReply(c,object,&tval, - "timeout is not an integer or out of range") != C_OK) - return C_ERR; + if (unit == UNIT_SECONDS) { + if (getLongDoubleFromObjectOrReply(c,object,&ftval, + "timeout is not an float or out of range") != C_OK) + return C_ERR; + tval = (long long) (ftval * 1000.0); + } else { + if (getLongLongFromObjectOrReply(c,object,&tval, + "timeout is not an integer or out of range") != C_OK) + return C_ERR; + } if (tval < 0) { addReplyError(c,"timeout is negative"); @@ -86,7 +94,6 @@ int getTimeoutFromObjectOrReply(client *c, robj *object, mstime_t *timeout, int } if (tval > 0) { - if (unit == UNIT_SECONDS) tval *= 1000; tval += mstime(); } *timeout = tval; diff --git a/tests/unit/type/list.tcl b/tests/unit/type/list.tcl index e4d568cf1..8daa30a77 100644 --- a/tests/unit/type/list.tcl +++ b/tests/unit/type/list.tcl @@ -436,8 +436,11 @@ start_server { test "$pop: with non-integer timeout" { set rd [redis_deferring_client] - $rd $pop blist1 1.1 - assert_error "ERR*not an integer*" {$rd read} + r del blist1 + $rd $pop blist1 0.1 + r rpush blist1 foo + assert_equal {blist1 foo} [$rd read] + assert_equal 0 [r exists blist1] } test "$pop: with zero timeout should block indefinitely" { From 82ae4f30ed8d2c55c27a465429adee572654bdb2 Mon Sep 17 00:00:00 2001 From: Chris Lamb Date: Fri, 29 Apr 2016 16:45:53 +0100 Subject: [PATCH 004/989] Use SOURCE_DATE_EPOCH over unreproducible uname + date calls. See for more details. Signed-off-by: Chris Lamb --- src/mkreleasehdr.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/mkreleasehdr.sh b/src/mkreleasehdr.sh index 1ae95886b..e6d558b17 100755 --- a/src/mkreleasehdr.sh +++ b/src/mkreleasehdr.sh @@ -2,6 +2,9 @@ GIT_SHA1=`(git show-ref --head --hash=8 2> /dev/null || echo 00000000) | head -n1` GIT_DIRTY=`git diff --no-ext-diff 2> /dev/null | wc -l` BUILD_ID=`uname -n`"-"`date +%s` +if [ -n "$SOURCE_DATE_EPOCH" ]; then + BUILD_ID=$(date -u -d "@$SOURCE_DATE_EPOCH" +%s 2>/dev/null || date -u -r "$SOURCE_DATE_EPOCH" +%s 2>/dev/null || date -u %s) +fi test -f release.h || touch release.h (cat release.h | grep SHA1 | grep $GIT_SHA1) && \ (cat release.h | grep DIRTY | grep $GIT_DIRTY) && exit 0 # Already up-to-date From a28683217073e8670bba79ff1f38d93fb3e90d65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20SO=C3=8BTE?= Date: Wed, 30 Nov 2016 15:26:59 +0100 Subject: [PATCH 005/989] Fix typo (unsupproted => unsupported) in error message --- src/server.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/server.c b/src/server.c index 309516683..f9f08cd8f 100644 --- a/src/server.c +++ b/src/server.c @@ -1658,7 +1658,7 @@ int listenToPort(int port, int *fds, int *count) { (*count)++; } else if (errno == EAFNOSUPPORT) { unsupported++; - serverLog(LL_WARNING,"Not listening to IPv6: unsupproted"); + serverLog(LL_WARNING,"Not listening to IPv6: unsupported"); } if (*count == 1 || unsupported) { @@ -1670,7 +1670,7 @@ int listenToPort(int port, int *fds, int *count) { (*count)++; } else if (errno == EAFNOSUPPORT) { unsupported++; - serverLog(LL_WARNING,"Not listening to IPv4: unsupproted"); + serverLog(LL_WARNING,"Not listening to IPv4: unsupported"); } } /* Exit the loop if we were able to bind * on IPv4 and IPv6, From 2ef8c2f6c22e27507e62bf937a5b4e9f7429fdbd Mon Sep 17 00:00:00 2001 From: Richard Li Date: Fri, 18 Aug 2017 11:27:04 +0800 Subject: [PATCH 006/989] Update the comment --- src/notify.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/notify.c b/src/notify.c index 94a1f2e79..79c1fc048 100644 --- a/src/notify.c +++ b/src/notify.c @@ -29,8 +29,8 @@ #include "server.h" -/* This file implements keyspace events notification via Pub/Sub ad - * described at http://redis.io/topics/keyspace-events. */ +/* This file implements keyspace events notification via Pub/Sub and + * described at https://redis.io/topics/notifications. */ /* Turn a string representing notification classes into an integer * representing notification classes flags xored. From 4317e2131f4355046fd44141c8b6515b81dc79c0 Mon Sep 17 00:00:00 2001 From: Itamar Haber Date: Sun, 10 Dec 2017 17:54:56 +0200 Subject: [PATCH 007/989] Standardizes `MEMORY HELP` subcommand --- src/object.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/src/object.c b/src/object.c index 43ab6b5f0..52d2d4662 100644 --- a/src/object.c +++ b/src/object.c @@ -1120,7 +1120,18 @@ NULL void memoryCommand(client *c) { robj *o; - if (!strcasecmp(c->argv[1]->ptr,"usage") && c->argc >= 3) { + if (c->argc == 2 && !strcasecmp(c->argv[1]->ptr,"help")) { + + 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 [samples ] -- Return memory in bytes used by and its value. Nested values are sampled up to times (default: 5).", +NULL + }; + addReplyHelp(c, help); + } else if (!strcasecmp(c->argv[1]->ptr,"usage") && c->argc >= 3) { long long samples = OBJ_COMPUTE_SIZE_DEF_SAMPLES; for (int j = 3; j < c->argc; j++) { if (!strcasecmp(c->argv[j]->ptr,"samples") && @@ -1234,19 +1245,7 @@ void memoryCommand(client *c) { addReply(c, shared.ok); /* Nothing to do for other allocators. */ #endif - } else if (!strcasecmp(c->argv[1]->ptr,"help") && c->argc == 2) { - addReplyMultiBulkLen(c,5); - addReplyBulkCString(c, -"MEMORY DOCTOR - Outputs memory problems report"); - addReplyBulkCString(c, -"MEMORY USAGE [SAMPLES ] - Estimate memory usage of key"); - addReplyBulkCString(c, -"MEMORY STATS - Show memory usage details"); - addReplyBulkCString(c, -"MEMORY PURGE - Ask the allocator to release memory"); - addReplyBulkCString(c, -"MEMORY MALLOC-STATS - Show allocator internal stats"); } else { - addReplyError(c,"Syntax error. Try MEMORY HELP"); + addReplyErrorFormat(c, "Unknown subcommand or wrong number of arguments for '%s'. Try MEMORY HELP", (char*)c->argv[1]->ptr); } } From 7820377d0084ac400345047ab67c0752e98897d8 Mon Sep 17 00:00:00 2001 From: Itamar Haber Date: Fri, 15 Dec 2017 21:19:41 +0200 Subject: [PATCH 008/989] Uppercases subcommands in MEMORY HELP --- src/object.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/object.c b/src/object.c index 52d2d4662..606cdd7e5 100644 --- a/src/object.c +++ b/src/object.c @@ -1123,11 +1123,11 @@ void memoryCommand(client *c) { if (c->argc == 2 && !strcasecmp(c->argv[1]->ptr,"help")) { 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 [samples ] -- Return memory in bytes used by and its value. Nested values are sampled up to 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 [SAMPLES ] -- Return memory in bytes used by and its value. Nested values are sampled up to times (default: 5).", NULL }; addReplyHelp(c, help); From d49bfc40808652389e3e3c3a0db3667153c3c14f Mon Sep 17 00:00:00 2001 From: Itamar Haber Date: Fri, 15 Dec 2017 21:21:12 +0200 Subject: [PATCH 009/989] Uppercases subcommands in OBJECT HELP --- src/object.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/object.c b/src/object.c index 606cdd7e5..b979b458a 100644 --- a/src/object.c +++ b/src/object.c @@ -1073,10 +1073,10 @@ void objectCommand(client *c) { if (c->argc == 2 && !strcasecmp(c->argv[1]->ptr,"help")) { const char *help[] = { -"encoding -- Return the kind of internal representation used in order to store the value associated with a key.", -"freq -- 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 -- Return the idle time of the key, that is the approximated number of seconds elapsed since the last access to the key.", -"refcount -- Return the number of references of the value associated with the specified key.", +"ENCODING -- Return the kind of internal representation used in order to store the value associated with a key.", +"FREQ -- 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 -- Return the idle time of the key, that is the approximated number of seconds elapsed since the last access to the key.", +"REFCOUNT -- Return the number of references of the value associated with the specified key.", NULL }; addReplyHelp(c, help); From 968cb2669346ebcb20016ac16923dcd31e31ad2f Mon Sep 17 00:00:00 2001 From: "zhaozhao.zz" Date: Fri, 26 Jan 2018 22:49:39 +0800 Subject: [PATCH 010/989] config: handle special configuration "" for auth --- src/config.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/config.c b/src/config.c index eddfe1f11..1e3fd1848 100644 --- a/src/config.c +++ b/src/config.c @@ -390,7 +390,7 @@ void loadServerConfigFromString(char *config) { } } else if (!strcasecmp(argv[0],"masterauth") && argc == 2) { zfree(server.masterauth); - server.masterauth = zstrdup(argv[1]); + server.masterauth = argv[1][0] ? zstrdup(argv[1]) : NULL; } else if (!strcasecmp(argv[0],"slave-serve-stale-data") && argc == 2) { if ((server.repl_serve_stale_data = yesnotoi(argv[1])) == -1) { err = "argument must be 'yes' or 'no'"; goto loaderr; @@ -496,7 +496,7 @@ void loadServerConfigFromString(char *config) { err = "Password is longer than CONFIG_AUTHPASS_MAX_LEN"; goto loaderr; } - server.requirepass = zstrdup(argv[1]); + server.requirepass = argv[1][0] ? zstrdup(argv[1]) : NULL; } else if (!strcasecmp(argv[0],"pidfile") && argc == 2) { zfree(server.pidfile); server.pidfile = zstrdup(argv[1]); From 5def65008ff92519a828e1ba403e9a46836ca802 Mon Sep 17 00:00:00 2001 From: Oran Agra Date: Wed, 21 Feb 2018 11:04:13 +0200 Subject: [PATCH 011/989] Fix zrealloc to behave similarly to je_realloc when size is 0 According to C11, the behavior of realloc with size 0 is now deprecated. it can either behave as free(ptr) and return NULL, or return a valid pointer. but in zmalloc it can lead to zmalloc_oom_handler and panic. and that can affect modules that use it. It looks like both glibc allocator and jemalloc behave like so: realloc(malloc(32),0) returns NULL realloc(NULL,0) returns a valid pointer This commit changes zmalloc to behave the same --- src/zmalloc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/zmalloc.c b/src/zmalloc.c index 094dd80fa..01ac8c797 100644 --- a/src/zmalloc.c +++ b/src/zmalloc.c @@ -147,6 +147,10 @@ void *zrealloc(void *ptr, size_t size) { size_t oldsize; void *newptr; + if (size == 0 && ptr!=NULL) { + zfree(ptr); + return NULL; + } if (ptr == NULL) return zmalloc(size); #ifdef HAVE_MALLOC_SIZE oldsize = zmalloc_size(ptr); From f4eb64cd3537ce34e0125fa1fb6cccb6dbfc3e48 Mon Sep 17 00:00:00 2001 From: "pan.liangp" Date: Fri, 2 Mar 2018 17:16:00 +0800 Subject: [PATCH 012/989] move get clients max buffer calculate into info clients command --- src/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server.c b/src/server.c index 1a6f30381..8e62dd176 100644 --- a/src/server.c +++ b/src/server.c @@ -2866,7 +2866,6 @@ sds genRedisInfoString(char *section) { getrusage(RUSAGE_SELF, &self_ru); getrusage(RUSAGE_CHILDREN, &c_ru); - getClientsMaxBuffers(&lol,&bib); /* Server */ if (allsections || defsections || !strcasecmp(section,"server")) { @@ -2936,6 +2935,7 @@ sds genRedisInfoString(char *section) { /* Clients */ if (allsections || defsections || !strcasecmp(section,"clients")) { + getClientsMaxBuffers(&lol,&bib); if (sections++) info = sdscat(info,"\r\n"); info = sdscatprintf(info, "# Clients\r\n" From 290a63dc54f9cd2a61681be3849f1d9d481aa060 Mon Sep 17 00:00:00 2001 From: Guy Benoish Date: Tue, 6 Mar 2018 19:34:44 +0700 Subject: [PATCH 013/989] Don't call sdscmp() with shared.maxstring or shared.minstring --- src/t_zset.c | 14 ++++++-------- tests/unit/type/zset.tcl | 18 +++++++++++++++++- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/src/t_zset.c b/src/t_zset.c index f7f4c6eb2..50652244b 100644 --- a/src/t_zset.c +++ b/src/t_zset.c @@ -519,12 +519,12 @@ int zslParseLexRangeItem(robj *item, sds *dest, int *ex) { switch(c[0]) { case '+': if (c[1] != '\0') return C_ERR; - *ex = 0; + *ex = 1; *dest = shared.maxstring; return C_OK; case '-': if (c[1] != '\0') return C_ERR; - *ex = 0; + *ex = 1; *dest = shared.minstring; return C_OK; case '(': @@ -597,9 +597,8 @@ int zslIsInLexRange(zskiplist *zsl, zlexrangespec *range) { zskiplistNode *x; /* Test for ranges that will always be empty. */ - if (sdscmplex(range->min,range->max) > 1 || - (sdscmp(range->min,range->max) == 0 && - (range->minex || range->maxex))) + int cmp = sdscmplex(range->min,range->max); + if (cmp > 0 || (cmp == 0 && (range->minex || range->maxex))) return 0; x = zsl->tail; if (x == NULL || !zslLexValueGteMin(x->ele,range)) @@ -872,9 +871,8 @@ int zzlIsInLexRange(unsigned char *zl, zlexrangespec *range) { unsigned char *p; /* Test for ranges that will always be empty. */ - if (sdscmplex(range->min,range->max) > 1 || - (sdscmp(range->min,range->max) == 0 && - (range->minex || range->maxex))) + int cmp = sdscmplex(range->min,range->max); + if (cmp > 0 || (cmp == 0 && (range->minex || range->maxex))) return 0; p = ziplistIndex(zl,-2); /* Last element. */ diff --git a/tests/unit/type/zset.tcl b/tests/unit/type/zset.tcl index 564825ae9..d8f3cfa53 100644 --- a/tests/unit/type/zset.tcl +++ b/tests/unit/type/zset.tcl @@ -388,7 +388,7 @@ start_server {tags {"zset"}} { 0 omega} } - test "ZRANGEBYLEX/ZREVRANGEBYLEX/ZCOUNT basics" { + test "ZRANGEBYLEX/ZREVRANGEBYLEX/ZLEXCOUNT basics" { create_default_lex_zset # inclusive range @@ -416,6 +416,22 @@ start_server {tags {"zset"}} { assert_equal {} [r zrevrangebylex zset \[elez \[elex] assert_equal {} [r zrevrangebylex zset (hill (omega] } + + test "ZLEXCOUNT advanced" { + create_default_lex_zset + + assert_equal 9 [r zlexcount zset - +] + assert_equal 0 [r zlexcount zset + -] + assert_equal 0 [r zlexcount zset + \[c] + assert_equal 0 [r zlexcount zset \[c -] + assert_equal 8 [r zlexcount zset \[bar +] + assert_equal 5 [r zlexcount zset \[bar \[foo] + assert_equal 4 [r zlexcount zset \[bar (foo] + assert_equal 4 [r zlexcount zset (bar \[foo] + assert_equal 3 [r zlexcount zset (bar (foo] + assert_equal 5 [r zlexcount zset - (foo] + assert_equal 1 [r zlexcount zset (maxstring +] + } test "ZRANGEBYSLEX with LIMIT" { create_default_lex_zset From b660fc2fbe545f4a20a907ffa6c8333396435907 Mon Sep 17 00:00:00 2001 From: Guy Benoish Date: Wed, 7 Mar 2018 10:40:37 +0700 Subject: [PATCH 014/989] Fix zlexrangespec mem-leak in genericZrangebylexCommand --- src/t_zset.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/t_zset.c b/src/t_zset.c index f7f4c6eb2..fa7793b15 100644 --- a/src/t_zset.c +++ b/src/t_zset.c @@ -2856,7 +2856,10 @@ void genericZrangebylexCommand(client *c, int reverse) { while (remaining) { if (remaining >= 3 && !strcasecmp(c->argv[pos]->ptr,"limit")) { if ((getLongFromObjectOrReply(c, c->argv[pos+1], &offset, NULL) != C_OK) || - (getLongFromObjectOrReply(c, c->argv[pos+2], &limit, NULL) != C_OK)) return; + (getLongFromObjectOrReply(c, c->argv[pos+2], &limit, NULL) != C_OK)) { + zslFreeLexRange(&range); + return; + } pos += 3; remaining -= 3; } else { zslFreeLexRange(&range); From fbef85ca5aca774c7533c6e0760edfd6258948c7 Mon Sep 17 00:00:00 2001 From: "zhaozhao.zz" Date: Thu, 29 Mar 2018 23:20:58 +0800 Subject: [PATCH 015/989] debug: avoid free client unexpectedly when reload & loadaof --- src/debug.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/debug.c b/src/debug.c index 293dbe36e..5d5029f5a 100644 --- a/src/debug.c +++ b/src/debug.c @@ -340,7 +340,10 @@ NULL return; } emptyDb(-1,EMPTYDB_NO_FLAGS,NULL); - if (rdbLoad(server.rdb_filename,NULL) != C_OK) { + aeDeleteFileEvent(server.el,c->fd,AE_READABLE); + int ret = rdbLoad(server.rdb_filename,NULL); + aeCreateFileEvent(server.el,c->fd,AE_READABLE,readQueryFromClient,c); + if (ret != C_OK) { addReplyError(c,"Error trying to load the RDB dump"); return; } @@ -349,7 +352,10 @@ NULL } else if (!strcasecmp(c->argv[1]->ptr,"loadaof")) { if (server.aof_state == AOF_ON) flushAppendOnlyFile(1); emptyDb(-1,EMPTYDB_NO_FLAGS,NULL); - if (loadAppendOnlyFile(server.aof_filename) != C_OK) { + aeDeleteFileEvent(server.el,c->fd,AE_READABLE); + int ret = loadAppendOnlyFile(server.aof_filename); + aeCreateFileEvent(server.el,c->fd,AE_READABLE,readQueryFromClient,c); + if (ret != C_OK) { addReply(c,shared.err); return; } From d56f4b4122aa51f97f5284e6e449943dd46ad659 Mon Sep 17 00:00:00 2001 From: Oran Agra Date: Mon, 2 Apr 2018 18:36:17 +0300 Subject: [PATCH 016/989] Add redis-cli support for diskless replication (CAPA EOF) when setting repl-diskless-sync yes, and sending SYNC. redis-cli needs to be able to understand the EOF marker protocol in order to be able to skip or download the rdb file --- src/redis-cli.c | 112 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 102 insertions(+), 10 deletions(-) diff --git a/src/redis-cli.c b/src/redis-cli.c index d80973e75..6fffa9024 100644 --- a/src/redis-cli.c +++ b/src/redis-cli.c @@ -1793,9 +1793,31 @@ static void latencyDistMode(void) { * Slave mode *--------------------------------------------------------------------------- */ +#define RDB_EOF_MARK_SIZE 40 + +void sendReplconf(const char* arg1, const char* arg2) { + printf("sending REPLCONF %s %s\n", arg1, arg2); + redisReply *reply = redisCommand(context, "REPLCONF %s %s", arg1, arg2); + + /* Handle any error conditions */ + if(reply == NULL) { + fprintf(stderr, "\nI/O error\n"); + exit(1); + } else if(reply->type == REDIS_REPLY_ERROR) { + fprintf(stderr, "REPLCONF %s error: %s\n", arg1, reply->str); + /* non fatal, old versions may not support it */ + } + freeReplyObject(reply); +} + +void sendCapa() { + sendReplconf("capa", "eof"); +} + /* Sends SYNC and reads the number of bytes in the payload. Used both by - * slaveMode() and getRDB(). */ -unsigned long long sendSync(int fd) { + * slaveMode() and getRDB(). + * returns 0 in case an EOF marker is used. */ +unsigned long long sendSync(int fd, char *out_eof) { /* To start we need to send the SYNC command and return the payload. * The hiredis client lib does not understand this part of the protocol * and we don't want to mess with its buffers, so everything is performed @@ -1825,17 +1847,33 @@ unsigned long long sendSync(int fd) { printf("SYNC with master failed: %s\n", buf); exit(1); } + if (strncmp(buf+1,"EOF:",4) == 0 && strlen(buf+5) >= RDB_EOF_MARK_SIZE) { + memcpy(out_eof, buf+5, RDB_EOF_MARK_SIZE); + return 0; + } return strtoull(buf+1,NULL,10); } static void slaveMode(void) { int fd = context->fd; - unsigned long long payload = sendSync(fd); + static char eofmark[RDB_EOF_MARK_SIZE]; + static char lastbytes[RDB_EOF_MARK_SIZE]; + static int usemark = 0; + unsigned long long payload = sendSync(fd, eofmark); char buf[1024]; int original_output = config.output; - fprintf(stderr,"SYNC with master, discarding %llu " - "bytes of bulk transfer...\n", payload); + if (payload == 0) { + payload = ULLONG_MAX; + memset(lastbytes,0,RDB_EOF_MARK_SIZE); + usemark = 1; + fprintf(stderr,"SYNC with master, discarding " + "bytes of bulk transfer until EOF marker...\n"); + } else { + fprintf(stderr,"SYNC with master, discarding %llu " + "bytes of bulk transfer...\n", payload); + } + /* Discard the payload. */ while(payload) { @@ -1847,8 +1885,29 @@ static void slaveMode(void) { exit(1); } payload -= nread; + + if (usemark) { + /* Update the last bytes array, and check if it matches our delimiter.*/ + if (nread >= RDB_EOF_MARK_SIZE) { + memcpy(lastbytes,buf+nread-RDB_EOF_MARK_SIZE,RDB_EOF_MARK_SIZE); + } else { + int rem = RDB_EOF_MARK_SIZE-nread; + memmove(lastbytes,lastbytes+nread,rem); + memcpy(lastbytes+rem,buf,nread); + } + if (memcmp(lastbytes,eofmark,RDB_EOF_MARK_SIZE) == 0) + break; + } } - fprintf(stderr,"SYNC done. Logging commands from master.\n"); + + if (usemark) { + unsigned long long offset = ULLONG_MAX - payload; + fprintf(stderr,"SYNC done after %llu bytes. Logging commands from master.\n", offset); + /* put the slave online */ + sleep(1); + sendReplconf("ACK", "0"); + } else + fprintf(stderr,"SYNC done. Logging commands from master.\n"); /* Now we can use hiredis to read the incoming protocol. */ config.output = OUTPUT_CSV; @@ -1865,11 +1924,22 @@ static void slaveMode(void) { static void getRDB(void) { int s = context->fd; int fd; - unsigned long long payload = sendSync(s); + static char eofmark[RDB_EOF_MARK_SIZE]; + static char lastbytes[RDB_EOF_MARK_SIZE]; + static int usemark = 0; + unsigned long long payload = sendSync(s, eofmark); char buf[4096]; - fprintf(stderr,"SYNC sent to master, writing %llu bytes to '%s'\n", - payload, config.rdb_filename); + if (payload == 0) { + payload = ULLONG_MAX; + memset(lastbytes,0,RDB_EOF_MARK_SIZE); + usemark = 1; + fprintf(stderr,"SYNC sent to master, writing bytes of bulk transfer until EOF marker to '%s'\n", + config.rdb_filename); + } else { + fprintf(stderr,"SYNC sent to master, writing %llu bytes to '%s'\n", + payload, config.rdb_filename); + } /* Write to file. */ if (!strcmp(config.rdb_filename,"-")) { @@ -1898,11 +1968,31 @@ static void getRDB(void) { exit(1); } payload -= nread; + + if (usemark) { + /* Update the last bytes array, and check if it matches our delimiter.*/ + if (nread >= RDB_EOF_MARK_SIZE) { + memcpy(lastbytes,buf+nread-RDB_EOF_MARK_SIZE,RDB_EOF_MARK_SIZE); + } else { + int rem = RDB_EOF_MARK_SIZE-nread; + memmove(lastbytes,lastbytes+nread,rem); + memcpy(lastbytes+rem,buf,nread); + } + if (memcmp(lastbytes,eofmark,RDB_EOF_MARK_SIZE) == 0) + break; + } + } + if (usemark) { + payload = ULLONG_MAX - payload - RDB_EOF_MARK_SIZE; + if (ftruncate(fd, payload) == -1) + fprintf(stderr,"ftruncate failed: %s.\n", strerror(errno)); + fprintf(stderr,"Transfer finished with success after %llu bytes\n", payload); + } else { + fprintf(stderr,"Transfer finished with success.\n"); } close(s); /* Close the file descriptor ASAP as fsync() may take time. */ fsync(fd); close(fd); - fprintf(stderr,"Transfer finished with success.\n"); exit(0); } @@ -2893,12 +2983,14 @@ int main(int argc, char **argv) { /* Slave mode */ if (config.slave_mode) { if (cliConnect(0) == REDIS_ERR) exit(1); + sendCapa(); slaveMode(); } /* Get RDB mode. */ if (config.getrdb_mode) { if (cliConnect(0) == REDIS_ERR) exit(1); + sendCapa(); getRDB(); } From 0fd2b25c8dc646dd86fe95021f2e5c0224f075da Mon Sep 17 00:00:00 2001 From: charpty Date: Fri, 6 Apr 2018 16:42:48 +0800 Subject: [PATCH 017/989] Remove unnecessary return statements Signed-off-by: charpty --- src/server.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/server.c b/src/server.c index 7f51778d7..6210fa18e 100644 --- a/src/server.c +++ b/src/server.c @@ -2866,7 +2866,6 @@ void bytesToHuman(char *s, unsigned long long n) { if (n < 1024) { /* Bytes */ sprintf(s,"%lluB",n); - return; } else if (n < (1024*1024)) { d = (double)n/(1024); sprintf(s,"%.2fK",d); From 8c8e85df874c852b5f125209e9d662a70e310f66 Mon Sep 17 00:00:00 2001 From: Guy Benoish Date: Wed, 18 Apr 2018 13:01:53 +0300 Subject: [PATCH 018/989] Use memtoll() in 'CONFIG SET client-output-buffer-limit' --- src/config.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/config.c b/src/config.c index a1122d059..a33981c63 100644 --- a/src/config.c +++ b/src/config.c @@ -983,8 +983,8 @@ void configSetCommand(client *c) { int soft_seconds; class = getClientTypeByName(v[j]); - hard = strtoll(v[j+1],NULL,10); - soft = strtoll(v[j+2],NULL,10); + hard = memtoll(v[j+1],NULL); + soft = memtoll(v[j+2],NULL); soft_seconds = strtoll(v[j+3],NULL,10); server.client_obuf_limits[class].hard_limit_bytes = hard; From 49890c8ee9776f13aaabf7fe76d796a89de6bf1a Mon Sep 17 00:00:00 2001 From: Itamar Haber Date: Mon, 30 Apr 2018 19:33:01 +0300 Subject: [PATCH 019/989] Adds memory information about the script's cache to INFO MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implementation notes: as INFO is "already broken", I didn't want to break it further. Instead of computing the server.lua_script dict size on every call, I'm keeping a running sum of the body's length and dict overheads. This implementation is naive as it **does not** take into consideration dict rehashing, but that inaccuracy pays off in speed ;) Demo time: ```bash $ redis-cli info memory | grep "script" used_memory_scripts:96 used_memory_scripts_human:96B number_of_cached_scripts:0 $ redis-cli eval "" 0 ; redis-cli info memory | grep "script" (nil) used_memory_scripts:120 used_memory_scripts_human:120B number_of_cached_scripts:1 $ redis-cli script flush ; redis-cli info memory | grep "script" OK used_memory_scripts:96 used_memory_scripts_human:96B number_of_cached_scripts:0 $ redis-cli eval "return('Hello, Script Cache :)')" 0 ; redis-cli info memory | grep "script" "Hello, Script Cache :)" used_memory_scripts:152 used_memory_scripts_human:152B number_of_cached_scripts:1 $ redis-cli eval "return redis.sha1hex(\"return('Hello, Script Cache :)')\")" 0 ; redis-cli info memory | grep "script" "1be72729d43da5114929c1260a749073732dc822" used_memory_scripts:232 used_memory_scripts_human:232B number_of_cached_scripts:2 ✔ 19:03:54 redis [lua_scripts-in-info-memory L ✚…⚑] $ redis-cli evalsha 1be72729d43da5114929c1260a749073732dc822 0 "Hello, Script Cache :)" ``` --- src/scripting.c | 3 +++ src/server.c | 8 ++++++++ src/server.h | 1 + 3 files changed, 12 insertions(+) diff --git a/src/scripting.c b/src/scripting.c index 3c0597c7a..e131d8ae0 100644 --- a/src/scripting.c +++ b/src/scripting.c @@ -919,6 +919,7 @@ void scriptingInit(int setup) { * This is useful for replication, as we need to replicate EVALSHA * as EVAL, so we need to remember the associated script. */ server.lua_scripts = dictCreate(&shaScriptObjectDictType,NULL); + server.lua_scripts_mem = sizeof(dict); /* Register the redis commands table and fields */ lua_newtable(lua); @@ -1073,6 +1074,7 @@ void scriptingInit(int setup) { * This function is used in order to reset the scripting environment. */ void scriptingRelease(void) { dictRelease(server.lua_scripts); + server.lua_scripts_mem = 0; lua_close(server.lua); } @@ -1207,6 +1209,7 @@ sds luaCreateFunction(client *c, lua_State *lua, robj *body) { * EVALSHA commands as EVAL using the original script. */ int retval = dictAdd(server.lua_scripts,sha,body); serverAssertWithInfo(c ? c : server.lua_client,NULL,retval == DICT_OK); + server.lua_scripts_mem += sdslen(body->ptr) + sizeof(dictEntry); incrRefCount(body); return sha; } diff --git a/src/server.c b/src/server.c index 7f51778d7..9bab389c0 100644 --- a/src/server.c +++ b/src/server.c @@ -2994,6 +2994,7 @@ sds genRedisInfoString(char *section) { char peak_hmem[64]; char total_system_hmem[64]; char used_memory_lua_hmem[64]; + char used_memory_scripts_hmem[64]; char used_memory_rss_hmem[64]; char maxmemory_hmem[64]; size_t zmalloc_used = zmalloc_used_memory(); @@ -3013,6 +3014,7 @@ sds genRedisInfoString(char *section) { bytesToHuman(peak_hmem,server.stat_peak_memory); bytesToHuman(total_system_hmem,total_system_mem); bytesToHuman(used_memory_lua_hmem,memory_lua); + bytesToHuman(used_memory_scripts_hmem,server.lua_scripts_mem); bytesToHuman(used_memory_rss_hmem,server.cron_malloc_stats.process_rss); bytesToHuman(maxmemory_hmem,server.maxmemory); @@ -3037,6 +3039,9 @@ sds genRedisInfoString(char *section) { "total_system_memory_human:%s\r\n" "used_memory_lua:%lld\r\n" "used_memory_lua_human:%s\r\n" + "used_memory_scripts:%lld\r\n" + "used_memory_scripts_human:%s\r\n" + "number_of_cached_scripts:%lu\r\n" "maxmemory:%lld\r\n" "maxmemory_human:%s\r\n" "maxmemory_policy:%s\r\n" @@ -3069,6 +3074,9 @@ sds genRedisInfoString(char *section) { total_system_hmem, memory_lua, used_memory_lua_hmem, + server.lua_scripts_mem, + used_memory_scripts_hmem, + dictSize(server.lua_scripts), server.maxmemory, maxmemory_hmem, evict_policy, diff --git a/src/server.h b/src/server.h index 0e9c3f285..260ba80d7 100644 --- a/src/server.h +++ b/src/server.h @@ -1203,6 +1203,7 @@ struct redisServer { client *lua_client; /* The "fake client" to query Redis from Lua */ client *lua_caller; /* The client running EVAL right now, or NULL */ dict *lua_scripts; /* A dictionary of SHA1 -> Lua scripts */ + unsigned long long lua_scripts_mem; /* Cached scripts' memory + oh */ mstime_t lua_time_limit; /* Script timeout in milliseconds */ mstime_t lua_time_start; /* Start time of script, milliseconds time */ int lua_write_dirty; /* True if a write command was called during the From 76ad23d012f194efa1acc0f8356d945b07681851 Mon Sep 17 00:00:00 2001 From: Itamar Haber Date: Thu, 7 Jun 2018 18:34:58 +0300 Subject: [PATCH 020/989] Adds MODULE HELP and implements addReplySubSyntaxError --- src/module.c | 13 +++++++++++-- src/networking.c | 12 ++++++++++++ src/server.h | 1 + 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/module.c b/src/module.c index cb03ad2cd..e4d6e2cf2 100644 --- a/src/module.c +++ b/src/module.c @@ -4499,7 +4499,15 @@ int moduleUnload(sds name) { * MODULE LOAD [args...] */ 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 [arg ...] -- Load a module library from .", +"unload -- Unload a module.", +NULL + }; + addReplyHelp(c, help); + } else if (!strcasecmp(subcmd,"load") && c->argc >= 3) { robj **argv = NULL; int argc = 0; @@ -4548,7 +4556,8 @@ void moduleCommand(client *c) { } dictReleaseIterator(di); } else { - addReply(c,shared.syntaxerr); + addReplySubSyntaxError(c); + return; } } diff --git a/src/networking.c b/src/networking.c index 00558974e..ac28ba2b8 100644 --- a/src/networking.c +++ b/src/networking.c @@ -560,6 +560,18 @@ void addReplyHelp(client *c, const char **help) { setDeferredMultiBulkLength(c,blenp,blen); } +/* Add a suggestive error reply. + * This function is typically invoked by from commands that support + * subcommands in response to an unknown subcommand or argument error. */ +void addReplySubSyntaxError(client *c) { + sds cmd = sdsnew((char*) c->argv[0]->ptr); + sdstoupper(cmd); + addReplyErrorFormat(c, + "Unknown subcommand or wrong number of arguments for '%s'. Try %s HELP.", + c->argv[1]->ptr,cmd); + sdsfree(cmd); +} + /* Copy 'src' client output buffers into 'dst' client output buffers. * The function takes care of freeing the old output buffers of the * destination client. */ diff --git a/src/server.h b/src/server.h index c34cdcfbf..26aee8932 100644 --- a/src/server.h +++ b/src/server.h @@ -1410,6 +1410,7 @@ void addReplyHumanLongDouble(client *c, long double d); void addReplyLongLong(client *c, long long ll); void addReplyMultiBulkLen(client *c, long length); void addReplyHelp(client *c, const char **help); +void addReplySubSyntaxError(client *c); void copyClientOutputBuffer(client *dst, client *src); size_t sdsZmallocSize(sds s); size_t getStringObjectSdsUsedMemory(robj *o); From c199280edb7ad344bb3d2af7572469f74d506da7 Mon Sep 17 00:00:00 2001 From: Itamar Haber Date: Thu, 7 Jun 2018 18:39:36 +0300 Subject: [PATCH 021/989] Globally applies addReplySubSyntaxError --- src/cluster.c | 3 +-- src/config.c | 3 +-- src/debug.c | 3 +-- src/object.c | 2 +- src/pubsub.c | 3 +-- src/scripting.c | 2 +- src/server.c | 2 +- src/slowlog.c | 2 +- 8 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/cluster.c b/src/cluster.c index 17ba6a744..56deb927c 100644 --- a/src/cluster.c +++ b/src/cluster.c @@ -4746,8 +4746,7 @@ NULL clusterReset(hard); addReply(c,shared.ok); } else { - addReplyErrorFormat(c, "Unknown subcommand or wrong number of arguments for '%s'. Try CLUSTER HELP", - (char*)c->argv[1]->ptr); + addReplySubSyntaxError(c); return; } } diff --git a/src/config.c b/src/config.c index bfb310303..4e6438e8e 100644 --- a/src/config.c +++ b/src/config.c @@ -2149,8 +2149,7 @@ NULL addReply(c,shared.ok); } } else { - addReplyErrorFormat(c, "Unknown subcommand or wrong number of arguments for '%s'. Try CONFIG HELP", - (char*)c->argv[1]->ptr); + addReplySubSyntaxError(c); return; } } diff --git a/src/debug.c b/src/debug.c index 0ab864e7f..0c5ea9a9e 100644 --- a/src/debug.c +++ b/src/debug.c @@ -553,8 +553,7 @@ NULL clearReplicationId2(); addReply(c,shared.ok); } else { - addReplyErrorFormat(c, "Unknown subcommand or wrong number of arguments for '%s'. Try DEBUG HELP", - (char*)c->argv[1]->ptr); + addReplySubSyntaxError(c); return; } } diff --git a/src/object.c b/src/object.c index 19af1ec0d..a4942fbe9 100644 --- a/src/object.c +++ b/src/object.c @@ -1197,7 +1197,7 @@ NULL * when the key is read or overwritten. */ addReplyLongLong(c,LFUDecrAndReturn(o)); } else { - addReplyErrorFormat(c, "Unknown subcommand or wrong number of arguments for '%s'. Try OBJECT help", (char *)c->argv[1]->ptr); + addReplySubSyntaxError(c); } } diff --git a/src/pubsub.c b/src/pubsub.c index d1fffa20a..7f7be52da 100644 --- a/src/pubsub.c +++ b/src/pubsub.c @@ -372,7 +372,6 @@ NULL /* PUBSUB NUMPAT */ addReplyLongLong(c,listLength(server.pubsub_patterns)); } else { - addReplyErrorFormat(c, "Unknown subcommand or wrong number of arguments for '%s'. Try PUBSUB HELP", - (char*)c->argv[1]->ptr); + addReplySubSyntaxError(c); } } diff --git a/src/scripting.c b/src/scripting.c index 3c0597c7a..85bce7bef 100644 --- a/src/scripting.c +++ b/src/scripting.c @@ -1514,7 +1514,7 @@ NULL return; } } else { - addReplyErrorFormat(c, "Unknown subcommand or wrong number of arguments for '%s'. Try SCRIPT HELP", (char*)c->argv[1]->ptr); + addReplySubSyntaxError(c); } } diff --git a/src/server.c b/src/server.c index 375c6477c..1e4d54b8b 100644 --- a/src/server.c +++ b/src/server.c @@ -2866,7 +2866,7 @@ NULL for (j = 0; j < numkeys; j++) addReplyBulk(c,c->argv[keys[j]+2]); getKeysFreeResult(keys); } else { - addReplyErrorFormat(c, "Unknown subcommand or wrong number of arguments for '%s'. Try COMMAND HELP", (char*)c->argv[1]->ptr); + addReplySubSyntaxError(c); } } diff --git a/src/slowlog.c b/src/slowlog.c index 2613435af..aed5707da 100644 --- a/src/slowlog.c +++ b/src/slowlog.c @@ -187,6 +187,6 @@ NULL } setDeferredMultiBulkLength(c,totentries,sent); } else { - addReplyErrorFormat(c, "Unknown subcommand or wrong number of arguments for '%s'. Try SLOWLOG HELP", (char*)c->argv[1]->ptr); + addReplySubSyntaxError(c); } } From 21ef0376feaaacee22b7913cb08948f65f9b8198 Mon Sep 17 00:00:00 2001 From: Itamar Haber Date: Sat, 9 Jun 2018 20:54:05 +0300 Subject: [PATCH 022/989] Capitalizes subscommands --- src/module.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/module.c b/src/module.c index e4d6e2cf2..3aaa94fe4 100644 --- a/src/module.c +++ b/src/module.c @@ -4501,9 +4501,9 @@ 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 [arg ...] -- Load a module library from .", -"unload -- Unload a module.", +"LIST -- Return a list of loaded modules.", +"LOAD [arg ...] -- Load a module library from .", +"UNLOAD -- Unload a module.", NULL }; addReplyHelp(c, help); From fefde6e3e4addf860829d4848386d90889590eac Mon Sep 17 00:00:00 2001 From: Itamar Haber Date: Sat, 9 Jun 2018 21:03:52 +0300 Subject: [PATCH 023/989] Capitalizes subcommands & orders lexicographically --- src/cluster.c | 40 ++++++++++++++++++++-------------------- src/config.c | 8 ++++---- src/debug.c | 38 +++++++++++++++++++------------------- src/pubsub.c | 6 +++--- src/scripting.c | 10 +++++----- src/server.c | 6 +++--- src/slowlog.c | 6 +++--- 7 files changed, 57 insertions(+), 57 deletions(-) diff --git a/src/cluster.c b/src/cluster.c index 56deb927c..39aab0cc7 100644 --- a/src/cluster.c +++ b/src/cluster.c @@ -4178,27 +4178,27 @@ void clusterCommand(client *c) { if (c->argc == 2 && !strcasecmp(c->argv[1]->ptr,"help")) { const char *help[] = { -"addslots [slot ...] -- Assign slots to current node.", -"bumpepoch -- Advance the cluster config epoch.", -"count-failure-reports -- Return number of failure reports for .", -"countkeysinslot - Return the number of keys in .", -"delslots [slot ...] -- Delete slots information from current node.", -"failover [force|takeover] -- Promote current slave node to being a master.", -"forget -- Remove a node from the cluster.", -"getkeysinslot -- Return key names stored by current node in a slot.", -"flushslots -- Delete current node own slots information.", -"info - Return onformation about the cluster.", -"keyslot -- Return the hash slot for .", -"meet [bus-port] -- Connect nodes into a working cluster.", -"myid -- Return the node id.", -"nodes -- Return cluster configuration seen by node. Output format:", +"ADDSLOTS [slot ...] -- Assign slots to current node.", +"BUMPEPOCH -- Advance the cluster config epoch.", +"COUNT-failure-reports -- Return number of failure reports for .", +"COUNTKEYSINSLOT - Return the number of keys in .", +"DELSLOTS [slot ...] -- Delete slots information from current node.", +"FAILOVER [force|takeover] -- Promote current slave node to being a master.", +"FORGET -- Remove a node from the cluster.", +"GETKEYSINSLOT -- Return key names stored by current node in a slot.", +"FLUSHSLOTS -- Delete current node own slots information.", +"INFO - Return onformation about the cluster.", +"KEYSLOT -- Return the hash slot for .", +"MEET [bus-port] -- Connect nodes into a working cluster.", +"MYID -- Return the node id.", +"NODES -- Return cluster configuration seen by node. Output format:", " ... ", -"replicate -- Configure current node as slave to .", -"reset [hard|soft] -- Reset current node (default: soft).", -"set-config-epoch - Set config epoch of current node.", -"setslot (importing|migrating|stable|node ) -- Set slot state.", -"slaves -- Return slaves.", -"slots -- Return information about slots range mappings. Each range is made of:", +"REPLICATE -- Configure current node as slave to .", +"RESET [hard|soft] -- Reset current node (default: soft).", +"SET-config-epoch - Set config epoch of current node.", +"SETSLOT (importing|migrating|stable|node ) -- Set slot state.", +"SLAVES -- Return slaves.", +"SLOTS -- Return information about slots range mappings. Each range is made of:", " start, end, master and replicas IP addresses, ports and ids", NULL }; diff --git a/src/config.c b/src/config.c index 4e6438e8e..edcafa7ad 100644 --- a/src/config.c +++ b/src/config.c @@ -2121,10 +2121,10 @@ void configCommand(client *c) { if (c->argc == 2 && !strcasecmp(c->argv[1]->ptr,"help")) { const char *help[] = { -"get -- Return parameters matching the glob-like and their values.", -"set -- Set parameter to value.", -"resetstat -- Reset statistics reported by INFO.", -"rewrite -- Rewrite the configuration file.", +"GET -- Return parameters matching the glob-like and their values.", +"SET -- Set parameter to value.", +"RESETSTAT -- Reset statistics reported by INFO.", +"REWRITE -- Rewrite the configuration file.", NULL }; addReplyHelp(c, help); diff --git a/src/debug.c b/src/debug.c index 0c5ea9a9e..7a9bddebd 100644 --- a/src/debug.c +++ b/src/debug.c @@ -285,25 +285,25 @@ void computeDatasetDigest(unsigned char *final) { 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 -- Hard crash and restart after delay.", -"digest -- Outputs an hex signature representing the current DB content.", -"htstats -- Return hash table statistics of the specified Redis database.", -"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 -- Show low level info about key and associated value.", -"panic -- Crash the server simulating a panic.", -"populate [prefix] [size] -- Create string keys named key:. If a prefix is specified is used instead of the 'key' prefix.", -"reload -- Save the RDB on disk and reload it back in memory.", -"restart -- Graceful restart: save config, db, restart.", -"sdslen -- 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.", -"sleep -- Stop the server for . Decimals allowed.", -"structsize -- Return the size of different Redis core C structures.", -"ziplist -- Show low level info about the ziplist encoding.", -"error -- Return a Redis protocol error with as message. Useful for clients unit tests to simulate Redis errors.", +"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 -- Hard crash and restart after delay.", +"DIGEST -- Output a hex signature representing the current DB content.", +"ERROR -- Return a Redis protocol error with as message. Useful for clients unit tests to simulate Redis errors.", +"HTSTATS -- Return hash table statistics of the specified Redis database.", +"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 -- Show low level info about key and associated value.", +"PANIC -- Crash the server simulating a panic.", +"POPULATE [prefix] [size] -- Create string keys named key:. If a prefix is specified is used instead of the 'key' prefix.", +"RELOAD -- Save the RDB on disk and reload it back in memory.", +"RESTART -- Graceful restart: save config, db, restart.", +"SDSLEN -- 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.", +"SLEEP -- Stop the server for . Decimals allowed.", +"STRUCTSIZE -- Return the size of different Redis core C structures.", +"ZIPLIST -- Show low level info about the ziplist encoding.", NULL }; addReplyHelp(c, help); diff --git a/src/pubsub.c b/src/pubsub.c index 7f7be52da..86a7f1c50 100644 --- a/src/pubsub.c +++ b/src/pubsub.c @@ -327,9 +327,9 @@ void publishCommand(client *c) { void pubsubCommand(client *c) { if (c->argc == 2 && !strcasecmp(c->argv[1]->ptr,"help")) { const char *help[] = { -"channels [] -- 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 [] -- 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).", NULL }; addReplyHelp(c, help); diff --git a/src/scripting.c b/src/scripting.c index 85bce7bef..f65540d89 100644 --- a/src/scripting.c +++ b/src/scripting.c @@ -1457,11 +1457,11 @@ 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 [ ...] -- Return information about the existence of the scripts in the script cache.", -"flush -- Flush the Lua scripts cache. Very dangerous on slaves.", -"kill -- Kill the currently executing Lua script.", -"load