From eca0187370c14aa2c126fe07e5310e44c2780a95 Mon Sep 17 00:00:00 2001 From: James Rouzier Date: Sat, 19 Sep 2015 14:01:10 -0400 Subject: [PATCH 01/25] 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 645d44d545ec958b9f541d4b7473ec021331ab04 Mon Sep 17 00:00:00 2001 From: "zhaozhao.zz" Date: Wed, 16 Jan 2019 19:19:10 +0800 Subject: [PATCH 02/25] Streams: checkType before XGROUP CREATE Fix issue #5785, in case create group on a key is not stream. --- src/t_stream.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/t_stream.c b/src/t_stream.c index 1a5acac42..9676e975e 100644 --- a/src/t_stream.c +++ b/src/t_stream.c @@ -1737,14 +1737,17 @@ NULL /* Everything but the "HELP" option requires a key and group name. */ if (c->argc >= 4) { o = lookupKeyWrite(c->db,c->argv[2]); - if (o) s = o->ptr; + if (o) { + if (checkType(c,o,OBJ_STREAM)) return; + s = o->ptr; + } grpname = c->argv[3]->ptr; } /* Check for missing key/group. */ if (c->argc >= 4 && !mkstream) { /* At this point key must exist, or there is an error. */ - if (o == NULL) { + if (s == NULL) { addReplyError(c, "The XGROUP subcommand requires the key to exist. " "Note that for CREATE you may want to use the MKSTREAM " @@ -1752,8 +1755,6 @@ NULL return; } - if (checkType(c,o,OBJ_STREAM)) return; - /* Certain subcommands require the group to exist. */ if ((cg = streamLookupCG(s,grpname)) == NULL && (!strcasecmp(opt,"SETID") || @@ -1781,7 +1782,8 @@ NULL } /* Handle the MKSTREAM option now that the command can no longer fail. */ - if (s == NULL && mkstream) { + if (s == NULL) { + serverAssert(mkstream); o = createStreamObject(); dbAdd(c->db,c->argv[2],o); s = o->ptr; From a16da7922895ad31e8b1a13aa5e23b3648e78aea Mon Sep 17 00:00:00 2001 From: chendianqiang Date: Fri, 1 Mar 2019 15:28:21 +0800 Subject: [PATCH 03/25] optimize cluster failover --- src/cluster.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cluster.c b/src/cluster.c index 1a3a348b5..50a9ae687 100644 --- a/src/cluster.c +++ b/src/cluster.c @@ -3031,6 +3031,7 @@ void clusterHandleSlaveFailover(void) { if (server.cluster->mf_end) { server.cluster->failover_auth_time = mstime(); server.cluster->failover_auth_rank = 0; + clusterDoBeforeSleep(CLUSTER_TODO_HANDLE_FAILOVER); } serverLog(LL_WARNING, "Start of election delayed for %lld milliseconds " From cd2743c0e6b7702535b410db4e51f6d5e22a7d4c Mon Sep 17 00:00:00 2001 From: Itamar Haber Date: Sun, 3 Mar 2019 23:10:45 +0200 Subject: [PATCH 04/25] Fixes BZ[REV]POP's arity --- src/server.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/server.c b/src/server.c index 9de579815..712cda1bd 100644 --- a/src/server.c +++ b/src/server.c @@ -480,11 +480,11 @@ struct redisCommand redisCommandTable[] = { "write fast @sortedset", 0,NULL,1,1,1,0,0,0}, - {"bzpopmin",bzpopminCommand,-2, + {"bzpopmin",bzpopminCommand,-3, "write no-script fast @sortedset @blocking", 0,NULL,1,-2,1,0,0,0}, - {"bzpopmax",bzpopmaxCommand,-2, + {"bzpopmax",bzpopmaxCommand,-3, "write no-script fast @sortedset @blocking", 0,NULL,1,-2,1,0,0,0}, From fb81d1b3f891746e886f44cad5df96a29e6b9f51 Mon Sep 17 00:00:00 2001 From: "zhaozhao.zz" Date: Mon, 4 Mar 2019 19:43:00 +0800 Subject: [PATCH 05/25] Fix compile warning when log aux field --- src/rdb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rdb.c b/src/rdb.c index b800ee481..52dddf210 100644 --- a/src/rdb.c +++ b/src/rdb.c @@ -1965,7 +1965,7 @@ int rdbLoadRio(rio *rdb, rdbSaveInfo *rsi, int loading_aof) { } } else if (!strcasecmp(auxkey->ptr,"redis-ver")) { serverLog(LL_NOTICE,"Loading RDB produced by version %s", - auxval->ptr); + (char*)auxval->ptr); } else if (!strcasecmp(auxkey->ptr,"ctime")) { time_t age = time(NULL)-strtol(auxval->ptr,NULL,10); if (age < 0) age = 0; From c33cb4938a6debf999a9af312498a4ab91271c81 Mon Sep 17 00:00:00 2001 From: antirez Date: Tue, 5 Mar 2019 15:51:37 +0100 Subject: [PATCH 06/25] ACL: GENPASS subcommand. --- src/acl.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/acl.c b/src/acl.c index 3cca50027..d9f431f4f 100644 --- a/src/acl.c +++ b/src/acl.c @@ -1389,6 +1389,8 @@ void ACLLoadUsersAtStartup(void) { * ACL SETUSER ... acl rules ... * ACL DELUSER [...] * ACL GETUSER + * ACL GENPASS + * ACL WHOAMI */ void aclCommand(client *c) { char *sub = c->argv[1]->ptr; @@ -1571,6 +1573,10 @@ void aclCommand(client *c) { } dictReleaseIterator(di); setDeferredArrayLen(c,dl,arraylen); + } else if (!strcasecmp(sub,"genpass") && c->argc == 2) { + char pass[32]; /* 128 bits of actual pseudo random data. */ + getRandomHexChars(pass,sizeof(pass)); + addReplyBulkCBuffer(c,pass,sizeof(pass)); } else if (!strcasecmp(sub,"help")) { const char *help[] = { "LOAD -- Reload users from the ACL file.", @@ -1581,6 +1587,7 @@ void aclCommand(client *c) { "DELUSER [...] -- Delete a list of users.", "CAT -- List available categories.", "CAT -- List commands inside category.", +"GENPASS -- Generate a secure user password.", "WHOAMI -- Return the current connection username.", NULL }; From 93e51239ce1d3778cbe068223221365a1ce7ad89 Mon Sep 17 00:00:00 2001 From: artix Date: Wed, 6 Mar 2019 16:38:36 +0100 Subject: [PATCH 07/25] Cluster Manager: add importing/migrating nodes to backup info --- src/redis-cli.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/redis-cli.c b/src/redis-cli.c index 0e52c16be..5968ee389 100644 --- a/src/redis-cli.c +++ b/src/redis-cli.c @@ -2732,6 +2732,36 @@ static sds clusterManagerNodeGetJSON(clusterManagerNode *node, json = sdscatprintf(json, ",\n \"cluster_errors\": %lu", error_count); } + if (node->migrating_count > 0 && node->migrating != NULL) { + int i = 0; + sds migrating = sdsempty(); + for (; i < node->migrating_count; i += 2) { + sds slot = node->migrating[i]; + sds dest = node->migrating[i + 1]; + if (slot && dest) { + if (sdslen(migrating) > 0) migrating = sdscat(migrating, ","); + migrating = sdscatfmt(migrating, "\"%S\": \"%S\"", slot, dest); + } + } + if (sdslen(migrating) > 0) + json = sdscatfmt(json, ",\n \"migrating\": {%S}", migrating); + sdsfree(migrating); + } + if (node->importing_count > 0 && node->importing != NULL) { + int i = 0; + sds importing = sdsempty(); + for (; i < node->importing_count; i += 2) { + sds slot = node->importing[i]; + sds from = node->importing[i + 1]; + if (slot && from) { + if (sdslen(importing) > 0) importing = sdscat(importing, ","); + importing = sdscatfmt(importing, "\"%S\": \"%S\"", slot, from); + } + } + if (sdslen(importing) > 0) + json = sdscatfmt(json, ",\n \"importing\": {%S}", importing); + sdsfree(importing); + } json = sdscat(json, "\n }"); sdsfree(replicate); sdsfree(slots); From d5b24d31d73d80f27feed5334d9c79eec00afc31 Mon Sep 17 00:00:00 2001 From: Brad Solomon Date: Wed, 6 Mar 2019 21:24:45 -0500 Subject: [PATCH 08/25] Provide an uninstall target in Makefile On `make uninstall`, removes: - /usr/local/bin/redis-benchmark - /usr/local/bin/redis-check-aof - /usr/local/bin/redis-check-rdb - /usr/local/bin/redis-cli - /usr/local/bin/redis-sentinel - /usr/local/bin/redis-server (Only the src/ versions are removed in `make clean`) --- src/Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Makefile b/src/Makefile index 9da1da8d3..93cfdc28e 100644 --- a/src/Makefile +++ b/src/Makefile @@ -310,3 +310,6 @@ install: all $(REDIS_INSTALL) $(REDIS_CHECK_RDB_NAME) $(INSTALL_BIN) $(REDIS_INSTALL) $(REDIS_CHECK_AOF_NAME) $(INSTALL_BIN) @ln -sf $(REDIS_SERVER_NAME) $(INSTALL_BIN)/$(REDIS_SENTINEL_NAME) + +uninstall: + rm -f $(INSTALL_BIN)/{$(REDIS_SERVER_NAME),$(REDIS_BENCHMARK_NAME),$(REDIS_CLI_NAME),$(REDIS_CHECK_RDB_NAME),$(REDIS_CHECK_AOF_NAME),$(REDIS_SENTINEL_NAME)} From 0e963e068d15e56254987c12e5aba9162e208099 Mon Sep 17 00:00:00 2001 From: artix Date: Thu, 7 Mar 2019 11:14:03 +0100 Subject: [PATCH 09/25] Redis Benchmark: add multithread idle mode Fix issue #5891 --- src/redis-benchmark.c | 55 ++++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/src/redis-benchmark.c b/src/redis-benchmark.c index 23a02d548..89245132b 100644 --- a/src/redis-benchmark.c +++ b/src/redis-benchmark.c @@ -817,22 +817,37 @@ static void showLatencyReport(void) { } } -static void benchmark(char *title, char *cmd, int len) { +static void initBenchmarkThreads() { int i; + if (config.threads) freeBenchmarkThreads(); + config.threads = zmalloc(config.num_threads * sizeof(benchmarkThread*)); + for (i = 0; i < config.num_threads; i++) { + benchmarkThread *thread = createBenchmarkThread(i); + config.threads[i] = thread; + } +} + +static void startBenchmarkThreads() { + int i; + for (i = 0; i < config.num_threads; i++) { + benchmarkThread *t = config.threads[i]; + if (pthread_create(&(t->thread), NULL, execBenchmarkThread, t)){ + fprintf(stderr, "FATAL: Failed to start thread %d.\n", i); + exit(1); + } + } + for (i = 0; i < config.num_threads; i++) + pthread_join(config.threads[i]->thread, NULL); +} + +static void benchmark(char *title, char *cmd, int len) { client c; config.title = title; config.requests_issued = 0; config.requests_finished = 0; - if (config.num_threads) { - if (config.threads) freeBenchmarkThreads(); - config.threads = zmalloc(config.num_threads * sizeof(benchmarkThread*)); - for (i = 0; i < config.num_threads; i++) { - benchmarkThread *thread = createBenchmarkThread(i); - config.threads[i] = thread; - } - } + if (config.num_threads) initBenchmarkThreads(); int thread_id = config.num_threads > 0 ? 0 : -1; c = createClient(cmd,len,NULL,thread_id); @@ -840,17 +855,7 @@ static void benchmark(char *title, char *cmd, int len) { config.start = mstime(); if (!config.num_threads) aeMain(config.el); - else { - for (i = 0; i < config.num_threads; i++) { - benchmarkThread *t = config.threads[i]; - if (pthread_create(&(t->thread), NULL, execBenchmarkThread, t)){ - fprintf(stderr, "FATAL: Failed to start thread %d.\n", i); - exit(1); - } - } - for (i = 0; i < config.num_threads; i++) - pthread_join(config.threads[i]->thread, NULL); - } + else startBenchmarkThreads(); config.totlatency = mstime()-config.start; showLatencyReport(); @@ -1546,9 +1551,15 @@ int main(int argc, const char **argv) { if (config.idlemode) { printf("Creating %d idle connections and waiting forever (Ctrl+C when done)\n", config.numclients); - c = createClient("",0,NULL,-1); /* will never receive a reply */ + int thread_id = -1, use_threads = (config.num_threads > 0); + if (use_threads) { + thread_id = 0; + initBenchmarkThreads(); + } + c = createClient("",0,NULL,thread_id); /* will never receive a reply */ createMissingClients(c); - aeMain(config.el); + if (use_threads) startBenchmarkThreads(); + else aeMain(config.el); /* and will wait for every */ } From c389ad0d52d7770f2b1b1e48608bbbd171bc5a3e Mon Sep 17 00:00:00 2001 From: artix Date: Thu, 7 Mar 2019 11:30:09 +0100 Subject: [PATCH 10/25] Redis Benchmark: fix key randomization with zero keyspacelen --- src/redis-benchmark.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/redis-benchmark.c b/src/redis-benchmark.c index 89245132b..83574f26c 100644 --- a/src/redis-benchmark.c +++ b/src/redis-benchmark.c @@ -345,7 +345,9 @@ static void randomizeClientKey(client c) { for (i = 0; i < c->randlen; i++) { char *p = c->randptr[i]+11; - size_t r = random() % config.randomkeys_keyspacelen; + size_t r = 0; + if (config.randomkeys_keyspacelen != 0) + r = random() % config.randomkeys_keyspacelen; size_t j; for (j = 0; j < 12; j++) { @@ -1288,6 +1290,11 @@ int parseOptions(int argc, const char **argv) { if (config.pipeline <= 0) config.pipeline=1; } else if (!strcmp(argv[i],"-r")) { if (lastarg) goto invalid; + const char *next = argv[++i], *p = next; + if (*p == '-') { + p++; + if (*p < '0' || *p > '9') goto invalid; + } config.randomkeys = 1; config.randomkeys_keyspacelen = atoi(argv[++i]); if (config.randomkeys_keyspacelen < 0) From feb4ebff45c5eb9e6aaabe3c1391d4844a480541 Mon Sep 17 00:00:00 2001 From: Yuan Zhou Date: Thu, 7 Mar 2019 18:35:27 +0800 Subject: [PATCH 11/25] server.h: remove dead code hashTypeTryObjectEncoding() is not used now --- src/server.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/server.h b/src/server.h index 71fef492f..7c635e5fe 100644 --- a/src/server.h +++ b/src/server.h @@ -1887,7 +1887,6 @@ void setTypeConvert(robj *subject, int enc); void hashTypeConvert(robj *o, int enc); void hashTypeTryConversion(robj *subject, robj **argv, int start, int end); -void hashTypeTryObjectEncoding(robj *subject, robj **o1, robj **o2); int hashTypeExists(robj *o, sds key); int hashTypeDelete(robj *o, sds key); unsigned long hashTypeLength(const robj *o); From 0137f1a2e33b6f14d7e365adddcf6299a4014b50 Mon Sep 17 00:00:00 2001 From: "zhaozhao.zz" Date: Thu, 7 Mar 2019 22:08:04 +0800 Subject: [PATCH 12/25] try lazyfree temp set in SUNION & SDIFF --- src/t_set.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/t_set.c b/src/t_set.c index 290a83e6d..cbe55aaa4 100644 --- a/src/t_set.c +++ b/src/t_set.c @@ -1064,7 +1064,8 @@ void sunionDiffGenericCommand(client *c, robj **setkeys, int setnum, sdsfree(ele); } setTypeReleaseIterator(si); - decrRefCount(dstset); + server.lazyfree_lazy_server_del ? freeObjAsync(dstset) : + decrRefCount(dstset); } else { /* If we have a target key where to store the resulting set * create this key with the result set inside */ From 8fadebfcca0d514fd6949eaa72599ab5e163bd4c Mon Sep 17 00:00:00 2001 From: artix Date: Fri, 8 Mar 2019 11:05:02 +0100 Subject: [PATCH 13/25] Redis Benchmark: handle CLUSTERDOWN error --- src/redis-benchmark.c | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/redis-benchmark.c b/src/redis-benchmark.c index 83574f26c..18d5c1020 100644 --- a/src/redis-benchmark.c +++ b/src/redis-benchmark.c @@ -449,27 +449,27 @@ static void readHandler(aeEventLoop *el, int fd, void *privdata, int mask) { } } - if (config.cluster_mode && is_err && c->cluster_node && - (!strncmp(r->str,"MOVED",5) || - !strcmp(r->str,"ASK"))) - { - /* Try to update slots configuration if the key of the - * command is using the slot hash tag. */ - if (c->staglen && !fetchClusterSlotsConfiguration(c)) - exit(1); - /* - clusterNode *node = c->cluster_node; - assert(node); - if (++node->current_slot_index >= node->slots_count) { - if (config.showerrors) { - fprintf(stderr, "WARN: No more available slots in " - "node %s:%d\n", node->ip, node->port); - } - freeReplyObject(reply); - freeClient(c); - return; + /* Try to update slots configuration if reply error is + * MOVED/ASK/CLUSTERDOWN and the key(s) used by the command + * contain(s) the slot hash tag. */ + if (is_err && c->cluster_node && c->staglen) { + int fetch_slots = 0, do_wait = 0; + if (!strncmp(r->str,"MOVED",5) || !strncmp(r->str,"ASK",3)) + fetch_slots = 1; + else if (!strncmp(r->str,"CLUSTERDOWN",11)) { + /* Usually the cluster is able to recover itself after + * a CLUSTERDOWN error, so try to sleep one second + * before requesting the new configuration. */ + fetch_slots = 1; + do_wait = 1; + printf("Error from server %s:%d: %s\n", + c->cluster_node->ip, + c->cluster_node->port, + r->str); } - */ + if (do_wait) sleep(1); + if (fetch_slots && !fetchClusterSlotsConfiguration(c)) + exit(1); } freeReplyObject(reply); From f1e7df4b7c0dfb8ceaaa2e844b2b29024e8dfbcc Mon Sep 17 00:00:00 2001 From: Steve Webster Date: Fri, 8 Mar 2019 17:09:11 +0000 Subject: [PATCH 14/25] Increment delivery counter on XCLAIM unless RETRYCOUNT specified The XCLAIM docs state the XCLAIM increments the delivery counter for messages. This PR makes the code match the documentation - which seems like the desired behaviour - whilst still allowing RETRYCOUNT to be specified manually. My understanding of the way streamPropagateXCLAIM() works is that this change will safely propagate to replicas since retry count is pulled directly from the streamNACK struct. Fixes #5194 --- src/t_stream.c | 8 ++++++-- tests/unit/type/stream-cgroups.tcl | 29 +++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/t_stream.c b/src/t_stream.c index 1a5acac42..f02b9e99b 100644 --- a/src/t_stream.c +++ b/src/t_stream.c @@ -2279,8 +2279,12 @@ void xclaimCommand(client *c) { /* Update the consumer and idle time. */ nack->consumer = consumer; nack->delivery_time = deliverytime; - /* Set the delivery attempts counter if given. */ - if (retrycount >= 0) nack->delivery_count = retrycount; + /* Set the delivery attempts counter if given, otherwise autoincrement */ + if (retrycount >= 0) { + nack->delivery_count = retrycount; + } else { + nack->delivery_count++; + } /* Add the entry in the new consumer local PEL. */ raxInsert(consumer->pel,buf,sizeof(buf),nack,NULL); /* Send the reply for this entry. */ diff --git a/tests/unit/type/stream-cgroups.tcl b/tests/unit/type/stream-cgroups.tcl index 13981cc22..3a056bfab 100644 --- a/tests/unit/type/stream-cgroups.tcl +++ b/tests/unit/type/stream-cgroups.tcl @@ -195,6 +195,35 @@ start_server { assert_equal "" [lindex $reply 0] } + test {XCLAIM increments delivery count} { + # Add 3 items into the stream, and create a consumer group + r del mystream + set id1 [r XADD mystream * a 1] + set id2 [r XADD mystream * b 2] + set id3 [r XADD mystream * c 3] + r XGROUP CREATE mystream mygroup 0 + + # Client 1 reads item 1 from the stream without acknowledgements. + # Client 2 then claims pending item 1 from the PEL of client 1 + set reply [ + r XREADGROUP GROUP mygroup client1 count 1 STREAMS mystream > + ] + assert {[llength [lindex $reply 0 1 0 1]] == 2} + assert {[lindex $reply 0 1 0 1] eq {a 1}} + r debug sleep 0.2 + set reply [ + r XCLAIM mystream mygroup client2 10 $id1 + ] + assert {[llength [lindex $reply 0 1]] == 2} + assert {[lindex $reply 0 1] eq {a 1}} + + set reply [ + r XPENDING mystream mygroup - + 10 + ] + assert {[llength [lindex $reply 0]] == 4} + assert {[lindex $reply 0 3] == 2} + } + start_server {} { set master [srv -1 client] set master_host [srv -1 host] From 79660e4ff43b55fee1eaa70a27263c4cc3c905a4 Mon Sep 17 00:00:00 2001 From: Brad Solomon Date: Sat, 9 Mar 2019 10:21:15 -0500 Subject: [PATCH 15/25] Note that install_server.sh is not for Mac OSX It will fail pretty quickly since there is no -f readlink flag there. --- README.md | 2 ++ utils/install_server.sh | 3 +++ 2 files changed, 5 insertions(+) diff --git a/README.md b/README.md index 2b4eeb19b..6c9435b53 100644 --- a/README.md +++ b/README.md @@ -166,6 +166,8 @@ for Ubuntu and Debian systems: % cd utils % ./install_server.sh +_Note_: `install_server.sh` will not work on Mac OSX; it is built for Linux only. + The script will ask you a few questions and will setup everything you need to run Redis properly as a background daemon that will start again on system reboots. diff --git a/utils/install_server.sh b/utils/install_server.sh index 7eb341417..8e5753bc6 100755 --- a/utils/install_server.sh +++ b/utils/install_server.sh @@ -43,6 +43,9 @@ # # /!\ This script should be run as root # +# NOTE: This script will not work on Mac OSX. +# It supports Debian and Ubuntu Linux. +# ################################################################################ die () { From 5b52bc738bcf0881d07805dc300aeee9cf555b77 Mon Sep 17 00:00:00 2001 From: John Sully Date: Sat, 9 Mar 2019 11:03:59 -0500 Subject: [PATCH 16/25] Replicas aren't allowed to run the replicaof command --- src/replication.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/replication.c b/src/replication.c index 9175bb420..26313893d 100644 --- a/src/replication.c +++ b/src/replication.c @@ -2038,6 +2038,14 @@ void replicaofCommand(client *c) { } else { long port; + if (c->flags & CLIENT_SLAVE) + { + /* If a client is already a replica they cannot run this command, + * because it involves flushing all replicas (including this client) */ + addReplyError(c, "Command is not valid when client is a replica."); + return; + } + if ((getLongFromObjectOrReply(c, c->argv[2], &port, NULL) != C_OK)) return; From 0298d3ad1833c0085ebc26baeda58dc3a511de25 Mon Sep 17 00:00:00 2001 From: wurongxin Date: Sun, 10 Mar 2019 15:30:32 +0800 Subject: [PATCH 17/25] fix a bufferoverflow bug --- src/redis-cli.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/redis-cli.c b/src/redis-cli.c index 0e52c16be..09d9cc72e 100644 --- a/src/redis-cli.c +++ b/src/redis-cli.c @@ -2268,7 +2268,7 @@ static clusterManagerNode *clusterManagerNewNode(char *ip, int port) { static sds clusterManagerGetNodeRDBFilename(clusterManagerNode *node) { assert(config.cluster_manager_command.backup_dir); sds filename = sdsnew(config.cluster_manager_command.backup_dir); - if (filename[sdslen(filename)] - 1 != '/') + if (filename[sdslen(filename) - 1] != '/') filename = sdscat(filename, "/"); filename = sdscatprintf(filename, "redis-node-%s-%d-%s.rdb", node->ip, node->port, node->name); From 8a46d32be2eaf07b6b2e8c3757e4d9f59cd1ab64 Mon Sep 17 00:00:00 2001 From: antirez Date: Sun, 10 Mar 2019 09:48:06 +0100 Subject: [PATCH 18/25] Make comment in #5911 stay inside 80 cols. --- src/replication.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/replication.c b/src/replication.c index 26313893d..3c30999af 100644 --- a/src/replication.c +++ b/src/replication.c @@ -2041,7 +2041,8 @@ void replicaofCommand(client *c) { if (c->flags & CLIENT_SLAVE) { /* If a client is already a replica they cannot run this command, - * because it involves flushing all replicas (including this client) */ + * because it involves flushing all replicas (including this + * client) */ addReplyError(c, "Command is not valid when client is a replica."); return; } From 468860ae18b11486f734c476bc2930de7860abe1 Mon Sep 17 00:00:00 2001 From: swilly22 Date: Mon, 11 Mar 2019 10:02:19 +0200 Subject: [PATCH 19/25] Extend REDISMODULE_CTX_FLAGS to indicate if command was sent by master --- src/module.c | 3 +++ src/redismodule.h | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/module.c b/src/module.c index 81982ba76..5ad999751 100644 --- a/src/module.c +++ b/src/module.c @@ -1391,6 +1391,9 @@ int RM_GetContextFlags(RedisModuleCtx *ctx) { flags |= REDISMODULE_CTX_FLAGS_LUA; if (ctx->client->flags & CLIENT_MULTI) flags |= REDISMODULE_CTX_FLAGS_MULTI; + /* Module command recieved from MASTER, is replicated. */ + if (ctx->client->flags & CLIENT_MASTER) + flags |= REDISMODULE_CTX_FLAGS_REPLICATED; } if (server.cluster_enabled) diff --git a/src/redismodule.h b/src/redismodule.h index d18c38881..540f8e3db 100644 --- a/src/redismodule.h +++ b/src/redismodule.h @@ -85,6 +85,9 @@ #define REDISMODULE_CTX_FLAGS_OOM (1<<10) /* Less than 25% of memory available according to maxmemory. */ #define REDISMODULE_CTX_FLAGS_OOM_WARNING (1<<11) +/* The command was sent over the replication link. */ +#define REDISMODULE_CTX_FLAGS_REPLICATED (1<<12) + #define REDISMODULE_NOTIFY_GENERIC (1<<2) /* g */ #define REDISMODULE_NOTIFY_STRING (1<<3) /* $ */ From 3621223fbba8d9b5e9e5ce6348c96513e0186be2 Mon Sep 17 00:00:00 2001 From: chendianqiang Date: Tue, 12 Mar 2019 20:46:40 +0800 Subject: [PATCH 20/25] remove temp-rewriteaof-xxx.aof when interrupt aofrewrite --- src/aof.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/aof.c b/src/aof.c index 46ae58324..cafcf961c 100644 --- a/src/aof.c +++ b/src/aof.c @@ -1611,6 +1611,9 @@ void aofRemoveTempFile(pid_t childpid) { snprintf(tmpfile,256,"temp-rewriteaof-bg-%d.aof", (int) childpid); unlink(tmpfile); + + snprintf(tmpfile,256,"temp-rewriteaof-%d.aof", (int) childpid); + unlink(tmpfile); } /* Update the server.aof_current_size field explicitly using stat(2) From bdc783b472769e9881b42ed8c45583ab98a791e8 Mon Sep 17 00:00:00 2001 From: vattezhang Date: Tue, 12 Mar 2019 22:01:02 +0800 Subject: [PATCH 21/25] fix: fix the if condition in clusterManagerShowClusterInfo --- src/redis-cli.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/redis-cli.c b/src/redis-cli.c index 0e52c16be..c28dfeeee 100644 --- a/src/redis-cli.c +++ b/src/redis-cli.c @@ -2841,7 +2841,7 @@ static void clusterManagerShowClusterInfo(void) { replicas++; } redisReply *reply = CLUSTER_MANAGER_COMMAND(node, "DBSIZE"); - if (reply != NULL || reply->type == REDIS_REPLY_INTEGER) + if (reply != NULL && reply->type == REDIS_REPLY_INTEGER) dbsize = reply->integer; if (dbsize < 0) { char *err = ""; From 5284d67e376eee1a01eece66a6d0e3273051f359 Mon Sep 17 00:00:00 2001 From: artix Date: Tue, 12 Mar 2019 17:07:19 +0100 Subject: [PATCH 22/25] Redis Benchmark: fix possible usage of freed pointer (getRedisConfig) Fixes issue #5912 --- src/redis-benchmark.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/redis-benchmark.c b/src/redis-benchmark.c index 18d5c1020..12e9f7e41 100644 --- a/src/redis-benchmark.c +++ b/src/redis-benchmark.c @@ -247,11 +247,11 @@ static redisConfig *getRedisConfig(const char *ip, int port, c = redisConnect(ip, port); else c = redisConnectUnix(hostsocket); - if (c->err) { + if (c == NULL || c->err) { fprintf(stderr,"Could not connect to Redis at "); - if (hostsocket == NULL) - fprintf(stderr,"%s:%d: %s\n",ip,port,c->errstr); - else fprintf(stderr,"%s: %s\n",hostsocket,c->errstr); + char *err = (c != NULL ? c->errstr : ""); + if (hostsocket == NULL) fprintf(stderr,"%s:%d: %s\n",ip,port,err); + else fprintf(stderr,"%s: %s\n",hostsocket,err); goto fail; } redisAppendCommand(c, "CONFIG GET %s", "save"); @@ -276,18 +276,16 @@ static redisConfig *getRedisConfig(const char *ip, int port, case 1: cfg->appendonly = sdsnew(value); break; } } - if (reply) freeReplyObject(reply); - if (c) redisFree(c); + freeReplyObject(reply); + redisFree(c); return cfg; fail: - if (reply) freeReplyObject(reply); - if (c) redisFree(c); - zfree(cfg); fprintf(stderr, "ERROR: failed to fetch CONFIG from "); - if (c->connection_type == REDIS_CONN_TCP) - fprintf(stderr, "%s:%d\n", c->tcp.host, c->tcp.port); - else if (c->connection_type == REDIS_CONN_UNIX) - fprintf(stderr, "%s\n", c->unix_sock.path); + if (hostsocket == NULL) fprintf(stderr, "%s:%d\n", ip, port); + else fprintf(stderr, "%s\n", hostsocket); + freeReplyObject(reply); + redisFree(c); + zfree(cfg); return NULL; } static void freeRedisConfig(redisConfig *cfg) { From dfcb227b5066275df18734ea7a6ab19212e57f1f Mon Sep 17 00:00:00 2001 From: Steve Webster Date: Tue, 12 Mar 2019 20:27:53 +0000 Subject: [PATCH 23/25] Only increment delivery count if JUSTID option is omitted --- src/t_stream.c | 5 +++-- tests/unit/type/stream-cgroups.tcl | 16 +++++++++++++++- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/t_stream.c b/src/t_stream.c index f02b9e99b..7816c775c 100644 --- a/src/t_stream.c +++ b/src/t_stream.c @@ -2279,10 +2279,11 @@ void xclaimCommand(client *c) { /* Update the consumer and idle time. */ nack->consumer = consumer; nack->delivery_time = deliverytime; - /* Set the delivery attempts counter if given, otherwise autoincrement */ + /* Set the delivery attempts counter if given, otherwise + * autoincrement unless JUSTID option provided */ if (retrycount >= 0) { nack->delivery_count = retrycount; - } else { + } else if (!justid) { nack->delivery_count++; } /* Add the entry in the new consumer local PEL. */ diff --git a/tests/unit/type/stream-cgroups.tcl b/tests/unit/type/stream-cgroups.tcl index 3a056bfab..34d4061c2 100644 --- a/tests/unit/type/stream-cgroups.tcl +++ b/tests/unit/type/stream-cgroups.tcl @@ -195,7 +195,7 @@ start_server { assert_equal "" [lindex $reply 0] } - test {XCLAIM increments delivery count} { + test {XCLAIM without JUSTID increments delivery count} { # Add 3 items into the stream, and create a consumer group r del mystream set id1 [r XADD mystream * a 1] @@ -222,6 +222,20 @@ start_server { ] assert {[llength [lindex $reply 0]] == 4} assert {[lindex $reply 0 3] == 2} + + # Client 3 then claims pending item 1 from the PEL of client 2 using JUSTID + r debug sleep 0.2 + set reply [ + r XCLAIM mystream mygroup client3 10 $id1 JUSTID + ] + assert {[llength $reply] == 1} + assert {[lindex $reply 0] eq $id1} + + set reply [ + r XPENDING mystream mygroup - + 10 + ] + assert {[llength [lindex $reply 0]] == 4} + assert {[lindex $reply 0 3] == 2} } start_server {} { From 89bf4db4fa41aaedac59c720e837f9e3235d5ad7 Mon Sep 17 00:00:00 2001 From: swilly22 Date: Wed, 13 Mar 2019 08:22:40 +0200 Subject: [PATCH 24/25] document additional flag of RM_GetContextFlags --- src/module.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/module.c b/src/module.c index 5ad999751..d3d122638 100644 --- a/src/module.c +++ b/src/module.c @@ -1359,6 +1359,9 @@ int RM_GetSelectedDb(RedisModuleCtx *ctx) { * * * REDISMODULE_CTX_FLAGS_MULTI: The command is running inside a transaction * + * * REDISMODULE_CTX_FLAGS_REPLICATED: The command was sent over the replication + * link by the MASTER + * * * REDISMODULE_CTX_FLAGS_MASTER: The Redis instance is a master * * * REDISMODULE_CTX_FLAGS_SLAVE: The Redis instance is a slave From 5a3d3d8be414d201abb670313f2801aeadd9ba69 Mon Sep 17 00:00:00 2001 From: "zhaozhao.zz" Date: Wed, 13 Mar 2019 16:54:34 +0800 Subject: [PATCH 25/25] Fix compile warning in redis-cli.c --- src/redis-cli.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/redis-cli.c b/src/redis-cli.c index 0e52c16be..5414de7ef 100644 --- a/src/redis-cli.c +++ b/src/redis-cli.c @@ -2726,7 +2726,7 @@ static sds clusterManagerNodeGetJSON(clusterManagerNode *node, slots, node->slots_count, flags, - node->current_epoch + (unsigned long long)node->current_epoch ); if (error_count > 0) { json = sdscatprintf(json, ",\n \"cluster_errors\": %lu",