From 95def3aee044468504bb07633084afd49b085db3 Mon Sep 17 00:00:00 2001 From: Adam Baldwin Date: Thu, 25 Oct 2012 20:27:10 -0700 Subject: [PATCH 01/40] Removed dofile() from Lua --- src/scripting.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/scripting.c b/src/scripting.c index 0b72e9cd..0a2ce1f3 100644 --- a/src/scripting.c +++ b/src/scripting.c @@ -839,6 +839,8 @@ void luaLoadLibraries(lua_State *lua) { void luaRemoveUnsupportedFunctions(lua_State *lua) { lua_pushnil(lua); lua_setglobal(lua,"loadfile"); + lua_pushnil(lua); + lua_setglobal(lua,"dofile"); } /* This function installs metamethods in the global table _G that prevent From 029dc0d97fd492a2fd579796d4c1cc04053c7190 Mon Sep 17 00:00:00 2001 From: antirez Date: Sat, 7 May 2016 13:03:25 +0200 Subject: [PATCH 02/40] redis-cli: integrate help.h with COMMAND output. Use the COMMAND output to fill with partial information the built-in help. This makes redis-cli able to at least complete commands that are exported by the Redis server it is connected to, but were not available in the help.h file when the redis-cli binary was compiled. --- src/redis-cli.c | 80 ++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 70 insertions(+), 10 deletions(-) diff --git a/src/redis-cli.c b/src/redis-cli.c index 1e47c340..cf939c8c 100644 --- a/src/redis-cli.c +++ b/src/redis-cli.c @@ -130,6 +130,7 @@ static void usage(void); static void slaveMode(void); char *redisGitSHA1(void); char *redisGitDirty(void); +static int cliConnect(int force); /*------------------------------------------------------------------------------ * Utility functions @@ -238,11 +239,11 @@ static void cliInitHelp(void) { helpEntry tmp; helpEntriesLen = len = commandslen+groupslen; - helpEntries = malloc(sizeof(helpEntry)*len); + helpEntries = zmalloc(sizeof(helpEntry)*len); for (i = 0; i < groupslen; i++) { tmp.argc = 1; - tmp.argv = malloc(sizeof(sds)); + tmp.argv = zmalloc(sizeof(sds)); tmp.argv[0] = sdscatprintf(sdsempty(),"@%s",commandGroups[i]); tmp.full = tmp.argv[0]; tmp.type = CLI_HELP_GROUP; @@ -259,6 +260,64 @@ static void cliInitHelp(void) { } } +/* cliInitHelp() setups the helpEntries array with the command and group + * names from the help.h file. However the Redis instance we are connecting + * to may support more commands, so this function integrates the previous + * entries with additional entries obtained using the COMMAND command + * available in recent versions of Redis. */ +static void cliIntegrateHelp(void) { + if (cliConnect(0) == REDIS_ERR) return; + + redisReply *reply = redisCommand(context, "COMMAND"); + if(reply == NULL || reply->type != REDIS_REPLY_ARRAY) return; + + /* Scan the array reported by COMMAND and fill only the entries that + * don't already match what we have. */ + for (size_t j = 0; j < reply->elements; j++) { + redisReply *entry = reply->element[j]; + char *cmdname = entry->element[0]->str; + int i; + + for (i = 0; i < helpEntriesLen; i++) { + helpEntry *he = helpEntries+i; + if (!strcasecmp(he->argv[0],cmdname)) + break; + } + if (i != helpEntriesLen) continue; + printf("%s\n", cmdname); + + helpEntriesLen++; + helpEntries = zrealloc(helpEntries,sizeof(helpEntry)*helpEntriesLen); + helpEntry *new = helpEntries+(helpEntriesLen-1); + + new->argc = 1; + new->argv = zmalloc(sizeof(sds)); + new->argv[0] = sdsnew(cmdname); + new->full = new->argv[0]; + new->type = CLI_HELP_COMMAND; + sdstoupper(new->argv[0]); + + struct commandHelp *ch = zmalloc(sizeof(*ch)); + ch->name = new->argv[0]; + ch->params = sdsempty(); + int args = llabs(entry->element[1]->integer); + if (entry->element[3]->integer == 1) { + ch->params = sdscat(ch->params,"key "); + args--; + } + while(args--) ch->params = sdscat(ch->params,"arg "); + if (entry->element[1]->integer < 0) + ch->params = sdscat(ch->params,"...options..."); + ch->summary = "Help not available"; + ch->group = 0; + ch->since = "not known"; + new->org = ch; + } + freeReplyObject(reply); + + printf("%s\n", helpEntries[80].full); +} + /* Output command help to stdout. */ static void cliOutputCommandHelp(struct commandHelp *help, int group) { printf("\r\n \x1b[1m%s\x1b[0m \x1b[90m%s\x1b[0m\r\n", help->name, help->params); @@ -828,7 +887,7 @@ static int cliSendCommand(int argc, char **argv, int repeat) { } /* Setup argument length */ - argvlen = malloc(argc*sizeof(size_t)); + argvlen = zmalloc(argc*sizeof(size_t)); for (j = 0; j < argc; j++) argvlen[j] = sdslen(argv[j]); @@ -851,12 +910,12 @@ static int cliSendCommand(int argc, char **argv, int repeat) { printf("Entering slave output mode... (press Ctrl-C to quit)\n"); slaveMode(); config.slave_mode = 0; - free(argvlen); + zfree(argvlen); return REDIS_ERR; /* Error = slaveMode lost connection to master */ } if (cliReadReply(output_raw) != REDIS_OK) { - free(argvlen); + zfree(argvlen); return REDIS_ERR; } else { /* Store database number when SELECT was successfully executed. */ @@ -871,7 +930,7 @@ static int cliSendCommand(int argc, char **argv, int repeat) { fflush(stdout); /* Make it grep friendly */ } - free(argvlen); + zfree(argvlen); return REDIS_OK; } @@ -1235,7 +1294,7 @@ static void repl(void) { if (argv == NULL) { printf("Invalid argument(s)\n"); - free(line); + linenoiseFree(line); continue; } else if (argc > 0) { if (strcasecmp(argv[0],"quit") == 0 || @@ -1294,7 +1353,7 @@ static void repl(void) { sdsfreesplitres(argv,argc); } /* linenoise() returns malloc-ed lines like readline() */ - free(line); + linenoiseFree(line); } exit(0); } @@ -2159,7 +2218,7 @@ static char *getInfoField(char *info, char *field) { n1 = strchr(p,'\r'); n2 = strchr(p,','); if (n2 && n2 < n1) n1 = n2; - result = malloc(sizeof(char)*(n1-p)+1); + result = zmalloc(sizeof(char)*(n1-p)+1); memcpy(result,p,(n1-p)); result[n1-p] = '\0'; return result; @@ -2173,7 +2232,7 @@ static long getLongInfoField(char *info, char *field) { if (!value) return LONG_MIN; l = strtol(value,NULL,10); - free(value); + zfree(value); return l; } @@ -2536,6 +2595,7 @@ int main(int argc, char **argv) { config.output = OUTPUT_STANDARD; config.mb_delim = sdsnew("\n"); cliInitHelp(); + cliIntegrateHelp(); firstarg = parseOptions(argc,argv); argc -= firstarg; From a7f0fb448c110e125eece44dc955d6939e494daa Mon Sep 17 00:00:00 2001 From: antirez Date: Wed, 18 May 2016 11:58:36 +0200 Subject: [PATCH 03/40] Actually use --with-lg-quantum=3 to build jemalloc. This change is documented in deps/README.md but was lost in one way or the other, neutralizing the benefits of 24 bytes size classes (and others). Close #3208. --- deps/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/Makefile b/deps/Makefile index 10ae6e79..1c10bce9 100644 --- a/deps/Makefile +++ b/deps/Makefile @@ -78,7 +78,7 @@ JEMALLOC_LDFLAGS= $(LDFLAGS) jemalloc: .make-prerequisites @printf '%b %b\n' $(MAKECOLOR)MAKE$(ENDCOLOR) $(BINCOLOR)$@$(ENDCOLOR) - cd jemalloc && ./configure --with-jemalloc-prefix=je_ --enable-cc-silence CFLAGS="$(JEMALLOC_CFLAGS)" LDFLAGS="$(JEMALLOC_LDFLAGS)" + cd jemalloc && ./configure --with-lg-quantum=3 --with-jemalloc-prefix=je_ --enable-cc-silence CFLAGS="$(JEMALLOC_CFLAGS)" LDFLAGS="$(JEMALLOC_LDFLAGS)" cd jemalloc && $(MAKE) CFLAGS="$(JEMALLOC_CFLAGS)" LDFLAGS="$(JEMALLOC_LDFLAGS)" lib/libjemalloc.a .PHONY: jemalloc From cb3e89e2cb0753d2d111eaeadc9c73cbe24025ab Mon Sep 17 00:00:00 2001 From: oranagra Date: Mon, 16 May 2016 20:12:11 +0300 Subject: [PATCH 04/40] reduce struct padding by reordering members --- src/quicklist.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/quicklist.h b/src/quicklist.h index 5c9530cc..e040368e 100644 --- a/src/quicklist.h +++ b/src/quicklist.h @@ -92,8 +92,8 @@ typedef struct quicklistEntry { quicklistNode *node; unsigned char *zi; unsigned char *value; - unsigned int sz; long long longval; + unsigned int sz; int offset; } quicklistEntry; From f991cdc3e19c187035855355808575efd6b4c149 Mon Sep 17 00:00:00 2001 From: antirez Date: Wed, 18 May 2016 14:53:30 +0200 Subject: [PATCH 05/40] Test for BITFIELD regression #3221. --- tests/unit/bitfield.tcl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/unit/bitfield.tcl b/tests/unit/bitfield.tcl index 368ff9fc..26e47db0 100644 --- a/tests/unit/bitfield.tcl +++ b/tests/unit/bitfield.tcl @@ -184,4 +184,9 @@ start_server {tags {"bitops"}} { } } } + + test {BITFIELD regression for #3221} { + r set bits 1 + r bitfield bits get u1 0 + } {0} } From 4ad088818a3353ebd619e8d43847b5d58108af20 Mon Sep 17 00:00:00 2001 From: antirez Date: Wed, 18 May 2016 15:23:18 +0200 Subject: [PATCH 06/40] Clarify that the LOG_STR_SIZE includes null term. --- src/server.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server.h b/src/server.h index f2ad9aa8..843ed82c 100644 --- a/src/server.h +++ b/src/server.h @@ -157,7 +157,7 @@ typedef long long mstime_t; /* millisecond time type. */ #define PROTO_REPLY_CHUNK_BYTES (16*1024) /* 16k output buffer */ #define PROTO_INLINE_MAX_SIZE (1024*64) /* Max size of inline reads */ #define PROTO_MBULK_BIG_ARG (1024*32) -#define LONG_STR_SIZE 21 /* Bytes needed for long -> str */ +#define LONG_STR_SIZE 21 /* Bytes needed for long -> str + '\0' */ #define AOF_AUTOSYNC_BYTES (1024*1024*32) /* fdatasync every 32MB */ /* When configuring the server eventloop, we setup it so that the total number From dcaeafc8280eb8329e7ce68e7ab02c67d98f0cf4 Mon Sep 17 00:00:00 2001 From: oranagra Date: Tue, 10 May 2016 11:19:45 +0300 Subject: [PATCH 07/40] fix crash in BITFIELD GET when key is integer encoded --- src/bitops.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/bitops.c b/src/bitops.c index ed7e384a..0dbbeb6e 100644 --- a/src/bitops.c +++ b/src/bitops.c @@ -1035,16 +1035,28 @@ void bitfieldCommand(client *c) { changes++; } else { /* GET */ - o = lookupKeyRead(c->db,c->argv[1]); - size_t olen = (o == NULL) ? 0 : sdslen(o->ptr); unsigned char buf[9]; + size_t olen = 0; + unsigned char *src = NULL; + char llbuf[32]; + + o = lookupKeyRead(c->db,c->argv[1]); + + /* Set the 'p' pointer to the string, that can be just a stack allocated + * array if our string was integer encoded. */ + if (o && o->encoding == OBJ_ENCODING_INT) { + src = (unsigned char*) llbuf; + olen = ll2string(llbuf,sizeof(llbuf),(long)o->ptr); + } else if (o) { + src = (unsigned char*) o->ptr; + olen = sdslen(o->ptr); + } /* For GET we use a trick: before executing the operation * copy up to 9 bytes to a local buffer, so that we can easily * execute up to 64 bit operations that are at actual string * object boundaries. */ memset(buf,0,9); - unsigned char *src = o ? o->ptr : NULL; int i; size_t byte = thisop->offset >> 3; for (i = 0; i < 9; i++) { From 2e6b99499abb5ff1fbeee3bac4d064e5ff4ea256 Mon Sep 17 00:00:00 2001 From: antirez Date: Wed, 18 May 2016 15:35:17 +0200 Subject: [PATCH 08/40] Code to access object string bytes repeated 3x refactored into 1 function. --- src/bitops.c | 74 +++++++++++++++++++++++++++------------------------- 1 file changed, 39 insertions(+), 35 deletions(-) diff --git a/src/bitops.c b/src/bitops.c index 0dbbeb6e..a7fad899 100644 --- a/src/bitops.c +++ b/src/bitops.c @@ -476,6 +476,37 @@ robj *lookupStringForBitCommand(client *c, size_t maxbit) { return o; } +/* Return a pointer to the string object content, and stores its length + * in 'len'. The user is required to pass (likely stack allocated) buffer + * 'llbuf' of at least LONG_STR_SIZE bytes. Such a buffer is used in the case + * the object is integer encoded in order to provide the representation + * without usign heap allocation. + * + * The function returns the pointer to the object array of bytes representing + * the string it contains, that may be a pointer to 'llbuf' or to the + * internal object representation. As a side effect 'len' is filled with + * the length of such buffer. + * + * If the source object is NULL the function is guaranteed to return NULL + * and set 'len' to 0. */ +unsigned char *getObjectReadOnlyString(robj *o, long *len, char *llbuf) { + serverAssert(o->type == OBJ_STRING); + unsigned char *p = NULL; + + /* Set the 'p' pointer to the string, that can be just a stack allocated + * array if our string was integer encoded. */ + if (o && o->encoding == OBJ_ENCODING_INT) { + p = (unsigned char*) llbuf; + if (len) *len = ll2string(llbuf,LONG_STR_SIZE,(long)o->ptr); + } else if (o) { + p = (unsigned char*) o->ptr; + if (len) *len = sdslen(o->ptr); + } else { + if (len) *len = 0; + } + return p; +} + /* SETBIT key offset bitvalue */ void setbitCommand(client *c) { robj *o; @@ -721,21 +752,12 @@ void bitcountCommand(client *c) { robj *o; long start, end, strlen; unsigned char *p; - char llbuf[32]; + char llbuf[LONG_STR_SIZE]; /* Lookup, check for type, and return 0 for non existing keys. */ if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == NULL || checkType(c,o,OBJ_STRING)) return; - - /* Set the 'p' pointer to the string, that can be just a stack allocated - * array if our string was integer encoded. */ - if (o->encoding == OBJ_ENCODING_INT) { - p = (unsigned char*) llbuf; - strlen = ll2string(llbuf,sizeof(llbuf),(long)o->ptr); - } else { - p = (unsigned char*) o->ptr; - strlen = sdslen(o->ptr); - } + p = getObjectReadOnlyString(o,&strlen,llbuf); /* Parse start/end range if any. */ if (c->argc == 4) { @@ -775,7 +797,7 @@ void bitposCommand(client *c) { robj *o; long bit, start, end, strlen; unsigned char *p; - char llbuf[32]; + char llbuf[LONG_STR_SIZE]; int end_given = 0; /* Parse the bit argument to understand what we are looking for, set @@ -795,16 +817,7 @@ void bitposCommand(client *c) { return; } if (checkType(c,o,OBJ_STRING)) return; - - /* Set the 'p' pointer to the string, that can be just a stack allocated - * array if our string was integer encoded. */ - if (o->encoding == OBJ_ENCODING_INT) { - p = (unsigned char*) llbuf; - strlen = ll2string(llbuf,sizeof(llbuf),(long)o->ptr); - } else { - p = (unsigned char*) o->ptr; - strlen = sdslen(o->ptr); - } + p = getObjectReadOnlyString(o,&strlen,llbuf); /* Parse start/end range if any. */ if (c->argc == 4 || c->argc == 5) { @@ -1036,21 +1049,12 @@ void bitfieldCommand(client *c) { } else { /* GET */ unsigned char buf[9]; - size_t olen = 0; + long strlen; unsigned char *src = NULL; - char llbuf[32]; + char llbuf[LONG_STR_SIZE]; o = lookupKeyRead(c->db,c->argv[1]); - - /* Set the 'p' pointer to the string, that can be just a stack allocated - * array if our string was integer encoded. */ - if (o && o->encoding == OBJ_ENCODING_INT) { - src = (unsigned char*) llbuf; - olen = ll2string(llbuf,sizeof(llbuf),(long)o->ptr); - } else if (o) { - src = (unsigned char*) o->ptr; - olen = sdslen(o->ptr); - } + src = getObjectReadOnlyString(o,&strlen,llbuf); /* For GET we use a trick: before executing the operation * copy up to 9 bytes to a local buffer, so that we can easily @@ -1060,7 +1064,7 @@ void bitfieldCommand(client *c) { int i; size_t byte = thisop->offset >> 3; for (i = 0; i < 9; i++) { - if (src == NULL || i+byte >= olen) break; + if (src == NULL || i+byte >= (size_t)strlen) break; buf[i] = src[i+byte]; } From 603234076f4e59967f331bc97de3c0db9947c8ef Mon Sep 17 00:00:00 2001 From: oranagra Date: Mon, 9 May 2016 09:12:38 +0300 Subject: [PATCH 09/40] minor fixes - mainly signalModifiedKey, and GEORADIUS --- src/geo.c | 1 + src/sds.c | 8 ++++---- src/server.c | 2 +- src/server.h | 3 +-- src/t_set.c | 9 ++++++--- src/t_zset.c | 12 ++++++------ 6 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/geo.c b/src/geo.c index 3890d6be..734e02b0 100644 --- a/src/geo.c +++ b/src/geo.c @@ -467,6 +467,7 @@ void georadiusGeneric(client *c, int type) { double radius_meters = 0, conversion = 1; if ((radius_meters = extractDistanceOrReply(c, c->argv + base_args - 2, &conversion)) < 0) { + addReplyError(c,"radius must be >= 0"); return; } diff --git a/src/sds.c b/src/sds.c index e3dd6735..26e90a6d 100644 --- a/src/sds.c +++ b/src/sds.c @@ -55,13 +55,13 @@ static inline int sdsHdrSize(char type) { } static inline char sdsReqType(size_t string_size) { - if (string_size < 32) + if (string_size < 1<<5) return SDS_TYPE_5; - if (string_size < 0xff) + if (string_size < 1<<8) return SDS_TYPE_8; - if (string_size < 0xffff) + if (string_size < 1<<16) return SDS_TYPE_16; - if (string_size < 0xffffffff) + if (string_size < 1ll<<32) return SDS_TYPE_32; return SDS_TYPE_64; } diff --git a/src/server.c b/src/server.c index 254c40a9..3e40ef85 100644 --- a/src/server.c +++ b/src/server.c @@ -663,7 +663,7 @@ int htNeedsResize(dict *dict) { size = dictSlots(dict); used = dictSize(dict); - return (size && used && size > DICT_HT_INITIAL_SIZE && + return (size > DICT_HT_INITIAL_SIZE && (used*100/size < HASHTABLE_MIN_FILL)); } diff --git a/src/server.h b/src/server.h index 843ed82c..64c97bcf 100644 --- a/src/server.h +++ b/src/server.h @@ -467,7 +467,7 @@ typedef struct redisObject { /* Macro used to obtain the current LRU clock. * If the current resolution is lower than the frequency we refresh the * LRU clock (as it should be in production servers) we return the - * precomputed value, otherwise we need to resort to a function call. */ + * precomputed value, otherwise we need to resort to a system call. */ #define LRU_CLOCK() ((1000/server.hz <= LRU_CLOCK_RESOLUTION) ? server.lruclock : getLRUClock()) /* Macro used to initialize a Redis object allocated on the stack. @@ -1320,7 +1320,6 @@ void serverLogFromHandler(int level, const char *msg); void usage(void); void updateDictResizePolicy(void); int htNeedsResize(dict *dict); -void oom(const char *msg); void populateCommandTable(void); void resetCommandTableStats(void); void adjustOpenFilesLimit(void); diff --git a/src/t_set.c b/src/t_set.c index 03f48d94..350c57b4 100644 --- a/src/t_set.c +++ b/src/t_set.c @@ -359,9 +359,6 @@ void smoveCommand(client *c) { dbDelete(c->db,c->argv[1]); notifyKeyspaceEvent(NOTIFY_GENERIC,"del",c->argv[1],c->db->id); } - signalModifiedKey(c->db,c->argv[1]); - signalModifiedKey(c->db,c->argv[2]); - server.dirty++; /* Create the destination set when it doesn't exist */ if (!dstset) { @@ -369,6 +366,10 @@ void smoveCommand(client *c) { dbAdd(c->db,c->argv[2],dstset); } + signalModifiedKey(c->db,c->argv[1]); + signalModifiedKey(c->db,c->argv[2]); + server.dirty++; + /* An extra key has changed when ele was successfully added to dstset */ if (setTypeAdd(dstset,ele)) { server.dirty++; @@ -554,6 +555,8 @@ void spopWithCountCommand(client *c) { * the alsoPropagate() API. */ decrRefCount(propargv[0]); preventCommandPropagation(c); + signalModifiedKey(c->db,c->argv[1]); + server.dirty++; } void spopCommand(client *c) { diff --git a/src/t_zset.c b/src/t_zset.c index 79a7c373..64901eff 100644 --- a/src/t_zset.c +++ b/src/t_zset.c @@ -2148,16 +2148,13 @@ void zunionInterGenericCommand(client *c, robj *dstkey, int op) { serverPanic("Unknown operator"); } - if (dbDelete(c->db,dstkey)) { - signalModifiedKey(c->db,dstkey); + if (dbDelete(c->db,dstkey)) touched = 1; - server.dirty++; - } if (dstzset->zsl->length) { zsetConvertToZiplistIfNeeded(dstobj,maxelelen); dbAdd(c->db,dstkey,dstobj); addReplyLongLong(c,zsetLength(dstobj)); - if (!touched) signalModifiedKey(c->db,dstkey); + signalModifiedKey(c->db,dstkey); notifyKeyspaceEvent(NOTIFY_ZSET, (op == SET_OP_UNION) ? "zunionstore" : "zinterstore", dstkey,c->db->id); @@ -2165,8 +2162,11 @@ void zunionInterGenericCommand(client *c, robj *dstkey, int op) { } else { decrRefCount(dstobj); addReply(c,shared.czero); - if (touched) + if (touched) { + signalModifiedKey(c->db,dstkey); notifyKeyspaceEvent(NOTIFY_GENERIC,"del",dstkey,c->db->id); + server.dirty++; + } } zfree(src); } From 620783e3b582e9ba6e1d8fbd47987281ce0b6317 Mon Sep 17 00:00:00 2001 From: Itamar Haber Date: Sat, 28 May 2016 20:01:46 +0300 Subject: [PATCH 10/40] Allow SPOP from Lua scripts The existing `R` flag appears to be sufficient and there's no apparent reason why the command should be blocked. --- src/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server.c b/src/server.c index 3e40ef85..67c2635a 100644 --- a/src/server.c +++ b/src/server.c @@ -163,7 +163,7 @@ struct redisCommand redisCommandTable[] = { {"smove",smoveCommand,4,"wF",0,NULL,1,2,1,0,0}, {"sismember",sismemberCommand,3,"rF",0,NULL,1,1,1,0,0}, {"scard",scardCommand,2,"rF",0,NULL,1,1,1,0,0}, - {"spop",spopCommand,-2,"wRsF",0,NULL,1,1,1,0,0}, + {"spop",spopCommand,-2,"wRF",0,NULL,1,1,1,0,0}, {"srandmember",srandmemberCommand,-2,"rR",0,NULL,1,1,1,0,0}, {"sinter",sinterCommand,-2,"rS",0,NULL,1,-1,1,0,0}, {"sinterstore",sinterstoreCommand,-3,"wm",0,NULL,1,-1,1,0,0}, From b5758cc5ce6c51ff75c86f9216214fe4d5e4c257 Mon Sep 17 00:00:00 2001 From: jspraul Date: Tue, 7 Jun 2016 16:46:00 -0400 Subject: [PATCH 11/40] Include 'fd_set' type name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix an MSYS2-build-breaking error: unknown type name ‘fd_set’ --- src/ae_select.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ae_select.c b/src/ae_select.c index e2b7a9e8..c039a8ea 100644 --- a/src/ae_select.c +++ b/src/ae_select.c @@ -29,6 +29,7 @@ */ +#include #include typedef struct aeApiState { From 6937f5960d1803ca0eda1ab6f4bc60023f50c914 Mon Sep 17 00:00:00 2001 From: bogdanvlviv Date: Tue, 19 Apr 2016 14:43:06 +0300 Subject: [PATCH 12/40] fix pidfile in redis.conf --- redis.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/redis.conf b/redis.conf index 0792cd4d..acdb88d5 100644 --- a/redis.conf +++ b/redis.conf @@ -146,7 +146,7 @@ supervised no # # Creating a pid file is best effort: if Redis is not able to create it # nothing bad happens, the server will start and run normally. -pidfile /var/run/redis.pid +pidfile /var/run/redis_6379.pid # Specify the server verbosity level. # This can be one of: From 8d029a5950f4ef40723c02b5c486b171aff0189c Mon Sep 17 00:00:00 2001 From: andyli Date: Tue, 7 Jun 2016 14:42:50 +0800 Subject: [PATCH 13/40] fix comment "b>a" to "a > b" --- src/sentinel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sentinel.c b/src/sentinel.c index 0d1eb78a..2371b2b3 100644 --- a/src/sentinel.c +++ b/src/sentinel.c @@ -3878,7 +3878,7 @@ int compareSlavesForPromotion(const void *a, const void *b) { if ((*sa)->slave_repl_offset > (*sb)->slave_repl_offset) { return -1; /* a < b */ } else if ((*sa)->slave_repl_offset < (*sb)->slave_repl_offset) { - return 1; /* b > a */ + return 1; /* a > b */ } /* If the replication offset is the same select the slave with that has From 3fd4baf1e77f125a306d57b788b72de5026c0564 Mon Sep 17 00:00:00 2001 From: antirez Date: Fri, 10 Jun 2016 09:15:01 +0200 Subject: [PATCH 14/40] Fixed typo in Sentinel compareSlavesForPromotion() comment. --- src/sentinel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sentinel.c b/src/sentinel.c index 2371b2b3..4d5f84a9 100644 --- a/src/sentinel.c +++ b/src/sentinel.c @@ -3874,7 +3874,7 @@ int compareSlavesForPromotion(const void *a, const void *b) { return (*sa)->slave_priority - (*sb)->slave_priority; /* If priority is the same, select the slave with greater replication - * offset (processed more data frmo the master). */ + * offset (processed more data from the master). */ if ((*sa)->slave_repl_offset > (*sb)->slave_repl_offset) { return -1; /* a < b */ } else if ((*sa)->slave_repl_offset < (*sb)->slave_repl_offset) { From a650aaaf4f074ec428b450ef88799db1dcd34b0f Mon Sep 17 00:00:00 2001 From: Pierre Chapuis Date: Sun, 5 Jun 2016 15:34:43 +0200 Subject: [PATCH 15/40] fix some compiler warnings --- src/bitops.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bitops.c b/src/bitops.c index a7fad899..a80ab28e 100644 --- a/src/bitops.c +++ b/src/bitops.c @@ -299,7 +299,7 @@ int checkUnsignedBitfieldOverflow(uint64_t value, int64_t incr, uint64_t bits, i handle_wrap: { - uint64_t mask = ((int64_t)-1) << bits; + uint64_t mask = ((uint64_t)-1) << bits; uint64_t res = value+incr; res &= ~mask; @@ -342,7 +342,7 @@ int checkSignedBitfieldOverflow(int64_t value, int64_t incr, uint64_t bits, int handle_wrap: { - uint64_t mask = ((int64_t)-1) << bits; + uint64_t mask = ((uint64_t)-1) << bits; uint64_t msb = (uint64_t)1 << (bits-1); uint64_t a = value, b = incr, c; c = a+b; /* Perform addition as unsigned so that's defined. */ From 40cfe13141c7178d22fd43e4ffbecc37686e0b43 Mon Sep 17 00:00:00 2001 From: antirez Date: Mon, 13 Jun 2016 12:03:14 +0200 Subject: [PATCH 16/40] Enable tcp-keepalive by default. --- redis.conf | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/redis.conf b/redis.conf index acdb88d5..0ef8a7ca 100644 --- a/redis.conf +++ b/redis.conf @@ -117,8 +117,9 @@ timeout 0 # Note that to close the connection the double of the time is needed. # On other kernels the period depends on the kernel configuration. # -# A reasonable value for this option is 60 seconds. -tcp-keepalive 0 +# A reasonable value for this option is 300 seconds, which is the new +# Redis default starting with Redis 3.2.1. +tcp-keepalive 300 ################################# GENERAL ##################################### From df419281a19e13429b27814a3e384f6f029c3519 Mon Sep 17 00:00:00 2001 From: antirez Date: Tue, 31 May 2016 16:43:49 +0200 Subject: [PATCH 17/40] Test: run GEO tests by default. Thanks to @oranagra for noticing it was missing. --- tests/test_helper.tcl | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_helper.tcl b/tests/test_helper.tcl index 6d1710cd..792b970c 100644 --- a/tests/test_helper.tcl +++ b/tests/test_helper.tcl @@ -50,6 +50,7 @@ set ::all_tests { unit/obuf-limits unit/bitops unit/bitfield + unit/geo unit/memefficiency unit/hyperloglog } From b4e5e2ec1ad7e9d1f4e7e559b61e0ecd4e50f2da Mon Sep 17 00:00:00 2001 From: antirez Date: Tue, 31 May 2016 16:43:21 +0200 Subject: [PATCH 18/40] Now that SPOP can be called by scripts use BLPOP on 's' flag test. --- tests/unit/scripting.tcl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/scripting.tcl b/tests/unit/scripting.tcl index 07553b1d..68e136fd 100644 --- a/tests/unit/scripting.tcl +++ b/tests/unit/scripting.tcl @@ -142,7 +142,7 @@ start_server {tags {"scripting"}} { test {EVAL - Scripts can't run certain commands} { set e {} - catch {r eval {return redis.pcall('spop','x')} 0} e + catch {r eval {return redis.pcall('blpop','x',0)} 0} e set e } {*not allowed*} From 014bf8044285c6d401d83e6e24829d276ab837f9 Mon Sep 17 00:00:00 2001 From: antirez Date: Tue, 31 May 2016 11:52:07 +0200 Subject: [PATCH 19/40] Avoid undefined behavior in BITFIELD implementation. Probably there is no compiler that will actaully break the code or raise a signal for unsigned -> signed overflowing conversion, still it was apparently possible to write it in a more correct way. All tests passing. --- src/bitops.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/bitops.c b/src/bitops.c index a80ab28e..699681bc 100644 --- a/src/bitops.c +++ b/src/bitops.c @@ -215,12 +215,7 @@ void setUnsignedBitfield(unsigned char *p, uint64_t offset, uint64_t bits, uint6 } void setSignedBitfield(unsigned char *p, uint64_t offset, uint64_t bits, int64_t value) { - uint64_t uv; - - if (value >= 0) - uv = value; - else - uv = UINT64_MAX + value + 1; + uint64_t uv = value; /* Casting will add UINT64_MAX + 1 if v is negative. */ setUnsignedBitfield(p,offset,bits,uv); } @@ -239,9 +234,21 @@ uint64_t getUnsignedBitfield(unsigned char *p, uint64_t offset, uint64_t bits) { } int64_t getSignedBitfield(unsigned char *p, uint64_t offset, uint64_t bits) { - int64_t value = getUnsignedBitfield(p,offset,bits); + int64_t value; + union {uint64_t u; int64_t i;} conv; + + /* Converting from unsigned to signed is undefined when the value does + * not fit, however here we assume two's complement and the original value + * was obtained from signed -> unsigned conversion, so we'll find the + * most significant bit set if the original value was negative. + * + * Note that two's complement is mandatory for exact-width types + * according to the C99 standard. */ + conv.u = getUnsignedBitfield(p,offset,bits); + value = conv.i; + /* If the top significant bit is 1, propagate it to all the - * higher bits for two complement representation of signed + * higher bits for two's complement representation of signed * integers. */ if (value & ((uint64_t)1 << (bits-1))) value |= ((uint64_t)-1) << bits; From 16102bc0af0912a0c9a92aedddf796eb24a80b9e Mon Sep 17 00:00:00 2001 From: antirez Date: Mon, 30 May 2016 15:31:19 +0200 Subject: [PATCH 20/40] Geo: fix typo in geohashEstimateStepsByRadius(). I'm the author of this line but I can't see a good reason for it to don't be a typo, a step of 26 should be valid with 52 bits per coordinate, moreover the line was: if (step > 26) step = 25; So a step of 26 was actually already used, except when one of 27 was computed (which is invalid) only then it was trimmed to 25 instead of 26. All tests passing after the change. --- deps/geohash-int/geohash_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/geohash-int/geohash_helper.c b/deps/geohash-int/geohash_helper.c index 4c3762fa..43763701 100644 --- a/deps/geohash-int/geohash_helper.c +++ b/deps/geohash-int/geohash_helper.c @@ -72,7 +72,7 @@ uint8_t geohashEstimateStepsByRadius(double range_meters, double lat) { /* Frame to valid range. */ if (step < 1) step = 1; - if (step > 26) step = 25; + if (step > 26) step = 26; return step; } From bb43f4cab2f756c0412ca2b94d9e29c3db5025ab Mon Sep 17 00:00:00 2001 From: antirez Date: Mon, 30 May 2016 12:45:49 +0200 Subject: [PATCH 21/40] Fix GEORADIUS wrong output with radius > Earth radius. Close #3266 --- deps/geohash-int/geohash_helper.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/deps/geohash-int/geohash_helper.c b/deps/geohash-int/geohash_helper.c index 43763701..4b889467 100644 --- a/deps/geohash-int/geohash_helper.c +++ b/deps/geohash-int/geohash_helper.c @@ -89,6 +89,8 @@ int geohashBoundingBox(double longitude, double latitude, double radius_meters, lonr = deg_rad(longitude); latr = deg_rad(latitude); + if (radius_meters > EARTH_RADIUS_IN_METERS) + radius_meters = EARTH_RADIUS_IN_METERS; double distance = radius_meters / EARTH_RADIUS_IN_METERS; double min_latitude = latr - distance; double max_latitude = latr + distance; From 6e4204fec9c78f3300d887ebc3db014df2c8b33e Mon Sep 17 00:00:00 2001 From: antirez Date: Tue, 14 Jun 2016 14:45:48 +0200 Subject: [PATCH 22/40] redis-cli help.h updated. --- src/help.h | 43 +++++++++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/src/help.h b/src/help.h index fe47c3ee..5f927c30 100644 --- a/src/help.h +++ b/src/help.h @@ -1,4 +1,4 @@ -/* Automatically generated by generate-command-help.rb, do not edit. */ +/* Automatically generated by utils/generate-command-help.rb, do not edit. */ #ifndef __REDIS_HELP_H #define __REDIS_HELP_H @@ -52,6 +52,11 @@ struct commandHelp { "Count set bits in a string", 1, "2.6.0" }, + { "BITFIELD", + "key [GET type offset] [SET type offset value] [INCRBY type offset increment] [OVERFLOW WRAP|SAT|FAIL]", + "Perform arbitrary bitfield integer operations on strings", + 1, + "3.2.0" }, { "BITOP", "operation destkey key [key ...]", "Perform bitwise operations between strings", @@ -83,7 +88,7 @@ struct commandHelp { 9, "2.6.9" }, { "CLIENT KILL", - "[ip:port] [ID client-id] [TYPE normal|slave|pubsub] [ADDR ip:port] [SKIPME yes/no]", + "[ip:port] [ID client-id] [TYPE normal|master|slave|pubsub] [ADDR ip:port] [SKIPME yes/no]", "Kill the connection of a client", 9, "2.4.0" }, @@ -97,6 +102,11 @@ struct commandHelp { "Stop processing commands from clients for some time", 9, "2.9.50" }, + { "CLIENT REPLY", + "ON|OFF|SKIP", + "Instruct the server whether to reply to commands", + 9, + "3.2" }, { "CLIENT SETNAME", "connection-name", "Set the current connection name", @@ -179,7 +189,7 @@ struct commandHelp { "3.0.0" }, { "CLUSTER SETSLOT", "slot IMPORTING|MIGRATING|STABLE|NODE [node-id]", - "Bind an hash slot to a specific node", + "Bind a hash slot to a specific node", 12, "3.0.0" }, { "CLUSTER SLAVES", @@ -321,32 +331,32 @@ struct commandHelp { "key longitude latitude member [longitude latitude member ...]", "Add one or more geospatial items in the geospatial index represented using a sorted set", 13, - "" }, + "3.2.0" }, { "GEODIST", "key member1 member2 [unit]", "Returns the distance between two members of a geospatial index", 13, - "" }, + "3.2.0" }, { "GEOHASH", "key member [member ...]", "Returns members of a geospatial index as standard geohash strings", 13, - "" }, + "3.2.0" }, { "GEOPOS", "key member [member ...]", "Returns longitude and latitude of members of a geospatial index", 13, - "" }, + "3.2.0" }, { "GEORADIUS", - "key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count]", + "key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST key]", "Query a sorted set representing a geospatial index to fetch members matching a given maximum distance from a point", 13, - "" }, + "3.2.0" }, { "GEORADIUSBYMEMBER", - "key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count]", + "key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST key]", "Query a sorted set representing a geospatial index to fetch members matching a given maximum distance from a member", 13, - "" }, + "3.2.0" }, { "GET", "key", "Get the value of a key", @@ -528,7 +538,7 @@ struct commandHelp { 1, "1.0.0" }, { "MIGRATE", - "host port key destination-db timeout [COPY] [REPLACE]", + "host port key|"" destination-db timeout [COPY] [REPLACE] [KEYS key]", "Atomically transfer a key from a Redis instance to another one.", 0, "2.6.0" }, @@ -593,7 +603,7 @@ struct commandHelp { 11, "2.8.9" }, { "PING", - "-", + "[message]", "Ping the server", 8, "1.0.0" }, @@ -707,6 +717,11 @@ struct commandHelp { "Get the number of members in a set", 3, "1.0.0" }, + { "SCRIPT DEBUG", + "YES|SYNC|NO", + "Set the debug mode for executed scripts.", + 10, + "3.2.0" }, { "SCRIPT EXISTS", "script [script ...]", "Check existence of scripts in the script cache.", @@ -768,7 +783,7 @@ struct commandHelp { 1, "2.2.0" }, { "SHUTDOWN", - "[NOSAVE] [SAVE]", + "[NOSAVE|SAVE]", "Synchronously save the dataset to disk and then shut down the server", 9, "1.0.0" }, From b23aa6706ac79a1c86c64aef07bd35e38f10f842 Mon Sep 17 00:00:00 2001 From: antirez Date: Tue, 14 Jun 2016 15:33:59 +0200 Subject: [PATCH 23/40] TTL and TYPE LRU access fixed. TOUCH implemented. --- src/db.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++------ src/server.c | 1 + src/server.h | 6 +++++- 3 files changed, 60 insertions(+), 8 deletions(-) diff --git a/src/db.c b/src/db.c index 4d15f2c8..fba731c9 100644 --- a/src/db.c +++ b/src/db.c @@ -41,7 +41,10 @@ void slotToKeyFlush(void); * C-level DB API *----------------------------------------------------------------------------*/ -robj *lookupKey(redisDb *db, robj *key) { +/* Low level key lookup API, not actually called directly from commands + * implementations that should instead rely on lookupKeyRead(), + * lookupKeyWrite() and lookupKeyReadWithFlags(). */ +robj *lookupKey(redisDb *db, robj *key, int flags) { dictEntry *de = dictFind(db->dict,key->ptr); if (de) { robj *val = dictGetVal(de); @@ -49,15 +52,40 @@ robj *lookupKey(redisDb *db, robj *key) { /* Update the access time for the ageing algorithm. * Don't do it if we have a saving child, as this will trigger * a copy on write madness. */ - if (server.rdb_child_pid == -1 && server.aof_child_pid == -1) + if (server.rdb_child_pid == -1 && + server.aof_child_pid == -1 && + !(flags & LOOKUP_NOTOUCH)) + { val->lru = LRU_CLOCK(); + } return val; } else { return NULL; } } -robj *lookupKeyRead(redisDb *db, robj *key) { +/* Lookup a key for read operations, or return NULL if the key is not found + * in the specified DB. + * + * As a side effect of calling this function: + * 1. A key gets expired if it reached it's TTL. + * 2. The key last access time is updated. + * 3. The global keys hits/misses stats are updated (reported in INFO). + * + * This API should not be used when we write to the key after obtaining + * the object linked to the key, but only for read only operations. + * + * Flags change the behavior of this command: + * + * LOOKUP_NONE (or zero): no special flags are passed. + * LOOKUP_NOTOUCH: don't alter the last access time of the key. + * + * Note: this function also returns NULL is the key is logically expired + * but still existing, in case this is a slave, since this API is called only + * for read operations. Even if the key expiry is master-driven, we can + * correctly report a key is expired on slaves even if the master is lagging + * expiring our key via DELs in the replication link. */ +robj *lookupKeyReadWithFlags(redisDb *db, robj *key, int flags) { robj *val; if (expireIfNeeded(db,key) == 1) { @@ -86,7 +114,7 @@ robj *lookupKeyRead(redisDb *db, robj *key) { return NULL; } } - val = lookupKey(db,key); + val = lookupKey(db,key,flags); if (val == NULL) server.stat_keyspace_misses++; else @@ -94,9 +122,20 @@ robj *lookupKeyRead(redisDb *db, robj *key) { return val; } +/* Like lookupKeyReadWithFlags(), but does not use any flag, which is the + * common case. */ +robj *lookupKeyRead(redisDb *db, robj *key) { + return lookupKeyReadWithFlags(db,key,LOOKUP_NONE); +} + +/* Lookup a key for write operations, and as a side effect, if needed, expires + * the key if its TTL is reached. + * + * Returns the linked value object if the key exists or NULL if the key + * does not exist in the specified DB. */ robj *lookupKeyWrite(redisDb *db, robj *key) { expireIfNeeded(db,key); - return lookupKey(db,key); + return lookupKey(db,key,LOOKUP_NONE); } robj *lookupKeyReadOrReply(client *c, robj *key, robj *reply) { @@ -645,7 +684,7 @@ void typeCommand(client *c) { robj *o; char *type; - o = lookupKeyRead(c->db,c->argv[1]); + o = lookupKeyReadWithFlags(c->db,c->argv[1],LOOKUP_NOTOUCH); if (o == NULL) { type = "none"; } else { @@ -967,7 +1006,7 @@ void ttlGenericCommand(client *c, int output_ms) { long long expire, ttl = -1; /* If the key does not exist at all, return -2 */ - if (lookupKeyRead(c->db,c->argv[1]) == NULL) { + if (lookupKeyReadWithFlags(c->db,c->argv[1],LOOKUP_NOTOUCH) == NULL) { addReplyLongLong(c,-2); return; } @@ -1009,6 +1048,14 @@ void persistCommand(client *c) { } } +/* TOUCH key1 [key2 key3 ... keyN] */ +void touchCommand(client *c) { + int touched = 0; + for (int j = 1; j < c->argc; j++) + if (lookupKeyRead(c->db,c->argv[j]) != NULL) touched++; + addReplyLongLong(c,touched); +} + /* ----------------------------------------------------------------------------- * API to get key arguments from commands * ---------------------------------------------------------------------------*/ diff --git a/src/server.c b/src/server.c index 67c2635a..8ef6620b 100644 --- a/src/server.c +++ b/src/server.c @@ -248,6 +248,7 @@ struct redisCommand redisCommandTable[] = { {"info",infoCommand,-1,"lt",0,NULL,0,0,0,0,0}, {"monitor",monitorCommand,1,"as",0,NULL,0,0,0,0,0}, {"ttl",ttlCommand,2,"rF",0,NULL,1,1,1,0,0}, + {"touch",touchCommand,-2,"rF",0,NULL,1,1,1,0,0}, {"pttl",pttlCommand,2,"rF",0,NULL,1,1,1,0,0}, {"persist",persistCommand,2,"wF",0,NULL,1,1,1,0,0}, {"slaveof",slaveofCommand,3,"ast",0,NULL,0,0,0,0,0}, diff --git a/src/server.h b/src/server.h index 64c97bcf..933ea53a 100644 --- a/src/server.h +++ b/src/server.h @@ -1394,11 +1394,14 @@ void propagateExpire(redisDb *db, robj *key); int expireIfNeeded(redisDb *db, robj *key); long long getExpire(redisDb *db, robj *key); void setExpire(redisDb *db, robj *key, long long when); -robj *lookupKey(redisDb *db, robj *key); +robj *lookupKey(redisDb *db, robj *key, int flags); robj *lookupKeyRead(redisDb *db, robj *key); robj *lookupKeyWrite(redisDb *db, robj *key); robj *lookupKeyReadOrReply(client *c, robj *key, robj *reply); robj *lookupKeyWriteOrReply(client *c, robj *key, robj *reply); +robj *lookupKeyReadWithFlags(redisDb *db, robj *key, int flags); +#define LOOKUP_NONE 0 +#define LOOKUP_NOTOUCH (1<<0) void dbAdd(redisDb *db, robj *key, robj *val); void dbOverwrite(redisDb *db, robj *key, robj *val); void setKey(redisDb *db, robj *key, robj *val); @@ -1541,6 +1544,7 @@ void pexpireCommand(client *c); void pexpireatCommand(client *c); void getsetCommand(client *c); void ttlCommand(client *c); +void touchCommand(client *c); void pttlCommand(client *c); void persistCommand(client *c); void slaveofCommand(client *c); From 0cb86064e602a093a23b56943a7321fe1af64984 Mon Sep 17 00:00:00 2001 From: antirez Date: Wed, 15 Jun 2016 11:49:49 +0200 Subject: [PATCH 24/40] Regression test for #3282. --- tests/unit/bitops.tcl | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/unit/bitops.tcl b/tests/unit/bitops.tcl index 30aa832c..926f3829 100644 --- a/tests/unit/bitops.tcl +++ b/tests/unit/bitops.tcl @@ -43,6 +43,16 @@ start_server {tags {"bitops"}} { r bitcount no-key } 0 + test {BITCOUNT returns 0 with out of range indexes} { + r set str "xxxx" + r bitcount str 4 10 + } 0 + + test {BITCOUNT returns 0 with negative indexes where start > end} { + r set str "xxxx" + r bitcount str -6 -7 + } 0 + catch {unset num} foreach vec [list "" "\xaa" "\x00\x00\xff" "foobar" "123"] { incr num From f45fa5d05f47a5729786a69962119c9b3dc12645 Mon Sep 17 00:00:00 2001 From: wenduo Date: Mon, 30 May 2016 16:21:08 +0800 Subject: [PATCH 25/40] bitcount bug:return non-zero value when start > end (both negative) --- src/bitops.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/bitops.c b/src/bitops.c index 699681bc..8d64f23e 100644 --- a/src/bitops.c +++ b/src/bitops.c @@ -775,6 +775,10 @@ void bitcountCommand(client *c) { /* Convert negative indexes */ if (start < 0) start = strlen+start; if (end < 0) end = strlen+end; + if ((start < 0) && (end < 0) && (start > end)) { + addReply(c,shared.czero); + return; + } if (start < 0) start = 0; if (end < 0) end = 0; if (end >= strlen) end = strlen-1; From 9942070f5a41fa3bc953e9628a7248aeb7c0befa Mon Sep 17 00:00:00 2001 From: antirez Date: Wed, 15 Jun 2016 12:16:39 +0200 Subject: [PATCH 26/40] Remove additional round brackets from fix for #3282. --- src/bitops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bitops.c b/src/bitops.c index 8d64f23e..2312432f 100644 --- a/src/bitops.c +++ b/src/bitops.c @@ -775,7 +775,7 @@ void bitcountCommand(client *c) { /* Convert negative indexes */ if (start < 0) start = strlen+start; if (end < 0) end = strlen+end; - if ((start < 0) && (end < 0) && (start > end)) { + if (start < 0 && end < 0 && start > end) { addReply(c,shared.czero); return; } From d4831e328759bf5bd07c2c6e6ce1d60e84ba196f Mon Sep 17 00:00:00 2001 From: antirez Date: Wed, 15 Jun 2016 12:48:58 +0200 Subject: [PATCH 27/40] GETRANGE: return empty string with negative, inverted start/end. --- src/bitops.c | 4 ++-- src/t_string.c | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/bitops.c b/src/bitops.c index 2312432f..781cc58d 100644 --- a/src/bitops.c +++ b/src/bitops.c @@ -773,12 +773,12 @@ void bitcountCommand(client *c) { if (getLongFromObjectOrReply(c,c->argv[3],&end,NULL) != C_OK) return; /* Convert negative indexes */ - if (start < 0) start = strlen+start; - if (end < 0) end = strlen+end; if (start < 0 && end < 0 && start > end) { addReply(c,shared.czero); return; } + if (start < 0) start = strlen+start; + if (end < 0) end = strlen+end; if (start < 0) start = 0; if (end < 0) end = 0; if (end >= strlen) end = strlen-1; diff --git a/src/t_string.c b/src/t_string.c index 35eb9d7c..8c737c4e 100644 --- a/src/t_string.c +++ b/src/t_string.c @@ -263,6 +263,10 @@ void getrangeCommand(client *c) { } /* Convert negative indexes */ + if (start < 0 && end < 0 && start > end) { + addReply(c,shared.emptybulk); + return; + } if (start < 0) start = strlen+start; if (end < 0) end = strlen+end; if (start < 0) start = 0; From f1c237cb6a647ad5400b0ebce124fd9802ea7f89 Mon Sep 17 00:00:00 2001 From: antirez Date: Wed, 15 Jun 2016 17:15:18 +0200 Subject: [PATCH 28/40] Test TOUCH and new TTL / TYPE behavior about object access time. --- tests/test_helper.tcl | 1 + tests/unit/introspection-2.tcl | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 tests/unit/introspection-2.tcl diff --git a/tests/test_helper.tcl b/tests/test_helper.tcl index 792b970c..9a6e6730 100644 --- a/tests/test_helper.tcl +++ b/tests/test_helper.tcl @@ -46,6 +46,7 @@ set ::all_tests { unit/scripting unit/maxmemory unit/introspection + unit/introspection-2 unit/limits unit/obuf-limits unit/bitops diff --git a/tests/unit/introspection-2.tcl b/tests/unit/introspection-2.tcl new file mode 100644 index 00000000..350a8a01 --- /dev/null +++ b/tests/unit/introspection-2.tcl @@ -0,0 +1,23 @@ +start_server {tags {"introspection"}} { + test {TTL and TYPYE do not alter the last access time of a key} { + r set foo bar + after 3000 + r ttl foo + r type foo + assert {[r object idletime foo] >= 2} + } + + test {TOUCH alters the last access time of a key} { + r set foo bar + after 3000 + r touch foo + assert {[r object idletime foo] < 2} + } + + test {TOUCH returns the number of existing keys specified} { + r flushdb + r set key1 1 + r set key2 2 + r touch key0 key1 key2 key3 + } 2 +} From 26555f5e008b099b888ef39cabec632f4b31a038 Mon Sep 17 00:00:00 2001 From: MOON_CLJ Date: Thu, 26 May 2016 13:10:12 +0800 Subject: [PATCH 29/40] fix check when can't send the command to the promoted slave --- src/sentinel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sentinel.c b/src/sentinel.c index 4d5f84a9..6c48f3ed 100644 --- a/src/sentinel.c +++ b/src/sentinel.c @@ -3996,7 +3996,7 @@ void sentinelFailoverSendSlaveOfNoOne(sentinelRedisInstance *ri) { /* We can't send the command to the promoted slave if it is now * disconnected. Retry again and again with this state until the timeout * is reached, then abort the failover. */ - if (ri->link->disconnected) { + if (ri->promoted_slave->link->disconnected) { if (mstime() - ri->failover_state_change_time > ri->failover_timeout) { sentinelEvent(LL_WARNING,"-failover-abort-slave-timeout",ri,"%@"); sentinelAbortFailover(ri); From a2e27b810edfad18b3ecc9c176a4606f94a2f0e4 Mon Sep 17 00:00:00 2001 From: oranagra Date: Tue, 24 May 2016 14:52:43 +0300 Subject: [PATCH 30/40] fix crash in BITFIELD GET on non existing key or wrong type see #3259 this was a bug in the recent refactoring: bee963c4459223d874e3294a0d8638a588d33c8e --- src/bitops.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/bitops.c b/src/bitops.c index 781cc58d..a07633fa 100644 --- a/src/bitops.c +++ b/src/bitops.c @@ -1060,12 +1060,14 @@ void bitfieldCommand(client *c) { } else { /* GET */ unsigned char buf[9]; - long strlen; + long strlen = 0; unsigned char *src = NULL; char llbuf[LONG_STR_SIZE]; - o = lookupKeyRead(c->db,c->argv[1]); - src = getObjectReadOnlyString(o,&strlen,llbuf); + if ((o = lookupKeyRead(c->db,c->argv[1])) != NULL) { + if (checkType(c,o,OBJ_STRING)) continue; + src = getObjectReadOnlyString(o,&strlen,llbuf); + } /* For GET we use a trick: before executing the operation * copy up to 9 bytes to a local buffer, so that we can easily From 2a3ee58ec73b6abdeeb4890937b25191119bce35 Mon Sep 17 00:00:00 2001 From: oranagra Date: Tue, 24 May 2016 23:31:36 +0300 Subject: [PATCH 31/40] check WRONGTYPE in BITFIELD before looping on the operations. optimization: lookup key only once, and grow at once to the max need fixes #3259 and #3221, and also an early return if wrongtype is discovered by SET --- src/bitops.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/src/bitops.c b/src/bitops.c index a07633fa..9ae52c81 100644 --- a/src/bitops.c +++ b/src/bitops.c @@ -906,6 +906,8 @@ void bitfieldCommand(client *c) { int j, numops = 0, changes = 0; struct bitfieldOp *ops = NULL; /* Array of ops to execute at end. */ int owtype = BFOVERFLOW_WRAP; /* Overflow type. */ + int readonly = 1; + long highestWriteOffset = 0; for (j = 2; j < c->argc; j++) { int remargs = c->argc-j-1; /* Remaining args other than current. */ @@ -953,8 +955,10 @@ void bitfieldCommand(client *c) { return; } - /* INCRBY and SET require another argument. */ if (opcode != BITFIELDOP_GET) { + readonly = 0; + highestWriteOffset = bitoffset + bits - 1; + /* INCRBY and SET require another argument. */ if (getLongLongFromObjectOrReply(c,c->argv[j+3],&i64,NULL) != C_OK){ zfree(ops); return; @@ -974,6 +978,18 @@ void bitfieldCommand(client *c) { j += 3 - (opcode == BITFIELDOP_GET); } + if (readonly) { + /* Lookup for read is ok if key doesn't exit, but errors + * if it's not a string*/ + o = lookupKeyRead(c->db,c->argv[1]); + if (o != NULL && checkType(c,o,OBJ_STRING)) return; + } else { + /* Lookup by making room up to the farest bit reached by + * this operation. */ + if ((o = lookupStringForBitCommand(c, + highestWriteOffset)) == NULL) return; + } + addReplyMultiBulkLen(c,numops); /* Actually process the operations. */ @@ -988,11 +1004,6 @@ void bitfieldCommand(client *c) { * for simplicity. SET return value is the previous value so * we need fetch & store as well. */ - /* Lookup by making room up to the farest bit reached by - * this operation. */ - if ((o = lookupStringForBitCommand(c, - thisop->offset + (thisop->bits-1))) == NULL) return; - /* We need two different but very similar code paths for signed * and unsigned operations, since the set of functions to get/set * the integers and the used variables types are different. */ @@ -1064,10 +1075,8 @@ void bitfieldCommand(client *c) { unsigned char *src = NULL; char llbuf[LONG_STR_SIZE]; - if ((o = lookupKeyRead(c->db,c->argv[1])) != NULL) { - if (checkType(c,o,OBJ_STRING)) continue; + if (o != NULL) src = getObjectReadOnlyString(o,&strlen,llbuf); - } /* For GET we use a trick: before executing the operation * copy up to 9 bytes to a local buffer, so that we can easily From bd23ea3f9f3defbbdf512864ee1a88fd02665a7f Mon Sep 17 00:00:00 2001 From: antirez Date: Thu, 16 Jun 2016 12:54:33 +0200 Subject: [PATCH 32/40] Minor aesthetic fixes to PR #3264. Comment format fixed + local var modified from camel case to underscore separators as Redis code base normally does (camel case is mostly used for global symbols like structure names, function names, global vars, ...). --- src/bitops.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/bitops.c b/src/bitops.c index 9ae52c81..302e811d 100644 --- a/src/bitops.c +++ b/src/bitops.c @@ -907,7 +907,7 @@ void bitfieldCommand(client *c) { struct bitfieldOp *ops = NULL; /* Array of ops to execute at end. */ int owtype = BFOVERFLOW_WRAP; /* Overflow type. */ int readonly = 1; - long highestWriteOffset = 0; + long higest_write_offset = 0; for (j = 2; j < c->argc; j++) { int remargs = c->argc-j-1; /* Remaining args other than current. */ @@ -957,7 +957,7 @@ void bitfieldCommand(client *c) { if (opcode != BITFIELDOP_GET) { readonly = 0; - highestWriteOffset = bitoffset + bits - 1; + higest_write_offset = bitoffset + bits - 1; /* INCRBY and SET require another argument. */ if (getLongLongFromObjectOrReply(c,c->argv[j+3],&i64,NULL) != C_OK){ zfree(ops); @@ -979,15 +979,15 @@ void bitfieldCommand(client *c) { } if (readonly) { - /* Lookup for read is ok if key doesn't exit, but errors - * if it's not a string*/ + /* Lookup for read is ok if key doesn't exit, but errors + * if it's not a string. */ o = lookupKeyRead(c->db,c->argv[1]); if (o != NULL && checkType(c,o,OBJ_STRING)) return; } else { /* Lookup by making room up to the farest bit reached by * this operation. */ if ((o = lookupStringForBitCommand(c, - highestWriteOffset)) == NULL) return; + higest_write_offset)) == NULL) return; } addReplyMultiBulkLen(c,numops); From 14e04847ac2960aefe31dccbec63d2503cf09ca5 Mon Sep 17 00:00:00 2001 From: oranagra Date: Mon, 23 May 2016 13:58:50 +0300 Subject: [PATCH 33/40] fix georadius returns multiple replies --- src/geo.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/geo.c b/src/geo.c index 734e02b0..f019c2a1 100644 --- a/src/geo.c +++ b/src/geo.c @@ -156,9 +156,13 @@ double extractDistanceOrReply(client *c, robj **argv, return -1; } + if (distance < 0) { + addReplyError(c,"radius cannot be negative"); + return -1; + } + double to_meters = extractUnitOrReply(c,argv[1]); if (to_meters < 0) { - addReplyError(c,"radius cannot be negative"); return -1; } @@ -467,7 +471,6 @@ void georadiusGeneric(client *c, int type) { double radius_meters = 0, conversion = 1; if ((radius_meters = extractDistanceOrReply(c, c->argv + base_args - 2, &conversion)) < 0) { - addReplyError(c,"radius must be >= 0"); return; } From 047ced4473ee35485e22e45db8b8b4a272bf1177 Mon Sep 17 00:00:00 2001 From: oranagra Date: Mon, 23 May 2016 11:42:21 +0300 Subject: [PATCH 34/40] CLIENT error message was out of date --- src/networking.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/networking.c b/src/networking.c index d70eb8e1..c6dd7138 100644 --- a/src/networking.c +++ b/src/networking.c @@ -1632,7 +1632,7 @@ void clientCommand(client *c) { pauseClients(duration); addReply(c,shared.ok); } else { - addReplyError(c, "Syntax error, try CLIENT (LIST | KILL ip:port | GETNAME | SETNAME connection-name)"); + addReplyError(c, "Syntax error, try CLIENT (LIST | KILL | GETNAME | SETNAME | PAUSE | REPLY)"); } } From f592b4d3178963878084a522b4fd050772c335ae Mon Sep 17 00:00:00 2001 From: antirez Date: Thu, 16 Jun 2016 15:53:57 +0200 Subject: [PATCH 35/40] RESTORE: accept RDB dumps with older versions. Reference issue #3218. Checking the code I can't find a reason why the original RESTORE code was so opinionated about restoring only the current version. The code in to `rdb.c` appears to be capable as always to restore data from older versions of Redis, and the only places where it is needed the current version in order to correctly restore data, is while loading the opcodes, not the values itself as it happens in the case of RESTORE. For the above reasons, this commit enables RESTORE to accept older versions of values payloads. --- src/cluster.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cluster.c b/src/cluster.c index d8bd2ba8..9d53c981 100644 --- a/src/cluster.c +++ b/src/cluster.c @@ -4437,7 +4437,7 @@ int verifyDumpPayload(unsigned char *p, size_t len) { /* Verify RDB version */ rdbver = (footer[1] << 8) | footer[0]; - if (rdbver != RDB_VERSION) return C_ERR; + if (rdbver > RDB_VERSION) return C_ERR; /* Verify CRC64 */ crc = crc64(0,p,len-8); From b6007b324b81dbd4ffe519b3bdb19ab65fbb407f Mon Sep 17 00:00:00 2001 From: Jan-Erik Rediger Date: Sat, 21 May 2016 13:50:01 +0200 Subject: [PATCH 36/40] Remove debug printing --- src/redis-cli.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/redis-cli.c b/src/redis-cli.c index cf939c8c..027a2658 100644 --- a/src/redis-cli.c +++ b/src/redis-cli.c @@ -284,7 +284,6 @@ static void cliIntegrateHelp(void) { break; } if (i != helpEntriesLen) continue; - printf("%s\n", cmdname); helpEntriesLen++; helpEntries = zrealloc(helpEntries,sizeof(helpEntry)*helpEntriesLen); @@ -314,8 +313,6 @@ static void cliIntegrateHelp(void) { new->org = ch; } freeReplyObject(reply); - - printf("%s\n", helpEntries[80].full); } /* Output command help to stdout. */ From 58f1d446c35e8fe62df7c9ebe10f3c40a386c022 Mon Sep 17 00:00:00 2001 From: antirez Date: Thu, 16 Jun 2016 17:23:31 +0200 Subject: [PATCH 37/40] redis-cli: really connect to the right server. I recently introduced populating the autocomplete help array with the COMMAND command if available. However this was performed before parsing the arguments, defaulting to instance 6379. After the connection is performed it remains stable. The effect is that if there is an instance running on port 6339, whatever port you specify is ignored and 6379 is connected to instead. The right port will be selected only after a reconnection. Close #3314. --- src/redis-cli.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/redis-cli.c b/src/redis-cli.c index 027a2658..17fb5339 100644 --- a/src/redis-cli.c +++ b/src/redis-cli.c @@ -2591,13 +2591,16 @@ int main(int argc, char **argv) { else config.output = OUTPUT_STANDARD; config.mb_delim = sdsnew("\n"); - cliInitHelp(); - cliIntegrateHelp(); firstarg = parseOptions(argc,argv); argc -= firstarg; argv += firstarg; + /* Initialize the help and, if possible, use the COMMAND command in order + * to retrieve missing entries. */ + cliInitHelp(); + cliIntegrateHelp(); + /* Latency mode */ if (config.latency_mode) { if (cliConnect(0) == REDIS_ERR) exit(1); From 6ad0371c9b4206a7a6692d50c9a301457baf9b6d Mon Sep 17 00:00:00 2001 From: antirez Date: Thu, 16 Jun 2016 19:24:34 +0200 Subject: [PATCH 38/40] Fix Sentinel pending commands counting. This bug most experienced effect was an inability of Redis to reconfigure back old masters to slaves after they are reachable again after a failover. This was due to failing to reset the count of the pending commands properly, so the master appeared fovever down. Was introduced in Redis 3.2 new Sentinel connection sharing feature which is a lot more complex than the 3.0 code, but more scalable. Many thanks to people reporting the issue, and especially to @sskorgal for investigating the issue in depth. Hopefully closes #3285. --- src/sentinel.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sentinel.c b/src/sentinel.c index 6c48f3ed..f8ebd0c6 100644 --- a/src/sentinel.c +++ b/src/sentinel.c @@ -1910,6 +1910,7 @@ void sentinelReconnectInstance(sentinelRedisInstance *ri) { link->cc->errstr); instanceLinkCloseConnection(link,link->cc); } else { + link->pending_commands = 0; link->cc_conn_time = mstime(); link->cc->data = link; redisAeAttach(server.el,link->cc); From 8207e828043e37a0d7e058530d2886bb3ff395ff Mon Sep 17 00:00:00 2001 From: oranagra Date: Sun, 22 May 2016 20:35:14 +0300 Subject: [PATCH 39/40] config set list-max-ziplist-size didn't support negative values, unlike config file --- src/config.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/config.c b/src/config.c index 6100fb2e..9ec44897 100644 --- a/src/config.c +++ b/src/config.c @@ -682,7 +682,7 @@ void loadServerConfig(char *filename, char *options) { #define config_set_numerical_field(_name,_var,min,max) \ } else if (!strcasecmp(c->argv[2]->ptr,_name)) { \ - if (getLongLongFromObject(o,&ll) == C_ERR || ll < 0) goto badfmt; \ + if (getLongLongFromObject(o,&ll) == C_ERR) goto badfmt; \ if (min != LLONG_MIN && ll < min) goto badfmt; \ if (max != LLONG_MAX && ll > max) goto badfmt; \ _var = ll; @@ -902,9 +902,9 @@ void configSetCommand(client *c) { } config_set_numerical_field( "hash-max-ziplist-value",server.hash_max_ziplist_value,0,LLONG_MAX) { } config_set_numerical_field( - "list-max-ziplist-size",server.list_max_ziplist_size,0,LLONG_MAX) { + "list-max-ziplist-size",server.list_max_ziplist_size,INT_MIN,INT_MAX) { } config_set_numerical_field( - "list-compress-depth",server.list_compress_depth,0,LLONG_MAX) { + "list-compress-depth",server.list_compress_depth,0,INT_MAX) { } config_set_numerical_field( "set-max-intset-entries",server.set_max_intset_entries,0,LLONG_MAX) { } config_set_numerical_field( From 04c7261f03cc423bcc089b27b5a24ad260279b22 Mon Sep 17 00:00:00 2001 From: antirez Date: Fri, 17 Jun 2016 15:15:21 +0200 Subject: [PATCH 40/40] Redis 3.2.1. --- 00-RELEASENOTES | 521 ++++++++++++++++++++++++++++++++++++++++++++++++ src/version.h | 2 +- 2 files changed, 522 insertions(+), 1 deletion(-) diff --git a/00-RELEASENOTES b/00-RELEASENOTES index dfed8591..ee7dec29 100644 --- a/00-RELEASENOTES +++ b/00-RELEASENOTES @@ -10,6 +10,527 @@ HIGH: There is a critical bug that may affect a subset of users. Upgrade! CRITICAL: There is a critical bug affecting MOST USERS. Upgrade ASAP. -------------------------------------------------------------------------------- + +================================================================================ +Redis 3.2.1 Released Fri Jun 17 15:01:56 CEST 2016 +================================================================================ + +Upgrade urgency HIGH: Critical fix to Redis Sentinel, due to 3.2.0 regression + compared to 3.0. + +Hey, this is Redis 3.2.1, and this release should bring some grain of +maturity to Redis 3.2. The list of commits following this note will tell +you the details, but the main things addressed in this release are the +following: + +1. A critical bug in Sentinel was hopefully fixed. During the big 3.2 + refactoring of Redis Sentinel, in order to implement connection sharing + to make Sentinel able to scale better (few Sentinels to monitor many + masters), a bug was introduced that mis-counted the number of pending + commands in the Redis link. This in turn resulted into an inability to talk + with certain Redis instances. A common result of this bug was the inability + of Redis Sentinel to reconfigure back the old master, after a failover, + when it is reachable again, as the slave of the new master. This was due + to the inability to talk with the old master at all. + +2. BITFIELD bugs fixed. + +3. GEO commands fixes on syntax errors and edge cases. + +4. RESTORE now accepts dumps generated by older Redis versions. + +5. Jemalloc now is really configured to save you memory, for a problem a + change in the jemalloc configuration did not really survived when the + 3.2.0 release was finalized. + +6. TTL and TYPE command no longer alter the last access time of a key, for + LRU evictions purposes. A new TOUCH command was introduced *just* to + update the access time of a key. + +7. A bug was fixed in redis-cli, that connected to the instance running on the + port 6379 if there was one, regardless of what was specified. + +8. TCP keep alive is now enabled by default. This should fix most ghost + connections problems without resulting in any practical change in otherwise + sane deployments. + +9. A Sentinel crash that could happen during failovers was fixed. + +And of course, more minor things that you can read in the detailed log +below. There are still reported bugs for 3.2 that were not fixed in this +release, but nothing critical AFAIK, and I wanted to release this one ASAP, +so likely a new release will not be too far. + +Enjoy, +Salvatore + ++------------------------------------------------------------------------------- +| config set list-max-ziplist-size didn't support negative values, unlike config file +| By oranagra, 2016-05-22 20:35:14 +0300 ++-------------------------------------------------------------------------------- +https://github.com/antirez/redis/commit/8207e828043e37a0d7e058530d2886bb3ff395ff + + + src/config.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + ++------------------------------------------------------------------------------- +| Fix Sentinel pending commands counting. +| By antirez, 2016-06-16 19:24:34 +0200 ++-------------------------------------------------------------------------------- +https://github.com/antirez/redis/commit/6ad0371c9b4206a7a6692d50c9a301457baf9b6d + +This bug most experienced effect was an inability of Redis to +reconfigure back old masters to slaves after they are reachable again +after a failover. This was due to failing to reset the count of the +pending commands properly, so the master appeared fovever down. + +Was introduced in Redis 3.2 new Sentinel connection sharing feature +which is a lot more complex than the 3.0 code, but more scalable. + +Many thanks to people reporting the issue, and especially to +@sskorgal for investigating the issue in depth. + +Hopefully closes #3285. + + src/sentinel.c | 1 + + 1 file changed, 1 insertion(+) + ++------------------------------------------------------------------------------- +| redis-cli: really connect to the right server. +| By antirez, 2016-06-16 17:23:31 +0200 ++-------------------------------------------------------------------------------- +https://github.com/antirez/redis/commit/58f1d446c35e8fe62df7c9ebe10f3c40a386c022 + +I recently introduced populating the autocomplete help array with the +COMMAND command if available. However this was performed before parsing +the arguments, defaulting to instance 6379. After the connection is +performed it remains stable. + +The effect is that if there is an instance running on port 6339, +whatever port you specify is ignored and 6379 is connected to instead. +The right port will be selected only after a reconnection. + +Close #3314. + + src/redis-cli.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + ++------------------------------------------------------------------------------- +| Remove debug printing +| By Jan-Erik Rediger, 2016-05-21 13:50:01 +0200 ++-------------------------------------------------------------------------------- +https://github.com/antirez/redis/commit/b6007b324b81dbd4ffe519b3bdb19ab65fbb407f + + + src/redis-cli.c | 3 --- + 1 file changed, 3 deletions(-) + ++------------------------------------------------------------------------------- +| RESTORE: accept RDB dumps with older versions. +| By antirez, 2016-06-16 15:53:57 +0200 ++-------------------------------------------------------------------------------- +https://github.com/antirez/redis/commit/f592b4d3178963878084a522b4fd050772c335ae + +Reference issue #3218. + +Checking the code I can't find a reason why the original RESTORE +code was so opinionated about restoring only the current version. The +code in to `rdb.c` appears to be capable as always to restore data from +older versions of Redis, and the only places where it is needed the +current version in order to correctly restore data, is while loading the +opcodes, not the values itself as it happens in the case of RESTORE. + +For the above reasons, this commit enables RESTORE to accept older +versions of values payloads. + + src/cluster.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + ++------------------------------------------------------------------------------- +| CLIENT error message was out of date +| By oranagra, 2016-05-23 11:42:21 +0300 ++-------------------------------------------------------------------------------- +https://github.com/antirez/redis/commit/047ced4473ee35485e22e45db8b8b4a272bf1177 + + + src/networking.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + ++------------------------------------------------------------------------------- +| fix georadius returns multiple replies +| By oranagra, 2016-05-23 13:58:50 +0300 ++-------------------------------------------------------------------------------- +https://github.com/antirez/redis/commit/14e04847ac2960aefe31dccbec63d2503cf09ca5 + + + src/geo.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + ++------------------------------------------------------------------------------- +| Minor aesthetic fixes to PR #3264. +| By antirez, 2016-06-16 12:54:33 +0200 ++-------------------------------------------------------------------------------- +https://github.com/antirez/redis/commit/bd23ea3f9f3defbbdf512864ee1a88fd02665a7f + +Comment format fixed + local var modified from camel case to underscore +separators as Redis code base normally does (camel case is mostly used +for global symbols like structure names, function names, global vars, +...). + + src/bitops.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + ++------------------------------------------------------------------------------- +| check WRONGTYPE in BITFIELD before looping on the operations. +| By oranagra, 2016-05-24 23:31:36 +0300 ++-------------------------------------------------------------------------------- +https://github.com/antirez/redis/commit/2a3ee58ec73b6abdeeb4890937b25191119bce35 + +optimization: lookup key only once, and grow at once to the max need +fixes #3259 and #3221, and also an early return if wrongtype is discovered by SET + + src/bitops.c | 27 ++++++++++++++++++--------- + 1 file changed, 18 insertions(+), 9 deletions(-) + ++------------------------------------------------------------------------------- +| fix crash in BITFIELD GET on non existing key or wrong type see #3259 +| By oranagra, 2016-05-24 14:52:43 +0300 ++-------------------------------------------------------------------------------- +https://github.com/antirez/redis/commit/a2e27b810edfad18b3ecc9c176a4606f94a2f0e4 + +this was a bug in the recent refactoring: bee963c4459223d874e3294a0d8638a588d33c8e + + src/bitops.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + ++------------------------------------------------------------------------------- +| fix check when can't send the command to the promoted slave +| By MOON_CLJ, 2016-05-26 13:10:12 +0800 ++-------------------------------------------------------------------------------- +https://github.com/antirez/redis/commit/26555f5e008b099b888ef39cabec632f4b31a038 + + + src/sentinel.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + ++------------------------------------------------------------------------------- +| Test TOUCH and new TTL / TYPE behavior about object access time. +| By antirez, 2016-06-15 17:15:18 +0200 ++-------------------------------------------------------------------------------- +https://github.com/antirez/redis/commit/f1c237cb6a647ad5400b0ebce124fd9802ea7f89 + + + tests/test_helper.tcl | 1 + + tests/unit/introspection-2.tcl | 23 +++++++++++++++++++++++ + 2 files changed, 24 insertions(+) + ++------------------------------------------------------------------------------- +| GETRANGE: return empty string with negative, inverted start/end. +| By antirez, 2016-06-15 12:48:58 +0200 ++-------------------------------------------------------------------------------- +https://github.com/antirez/redis/commit/d4831e328759bf5bd07c2c6e6ce1d60e84ba196f + + + src/bitops.c | 4 ++-- + src/t_string.c | 4 ++++ + 2 files changed, 6 insertions(+), 2 deletions(-) + ++------------------------------------------------------------------------------- +| Remove additional round brackets from fix for #3282. +| By antirez, 2016-06-15 12:16:39 +0200 ++-------------------------------------------------------------------------------- +https://github.com/antirez/redis/commit/9942070f5a41fa3bc953e9628a7248aeb7c0befa + + + src/bitops.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + ++------------------------------------------------------------------------------- +| bitcount bug:return non-zero value when start > end (both negative) +| By wenduo, 2016-05-30 16:21:08 +0800 ++-------------------------------------------------------------------------------- +https://github.com/antirez/redis/commit/f45fa5d05f47a5729786a69962119c9b3dc12645 + + + src/bitops.c | 4 ++++ + 1 file changed, 4 insertions(+) + ++------------------------------------------------------------------------------- +| Regression test for #3282. +| By antirez, 2016-06-15 11:49:49 +0200 ++-------------------------------------------------------------------------------- +https://github.com/antirez/redis/commit/0cb86064e602a093a23b56943a7321fe1af64984 + + + tests/unit/bitops.tcl | 10 ++++++++++ + 1 file changed, 10 insertions(+) + ++------------------------------------------------------------------------------- +| TTL and TYPE LRU access fixed. TOUCH implemented. +| By antirez, 2016-06-14 15:33:59 +0200 ++-------------------------------------------------------------------------------- +https://github.com/antirez/redis/commit/b23aa6706ac79a1c86c64aef07bd35e38f10f842 + + + src/db.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++------- + src/server.c | 1 + + src/server.h | 6 +++++- + 3 files changed, 60 insertions(+), 8 deletions(-) + ++------------------------------------------------------------------------------- +| redis-cli help.h updated. +| By antirez, 2016-06-14 14:45:48 +0200 ++-------------------------------------------------------------------------------- +https://github.com/antirez/redis/commit/6e4204fec9c78f3300d887ebc3db014df2c8b33e + + + src/help.h | 43 +++++++++++++++++++++++++++++-------------- + 1 file changed, 29 insertions(+), 14 deletions(-) + ++------------------------------------------------------------------------------- +| Fix GEORADIUS wrong output with radius > Earth radius. +| By antirez, 2016-05-30 12:45:49 +0200 ++-------------------------------------------------------------------------------- +https://github.com/antirez/redis/commit/bb43f4cab2f756c0412ca2b94d9e29c3db5025ab + +Close #3266 + + deps/geohash-int/geohash_helper.c | 2 ++ + 1 file changed, 2 insertions(+) + ++------------------------------------------------------------------------------- +| Geo: fix typo in geohashEstimateStepsByRadius(). +| By antirez, 2016-05-30 15:31:19 +0200 ++-------------------------------------------------------------------------------- +https://github.com/antirez/redis/commit/16102bc0af0912a0c9a92aedddf796eb24a80b9e + +I'm the author of this line but I can't see a good reason for it to +don't be a typo, a step of 26 should be valid with 52 bits per +coordinate, moreover the line was: + + if (step > 26) step = 25; + +So a step of 26 was actually already used, except when one of 27 was +computed (which is invalid) only then it was trimmed to 25 instead of +26. + +All tests passing after the change. + + deps/geohash-int/geohash_helper.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + ++------------------------------------------------------------------------------- +| Avoid undefined behavior in BITFIELD implementation. +| By antirez, 2016-05-31 11:52:07 +0200 ++-------------------------------------------------------------------------------- +https://github.com/antirez/redis/commit/014bf8044285c6d401d83e6e24829d276ab837f9 + +Probably there is no compiler that will actaully break the code or raise +a signal for unsigned -> signed overflowing conversion, still it was +apparently possible to write it in a more correct way. + +All tests passing. + + src/bitops.c | 23 +++++++++++++++-------- + 1 file changed, 15 insertions(+), 8 deletions(-) + ++------------------------------------------------------------------------------- +| Now that SPOP can be called by scripts use BLPOP on 's' flag test. +| By antirez, 2016-05-31 16:43:21 +0200 ++-------------------------------------------------------------------------------- +https://github.com/antirez/redis/commit/b4e5e2ec1ad7e9d1f4e7e559b61e0ecd4e50f2da + + + tests/unit/scripting.tcl | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + ++------------------------------------------------------------------------------- +| Test: run GEO tests by default. +| By antirez, 2016-05-31 16:43:49 +0200 ++-------------------------------------------------------------------------------- +https://github.com/antirez/redis/commit/df419281a19e13429b27814a3e384f6f029c3519 + +Thanks to @oranagra for noticing it was missing. + + tests/test_helper.tcl | 1 + + 1 file changed, 1 insertion(+) + ++------------------------------------------------------------------------------- +| Enable tcp-keepalive by default. +| By antirez, 2016-06-13 12:03:14 +0200 ++-------------------------------------------------------------------------------- +https://github.com/antirez/redis/commit/40cfe13141c7178d22fd43e4ffbecc37686e0b43 + + + redis.conf | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + ++------------------------------------------------------------------------------- +| fix some compiler warnings +| By Pierre Chapuis, 2016-06-05 15:34:43 +0200 ++-------------------------------------------------------------------------------- +https://github.com/antirez/redis/commit/a650aaaf4f074ec428b450ef88799db1dcd34b0f + + + src/bitops.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + ++------------------------------------------------------------------------------- +| Fixed typo in Sentinel compareSlavesForPromotion() comment. +| By antirez, 2016-06-10 09:15:01 +0200 ++-------------------------------------------------------------------------------- +https://github.com/antirez/redis/commit/3fd4baf1e77f125a306d57b788b72de5026c0564 + + + src/sentinel.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + ++------------------------------------------------------------------------------- +| fix comment "b>a" to "a > b" +| By andyli, 2016-06-07 14:42:50 +0800 ++-------------------------------------------------------------------------------- +https://github.com/antirez/redis/commit/8d029a5950f4ef40723c02b5c486b171aff0189c + + + src/sentinel.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + ++------------------------------------------------------------------------------- +| fix pidfile in redis.conf +| By bogdanvlviv, 2016-04-19 14:43:06 +0300 ++-------------------------------------------------------------------------------- +https://github.com/antirez/redis/commit/6937f5960d1803ca0eda1ab6f4bc60023f50c914 + + + redis.conf | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + ++------------------------------------------------------------------------------- +| Include 'fd_set' type name +| By jspraul, 2016-06-07 16:46:00 -0400 ++-------------------------------------------------------------------------------- +https://github.com/antirez/redis/commit/b5758cc5ce6c51ff75c86f9216214fe4d5e4c257 + +Fix an MSYS2-build-breaking error: unknown type name ‘fd_set’ + src/ae_select.c | 1 + + 1 file changed, 1 insertion(+) + ++------------------------------------------------------------------------------- +| Allow SPOP from Lua scripts +| By Itamar Haber, 2016-05-28 20:01:46 +0300 ++-------------------------------------------------------------------------------- +https://github.com/antirez/redis/commit/620783e3b582e9ba6e1d8fbd47987281ce0b6317 + +The existing `R` flag appears to be sufficient and there's no apparent reason why the command should be blocked. + src/server.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + ++------------------------------------------------------------------------------- +| minor fixes - mainly signalModifiedKey, and GEORADIUS +| By oranagra, 2016-05-09 09:12:38 +0300 ++-------------------------------------------------------------------------------- +https://github.com/antirez/redis/commit/603234076f4e59967f331bc97de3c0db9947c8ef + + + src/geo.c | 1 + + src/sds.c | 8 ++++---- + src/server.c | 2 +- + src/server.h | 3 +-- + src/t_set.c | 9 ++++++--- + src/t_zset.c | 12 ++++++------ + 6 files changed, 19 insertions(+), 16 deletions(-) + ++------------------------------------------------------------------------------- +| Code to access object string bytes repeated 3x refactored into 1 function. +| By antirez, 2016-05-18 15:35:17 +0200 ++-------------------------------------------------------------------------------- +https://github.com/antirez/redis/commit/2e6b99499abb5ff1fbeee3bac4d064e5ff4ea256 + + + src/bitops.c | 74 ++++++++++++++++++++++++++++++++---------------------------- + 1 file changed, 39 insertions(+), 35 deletions(-) + ++------------------------------------------------------------------------------- +| fix crash in BITFIELD GET when key is integer encoded +| By oranagra, 2016-05-10 11:19:45 +0300 ++-------------------------------------------------------------------------------- +https://github.com/antirez/redis/commit/dcaeafc8280eb8329e7ce68e7ab02c67d98f0cf4 + + + src/bitops.c | 18 +++++++++++++++--- + 1 file changed, 15 insertions(+), 3 deletions(-) + ++------------------------------------------------------------------------------- +| Clarify that the LOG_STR_SIZE includes null term. +| By antirez, 2016-05-18 15:23:18 +0200 ++-------------------------------------------------------------------------------- +https://github.com/antirez/redis/commit/4ad088818a3353ebd619e8d43847b5d58108af20 + + + src/server.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + ++------------------------------------------------------------------------------- +| Test for BITFIELD regression #3221. +| By antirez, 2016-05-18 14:53:30 +0200 ++-------------------------------------------------------------------------------- +https://github.com/antirez/redis/commit/f991cdc3e19c187035855355808575efd6b4c149 + + + tests/unit/bitfield.tcl | 5 +++++ + 1 file changed, 5 insertions(+) + ++------------------------------------------------------------------------------- +| reduce struct padding by reordering members +| By oranagra, 2016-05-16 20:12:11 +0300 ++-------------------------------------------------------------------------------- +https://github.com/antirez/redis/commit/cb3e89e2cb0753d2d111eaeadc9c73cbe24025ab + + + src/quicklist.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + ++------------------------------------------------------------------------------- +| Actually use --with-lg-quantum=3 to build jemalloc. +| By antirez, 2016-05-18 11:58:36 +0200 ++-------------------------------------------------------------------------------- +https://github.com/antirez/redis/commit/a7f0fb448c110e125eece44dc955d6939e494daa + +This change is documented in deps/README.md but was lost in one way or +the other, neutralizing the benefits of 24 bytes size classes (and +others). + +Close #3208. + + deps/Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + ++------------------------------------------------------------------------------- +| redis-cli: integrate help.h with COMMAND output. +| By antirez, 2016-05-07 13:03:25 +0200 ++-------------------------------------------------------------------------------- +https://github.com/antirez/redis/commit/029dc0d97fd492a2fd579796d4c1cc04053c7190 + +Use the COMMAND output to fill with partial information the built-in +help. This makes redis-cli able to at least complete commands that are +exported by the Redis server it is connected to, but were not available +in the help.h file when the redis-cli binary was compiled. + + src/redis-cli.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++-------- + 1 file changed, 70 insertions(+), 10 deletions(-) + ++------------------------------------------------------------------------------- +| Removed dofile() from Lua +| By Adam Baldwin, 2012-10-25 20:27:10 -0700 ++-------------------------------------------------------------------------------- +https://github.com/antirez/redis/commit/95def3aee044468504bb07633084afd49b085db3 + + + src/scripting.c | 2 ++ + 1 file changed, 2 insertions(+) + + ================================================================================ Redis 3.2.0 Released Fri May 06 08:47:10 CEST 2016 ================================================================================ diff --git a/src/version.h b/src/version.h index 97eb0d7b..16a0038e 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define REDIS_VERSION "3.2.0" +#define REDIS_VERSION "3.2.1"