Compare commits

..
40 Commits
Author SHA1 Message Date
antirez 04c7261f03 Redis 3.2.1. 2016-06-17 15:15:21 +02:00
oranagra 8207e82804 config set list-max-ziplist-size didn't support negative values, unlike config file 2016-06-17 14:49:37 +02:00
antirez 6ad0371c9b 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.
2016-06-16 19:24:34 +02:00
antirez 58f1d446c3 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.
2016-06-16 17:25:13 +02:00
Jan-Erik Rediger b6007b324b Remove debug printing 2016-06-16 17:18:06 +02:00
antirez f592b4d317 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.
2016-06-16 15:56:29 +02:00
oranagra 047ced4473 CLIENT error message was out of date 2016-06-16 12:59:26 +02:00
oranagra 14e04847ac fix georadius returns multiple replies 2016-06-16 12:58:18 +02:00
antirez bd23ea3f9f 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,
...).
2016-06-16 12:56:28 +02:00
oranagra 2a3ee58ec7 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
2016-06-16 12:56:17 +02:00
oranagra a2e27b810e fix crash in BITFIELD GET on non existing key or wrong type see #3259
this was a bug in the recent refactoring: bee963c4459223d874e3294a0d8638a588d33c8e
2016-06-16 12:56:17 +02:00
MOON_CLJ 26555f5e00 fix check when can't send the command to the promoted slave 2016-06-15 17:24:43 +02:00
antirez f1c237cb6a Test TOUCH and new TTL / TYPE behavior about object access time. 2016-06-15 17:16:13 +02:00
antirez d4831e3287 GETRANGE: return empty string with negative, inverted start/end. 2016-06-15 16:05:54 +02:00
antirez 9942070f5a Remove additional round brackets from fix for #3282. 2016-06-15 16:05:39 +02:00
wenduo f45fa5d05f bitcount bug:return non-zero value when start > end (both negative) 2016-06-15 16:05:33 +02:00
antirez 0cb86064e6 Regression test for #3282. 2016-06-15 16:04:44 +02:00
antirez b23aa6706a TTL and TYPE LRU access fixed. TOUCH implemented. 2016-06-15 09:18:55 +02:00
antirez 6e4204fec9 redis-cli help.h updated. 2016-06-14 14:45:48 +02:00
antirez bb43f4cab2 Fix GEORADIUS wrong output with radius > Earth radius.
Close #3266
2016-06-13 12:11:15 +02:00
antirez 16102bc0af 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.
2016-06-13 12:11:02 +02:00
antirez 014bf80442 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.
2016-06-13 12:10:58 +02:00
antirez b4e5e2ec1a Now that SPOP can be called by scripts use BLPOP on 's' flag test. 2016-06-13 12:10:52 +02:00
antirez df419281a1 Test: run GEO tests by default.
Thanks to @oranagra for noticing it was missing.
2016-06-13 12:10:47 +02:00
antirez 40cfe13141 Enable tcp-keepalive by default. 2016-06-13 12:03:19 +02:00
Pierre Chapuis a650aaaf4f fix some compiler warnings 2016-06-10 10:23:17 +02:00
antirez 3fd4baf1e7 Fixed typo in Sentinel compareSlavesForPromotion() comment. 2016-06-10 09:15:37 +02:00
andyli 8d029a5950 fix comment "b>a" to "a > b" 2016-06-10 09:15:21 +02:00
bogdanvlviv 6937f5960d fix pidfile in redis.conf 2016-06-10 09:02:22 +02:00
jspraul b5758cc5ce Include 'fd_set' type name
Fix an MSYS2-build-breaking error: unknown type name ‘fd_set’
2016-06-10 09:00:10 +02:00
Itamar Haber 620783e3b5 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.
2016-05-30 17:48:18 +02:00
oranagra 603234076f minor fixes - mainly signalModifiedKey, and GEORADIUS 2016-05-18 16:52:26 +02:00
antirez 2e6b99499a Code to access object string bytes repeated 3x refactored into 1 function. 2016-05-18 15:37:28 +02:00
oranagra dcaeafc828 fix crash in BITFIELD GET when key is integer encoded 2016-05-18 15:37:25 +02:00
antirez 4ad088818a Clarify that the LOG_STR_SIZE includes null term. 2016-05-18 15:36:44 +02:00
antirez f991cdc3e1 Test for BITFIELD regression #3221. 2016-05-18 15:36:38 +02:00
oranagra cb3e89e2cb reduce struct padding by reordering members 2016-05-18 12:12:20 +02:00
antirez a7f0fb448c 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.
2016-05-18 12:12:15 +02:00
antirez 029dc0d97f 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.
2016-05-08 19:00:07 +02:00
Adam Baldwin 95def3aee0 Removed dofile() from Lua 2016-05-08 18:05:05 +02:00
28 changed files with 853 additions and 110 deletions
+521
View File
@@ -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
================================================================================
+1 -1
View File
@@ -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
+3 -1
View File
@@ -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;
}
@@ -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;
+4 -3
View File
@@ -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 #####################################
@@ -146,7 +147,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:
+1
View File
@@ -29,6 +29,7 @@
*/
#include <sys/select.h>
#include <string.h>
typedef struct aeApiState {
+80 -42
View File
@@ -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;
@@ -299,7 +306,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 +349,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. */
@@ -476,6 +483,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 +759,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) {
@@ -744,6 +773,10 @@ void bitcountCommand(client *c) {
if (getLongFromObjectOrReply(c,c->argv[3],&end,NULL) != C_OK)
return;
/* Convert negative indexes */
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;
@@ -775,7 +808,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 +828,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) {
@@ -882,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 higest_write_offset = 0;
for (j = 2; j < c->argc; j++) {
int remargs = c->argc-j-1; /* Remaining args other than current. */
@@ -929,8 +955,10 @@ void bitfieldCommand(client *c) {
return;
}
/* INCRBY and SET require another argument. */
if (opcode != BITFIELDOP_GET) {
readonly = 0;
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);
return;
@@ -950,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,
higest_write_offset)) == NULL) return;
}
addReplyMultiBulkLen(c,numops);
/* Actually process the operations. */
@@ -964,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. */
@@ -1035,20 +1070,23 @@ 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];
long strlen = 0;
unsigned char *src = NULL;
char llbuf[LONG_STR_SIZE];
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
* 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++) {
if (src == NULL || i+byte >= olen) break;
if (src == NULL || i+byte >= (size_t)strlen) break;
buf[i] = src[i+byte];
}
+1 -1
View File
@@ -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);
+3 -3
View File
@@ -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(
+54 -7
View File
@@ -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
* ---------------------------------------------------------------------------*/
+5 -1
View File
@@ -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;
}
+29 -14
View File
@@ -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" },
+1 -1
View File
@@ -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)");
}
}
+1 -1
View File
@@ -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;
+71 -11
View File
@@ -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,61 @@ 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;
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);
}
/* 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 +884,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 +907,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 +927,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 +1291,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 +1350,7 @@ static void repl(void) {
sdsfreesplitres(argv,argc);
}
/* linenoise() returns malloc-ed lines like readline() */
free(line);
linenoiseFree(line);
}
exit(0);
}
@@ -2159,7 +2215,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 +2229,7 @@ static long getLongInfoField(char *info, char *field) {
if (!value) return LONG_MIN;
l = strtol(value,NULL,10);
free(value);
zfree(value);
return l;
}
@@ -2535,12 +2591,16 @@ int main(int argc, char **argv) {
else
config.output = OUTPUT_STANDARD;
config.mb_delim = sdsnew("\n");
cliInitHelp();
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);
+2
View File
@@ -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
+4 -4
View File
@@ -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;
}
+4 -3
View File
@@ -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);
@@ -3874,11 +3875,11 @@ 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) {
return 1; /* b > a */
return 1; /* a > b */
}
/* If the replication offset is the same select the slave with that has
@@ -3996,7 +3997,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);
+3 -2
View File
@@ -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},
@@ -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},
@@ -663,7 +664,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));
}
+7 -4
View File
@@ -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
@@ -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);
@@ -1395,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);
@@ -1542,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);
+6 -3
View File
@@ -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) {
+4
View File
@@ -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;
+6 -6
View File
@@ -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);
}
+1 -1
View File
@@ -1 +1 @@
#define REDIS_VERSION "3.2.0"
#define REDIS_VERSION "3.2.1"
+2
View File
@@ -46,10 +46,12 @@ set ::all_tests {
unit/scripting
unit/maxmemory
unit/introspection
unit/introspection-2
unit/limits
unit/obuf-limits
unit/bitops
unit/bitfield
unit/geo
unit/memefficiency
unit/hyperloglog
}
+5
View File
@@ -184,4 +184,9 @@ start_server {tags {"bitops"}} {
}
}
}
test {BITFIELD regression for #3221} {
r set bits 1
r bitfield bits get u1 0
} {0}
}
+10
View File
@@ -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
+23
View File
@@ -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
}
+1 -1
View File
@@ -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*}