Compare commits

...
Author SHA1 Message Date
Jesse 958ce1ad62 Merge commit 'e8d0057710d11b3361daf37b93e479947aebee5a' into jesse/feature/merge-redis-6.2.2 2021-04-29 14:39:46 -07:00
Jesse 20cd988fc0 Merge commit '3e9e27e98fa7ecdbb5a34676e51cda54de671d8a' into jesse/feature/merge-redis-6.2.2 2021-04-29 14:38:28 -07:00
Jesse 448b20dbd6 Merge commit '6f2240aefd86c7150f3b4cd3331a2f452fdca991' into jesse/feature/merge-redis-6.2.2 2021-04-29 13:48:19 -07:00
Jesse 3534bda474 Merge commit 'bd60c11bd8ca652f6cb6ecc57d0d10bc8aaa3481' into jesse/feature/merge-redis-6.2.2 2021-04-29 13:48:19 -07:00
Jesse b764fddb20 Merge commit '38f6207f884f514e928513acb6560fdb375daa2e' into jesse/feature/merge-redis-6.2.2 2021-04-29 13:48:17 -07:00
Jesse df7b3ef202 Merge commit 'dd05b7f67f8191aacbbe73a1b415658233715926' into jesse/feature/merge-redis-6.2.2 2021-04-29 13:47:51 -07:00
Jesse 5bab7047ee Merge commit '67ee87522ab5b3c3bae8ee4c84808664b14de2cc' into jesse/feature/merge-redis-6.2.2 2021-04-29 13:45:27 -07:00
Jesse c2ba9a3bf9 Merge commit '3f6d00d387b85b0eaa459427c2891ca979dc8363' into jesse/feature/merge-redis-6.2.2 2021-04-29 13:45:25 -07:00
Jesse 964f25daae Merge commit '7ef2270ee73e75b00b0c1bde40fb1df55c7ec6ff' into jesse/feature/merge-redis-6.2.2 2021-04-29 13:43:47 -07:00
Jesse e868c6e0fa Merge commit '456bbc02c8b5161e8e49b926325cdb54a69d12bb' into jesse/feature/merge-redis-6.2.2 2021-04-29 13:42:47 -07:00
Jesse 226152ad7d Merge commit '1d4ea00d12885108d936b76cd31097dc4894f5ca' into jesse/feature/merge-redis-6.2.2 2021-04-29 13:42:45 -07:00
Jesse 7e9852633c Merge commit 'abf8150b2e91927f73dccd670e49b655615b8b5a' into jesse/feature/merge-redis-6.2.2 2021-04-29 13:40:31 -07:00
Jesse 78c2edb9b7 Merge commit '2d7dc71b6fcf1638338f2d24d2d9c94297157416' into jesse/feature/merge-redis-6.2.2 2021-04-29 13:38:12 -07:00
Jesse 5d46886e73 Merge commit '7d5fb5df3f2dff8102ead8542e7697a5bc312e94' into jesse/feature/merge-redis-6.2.2 2021-04-29 13:37:08 -07:00
Jesse 1daf89f92c Merge commit '28d146bed69cd1d288ff435fe86ca9ad2c9cb879' into jesse/feature/merge-redis-6.2.2 2021-04-29 13:31:16 -07:00
Jesse 74f9e41247 Merge commit '9506c860f6642bc14aa4079e991c1c298138044a' into jesse/feature/merge-redis-6.2.2 2021-04-29 13:29:01 -07:00
Jesse 856ce4e15b Merge commit 'baa88a1c144954469e3762023fb41617242dc30e' into jesse/feature/merge-redis-6.2.2 2021-04-29 13:28:59 -07:00
Jesse dd287a22a0 Merge commit 'd28948b14303fdf00b331090ef177cc6cca54fe1' into jesse/feature/merge-redis-6.2.2 2021-04-29 13:28:56 -07:00
Jesse ebfd4726b4 Merge commit 'a8c912ead65e85b5ce3dae936320e77e047df9c9' into jesse/feature/merge-redis-6.2.2 2021-04-29 13:25:57 -07:00
Jesse d08bd7f127 Merge commit '24896427fc88e944d466874954503b1100263b65' into jesse/feature/merge-redis-6.2.2 2021-04-29 13:23:11 -07:00
Jesse e0e2ff2858 Merge commit 'b5f52bf01cd99d0bb2d51d158fd009690a36d042' into jesse/feature/merge-redis-6.2.2 2021-04-29 13:21:50 -07:00
Jesse 206f8cde24 Merge commit '8105f91a0202829c685da7967c2f60d477c2d1e9' into jesse/feature/merge-redis-6.2.2 2021-04-29 13:21:25 -07:00
Jesse 61dbf96e79 Merge commit 'b8b8dd5c159f37f1ebb1b045254ad29063a40425' into jesse/feature/merge-redis-6.2.2 2021-04-29 13:21:23 -07:00
Jesse 856cdf6ed3 Merge commit '9466dae4e5377056cd27fcdb0f4b47a5497bb08d' into jesse/feature/merge-redis-6.2.2 2021-04-29 13:21:21 -07:00
Jesse d9c153111d Merge commit '5234bff5790581c7d52e668e65b87a5beac1863e' into jesse/feature/merge-redis-6.2.2 2021-04-29 13:17:27 -07:00
Jesse 905d82f986 Merge commit '51a01ca8a630fbdee3a1e71fbf318225652afea9' into jesse/feature/merge-redis-6.2.2 2021-04-29 13:17:14 -07:00
Jesse a1b11ddb19 Merge commit 'b8d315ff7686dcf7883a3ed2970ff8cc68215daa' into jesse/feature/merge-redis-6.2.2 2021-04-29 13:15:19 -07:00
Jesse 3db157fc4a Merge commit 'bb936867546ceaa7993b5b28d610fd78198247c2' into jesse/feature/merge-redis-6.2.2 2021-04-29 13:15:06 -07:00
Jesse 79f34b4b2b Merge commit '64ef0ad71abe50c98fd996cf86989aae1b58716d' into jesse/feature/merge-redis-6.2.2 2021-04-29 13:13:28 -07:00
Jesse de95bb7f8f Merge commit '0f3c353dd3e274f5a7d21c8c2490252c2e5fa7ad' into jesse/feature/merge-redis-6.2.2 2021-04-29 13:13:25 -07:00
Jesse fc6dd57238 Merge commit 'f616ecf361d673e750c940cc67d19a1e21b1db20' into jesse/feature/merge-redis-6.2.2 2021-04-29 13:13:23 -07:00
Jesse 2c24288806 Merge commit '2ee4f9f34e66b30d0623f1adb6a860860891f94d' into jesse/feature/merge-redis-6.2.2 2021-04-29 13:13:21 -07:00
Jesse c1e5fefff9 Merge commit 'c89ec5af1e79ce44b930d171d4cacac21dddc990' into jesse/feature/merge-redis-6.2.2 2021-04-29 13:13:19 -07:00
Jesse a5ea548c91 Merge commit '0e38c5f39c7370690e1afe8d8c213d27842c5571' into jesse/feature/merge-redis-6.2.2 2021-04-29 13:13:16 -07:00
Jesse eddf0b1a96 Merge commit '7080a28efc28bd3a3004bd37c9b85d58233fc1ed' into jesse/feature/merge-redis-6.2.2 2021-04-29 13:11:22 -07:00
Jesse 2ef2da37ac Merge commit 'fda2bf9c92fe1c4adbb5c968b9b234710a85a7ed' into jesse/feature/merge-redis-6.2.2 2021-04-29 13:10:55 -07:00
Jesse c27e0bed41 Merge commit '63e46e5f8db68f3b8b5e0ea6b3b852b1068c9894' into jesse/feature/merge-redis-6.2.2 2021-04-29 13:10:30 -07:00
Jesse 5f33a992da Merge commit 'd6a13f444003e75e8ccbe97297bf32f0eb58cb23' into jesse/feature/merge-redis-6.2.2 2021-04-29 13:10:28 -07:00
Jesse f9e2f851c7 Merge commit '18c26760846fa51aee4ad5d6c4a6d06c64d7269e' into jesse/feature/merge-redis-6.2.2 2021-04-29 13:10:25 -07:00
Jesse e02cca9624 Merge commit '9387f7333e0ccc200dda10032e517e2fb93cc368' into jesse/feature/merge-redis-6.2.2 2021-04-29 13:10:22 -07:00
Jesse 88710fc7c5 Merge commit '2f8134a7ff9d3c435dad16a73bf96e3daa919a21' into jesse/feature/merge-redis-6.2.2 2021-04-29 13:03:48 -07:00
Jesse 76c3659a0b Merge commit '408e8e9f44b2f979e13559ba487d907974684846' into jesse/feature/merge-redis-6.2.2 2021-04-29 13:02:47 -07:00
Jesse 11a62b41b4 Merge commit '0af467d18f9d12b137af3b709c0af579c29d8414' into jesse/feature/merge-redis-6.2.2 2021-04-29 12:59:18 -07:00
Jesse 0e71591999 rename expire 2021-04-29 12:55:32 -07:00
Jesse 5db98031c5 Merge commit 'e5565a793e139f29970d46e3c681316f87fa16e8' into jesse/feature/merge-redis-6.2.2 2021-04-29 12:54:22 -07:00
Jesse 559cc5ec91 Merge commit '2bc8db9ca5f80e7c69ca51932aed05745d727ec5' into jesse/feature/merge-redis-6.2.2 2021-04-29 12:50:25 -07:00
Jesse b68d07b811 rename replication 2021-04-29 12:46:05 -07:00
Jesse 933c4c57ee Merge commit '3848849013e6ec7efa244897f5fdebb843fcfaa4' into jesse/feature/merge-redis-6.2.2 2021-04-28 14:05:54 -07:00
Jesse 576cfb391c Merge commit '0992ada2fe1cbc8f5f25c0cdec67cb69bb8d3810' into jesse/feature/merge-redis-6.2.2 2021-04-28 14:05:20 -07:00
Jesse 4de58cf1b1 Merge commit 'a3b0d8631ff8852967e864e3dd91d6238fe6bda1' into jesse/feature/merge-redis-6.2.2 2021-04-28 14:04:16 -07:00
Jesse f253c6be3e Merge commit 'd7d13721d38f391f31ed0d9b1081b59245b468ab' into jesse/feature/merge-redis-6.2.2 2021-04-28 14:02:29 -07:00
Jesse ef0f2e1388 Merge commit 'a351e74fe9e5d2da5b567520b485d55eff99771f' into jesse/feature/merge-redis-6.2.2 2021-04-28 13:55:52 -07:00
Jesse 409d4adaf8 Merge commit '6e4f70b8170e14ba8a2ada2fde4a75e073effee3' into jesse/feature/merge-redis-6.2.2 2021-04-28 13:52:34 -07:00
Jesse 20292422c7 Merge commit 'faea46710c4abf56bac9e5e0dba84aa4ad46820b' into jesse/feature/merge-redis-6.2.2 2021-04-28 13:52:31 -07:00
Jesse b56e3aebed Change lua-replicate-commands to MODIFIABLE_CONFIG 2021-04-28 13:51:06 -07:00
Jesse 6e250ea122 Merge commit '5521910de77d8a9d7587ec8497cc589c4245a599' into jesse/feature/merge-redis-6.2.2 2021-04-28 13:34:22 -07:00
Jesse aff31e0e5f Merge commit '3ff95d9074a88d53c339260225beaf304d393c70' into jesse/feature/merge-redis-6.2.2 2021-04-28 13:33:30 -07:00
Jesse 273c841655 Merge commit '1bae5dfff612287dccafeca25230970666bb262d' into jesse/feature/merge-redis-6.2.2 2021-04-28 13:33:25 -07:00
Jesse 8501e6a8b7 Merge commit '0c3fe52ef7e3acf135428be81dd8e27b4ef191e5' into jesse/feature/merge-redis-6.2.2 2021-04-28 13:33:20 -07:00
Jesse 2d025ef6b4 Merge commit '1f75ce30dfdb1c8c4df8474f9580f2aff032cfb4' into jesse/feature/merge-redis-6.2.2 2021-04-28 13:25:41 -07:00
Jesse 20516bb99e Merge commit '0c898bdb07e7d5716db7a3b311a1d7586ffbdca0' into jesse/feature/merge-redis-6.2.2 2021-04-28 12:58:02 -07:00
Jesse 3192b03f97 Merge commit '660645c7421fab93b69205ff7208e577ef225f0d' into jesse/feature/merge-redis-6.2.2 2021-04-28 12:56:08 -07:00
Jesse 0956a34430 Merge commit 'af02478ba02da8320d80661ccbf91a5b125b03ab' into jesse/feature/merge-redis-6.2.2 2021-04-28 12:31:45 -07:00
Jesse ac34bfec67 Merge commit '337dcde9fafa6c4bab78f1ec74f8e8abf253c86c' into jesse/feature/merge-redis-6.2.2 2021-04-28 12:31:33 -07:00
Jesse 9d765ecb25 Merge commit '324e22accf457edc996971bc97f5474349cd7c4c' into jesse/feature/merge-redis-6.2.2 2021-04-28 12:31:24 -07:00
Jesse dc1a9f1d66 rename replication 2021-04-28 12:28:40 -07:00
Jesse d12a06dc0a Merge commit 'dfb598cf3304818e608ceb6b5d9529a293345c4a' into jesse/feature/merge-redis-6.2.2 2021-04-28 12:28:33 -07:00
Jesse 1ff51ffdb1 Rename replication 2021-04-28 12:27:27 -07:00
Jesse 1c00c0f0b2 Merge commit '3c0ed0309ac5bae52464ecb45e92056e212f2b7f' into jesse/feature/merge-redis-6.2.2 2021-04-28 12:26:23 -07:00
Jesse 5136c7fe6e Merge commit '5e0fe4c77c556255b738cecb330dc1bae060a3d0' into jesse/feature/merge-redis-6.2.2 2021-04-28 12:13:43 -07:00
Jesse e2c45d7089 Merge commit '173cca54135230ba2a8d180574a56baee67304ea' into jesse/feature/merge-redis-6.2.2 2021-04-28 12:13:29 -07:00
Jesse 7f7e06f416 Merge commit '8beec4f0e78cebce9cd14d72fa4a622538b7c045' into jesse/feature/merge-redis-6.2.2 2021-04-28 12:13:13 -07:00
Jesse ad03da3822 Merge commit '45af2b174270af23a63b9032b2cbbb342d4e3a5f' into jesse/feature/merge-redis-6.2.2 2021-04-28 12:10:30 -07:00
Jesse 07e735b654 Merge commit '1398fac3f1bd190c572a695aa898d71d1573f7e5' into jesse/feature/merge-redis-6.2.2 2021-04-28 12:08:01 -07:00
Jesse 999c7b8754 Merge commit '8b33975944397a0522f6d05d0776d9871a7c6be0' into jesse/feature/merge-redis-6.2.2 2021-04-28 12:05:33 -07:00
Jesse c5ed5cb0c0 Merge commit 'dfb12f06283f22c157d99830de21700a7f86c139' into jesse/feature/merge-redis-6.2.2 2021-04-28 11:56:34 -07:00
Jesse 9f5f6f8f99 Rename server 2021-04-28 11:52:36 -07:00
Jesse 4c36328104 Gitignore 2021-04-28 11:02:43 -07:00
Jesse 7171e6ccea Fix unsafe_robjcast in t_stream 2021-04-28 09:09:17 -07:00
Jesse 2a59b09ebe Merge tag '6.0.12' into jesse/feature/merge-redis-6.2.2 2021-04-27 16:33:34 -07:00
Jesse 9e16ce8253 Put in major hack to get linker to work 2021-04-27 16:24:26 -07:00
Jesse f22266c44e Fix tricky merge conflict & some compiler errors 2021-04-27 08:24:33 -07:00
Jesse 75cbe288ef Merge tag '6.0.11' into unstable 2021-04-26 15:44:08 -07:00
Jesse 70e593c589 Add a couple things to gitignore 2021-04-26 08:47:22 -07:00
Oran Agra f86385f70b Redis 6.0.12 2021-03-02 08:13:08 +02:00
Yossi Gottlieb d0762100b0 Fix failed tests on Linux Alpine and add a CI job. (#8532)
* Remove linux/version.h dependency.

This introduces unnecessary dependencies, and generally not a good idea
as the platform we build on may be different than the platform we run
on.

To determine if sync_file_range exists we can simply rely on header file
hints.

* Fix setproctitle() on libmusl.

The previous ifdef checks were a bit too strict for no apparent
reason.

* Fix tests failure on Linux with no backtrace.

* Add alpine daily CI job.

(cherry picked from commit 95ea74549c)
2021-03-02 08:13:08 +02:00
sundb 40ec7a2796 Fix timing error oom-score-adj test (#8513)
fixes timing issue, fork didn't always get to set the oom score before the test verified it.

(cherry picked from commit 46346e9e3a)
2021-03-02 08:13:08 +02:00
Yossi Gottlieb 10b240fd31 Fix compile errors with no HAVE_MALLOC_SIZE. (#8533)
Also adds a new daily CI test, relying on the fact that we don't use malloc_size() on alpine libmusl.

Fixes #8531

(cherry picked from commit dd885780d6)
2021-03-02 08:13:08 +02:00
Oran Agra 91ffe99e03 Redis 6.0.11 2021-02-23 01:35:37 +02:00
Yossi Gottlieb c992857618 Fix integer overflow (CVE-2021-21309). (#8522)
On 32-bit systems, setting the proto-max-bulk-len config parameter to a high value may result with integer overflow and a subsequent heap overflow when parsing an input bulk (CVE-2021-21309).

This fix has two parts:

Set a reasonable limit to the config parameter.
Add additional checks to prevent the problem in other potential but unknown code paths.

(cherry picked from commit d32f2e9999)
2021-02-23 01:35:37 +02:00
Oran Agra 4bba84f096 Update CI on Ubuntu to tcl8.6 (since 20.04 is now used) (#8460)
Github started shifting some repositoreis to use ubuntu 20.04 by default
tcl8.5 is missing in these, but 8.6 exists in both 20.04 and 18.04

(cherry picked from commit 018f7b7378)
2021-02-23 01:35:37 +02:00
Viktor Söderqvist 17c3ac89e7 RM_ZsetRem: Delete key if empty (#8453)
Without this fix, RM_ZsetRem can leave empty sorted sets which are
not allowed to exist.

Removing from a sorted set while iterating seems to work (while
inserting causes failed assetions). RM_ZsetRangeEndReached is
modified to return 1 if the key doesn't exist, to terminate
iteration when the last element has been removed.

(cherry picked from commit aea6e71ef8)
2021-02-23 01:35:37 +02:00
Greg Femec cde69883a1 Fix random element selection for large hash tables. (#8133)
When a database on a 64 bit build grows past 2^31 keys, the underlying hash table expands to 2^32 buckets. After this point, the algorithms for selecting random elements only return elements from half of the available buckets because they use random() which has a range of 0 to 2^31 - 1. This causes problems for eviction policies which use dictGetSomeKeys or dictGetRandomKey. Over time they cause the hash table to become unbalanced because, while new keys are spread out evenly across all buckets, evictions come from only half of the available buckets. Eventually this half of the table starts to run out of keys and it takes longer and longer to find candidates for eviction. This continues until no more evictions can happen.

This solution addresses this by using a 64 bit PRNG instead of libc random().

Co-authored-by: Greg Femec <gfemec@google.com>
(cherry picked from commit 266949c7fc)
2021-02-23 01:35:37 +02:00
Huang Zw e6a94aa569 Client tracking tracking-redir-broken push len is 2 not 3 (#8456)
When redis responds with tracking-redir-broken push message (RESP3),
it was responding with a broken protocol: an array of 3 elements, but only
pushes 2 elements.

(cherry picked from commit f687ac0c32)
2021-02-23 01:35:37 +02:00
filipe oliveira 840b393c06 redis-benchmark: Fix broken protocol when used with -a or --dbnum (#8486)
Fix the pointers to the slot hash tags in the case of prefixed commands usage
i.e. AUTH / SELECT

It adjusts the pointers to the slot hash tags in the case of prefixed commands
usage as soon as we get the 1st reply (same like we already did for the random
strings within the command )

(cherry picked from commit efccd6353b)
2021-02-23 01:35:37 +02:00
zhaozhao.zz 56ef0aa7c8 XINFO should use lookupKeyReadOrReply (#8436)
This bug would have let users observe logically expired keys on replicas and
during CLIENT PAUSE WRITE.

(cherry picked from commit f2a5fe3678)
2021-02-23 01:35:37 +02:00
Yossi Gottlieb dcf409f8e7 Avoid assertions when testing arm64 cow bug. (#8405)
At least in one case the arm64 cow kernel bug test triggers an assert, which is a problem because it cannot be ignored like cases where the bug is found.

On older systems (Linux <4.5) madvise fails because MADV_FREE is not supported. We treat these failures as an indication the system is not affected.

Fixes #8351, #8406

(cherry picked from commit 3a5049042a)
2021-02-23 01:35:37 +02:00
Yossi Gottlieb 1237cce65d CONFIG REWRITE should honor umask settings. (#8371)
Fixes a regression introduced due to a new (safer) way of rewriting configuration files. In the past the file was simply overwritten (same inode), but now Redis creates a new temporary file and later renames it over the old one.

The temp file typically gets created with 0600 permissions so we later fchmod it to fix that. Unlike open with O_CREAT, fchmod doesn't consider umask so we have to do that explicitly.

Fixes #8369

(cherry picked from commit b548ffabbe)
2021-02-23 01:35:37 +02:00
guybe7 d182820fa7 Fix firstkey,lastkey,step in COMMAND command for some commands (#8367)
The output for COMMAND command was wrong for some commands.
clients can use firstkey,lastkey,step to find (some) key name arguments, and the
"movablekeys" flag to know that they can't know all (or any) of the key name arguments.

These commands had the wrong output:
1. GEORADIUS*_RO used to have "movablekeys" (which it doesn't really need)
2. XREAD and XREADGROUP used to have (1,1,1). but that's completely wrong.
3. Z*STORE used to have (0,0,0) but it can at lest give the index of the dstkey (1,1,1)

(cherry picked from commit baf92f3f1c)
2021-02-23 01:35:37 +02:00
Madelyn Olson 0c65342889 Remove race condition and consistency issues with client pause and threaded IO (#8520)
clientsArePaused isn't thread safe because it has a side effect of attempting to unpause,
which may cause multiple threads concurrently updating the unblocked_clients global list.
This change resolves this issue by no longer postponing client for threaded reads when
clients are paused and then skipping the check for client paused for threaded reads,
in case one is postponed and then clients are paused. (I don't think this is strictly possible,
but being defensive seems better here)
2021-02-22 23:05:00 +02:00
antirez e8d0057710 ACL LOG: implement ACL LOG subcommadn skeleton. 2020-01-28 17:30:50 +01:00
antirez 3e9e27e98f ACL LOG: data structures and initial functions. 2020-01-27 18:37:52 +01:00
qetu3790 6f2240aefd Merge pull request #1 from qetu3790/qetu3790-patch-1
Fix not used constant in lru_test_mode.
2020-01-23 17:30:35 +08:00
qetu3790 bd60c11bd8 Fix not used constant in lru_test_mode.
LRU_CYCLE_PERIOD is defined,but not used.
2020-01-23 17:18:07 +08:00
srzhao 38f6207f88 Check OOM at script start to get stable lua OOM state.
Checking OOM by `getMaxMemoryState` inside script might get different result
with `freeMemoryIfNeededAndSafe` at script start, because lua stack and
arguments also consume memory.

This leads to memory `borderline` when memory grows near server.maxmemory:

- `freeMemoryIfNeededAndSafe` at script start detects no OOM, no memory freed
- `getMaxMemoryState` inside script detects OOM, script aborted

We solve this 'borderline' issue by saving OOM state at script start to get
stable lua OOM state.

related to issue #6565 and #5250.
2020-01-20 21:34:05 +08:00
srzhao dd05b7f67f fix impl of aof-child whitelist SIGUSR1 feature. 2020-01-17 11:50:51 +08:00
hwware 67ee87522a format fix 2020-01-16 17:35:26 -05:00
hwware 3f6d00d387 fix potentical memory leaks 2020-01-16 17:33:23 -05:00
antirez 7ef2270ee7 Change error message for #6775. 2020-01-15 17:55:24 +01:00
Salvatore Sanfilippo 456bbc02c8 Merge pull request #6775 from SqREL/make-error-of-invalid-command-withing-context-explicit
Make error when submitting command in incorrect context more explicit
2020-01-15 17:53:51 +01:00
Ponnuvel Palaniyappan 1d4ea00d12 Fix a potential overflow with strncpy 2020-01-14 08:10:39 +00:00
Ponnuvel Palaniyappan abf8150b2e Fix typos in README.md 2020-01-14 07:38:57 +00:00
antirez 2d7dc71b6f Document I/O threads in redis.conf. 2020-01-13 19:10:42 +01:00
antirez 7d5fb5df3f Setting N I/O threads should mean N-1 additional + 1 main thread. 2020-01-13 18:53:36 +01:00
antirez 28d146bed6 Simplify #6379 changes. 2020-01-13 13:25:37 +01:00
Salvatore Sanfilippo 9506c860f6 Merge pull request #6739 from trevor211/fixMemoryLeak
Fix potential memory leak of rioWriteBulkStreamID().
2020-01-13 13:23:49 +01:00
antirez baa88a1c14 Jump to right label on AOF parsing error.
Related to #6054.
2020-01-13 13:16:15 +01:00
antirez d28948b143 Port PR #6110 to new connection object code. 2020-01-13 12:54:39 +01:00
antirez a8c912ead6 A few comments about main thread serving I/O as well.
Related to #6110.
2020-01-13 12:50:26 +01:00
Salvatore Sanfilippo 24896427fc Merge pull request #6110 from soloestoy/enhance-io-threaded
Enhance IO Threaded: use main thread to handle read/write work
2020-01-13 12:46:40 +01:00
Vasyl Melnychuk b5f52bf01c Make error when submitting command in incorrect context more explicit
So error message `ERR only (P)SUBSCRIBE / (P)UNSUBSCRIBE / PING / QUIT allowed in this context` will become
`ERR 'get' command submitted, but only (P)SUBSCRIBE / (P)UNSUBSCRIBE / PING / QUIT allowed in this context`
2020-01-10 23:34:15 +02:00
antirez 8105f91a02 Merge branch 'unstable' of github.com:/antirez/redis into unstable 2020-01-10 13:15:36 +01:00
Salvatore Sanfilippo b8b8dd5c15 Merge pull request #6114 from ShooterIT/async-rename-rdb
Rename rdb when replica finish receiving rdb asynchronously
2020-01-10 13:06:39 +01:00
antirez 9466dae4e5 Free fakeclient argv on AOF error.
We exit later, so no bug fixed, but it is more correct.

See #6054, thanks to @ShooterIT for finding the issue.
2020-01-10 13:02:45 +01:00
antirez 5234bff579 Git ignore: ignore more files. 2020-01-10 12:22:16 +01:00
Salvatore Sanfilippo 51a01ca8a6 Merge pull request #6746 from leomurillo/unstable
Fix bug on KEYS command where pattern starts with * followed by \x00
2020-01-10 12:18:19 +01:00
Salvatore Sanfilippo b8d315ff76 Merge pull request #6457 from IAmATeaPot418/patch-1
Update to directive in redis.conf (missing s)
2020-01-10 12:16:13 +01:00
Salvatore Sanfilippo bb93686754 Merge pull request #6703 from guybe7/blocking_xread_empty_reply
Blocking XREAD[GROUP] should always reply with valid data (or timeout)
2020-01-09 17:32:14 +01:00
Salvatore Sanfilippo 64ef0ad71a Merge pull request #6724 from JohnSully/incremental
Add support for incremental build with header files
2020-01-09 17:10:02 +01:00
Salvatore Sanfilippo 0f3c353dd3 Merge pull request #6715 from trevor211/fixPotentialClusterLinkError
Fix petential cluster link error.
2020-01-09 17:05:54 +01:00
Salvatore Sanfilippo f616ecf361 Merge pull request #6698 from yossigo/ctx-flags-multi-dirty
Add REDISMODULE_CTX_FLAGS_MULTI_DIRTY.
2020-01-08 13:09:48 +01:00
Salvatore Sanfilippo 2ee4f9f34e Merge pull request #6748 from hwware/typofix
typo fix in acl.c
2020-01-08 13:06:06 +01:00
Salvatore Sanfilippo c89ec5af1e Merge pull request #6735 from itamarhaber/io-threads
Adjusts 'io_threads_num' max in config.c
2020-01-08 12:50:13 +01:00
Salvatore Sanfilippo 0e38c5f39c Merge pull request #6743 from yz1509/unstable
Sentinel: avoid sentinel changes promoted_slave to be its own replica.
2020-01-08 12:30:49 +01:00
antirez 7080a28efc XCLAIM: Create the consumer only on successful claims.
Fixes #6744.
2020-01-08 10:10:11 +01:00
hwware fda2bf9c92 typo fix in acl.c 2020-01-07 21:09:44 -05:00
Leo Murillo 63e46e5f8d Fix bug on KEYS command where pattern starts with * followed by \x00 (null char). 2020-01-07 13:55:26 -06:00
WuYunlong d6a13f4440 Free allocated sds in pfdebugCommand() to avoid memory leak. 2020-01-07 11:17:52 +08:00
yz1509 18c2676084 avoid sentinel changes promoted_slave to be its own replica. 2020-01-07 10:29:54 +08:00
WuYunlong 9387f7333e Fix potential memory leak of clusterLoadConfig(). 2020-01-07 10:28:36 +08:00
WuYunlong 2f8134a7ff Fix potential memory leak of rioWriteBulkStreamID(). 2020-01-06 19:58:13 +08:00
Itamar Haber 408e8e9f44 Adjusts 'io_threads_num' max to 128
Instead of 512, use the defined max from networking.c
2020-01-04 18:33:24 +02:00
antirez 0af467d18f Fix active expire division by zero.
Likely fix #6723.

This is what happens AFAIK: we enter the main loop where we expire stuff
until a given percentage of keys is still found to be logically expired.
There are however other potential exit conditions.

However the "sampled" variable is not always incremented inside the
loop, because we may found no valid slot as we scan the hash table, but
just NULLs ad dict entries. So when the do/while loop condition is
triggered at the end, we do (expired*100/sampled), dividing by zero if
we sampled 0 keys.
2020-01-01 18:13:13 +01:00
John Sully e5565a793e Add support for incremental build with header files 2020-01-01 10:33:02 -05:00
ShooterIT 2bc8db9ca5 Rename rdb asynchronously 2019-12-31 21:45:32 +08:00
wangyuan21 3848849013 free time event when delete eventloop 2019-12-31 19:57:02 +08:00
WuYunlong 0992ada2fe Fix petential cluster link error.
Funcion adjustOpenFilesLimit() has an implicit parameter, which is server.maxclients.
This function aims to ajust maximum file descriptor number according to server.maxclients
by best effort, which is "bestlimit" could be lower than "maxfiles" but greater than "oldlimit".
When we try to increase "maxclients" using CONFIG SET command, we could increase maximum
file descriptor number to a bigger value without calling aeResizeSetSize the same time.
When later more and more clients connect to server, the allocated fd could be bigger and bigger,
and eventually exceeds events size of aeEventLoop.events. When new nodes joins the cluster,
new link is created, together with new fd, but when calling aeCreateFileEvent, we did not
check the return value. In this case, we have a non-null "link" but the associated fd is not
registered.

So when we dynamically set "maxclients" we could reach an inconsistency between maximum file
descriptor number of the process and server.maxclients. And later could cause cluster link and link
fd inconsistency.

While setting "maxclients" dynamically, we consider it as failed when resulting "maxclients" is not
the same as expected. We try to restore back the maximum file descriptor number when we failed to set
"maxclients" to the specified value, so that server.maxclients could act as a guard as before.
2019-12-31 18:16:30 +08:00
hayashier a3b0d8631f fix typo from fss to rss 2019-12-31 17:46:48 +09:00
Guy Benoish d7d13721d3 Modules: Fix blocked-client-related memory leak
If a blocked module client times-out (or disconnects, unblocked
by CLIENT command, etc.) we need to call moduleUnblockClient
in order to free memory allocated by the module sub-system
and blocked-client private data

Other changes:
Made blockedonkeys.tcl tests a bit more aggressive in order
to smoke-out potential memory leaks
2019-12-30 10:10:59 +05:30
Guy Benoish a351e74fe9 Blocking XREAD[GROUP] should always reply with valid data (or timeout)
This commit solves the following bug:
127.0.0.1:6379> XGROUP CREATE x grp $ MKSTREAM
OK
127.0.0.1:6379> XADD x 666 f v
"666-0"
127.0.0.1:6379> XREADGROUP GROUP grp Alice BLOCK 0 STREAMS x >
1) 1) "x"
   2) 1) 1) "666-0"
         2) 1) "f"
            2) "v"
127.0.0.1:6379> XADD x 667 f v
"667-0"
127.0.0.1:6379> XDEL x 667
(integer) 1
127.0.0.1:6379> XREADGROUP GROUP grp Alice BLOCK 0 STREAMS x >
1) 1) "x"
   2) (empty array)

The root cause is that we use s->last_id in streamCompareID
while we should use the last *valid* ID
2019-12-30 10:06:01 +05:30
antirez 6e4f70b817 Fix duplicated CLIENT SETNAME reply.
Happened when we set the name to "" to cancel the name.
Was introduced during the RESP3 refactoring.

See #6036.
2019-12-29 15:44:59 +01:00
antirez faea46710c Merge branch 'unstable' of github.com:/antirez/redis into unstable 2019-12-29 15:42:08 +01:00
antirez 5521910de7 Inline protocol: handle empty strings well.
This bug is from the first version of Redis. Probably the problem here
is that before we used an SDS split function that created empty strings
for additional spaces, like in "SET    foo          bar".
AFAIK later we replaced it with the curretn sdssplitarg() API that has
no such a problem. As a result, we introduced a bug, where it is no
longer possible to do something like:

    SET foo ""

Using the inline protocol. Now it is fixed.
2019-12-29 15:40:40 +01:00
Salvatore Sanfilippo 3ff95d9074 Merge pull request #6706 from guybe7/stream_id_edge_cases
Stream: Handle streamID-related edge cases
2019-12-29 14:53:06 +01:00
Salvatore Sanfilippo 1bae5dfff6 Merge pull request #6707 from oranagra/fix_config_limits
config.c adjust config limits and mutable
2019-12-29 14:51:40 +01:00
Oran Agra 0c3fe52ef7 config.c adjust config limits and mutable
- make lua-replicate-commands mutable (it never was, but i don't see why)
- make tcp-backlog immutable (fix a recent refactory mistake)
- increase the max limit of a few configs to match what they were before
the recent refactory
2019-12-26 15:16:15 +02:00
Guy Benoish 1f75ce30df Stream: Handle streamID-related edge cases
This commit solves several edge cases that are related to
exhausting the streamID limits: We should correctly calculate
the succeeding streamID instead of blindly incrementing 'seq'
This affects both XREAD and XADD.

Other (unrelated) changes:
Reply with a better error message when trying to add an entry
to a stream that has exhausted last_id
2019-12-26 15:31:37 +05:30
Yossi Gottlieb 0c898bdb07 Add REDISMODULE_CTX_FLAGS_MULTI_DIRTY. 2019-12-23 19:43:51 +02:00
Oran Agra 660645c742 modules don't signalModifiedKey in setKey() since that's done (optionally) in RM_CloseKey 2019-12-23 10:15:52 +02:00
Khem Raj af02478ba0 Mark extern definition of SDS_NOINIT in sds.h
This helps in avoiding multiple definition of this variable, its also
defined globally in sds.c

Signed-off-by: Khem Raj <raj.khem@gmail.com>
2019-12-21 11:47:31 -08:00
bodong.ybd 337dcde9fa Fix spop return nil #4709 2019-12-21 21:27:38 +08:00
antirez 324e22accf Fix ip and missing mode in RM_GetClusterNodeInfo(). 2019-12-20 12:29:02 +01:00
Johannes Truschnigg dfb598cf33 Signal systemd readiness atfer Partial Resync
"Partial Resynchronization" is a special variant of replication success
that we have to tell systemd about if it is managing redis-server via a
Type=Notify service unit.
2019-12-19 21:47:24 +01:00
zhaozhao.zz 3c0ed0309a lazyfree: add a new configuration lazyfree-lazy-user-del
Delete keys in async way when executing DEL command, if
lazyfree-lazy-user-del is yes.
2019-12-18 16:54:49 +08:00
Guy Benoish 5e0fe4c77c streamReplyWithRangeFromConsumerPEL: Redundant streamDecodeID 2019-12-18 12:27:37 +05:30
Oran Agra 173cca5413 fix possible warning on incomplete struct init 2019-12-10 11:16:13 +02:00
Guy Benoish 8beec4f0e7 Make sure Redis does not reply with negative zero 2019-11-05 19:23:37 +05:30
Jamie Scott 45af2b1742 Update to directive in redis.conf (missing s)
The directive tls-prefer-server-cipher is actually tls-prefer-server-ciphers in config.c. This results in a failed directive call shown below. This pull request adds the "s" in ciphers so that the directive is able to be properly called in config.c

ubuntu@ip-172-31-16-31:~/redis$ src/redis-server ./redis.conf 

*** FATAL CONFIG FILE ERROR ***
Reading the configuration file, at line 200
>>> 'tls-prefer-server-cipher yes'
Bad directive or wrong number of arguments
2019-10-16 13:31:19 -07:00
zhaozhao.zz 1398fac3f1 Threaded IO: use main thread to handle read work 2019-05-21 11:42:10 +08:00
zhaozhao.zz 8b33975944 Threaded IO: use main thread to handle write work 2019-05-21 11:37:13 +08:00
伯成 dfb12f0628 Boost up performance for redis PUB-SUB patterns matching
If lots of clients PSUBSCRIBE to same patterns, multiple pattens matching will take place. This commit change it into just one single pattern matching by using a `dict *` to store the unique pattern and which clients subscribe to it.
2018-03-01 11:46:56 +08:00
39 changed files with 739 additions and 91 deletions

No files matched your search

+2 -2
View File
@@ -17,7 +17,7 @@ jobs:
run: ./utils/gen-test-certs.sh
- name: test-tls
run: |
sudo apt-get -y install tcl tcl-tls
sudo apt-get -y install tcl8.6 tcl-tls
./runtest --clients 2 --verbose --tls
- name: cluster-test
run: |
@@ -28,7 +28,7 @@ jobs:
- name: module tests
run: |
./runtest-moduleapi
build-ubuntu-old:
runs-on: ubuntu-16.04
steps:
+46 -5
View File
@@ -22,7 +22,7 @@ jobs:
make
- name: test
run: |
sudo apt-get install tcl8.5
sudo apt-get install tcl8.6
./runtest --accurate --verbose
- name: module api test
run: ./runtest-moduleapi --verbose
@@ -43,7 +43,7 @@ jobs:
make MALLOC=libc
- name: test
run: |
sudo apt-get install tcl8.5
sudo apt-get install tcl8.6
./runtest --accurate --verbose
- name: module api test
run: ./runtest-moduleapi --verbose
@@ -64,7 +64,7 @@ jobs:
make BUILD_TLS=yes -j2
- name: "test (tls)"
run: |
sudo apt-get install tcl8.5 tcl-tls
sudo apt-get install tcl8.6 tcl-tls
./utils/gen-test-certs.sh
./runtest --accurate --verbose --tls
- name: test
@@ -82,7 +82,7 @@ jobs:
make -j4
- name: test
run: |
sudo apt-get -y install tcl8.5
sudo apt-get -y install tcl8.6
./runtest --clients 2 --verbose
- name: module tests
run: |
@@ -101,7 +101,7 @@ jobs:
- name: test
run: |
sudo apt-get update
sudo apt-get install tcl8.5 valgrind -y
sudo apt-get install tcl8.6 valgrind -y
./runtest --valgrind --verbose --clients 1
- name: module api test
run: ./runtest-moduleapi --valgrind --verbose --clients 1
@@ -178,3 +178,44 @@ jobs:
- name: cluster tests
run: ./runtest-cluster
test-alpine-jemalloc:
runs-on: ubuntu-latest
if: github.repository == 'redis/redis'
container: alpine:latest
steps:
- uses: actions/checkout@v2
- name: make
run: |
apk add build-base
make REDIS_CFLAGS='-Werror'
- name: test
run: |
apk add tcl procps
./runtest --accurate --verbose
- name: module api test
run: ./runtest-moduleapi --verbose
- name: sentinel tests
run: ./runtest-sentinel
- name: cluster tests
run: ./runtest-cluster
test-alpine-libc-malloc:
runs-on: ubuntu-latest
if: github.repository == 'redis/redis'
container: alpine:latest
steps:
- uses: actions/checkout@v2
- name: make
run: |
apk add build-base
make REDIS_CFLAGS='-Werror' USE_JEMALLOC=no
- name: test
run: |
apk add tcl procps
./runtest --accurate --verbose
- name: module api test
run: ./runtest-moduleapi --verbose
- name: sentinel tests
run: ./runtest-sentinel
- name: cluster tests
run: ./runtest-cluster
+8
View File
@@ -1,3 +1,11 @@
this.sh
next.sh
commits_to_merge.remaining
commits_to_merge.total
make.sh
to_merge
Session.vim
tags
.*.swp
core
*.o
+37
View File
@@ -11,6 +11,43 @@ CRITICAL: There is a critical bug affecting MOST USERS. Upgrade ASAP.
SECURITY: There are security fixes in the release.
--------------------------------------------------------------------------------
================================================================================
Redis 6.0.12 Released Mon Mar 1 17:29:52 IST 2021
================================================================================
Upgrade urgency: LOW, fixes a compilation issue.
Bug fixes:
* Fix compilation error on non-glibc systems if jemalloc is not used (#8533)
================================================================================
Redis 6.0.11 Released Mon Feb 22 16:13:23 IST 2021
================================================================================
Upgrade urgency: SECURITY if you use 32bit build of redis (see bellow), LOW
otherwise.
Integer overflow on 32-bit systems (CVE-2021-21309):
Redis 4.0 or newer uses a configurable limit for the maximum supported bulk
input size. By default, it is 512MB which is a safe value for all platforms.
If the limit is significantly increased, receiving a large request from a client
may trigger several integer overflow scenarios, which would result with buffer
overflow and heap corruption.
Bug fixes:
* Avoid 32-bit overflows when proto-max-bulk-len is set high (#8522)
* Fix handling of threaded IO and CLIENT PAUSE (failover), could lead to data loss or a crash (#8520)
* Fix the selection of a random element from large hash tables (#8133)
* Fix broken protocol in client tracking tracking-redir-broken message (#8456)
* XINFO able to access expired keys on a replica (#8436)
* Fix broken protocol in redis-benchmark when used with -a or --dbnum (#8486)
* Avoid assertions (on older kernels) when testing arm64 CoW bug (#8405)
* CONFIG REWRITE should honor umask settings (#8371)
* Fix firstkey,lastkey,step in COMMAND command for some commands (#8367)
Modules:
* RM_ZsetRem: Delete key if empty, the bug could leave empty zset keys (#8453)
================================================================================
Redis 6.0.10 Released Tue Jan 12 16:20:20 IST 2021
================================================================================
+4 -1
View File
@@ -780,7 +780,9 @@ replica-priority 100
# or SORT with STORE option may delete existing keys. The SET command
# itself removes any old content of the specified key in order to replace
# it with the specified string.
# 4) During replication, when a replica performs a full resynchronization with
# 4) The DEL command itself, and normally it's not easy to replace DEL with
# UNLINK in user's codes.
# 5) During replication, when a replica performs a full resynchronization with
# its master, the content of the whole database is removed in order to
# load the RDB file just transferred.
#
@@ -792,6 +794,7 @@ replica-priority 100
lazyfree-lazy-eviction no
lazyfree-lazy-expire no
lazyfree-lazy-server-del no
lazyfree-lazy-user-del no
replica-lazy-flush no
############################## APPEND ONLY MODE ###############################
@@ -794,6 +794,52 @@ lazyfree-lazy-expire no
lazyfree-lazy-server-del no
replica-lazy-flush no
################################ THREADED I/O #################################
# Redis is mostly single threaded, however there are certain threaded
# operations such as UNLINK, slow I/O accesses and other things that are
# performed on side threads.
#
# Now it is also possible to handle Redis clients socket reads and writes
# in different I/O threads. Since especially writing is so slow, normally
# Redis users use pipelining in order to speedup the Redis performances per
# core, and spawn multiple instances in order to scale more. Using I/O
# threads it is possible to easily speedup two times Redis without resorting
# to pipelining nor sharding of the instance.
#
# By default threading is disabled, we suggest enabling it only in machines
# that have at least 4 or more cores, leaving at least one spare core.
# Using more than 8 threads is unlikely to help much. We also recommend using
# threaded I/O only if you actually have performance problems, with Redis
# instances being able to use a quite big percentage of CPU time, otherwise
# there is no point in using this feature.
#
# So for instance if you have a four cores boxes, try to use 2 or 3 I/O
# threads, if you have a 8 cores, try to use 6 threads. In order to
# enable I/O threads use the following configuration directive:
#
# io-threads 4
#
# Setting io-threads to 1 will just use the main thread as usually.
# When I/O threads are enabled, we only use threads for writes, that is
# to thread the write(2) syscall and transfer the client buffers to the
# socket. However it is also possible to enable threading of reads and
# protocol parsing using the following configuration directive, by setting
# it to yes:
#
# io-threads-do-reads no
#
# Usually threading reads doesn't help much.
#
# NOTE 1: This configuration directive cannot be changed at runtime via
# CONFIG SET. Aso this feature currently does not work when SSL is
# enabled.
#
# NOTE 2: If you want to test the Redis speedup using redis-benchmark, make
# sure you also run the benchmark itself in threaded mode, using the
# --threads option to match the number of Redis theads, otherwise you'll not
# be able to notice the improvements.
############################## APPEND ONLY MODE ###############################
# By default Redis asynchronously dumps the dataset on disk. This mode is
+1
View File
@@ -30,5 +30,6 @@ $TCLSH tests/test_helper.tcl \
--single unit/moduleapi/moduleloadsave \
--single unit/moduleapi/getkeys \
--single unit/moduleapi/timers \
--single unit/moduleapi/zset \
--config server-threads 3 \
"${@}"
+4 -4
View File
@@ -296,11 +296,11 @@ endif
REDIS_SERVER_NAME=keydb-server$(PROG_SUFFIX)
REDIS_SENTINEL_NAME=keydb-sentinel$(PROG_SUFFIX)
REDIS_SERVER_OBJ=adlist.o quicklist.o ae.o anet.o dict.o server.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o t_nhash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o cluster.o crc16.o endianconv.o slowlog.o scripting.o bio.o rio.o rand.o memtest.o crcspeed.o crc64.o bitops.o sentinel.o notify.o setproctitle.o blocked.o hyperloglog.o latency.o sparkline.o redis-check-rdb.o redis-check-aof.o geo.o lazyfree.o module.o evict.o expire.o geohash.o geohash_helper.o childinfo.o defrag.o siphash.o rax.o t_stream.o listpack.o localtime.o acl.o storage.o rdb-s3.o fastlock.o new.o tracking.o cron.o connection.o tls.o sha256.o motd.o timeout.o setcpuaffinity.o $(ASM_OBJ)
REDIS_SERVER_OBJ=adlist.o quicklist.o ae.o anet.o dict.o server.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o t_nhash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o cluster.o crc16.o endianconv.o slowlog.o scripting.o bio.o rio.o rand.o memtest.o crcspeed.o crc64.o bitops.o sentinel.o notify.o setproctitle.o blocked.o hyperloglog.o latency.o sparkline.o redis-check-rdb.o redis-check-aof.o geo.o lazyfree.o module.o evict.o expire.o geohash.o geohash_helper.o childinfo.o defrag.o siphash.o rax.o t_stream.o listpack.o localtime.o acl.o storage.o rdb-s3.o fastlock.o new.o tracking.o cron.o connection.o tls.o sha256.o motd.o timeout.o setcpuaffinity.o mt19937-64.o $(ASM_OBJ)
REDIS_CLI_NAME=keydb-cli$(PROG_SUFFIX)
REDIS_CLI_OBJ=anet.o adlist.o dict.o redis-cli.o redis-cli-cpphelper.o zmalloc.o release.o anet.o ae.o crcspeed.o crc64.o siphash.o crc16.o storage-lite.o fastlock.o new.o motd.o $(ASM_OBJ)
REDIS_CLI_OBJ=anet.o adlist.o dict.o redis-cli.o redis-cli-cpphelper.o zmalloc.o release.o anet.o ae.o crcspeed.o crc64.o siphash.o crc16.o storage-lite.o fastlock.o new.o motd.o mt19937-64.o $(ASM_OBJ)
REDIS_BENCHMARK_NAME=keydb-benchmark$(PROG_SUFFIX)
REDIS_BENCHMARK_OBJ=ae.o anet.o redis-benchmark.o adlist.o dict.o zmalloc.o siphash.o redis-benchmark.o storage-lite.o fastlock.o new.o $(ASM_OBJ)
REDIS_BENCHMARK_OBJ=ae.o anet.o redis-benchmark.o adlist.o dict.o zmalloc.o siphash.o redis-benchmark.o storage-lite.o fastlock.o new.o mt19937-64.o $(ASM_OBJ)
REDIS_CHECK_RDB_NAME=keydb-check-rdb$(PROG_SUFFIX)
REDIS_CHECK_AOF_NAME=keydb-check-aof$(PROG_SUFFIX)
@@ -376,7 +376,7 @@ $(REDIS_CLI_NAME): $(REDIS_CLI_OBJ)
$(REDIS_BENCHMARK_NAME): $(REDIS_BENCHMARK_OBJ)
$(REDIS_LD) -o $@ $^ ../deps/hiredis/libhiredis.a $(FINAL_LIBS)
dict-benchmark: dict.cpp zmalloc.cpp sds.c siphash.c
dict-benchmark: dict.cpp zmalloc.cpp sds.c siphash.c mt19937-64.c
$(REDIS_CC) $(FINAL_CFLAGS) $^ -D DICT_BENCHMARK_MAIN -o $@ $(FINAL_LIBS)
DEP = $(REDIS_SERVER_OBJ:%.o=%.d) $(REDIS_CLI_OBJ:%.o=%.d) $(REDIS_BENCHMARK_OBJ:%.o=%.d)
-1
View File
@@ -1959,7 +1959,6 @@ void backgroundRewriteDoneHandler(int exitcode, int bysignal) {
* triggering an error condition. */
if (bysignal != SIGUSR1)
g_pserver->aof_lastbgrewrite_status = C_ERR;
serverLog(LL_WARNING,
"Background AOF rewrite terminated by signal %d", bysignal);
}
+10 -1
View File
@@ -105,11 +105,15 @@ void processUnblockedClients(int iel) {
while (listLength(unblocked_clients)) {
ln = listFirst(unblocked_clients);
/* If clients are paused we yield for now, since
* we don't want to process any commands later. */
if (clientsArePaused()) return;
serverAssert(ln != NULL);
c = (client*)ln->value;
listDelNode(unblocked_clients,ln);
AssertCorrectThread(c);
fastlock_lock(&c->lock);
c->flags &= ~CLIENT_UNBLOCKED;
@@ -118,6 +122,11 @@ void processUnblockedClients(int iel) {
* client is not blocked before to proceed, but things may change and
* the code is conceptually more correct this way. */
if (!(c->flags & CLIENT_BLOCKED)) {
/* If we have a queued command, execute it now. */
if (processPendingCommandsAndResetClient(c) == C_ERR) {
continue;
}
/* Then process client if it has more data in it's buffer. */
if (c->querybuf && sdslen(c->querybuf) > 0) {
processInputBuffer(c, CMD_CALL_FULL);
}
+2 -1
View File
@@ -1724,7 +1724,7 @@ int rewriteConfigOverwriteFile(char *configfile, sds content) {
if (fsync(fd))
serverLog(LL_WARNING, "Could not sync tmp config file to disk (%s)", strerror(errno));
else if (fchmod(fd, 0644) == -1)
else if (fchmod(fd, 0644 & ~g_pserver->umask) == -1)
serverLog(LL_WARNING, "Could not chmod config file (%s)", strerror(errno));
else if (rename(tmp_conffile, configfile) == -1)
serverLog(LL_WARNING, "Could not rename tmp config file (%s)", strerror(errno));
@@ -2517,6 +2517,7 @@ standardConfig configs[] = {
createIntConfig("min-replicas-max-lag", "min-slaves-max-lag", MODIFIABLE_CONFIG, 0, INT_MAX, g_pserver->repl_min_slaves_max_lag, 10, INTEGER_CONFIG, NULL, updateGoodSlaves),
createIntConfig("min-clients-per-thread", NULL, MODIFIABLE_CONFIG, 0, 400, cserver.thread_min_client_threshold, 20, INTEGER_CONFIG, NULL, NULL),
createIntConfig("replica-quorum", NULL, MODIFIABLE_CONFIG, -1, INT_MAX, g_pserver->repl_quorum, -1, INTEGER_CONFIG, NULL, NULL),
/* Unsigned int configs */
createUIntConfig("maxclients", NULL, MODIFIABLE_CONFIG, 1, UINT_MAX, g_pserver->maxclients, 10000, INTEGER_CONFIG, NULL, updateMaxclients),
createUIntConfig("loading-process-events-interval-keys", NULL, MODIFIABLE_CONFIG, 0, LONG_MAX, g_pserver->loading_process_events_interval_keys, 8192, MEMORY_CONFIG, NULL, NULL),
+2 -15
View File
@@ -35,7 +35,6 @@
#endif
#ifdef __linux__
#include <linux/version.h>
#include <features.h>
#endif
@@ -99,19 +98,7 @@
/* Define rdb_fsync_range to sync_file_range() on Linux, otherwise we use
* the plain fsync() call. */
#ifdef __linux__
#if defined(__GLIBC__) && defined(__GLIBC_PREREQ)
#if (LINUX_VERSION_CODE >= 0x020611 && __GLIBC_PREREQ(2, 6))
#define HAVE_SYNC_FILE_RANGE 1
#endif
#else
#if (LINUX_VERSION_CODE >= 0x020611)
#define HAVE_SYNC_FILE_RANGE 1
#endif
#endif
#endif
#ifdef HAVE_SYNC_FILE_RANGE
#if (defined(__linux__) && defined(SYNC_FILE_RANGE_WAIT_BEFORE))
#define rdb_fsync_range(fd,off,size) sync_file_range(fd,off,size,SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE)
#else
#define rdb_fsync_range(fd,off,size) fsync(fd)
@@ -128,7 +115,7 @@
#define ESOCKTNOSUPPORT 0
#endif
#if ((defined __linux && defined(__GLIBC__)) || defined __APPLE__)
#if (defined __linux || defined __APPLE__)
#define USE_SETPROCTITLE
#define INIT_SETPROCTITLE_REPLACEMENT
#ifdef __cplusplus
+1
View File
@@ -335,6 +335,7 @@ void genericSetKey(client *c, redisDb *db, robj *key, robj *val, int keepttl, in
dbOverwriteCore(db,de,key,val,!!g_pserver->fActiveReplica,!keepttl);
}
incrRefCount(val);
if (!keepttl) removeExpire(db,key);
if (signal) signalModifiedKey(c,db,key);
}
+12 -7
View File
@@ -779,15 +779,13 @@ dictEntry *dictGetRandomKey(dict *d)
do {
/* We are sure there are no elements in indexes from 0
* to rehashidx-1 */
h = d->rehashidx + (random() % (d->ht[0].size +
d->ht[1].size -
d->rehashidx));
h = d->rehashidx + (randomULong() % (dictSlots(d) - d->rehashidx));
he = (h >= d->ht[0].size) ? d->ht[1].table[h - d->ht[0].size] :
d->ht[0].table[h];
} while(he == NULL);
} else {
do {
h = random() & d->ht[0].sizemask;
h = randomULong() & d->ht[0].sizemask;
he = d->ht[0].table[h];
} while(he == NULL);
}
@@ -853,7 +851,7 @@ unsigned int dictGetSomeKeys(dict *d, dictEntry **des, unsigned int count) {
maxsizemask = d->ht[1].sizemask;
/* Pick a random point inside the larger table. */
unsigned long i = random() & maxsizemask;
unsigned long i = randomULong() & maxsizemask;
unsigned long emptylen = 0; /* Continuous empty entries so far. */
while(stored < count && maxsteps--) {
for (j = 0; j < tables; j++) {
@@ -878,7 +876,7 @@ unsigned int dictGetSomeKeys(dict *d, dictEntry **des, unsigned int count) {
if (he == NULL) {
emptylen++;
if (emptylen >= 5 && emptylen > count) {
i = random() & maxsizemask;
i = randomULong() & maxsizemask;
emptylen = 0;
}
} else {
@@ -1322,7 +1320,7 @@ int compareCallback(void *privdata, const void *key1, const void *key2) {
void freeCallback(void *privdata, void *val) {
DICT_NOTUSED(privdata);
sdsfree(val);
sdsfree((const char*)val);
}
dictType BenchmarkDictType = {
@@ -1393,6 +1391,13 @@ int main(int argc, char **argv) {
}
end_benchmark("Random access of existing elements");
start_benchmark();
for (j = 0; j < count; j++) {
dictEntry *de = dictGetRandomKey(dict);
assert(de != NULL);
}
end_benchmark("Accessing random keys");
start_benchmark();
for (j = 0; j < count; j++) {
sds key = sdsfromlonglong(rand() % count);
+13
View File
@@ -33,6 +33,7 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
// TODO(Jesse): Redis upstream removed this header, can we?
#include <stdint.h>
#ifdef __cplusplus
@@ -48,6 +49,11 @@ extern "C" {
#ifndef __DICT_H
#define __DICT_H
#include "mt19937-64.h"
#include <limits.h>
#include <stdint.h>
#include <stdlib.h>
#define DICT_OK 0
#define DICT_ERR 1
@@ -185,6 +191,13 @@ typedef void (dictScanBucketFunction)(void *privdata, dictEntry **bucketref);
#define dictSize(d) ((d)->ht[0].used+(d)->ht[1].used)
#define dictIsRehashing(d) ((d)->rehashidx != -1)
/* If our unsigned long type can store a 64 bit number, use a 64 bit PRNG. */
#if ULONG_MAX >= 0xffffffffffffffff
#define randomULong() ((unsigned long) genrand64_int64())
#else
#define randomULong() random()
#endif
/* API */
dict *dictCreate(dictType *type, void *privDataPtr);
int dictExpand(dict *d, unsigned long size);
+1 -1
View File
@@ -842,4 +842,4 @@ void expireEntryFat::popfrontExpireEntry()
serverAssert(res == DICT_OK);
}
m_vecexpireEntries.erase(m_vecexpireEntries.begin());
}
}
+5
View File
@@ -65,4 +65,9 @@
#endif
#define _FILE_OFFSET_BITS 64
#ifdef __linux__
/* features.h uses the defines above to set feature specific defines. */
#include <features.h>
#endif
#endif
+2
View File
@@ -2584,6 +2584,7 @@ int RM_ZsetRem(RedisModuleKey *key, RedisModuleString *ele, int *deleted) {
if (key->value && key->value->type != OBJ_ZSET) return REDISMODULE_ERR;
if (key->value != NULL && zsetDel(key->value,szFromObj(ele))) {
if (deleted) *deleted = 1;
moduleDelKeyIfEmpty(key);
} else {
if (deleted) *deleted = 0;
}
@@ -2628,6 +2629,7 @@ void RM_ZsetRangeStop(RedisModuleKey *key) {
/* Return the "End of range" flag value to signal the end of the iteration. */
int RM_ZsetRangeEndReached(RedisModuleKey *key) {
if (!key->value || key->value->type != OBJ_ZSET) return 1;
return key->zer;
}
+190
View File
@@ -0,0 +1,190 @@
/*
A C-program for MT19937-64 (2004/9/29 version).
Coded by Takuji Nishimura and Makoto Matsumoto.
This is a 64-bit version of Mersenne Twister pseudorandom number
generator.
Before using, initialize the state by using init_genrand64(seed)
or init_by_array64(init_key, key_length).
Copyright (C) 2004, Makoto Matsumoto and Takuji Nishimura,
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The names of its contributors may not be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
References:
T. Nishimura, ``Tables of 64-bit Mersenne Twisters''
ACM Transactions on Modeling and
Computer Simulation 10. (2000) 348--357.
M. Matsumoto and T. Nishimura,
``Mersenne Twister: a 623-dimensionally equidistributed
uniform pseudorandom number generator''
ACM Transactions on Modeling and
Computer Simulation 8. (Jan. 1998) 3--30.
Any feedback is very welcome.
http://www.math.hiroshima-u.ac.jp/~m-mat/MT/emt.html
email: m-mat @ math.sci.hiroshima-u.ac.jp (remove spaces)
*/
#include "mt19937-64.h"
#include <stdio.h>
// { @mt19937_copy_paste
#define NN 312
#define MM 156
#define MATRIX_A 0xB5026F5AA96619E9ULL
#define UM 0xFFFFFFFF80000000ULL /* Most significant 33 bits */
#define LM 0x7FFFFFFFULL /* Least significant 31 bits */
/* The array for the state vector */
static unsigned long long mt[NN];
/* mti==NN+1 means mt[NN] is not initialized */
static int mti=NN+1;
/* initializes mt[NN] with a seed */
void init_genrand64(unsigned long long seed)
{
mt[0] = seed;
for (mti=1; mti<NN; mti++)
mt[mti] = (6364136223846793005ULL * (mt[mti-1] ^ (mt[mti-1] >> 62)) + mti);
}
// } @mt19937_copy_paste
/* initialize by an array with array-length */
/* init_key is the array for initializing keys */
/* key_length is its length */
void init_by_array64(unsigned long long init_key[],
unsigned long long key_length)
{
unsigned long long i, j, k;
init_genrand64(19650218ULL);
i=1; j=0;
k = (NN>key_length ? NN : key_length);
for (; k; k--) {
mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 62)) * 3935559000370003845ULL))
+ init_key[j] + j; /* non linear */
i++; j++;
if (i>=NN) { mt[0] = mt[NN-1]; i=1; }
if (j>=key_length) j=0;
}
for (k=NN-1; k; k--) {
mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 62)) * 2862933555777941757ULL))
- i; /* non linear */
i++;
if (i>=NN) { mt[0] = mt[NN-1]; i=1; }
}
mt[0] = 1ULL << 63; /* MSB is 1; assuring non-zero initial array */
}
/* generates a random number on [0, 2^64-1]-interval */
unsigned long long genrand64_int64(void)
{
int i;
unsigned long long x;
static unsigned long long mag01[2]={0ULL, MATRIX_A};
if (mti >= NN) { /* generate NN words at one time */
/* if init_genrand64() has not been called, */
/* a default initial seed is used */
if (mti == NN+1)
init_genrand64(5489ULL);
for (i=0;i<NN-MM;i++) {
x = (mt[i]&UM)|(mt[i+1]&LM);
mt[i] = mt[i+MM] ^ (x>>1) ^ mag01[(int)(x&1ULL)];
}
for (;i<NN-1;i++) {
x = (mt[i]&UM)|(mt[i+1]&LM);
mt[i] = mt[i+(MM-NN)] ^ (x>>1) ^ mag01[(int)(x&1ULL)];
}
x = (mt[NN-1]&UM)|(mt[0]&LM);
mt[NN-1] = mt[MM-1] ^ (x>>1) ^ mag01[(int)(x&1ULL)];
mti = 0;
}
x = mt[mti++];
x ^= (x >> 29) & 0x5555555555555555ULL;
x ^= (x << 17) & 0x71D67FFFEDA60000ULL;
x ^= (x << 37) & 0xFFF7EEE000000000ULL;
x ^= (x >> 43);
return x;
}
/* generates a random number on [0, 2^63-1]-interval */
long long genrand64_int63(void)
{
return (long long)(genrand64_int64() >> 1);
}
/* generates a random number on [0,1]-real-interval */
double genrand64_real1(void)
{
return (genrand64_int64() >> 11) * (1.0/9007199254740991.0);
}
/* generates a random number on [0,1)-real-interval */
double genrand64_real2(void)
{
return (genrand64_int64() >> 11) * (1.0/9007199254740992.0);
}
/* generates a random number on (0,1)-real-interval */
double genrand64_real3(void)
{
return ((genrand64_int64() >> 12) + 0.5) * (1.0/4503599627370496.0);
}
#ifdef MT19937_64_MAIN
int main(void)
{
int i;
unsigned long long init[4]={0x12345ULL, 0x23456ULL, 0x34567ULL, 0x45678ULL}, length=4;
init_by_array64(init, length);
printf("1000 outputs of genrand64_int64()\n");
for (i=0; i<1000; i++) {
printf("%20llu ", genrand64_int64());
if (i%5==4) printf("\n");
}
printf("\n1000 outputs of genrand64_real2()\n");
for (i=0; i<1000; i++) {
printf("%10.8f ", genrand64_real2());
if (i%5==4) printf("\n");
}
return 0;
}
#endif
+87
View File
@@ -0,0 +1,87 @@
/*
A C-program for MT19937-64 (2004/9/29 version).
Coded by Takuji Nishimura and Makoto Matsumoto.
This is a 64-bit version of Mersenne Twister pseudorandom number
generator.
Before using, initialize the state by using init_genrand64(seed)
or init_by_array64(init_key, key_length).
Copyright (C) 2004, Makoto Matsumoto and Takuji Nishimura,
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The names of its contributors may not be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
References:
T. Nishimura, ``Tables of 64-bit Mersenne Twisters''
ACM Transactions on Modeling and
Computer Simulation 10. (2000) 348--357.
M. Matsumoto and T. Nishimura,
``Mersenne Twister: a 623-dimensionally equidistributed
uniform pseudorandom number generator''
ACM Transactions on Modeling and
Computer Simulation 8. (Jan. 1998) 3--30.
Any feedback is very welcome.
http://www.math.hiroshima-u.ac.jp/~m-mat/MT/emt.html
email: m-mat @ math.sci.hiroshima-u.ac.jp (remove spaces)
*/
#ifndef __MT19937_64_H
#define __MT19937_64_H
/* initializes mt[NN] with a seed */
void init_genrand64(unsigned long long seed);
/* initialize by an array with array-length */
/* init_key is the array for initializing keys */
/* key_length is its length */
void init_by_array64(unsigned long long init_key[],
unsigned long long key_length);
/* generates a random number on [0, 2^64-1]-interval */
unsigned long long genrand64_int64(void);
/* generates a random number on [0, 2^63-1]-interval */
long long genrand64_int63(void);
/* generates a random number on [0,1]-real-interval */
double genrand64_real1(void);
/* generates a random number on [0,1)-real-interval */
double genrand64_real2(void);
/* generates a random number on (0,1)-real-interval */
double genrand64_real3(void);
/* generates a random number on (0,1]-real-interval */
double genrand64_real4(void);
#endif
+33 -3
View File
@@ -2300,6 +2300,19 @@ int processCommandAndResetClient(client *c, int flags) {
return deadclient ? C_ERR : C_OK;
}
/* This function will execute any fully parsed commands pending on
* the client. Returns C_ERR if the client is no longer valid after executing
* the command, and C_OK for all other cases. */
int processPendingCommandsAndResetClient(client *c) {
if (c->flags & CLIENT_EXECUTING_COMMAND) {
c->flags &= ~CLIENT_EXECUTING_COMMAND;
if (processCommandAndResetClient(c, c->flags) == C_ERR) {
return C_ERR;
}
}
return C_OK;
}
/* This function is called every time, in the client structure 'c', there is
* more query buffer to process, because we read more data from the socket
* or because a client was blocked and later reactivated, so there could be
@@ -2310,7 +2323,9 @@ void processInputBuffer(client *c, int callFlags) {
/* Keep processing while there is something in the input buffer */
while(c->qb_pos < sdslen(c->querybuf)) {
/* Return if clients are paused. */
if (!(c->flags & CLIENT_SLAVE) && clientsArePaused()) break;
if (!(c->flags & CLIENT_SLAVE) &&
!(c->flags & CLIENT_PENDING_READ) &&
clientsArePaused()) break;
/* Immediately abort if the client is in the middle of something. */
if (c->flags & CLIENT_BLOCKED) break;
@@ -3440,6 +3455,21 @@ void processEventsWhileBlocked(int iel) {
listNode *ln;
listRewind(g_pserver->clients, &li);
// TODO(Jesse): Upstream Redis used the following code here. If tests fail
// it could be this.
//
// @6.2.2-merge
#if 0
int item_id = 0;
while((ln = listNext(&li))) {
client *c = listNodeValue(ln);
c->flags &= ~CLIENT_PENDING_WRITE;
int target_id = item_id % server.io_threads_num;
listAddNodeTail(io_threads_list[target_id],c);
item_id++;
}
#endif
// All client locks must be acquired *after* the global lock is reacquired to prevent deadlocks
// so unlock here, and save them for reacquisition later
while ((ln = listNext(&li)) != nullptr)
@@ -3451,7 +3481,7 @@ void processEventsWhileBlocked(int iel) {
vecclients.push_back(c);
}
}
/* Since we're about to release our lock we need to flush the repl backlog queue */
bool fReplBacklog = g_pserver->repl_batch_offStart >= 0;
if (fReplBacklog) {
@@ -3486,7 +3516,7 @@ void processEventsWhileBlocked(int iel) {
c->lock.lock();
throw;
}
AeLocker locker;
locker.arm(nullptr);
locker.release();
+6 -2
View File
@@ -52,6 +52,7 @@ extern "C" {
#include "storage.h"
#include "atomicvar.h"
#include "crc16_slottable.h"
#include "mt19937-64.h"
#define UNUSED(V) ((void) V)
#define RANDPTR_INITIAL_SIZE 8
@@ -533,6 +534,9 @@ static void readHandler(aeEventLoop *el, int fd, void *privdata, int mask) {
* we need to randomize. */
for (j = 0; j < c->randlen; j++)
c->randptr[j] -= c->prefixlen;
/* Fix the pointers to the slot hash tags */
for (j = 0; j < c->staglen; j++)
c->stagptr[j] -= c->prefixlen;
c->prefixlen = 0;
}
continue;
@@ -1531,8 +1535,8 @@ int main(int argc, const char **argv) {
client c;
storage_init(NULL, 0);
srandom(time(NULL));
srandom(time(NULL) ^ getpid());
init_genrand64(ustime() ^ getpid());
signal(SIGHUP, SIG_IGN);
signal(SIGPIPE, SIG_IGN);
+39
View File
@@ -27,10 +27,13 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "mt19937-64.h"
#include "server.h"
#include "rdb.h"
#include <stdarg.h>
#include <sys/time.h>
#include <unistd.h>
void createSharedObjects(void);
void rdbLoadProgressCallback(rio *r, const void *buf, size_t len);
@@ -348,6 +351,36 @@ err:
return 1;
}
// TODO(Jesse): While merging Redis 6.0.11 I could not for the life of me get
// this code to link correctly. As a stop-gap I copy pasted code from
// @mt19937_copy_paste here. Remove this code and figure out how to get that to
// link!!!!!!
// {
#define JESSE_FIX_ME_IMMEDIATELY 1
#if JESSE_FIX_ME_IMMEDIATELY
#define NN 312
#define MM 156
#define MATRIX_A 0xB5026F5AA96619E9ULL
#define UM 0xFFFFFFFF80000000ULL /* Most significant 33 bits */
#define LM 0x7FFFFFFFULL /* Least significant 31 bits */
/* The array for the state vector */
static unsigned long long mt[NN];
/* mti==NN+1 means mt[NN] is not initialized */
static int mti=NN+1;
/* initializes mt[NN] with a seed */
void init_genrand64(unsigned long long seed)
{
mt[0] = seed;
for (mti=1; mti<NN; mti++)
mt[mti] = (6364136223846793005ULL * (mt[mti-1] ^ (mt[mti-1] >> 62)) + mti);
}
#endif
// }
/* RDB check main: called form server.c when Redis is executed with the
* keydb-check-rdb alias, on during RDB loading errors.
*
@@ -361,10 +394,16 @@ err:
* Otherwise if called with a non NULL fp, the function returns C_OK or
* C_ERR depending on the success or failure. */
int redis_check_rdb_main(int argc, const char **argv, FILE *fp) {
struct timeval tv;
if (argc != 2 && fp == NULL) {
fprintf(stderr, "Usage: %s <rdb-file-name>\n", argv[0]);
exit(1);
}
gettimeofday(&tv, NULL);
init_genrand64( (unsigned long long) ( ((long long) tv.tv_sec * 1000000 + tv.tv_usec) ^ getpid() ));
/* In order to call the loading functions we need to create the shared
* integer objects, however since this function may be called from
* an already initialized Redis instance, check if we really need to. */
+5
View File
@@ -63,6 +63,7 @@
#include "ae.h"
#include "storage.h"
#include "motd.h"
#include "mt19937-64.h"
#include "redis-cli.h"
@@ -6947,6 +6948,7 @@ static sds askPassword() {
int main(int argc, char **argv) {
int firstarg;
struct timeval tv;
storage_init(NULL, 0);
config.hostip = sdsnew("127.0.0.1");
@@ -7033,6 +7035,9 @@ int main(int argc, char **argv) {
}
#endif
gettimeofday(&tv, NULL);
init_genrand64(((long long) tv.tv_sec * 1000000 + tv.tv_usec) ^ getpid());
/* Cluster Manager mode */
if (CLUSTER_MANAGER_MODE()) {
clusterManagerCommandProc *proc = validateClusterManagerCommand();
+4
View File
@@ -105,7 +105,9 @@ sds sdsnewlen(const void *init, ssize_t initlen) {
int hdrlen = sdsHdrSize(type);
unsigned char *fp; /* flags pointer. */
assert(initlen + hdrlen + 1 > initlen); /* Catch size_t overflow */
sh = s_malloc(hdrlen+initlen+1, MALLOC_SHARED);
if (sh == NULL) return NULL;
if (init==SDS_NOINIT)
init = NULL;
@@ -246,6 +248,7 @@ sds sdsMakeRoomFor(sds s, size_t addlen) {
len = sdslen(s);
sh = (char*)s-sdsHdrSize(oldtype);
newlen = (len+addlen);
assert(newlen > len); /* Catch size_t overflow */
if (newlen < SDS_MAX_PREALLOC)
newlen *= 2;
else
@@ -259,6 +262,7 @@ sds sdsMakeRoomFor(sds s, size_t addlen) {
if (type == SDS_TYPE_5) type = SDS_TYPE_8;
hdrlen = sdsHdrSize(type);
assert(hdrlen + newlen + 1 > len); /* Catch size_t overflow */
if (oldtype==type && (len+1024) >= avail) {
// note: if we have a lot of free space don't use this as we don't want s_realloc copying
// uninitialized data
+82 -39
View File
@@ -37,6 +37,7 @@
#include "storage.h"
#include "cron.h"
#include <thread>
#include "mt19937-64.h"
#include <time.h>
#include <signal.h>
#include <sys/wait.h>
@@ -457,11 +458,11 @@ struct redisCommand redisCommandTable[] = {
{"zunionstore",zunionstoreCommand,-4,
"write use-memory @sortedset",
0,zunionInterGetKeys,0,0,0,0,0,0},
0,zunionInterGetKeys,1,1,1,0,0,0},
{"zinterstore",zinterstoreCommand,-4,
"write use-memory @sortedset",
0,zunionInterGetKeys,0,0,0,0,0,0},
0,zunionInterGetKeys,1,1,1,0,0,0},
{"zrange",zrangeCommand,-4,
"read-only @sortedset",
@@ -933,7 +934,7 @@ struct redisCommand redisCommandTable[] = {
{"georadius_ro",georadiusroCommand,-6,
"read-only @geo",
0,georadiusGetKeys,1,1,1,0,0,0},
0,NULL,1,1,1,0,0,0},
{"georadiusbymember",georadiusbymemberCommand,-5,
"write use-memory @geo",
@@ -941,7 +942,7 @@ struct redisCommand redisCommandTable[] = {
{"georadiusbymember_ro",georadiusbymemberroCommand,-5,
"read-only @geo",
0,georadiusGetKeys,1,1,1,0,0,0},
0,NULL,1,1,1,0,0,0},
{"geohash",geohashCommand,-2,
"read-only @geo",
@@ -997,11 +998,11 @@ struct redisCommand redisCommandTable[] = {
{"xread",xreadCommand,-4,
"read-only @stream @blocking",
0,xreadGetKeys,1,1,1,0,0,0},
0,xreadGetKeys,0,0,0,0,0,0},
{"xreadgroup",xreadCommand,-7,
"write @stream @blocking",
0,xreadGetKeys,1,1,1,0,0,0},
0,xreadGetKeys,0,0,0,0,0,0},
{"xgroup",xgroupCommand,-2,
"write use-memory @stream",
@@ -5191,7 +5192,7 @@ static int smapsGetSharedDirty(unsigned long addr) {
FILE *f;
f = fopen("/proc/self/smaps", "r");
serverAssert(f);
if (!f) return -1;
while (1) {
if (!fgets(buf, sizeof(buf), f))
@@ -5202,8 +5203,8 @@ static int smapsGetSharedDirty(unsigned long addr) {
in_mapping = from <= addr && addr < to;
if (in_mapping && !memcmp(buf, "Shared_Dirty:", 13)) {
ret = sscanf(buf, "%*s %d", &val);
serverAssert(ret == 1);
sscanf(buf, "%*s %d", &val);
/* If parsing fails, we remain with val == -1 */
break;
}
}
@@ -5217,23 +5218,33 @@ static int smapsGetSharedDirty(unsigned long addr) {
* kernel is affected.
* The bug was fixed in commit ff1712f953e27f0b0718762ec17d0adb15c9fd0b
* titled: "arm64: pgtable: Ensure dirty bit is preserved across pte_wrprotect()"
* Return 1 if the kernel seems to be affected, and 0 otherwise. */
* Return -1 on unexpected test failure, 1 if the kernel seems to be affected,
* and 0 otherwise. */
int linuxMadvFreeForkBugCheck(void) {
int ret, pipefd[2];
int ret, pipefd[2] = { -1, -1 };
pid_t pid;
char *p, *q, bug_found = 0;
const long map_size = 3 * 4096;
char *p = NULL, *q;
int bug_found = 0;
long page_size = sysconf(_SC_PAGESIZE);
long map_size = 3 * page_size;
/* Create a memory map that's in our full control (not one used by the allocator). */
p = (char*)mmap(NULL, map_size, PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
serverAssert(p != MAP_FAILED);
if (p == MAP_FAILED) {
serverLog(LL_WARNING, "Failed to mmap(): %s", strerror(errno));
return -1;
}
q = p + 4096;
q = p + page_size;
/* Split the memory map in 3 pages by setting their protection as RO|RW|RO to prevent
* Linux from merging this memory map with adjacent VMAs. */
ret = mprotect(q, 4096, PROT_READ | PROT_WRITE);
serverAssert(!ret);
ret = mprotect(q, page_size, PROT_READ | PROT_WRITE);
if (ret < 0) {
serverLog(LL_WARNING, "Failed to mprotect(): %s", strerror(errno));
bug_found = -1;
goto exit;
}
/* Write to the page once to make it resident */
*(volatile char*)q = 0;
@@ -5242,8 +5253,16 @@ int linuxMadvFreeForkBugCheck(void) {
#ifndef MADV_FREE
#define MADV_FREE 8
#endif
ret = madvise(q, 4096, MADV_FREE);
serverAssert(!ret);
ret = madvise(q, page_size, MADV_FREE);
if (ret < 0) {
/* MADV_FREE is not available on older kernels that are presumably
* not affected. */
if (errno == EINVAL) goto exit;
serverLog(LL_WARNING, "Failed to madvise(): %s", strerror(errno));
bug_found = -1;
goto exit;
}
/* Write to the page after being marked for freeing, this is supposed to take
* ownership of that page again. */
@@ -5251,37 +5270,47 @@ int linuxMadvFreeForkBugCheck(void) {
/* Create a pipe for the child to return the info to the parent. */
ret = pipe(pipefd);
serverAssert(!ret);
if (ret < 0) {
serverLog(LL_WARNING, "Failed to create pipe: %s", strerror(errno));
bug_found = -1;
goto exit;
}
/* Fork the process. */
pid = fork();
serverAssert(pid >= 0);
if (!pid) {
/* Child: check if the page is marked as dirty, expecing 4 (kB).
if (pid < 0) {
serverLog(LL_WARNING, "Failed to fork: %s", strerror(errno));
bug_found = -1;
goto exit;
} else if (!pid) {
/* Child: check if the page is marked as dirty, page_size in kb.
* A value of 0 means the kernel is affected by the bug. */
if (!smapsGetSharedDirty((unsigned long)q))
ret = smapsGetSharedDirty((unsigned long) q);
if (!ret)
bug_found = 1;
else if (ret == -1) /* Failed to read */
bug_found = -1;
ret = write(pipefd[1], &bug_found, 1);
serverAssert(ret == 1);
if (write(pipefd[1], &bug_found, sizeof(bug_found)) < 0)
serverLog(LL_WARNING, "Failed to write to parent: %s", strerror(errno));
exit(0);
} else {
/* Read the result from the child. */
ret = read(pipefd[0], &bug_found, 1);
serverAssert(ret == 1);
ret = read(pipefd[0], &bug_found, sizeof(bug_found));
if (ret < 0) {
serverLog(LL_WARNING, "Failed to read from child: %s", strerror(errno));
bug_found = -1;
}
/* Reap the child pid. */
serverAssert(waitpid(pid, NULL, 0) == pid);
waitpid(pid, NULL, 0);
}
exit:
/* Cleanup */
ret = close(pipefd[0]);
serverAssert(!ret);
ret = close(pipefd[1]);
serverAssert(!ret);
ret = munmap(p, map_size);
serverAssert(!ret);
if (pipefd[0] != -1) close(pipefd[0]);
if (pipefd[1] != -1) close(pipefd[1]);
if (p != NULL) munmap(p, map_size);
return bug_found;
}
@@ -5803,9 +5832,16 @@ int main(int argc, char **argv) {
zmalloc_set_oom_handler(redisOutOfMemoryHandler);
srand(time(NULL)^getpid());
gettimeofday(&tv,NULL);
init_genrand64(((unsigned long long) tv.tv_sec * 1000000 + tv.tv_usec) ^ getpid());
crc64_init();
serverAssert(g_pserver->repl_batch_offStart < 0);
/* Store umask value. Because umask(2) only offers a set-and-get API we have
* to reset it and restore it back. We do this early to avoid a potential
* race condition with threads that could be creating files or directories.
*/
umask(g_pserver->umask = umask(0777));
uint8_t hashseed[16];
getRandomHexChars((char*)hashseed,sizeof(hashseed));
dictSetHashFunctionSeed(hashseed);
@@ -5959,10 +5995,17 @@ int main(int argc, char **argv) {
#ifdef __linux__
linuxMemoryWarnings();
#if defined (__arm64__)
if (linuxMadvFreeForkBugCheck()) {
serverLog(LL_WARNING,"WARNING Your kernel has a bug that could lead to data corruption during background save. Please upgrade to the latest stable kernel.");
int ret;
if ((ret = linuxMadvFreeForkBugCheck())) {
if (ret == 1)
serverLog(LL_WARNING,"WARNING Your kernel has a bug that could lead to data corruption during background save. "
"Please upgrade to the latest stable kernel.");
else
serverLog(LL_WARNING, "Failed to test the kernel for a bug that could lead to data corruption during background save. "
"Your system could be affected, please report this error.");
if (!checkIgnoreWarning("ARM64-COW-BUG")) {
serverLog(LL_WARNING,"Redis will now exit to prevent data corruption. Note that it is possible to suppress this warning by setting the following config: ignore-warnings ARM64-COW-BUG");
serverLog(LL_WARNING,"Redis will now exit to prevent data corruption. "
"Note that it is possible to suppress this warning by setting the following config: ignore-warnings ARM64-COW-BUG");
exit(1);
}
}
+2
View File
@@ -1486,6 +1486,7 @@ struct redisServer {
the actual 'hz' field value if dynamic-hz
is enabled. */
std::atomic<int> hz; /* serverCron() calls frequency in hertz */
mode_t umask; /* The umask value of the process on startup */
int in_fork_child; /* indication that this is a fork child */
redisDb *db;
::dict *commands; /* Command table */
@@ -2409,6 +2410,7 @@ size_t freeMemoryGetNotCountedMemory();
int freeMemoryIfNeeded(void);
int freeMemoryIfNeededAndSafe(void);
int processCommand(client *c, int callFlags);
int processPendingCommandsAndResetClient(client *c);
void setupSignalHandlers(void);
struct redisCommand *lookupCommand(sds name);
struct redisCommand *lookupCommandByCString(const char *s);
+1 -1
View File
@@ -232,7 +232,7 @@ void spt_init(int argc, char *argv[]) {
if (!(SPT.arg0 = strdup(argv[0])))
goto syerr;
#if __GLIBC__
#if __linux__
if (!(tmp = strdup(program_invocation_name)))
goto syerr;
+9 -2
View File
@@ -1275,6 +1275,13 @@ void xaddCommand(client *c) {
return;
}
/* Return ASAP if the stream has reached the last possible ID */
if (s->last_id.ms == UINT64_MAX && s->last_id.seq == UINT64_MAX) {
addReplyError(c,"The stream has exhausted the last possible ID, "
"unable to add more items");
return;
}
/* Append using the low level function and return the ID. */
if (streamAppendItem(s,c->argv+field_pos,(c->argc-field_pos)/2,
&id, id_given ? &id : NULL)
@@ -2726,8 +2733,8 @@ NULL
key = c->argv[2];
/* Lookup the key now, this is common for all the subcommands but HELP. */
robj *o = lookupKeyWriteOrReply(c,key,shared.nokeyerr);
if (o == NULL || checkType(c,o,OBJ_STREAM)) return;
robj_roptr o = lookupKeyReadOrReply(c,key,shared.nokeyerr);
if (o == nullptr || checkType(c,o,OBJ_STREAM)) return;
s = (stream*)ptrFromObj(o);
/* Dispatch the different subcommands. */
+1 -1
View File
@@ -220,7 +220,7 @@ void sendTrackingMessage(client *c, char *keyname, size_t keylen, int proto) {
* are unable to send invalidation messages to the redirected
* connection, because the client no longer exist. */
if (c->resp > 2) {
addReplyPushLen(c,3);
addReplyPushLen(c,2);
addReplyBulkCBuffer(c,"tracking-redir-broken",21);
addReplyLongLong(c,c->client_tracking_redirection);
}
-1
View File
@@ -1,4 +1,3 @@
#define KEYDB_REAL_VERSION "255.255.255"
#define KEYDB_VERSION_NUM 0x00ffffff
extern const char *KEYDB_SET_VERSION; // Unlike real version, this can be overriden by the config
+10
View File
@@ -31,6 +31,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>
/* This function provide us access to the original libc free(). This is useful
* for instance to free results obtained by backtrace_symbols(). We need
@@ -48,6 +49,7 @@ extern "C" void zlibc_free(void *ptr) {
#ifdef HAVE_MALLOC_SIZE
#define PREFIX_SIZE (0)
#define ASSERT_NO_SIZE_OVERFLOW(sz)
#else
#define PREFIX_SIZE 16
#if defined(__sun) || defined(__sparc) || defined(__sparc__)
@@ -59,6 +61,10 @@ static_assert(PREFIX_SIZE >= (sizeof(size_t)), "");
static_assert((PREFIX_SIZE % 16) == 0, "Our prefix must be modulo 16-bytes or our pointers will not be aligned");
#if PREFIX_SIZE > 0
#define ASSERT_NO_SIZE_OVERFLOW(sz) assert((sz) + PREFIX_SIZE > (sz))
#endif
/* Explicitly override malloc/free etc when using tcmalloc. */
#if defined(USE_MEMKIND)
#define malloc(size, type) salloc(size, type)
@@ -99,6 +105,7 @@ static void zmalloc_default_oom(size_t size) {
static void (*zmalloc_oom_handler)(size_t) = zmalloc_default_oom;
void *zmalloc(size_t size, enum MALLOC_CLASS mclass) {
ASSERT_NO_SIZE_OVERFLOW(size);
(void)mclass;
void *ptr = malloc(size+PREFIX_SIZE, mclass);
@@ -118,6 +125,7 @@ void *zmalloc(size_t size, enum MALLOC_CLASS mclass) {
* Currently implemented only for jemalloc. Used for online defragmentation. */
#ifdef HAVE_DEFRAG
void *zmalloc_no_tcache(size_t size) {
ASSERT_NO_SIZE_OVERFLOW(size);
void *ptr = mallocx(size+PREFIX_SIZE, MALLOCX_TCACHE_NONE);
if (!ptr) zmalloc_oom_handler(size);
update_zmalloc_stat_alloc(zmalloc_size(ptr));
@@ -132,6 +140,7 @@ void zfree_no_tcache(void *ptr) {
#endif
void *zcalloc(size_t size, enum MALLOC_CLASS mclass) {
ASSERT_NO_SIZE_OVERFLOW(size);
(void)(mclass);
void *ptr = calloc(1, size+PREFIX_SIZE, mclass);
@@ -147,6 +156,7 @@ void *zcalloc(size_t size, enum MALLOC_CLASS mclass) {
}
void *zrealloc(void *ptr, size_t size, enum MALLOC_CLASS mclass) {
ASSERT_NO_SIZE_OVERFLOW(size);
#ifndef HAVE_MALLOC_SIZE
void *realptr;
#endif
+15 -1
View File
@@ -3,7 +3,21 @@ set system_name [string tolower [exec uname -s]]
# ldd --version returns 1 under musl for unknown reasons. If this check stops working, that may be why
set is_musl [catch {exec ldd --version}]
if {$system_name eq {linux} && $is_musl eq 0 || $system_name eq {darwin}} {
set system_supported 0
# We only support darwin or Linux with glibc
if {$system_name eq {darwin}} {
set system_supported 1
} elseif {$system_name eq {linux}} {
# Avoid the test on libmusl, which does not support backtrace
set ldd [exec ldd src/keydb-server]
if {![string match {*libc.musl*} $ldd]} {
set system_supported 1
}
}
if {$system_supported} {
set server_path [tmpdir server.log]
start_server [list overrides [list dir $server_path]] {
test "Server is able to generate a stack trace on selected systems" {
r config set watchdog-period 200
+1
View File
@@ -26,6 +26,7 @@ TEST_MODULES = \
keyspace_events.so \
blockedclient.so \
getkeys.so \
zset.so \
timers.so
+3 -2
View File
@@ -164,10 +164,10 @@ int bpopgt_reply_callback(RedisModuleCtx *ctx, RedisModuleString **argv, int arg
long long *pgt = RedisModule_GetBlockedClientPrivateData(ctx);
fsl_t *fsl;
if (!get_fsl(ctx, keyname, REDISMODULE_READ, 0, &fsl, 0) || !fsl)
if (!get_fsl(ctx, keyname, REDISMODULE_READ, 0, &fsl, 0))
return REDISMODULE_ERR;
if (fsl->list[fsl->length-1] <= *pgt)
if (!fsl || fsl->list[fsl->length-1] <= *pgt)
return REDISMODULE_ERR;
RedisModule_ReplyWithLongLong(ctx, fsl->list[--fsl->length]);
@@ -207,6 +207,7 @@ int fsl_bpopgt(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
/* We use malloc so the tests in blockedonkeys.tcl can check for memory leaks */
long long *pgt = RedisModule_Alloc(sizeof(long long));
*pgt = gt;
/* Key is empty or has <2 elements, we must block */
RedisModule_BlockClientOnKeys(ctx, bpopgt_reply_callback, bpopgt_timeout_callback,
bpopgt_free_privdata, timeout, &argv[1], 1, pgt);
} else {
+30
View File
@@ -0,0 +1,30 @@
#include "redismodule.h"
/* ZSET.REM key element
*
* Removes an occurrence of an element from a sorted set. Replies with the
* number of removed elements (0 or 1).
*/
int zset_rem(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
if (argc != 3) return RedisModule_WrongArity(ctx);
RedisModule_AutoMemory(ctx);
int keymode = REDISMODULE_READ | REDISMODULE_WRITE;
RedisModuleKey *key = RedisModule_OpenKey(ctx, argv[1], keymode);
int deleted;
if (RedisModule_ZsetRem(key, argv[2], &deleted) == REDISMODULE_OK)
return RedisModule_ReplyWithLongLong(ctx, deleted);
else
return RedisModule_ReplyWithError(ctx, "ERR ZsetRem failed");
}
int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
REDISMODULE_NOT_USED(argv);
REDISMODULE_NOT_USED(argc);
if (RedisModule_Init(ctx, "zset", 1, REDISMODULE_APIVER_1) ==
REDISMODULE_OK &&
RedisModule_CreateCommand(ctx, "zset.rem", zset_rem, "",
1, 1, 1) == REDISMODULE_OK)
return REDISMODULE_OK;
else
return REDISMODULE_ERR;
}
+16
View File
@@ -0,0 +1,16 @@
set testmodule [file normalize tests/modules/zset.so]
start_server {tags {"modules"}} {
r module load $testmodule
test {Module zset rem} {
r del k
r zadd k 100 hello 200 world
assert_equal 1 [r zset.rem k hello]
assert_equal 0 [r zset.rem k hello]
assert_equal 1 [r exists k]
# Check that removing the last element deletes the key
assert_equal 1 [r zset.rem k world]
assert_equal 0 [r exists k]
}
}
+6 -1
View File
@@ -39,7 +39,12 @@ if {$system_name eq {linux}} {
r bgsave
set child_pid [get_child_pid 0]
assert {[get_oom_score_adj $child_pid] == [expr $base + 30]}
# Wait until background child process to setOOMScoreAdj success.
wait_for_condition 100 10 {
[get_oom_score_adj $child_pid] == [expr $base + 30]
} else {
fail "Set oom-score-adj of background child process is not ok"
}
}
# Failed oom-score-adj tests can only run unprivileged
+3
View File
@@ -360,7 +360,10 @@ start_server {
r del x
set rd [redis_deferring_client]
$rd XREAD BLOCK 0 STREAMS x 1-18446744073709551615
# this wasn't in upstream
after 100
r XADD x 1-1 f v
r XADD x 1-18446744073709551615 f v
r XADD x 2-1 f v