Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
04c7261f03 | ||
|
|
8207e82804 | ||
|
|
6ad0371c9b | ||
|
|
58f1d446c3 | ||
|
|
b6007b324b | ||
|
|
f592b4d317 | ||
|
|
047ced4473 | ||
|
|
14e04847ac | ||
|
|
bd23ea3f9f | ||
|
|
2a3ee58ec7 | ||
|
|
a2e27b810e | ||
|
|
26555f5e00 | ||
|
|
f1c237cb6a | ||
|
|
d4831e3287 | ||
|
|
9942070f5a | ||
|
|
f45fa5d05f | ||
|
|
0cb86064e6 | ||
|
|
b23aa6706a | ||
|
|
6e4204fec9 | ||
|
|
bb43f4cab2 | ||
|
|
16102bc0af | ||
|
|
014bf80442 | ||
|
|
b4e5e2ec1a | ||
|
|
df419281a1 | ||
|
|
40cfe13141 | ||
|
|
a650aaaf4f | ||
|
|
3fd4baf1e7 | ||
|
|
8d029a5950 | ||
|
|
6937f5960d | ||
|
|
b5758cc5ce | ||
|
|
620783e3b5 | ||
|
|
603234076f | ||
|
|
2e6b99499a | ||
|
|
dcaeafc828 | ||
|
|
4ad088818a | ||
|
|
f991cdc3e1 | ||
|
|
cb3e89e2cb | ||
|
|
a7f0fb448c | ||
|
|
029dc0d97f | ||
|
|
95def3aee0 |
+521
@@ -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
|
||||
================================================================================
|
||||
|
||||
Vendored
+1
-1
@@ -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
|
||||
|
||||
Vendored
+3
-1
@@ -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
@@ -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:
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
*/
|
||||
|
||||
|
||||
#include <sys/select.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef struct aeApiState {
|
||||
|
||||
+80
-42
@@ -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
@@ -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
@@ -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(
|
||||
|
||||
@@ -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
|
||||
* ---------------------------------------------------------------------------*/
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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) {
|
||||
|
||||
@@ -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
@@ -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
@@ -1 +1 @@
|
||||
#define REDIS_VERSION "3.2.0"
|
||||
#define REDIS_VERSION "3.2.1"
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -184,4 +184,9 @@ start_server {tags {"bitops"}} {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
test {BITFIELD regression for #3221} {
|
||||
r set bits 1
|
||||
r bitfield bits get u1 0
|
||||
} {0}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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*}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user