Compare commits
171
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
958ce1ad62 | ||
|
|
20cd988fc0 | ||
|
|
448b20dbd6 | ||
|
|
3534bda474 | ||
|
|
b764fddb20 | ||
|
|
df7b3ef202 | ||
|
|
5bab7047ee | ||
|
|
c2ba9a3bf9 | ||
|
|
964f25daae | ||
|
|
e868c6e0fa | ||
|
|
226152ad7d | ||
|
|
7e9852633c | ||
|
|
78c2edb9b7 | ||
|
|
5d46886e73 | ||
|
|
1daf89f92c | ||
|
|
74f9e41247 | ||
|
|
856ce4e15b | ||
|
|
dd287a22a0 | ||
|
|
ebfd4726b4 | ||
|
|
d08bd7f127 | ||
|
|
e0e2ff2858 | ||
|
|
206f8cde24 | ||
|
|
61dbf96e79 | ||
|
|
856cdf6ed3 | ||
|
|
d9c153111d | ||
|
|
905d82f986 | ||
|
|
a1b11ddb19 | ||
|
|
3db157fc4a | ||
|
|
79f34b4b2b | ||
|
|
de95bb7f8f | ||
|
|
fc6dd57238 | ||
|
|
2c24288806 | ||
|
|
c1e5fefff9 | ||
|
|
a5ea548c91 | ||
|
|
eddf0b1a96 | ||
|
|
2ef2da37ac | ||
|
|
c27e0bed41 | ||
|
|
5f33a992da | ||
|
|
f9e2f851c7 | ||
|
|
e02cca9624 | ||
|
|
88710fc7c5 | ||
|
|
76c3659a0b | ||
|
|
11a62b41b4 | ||
|
|
0e71591999 | ||
|
|
5db98031c5 | ||
|
|
559cc5ec91 | ||
|
|
b68d07b811 | ||
|
|
933c4c57ee | ||
|
|
576cfb391c | ||
|
|
4de58cf1b1 | ||
|
|
f253c6be3e | ||
|
|
ef0f2e1388 | ||
|
|
409d4adaf8 | ||
|
|
20292422c7 | ||
|
|
b56e3aebed | ||
|
|
6e250ea122 | ||
|
|
aff31e0e5f | ||
|
|
273c841655 | ||
|
|
8501e6a8b7 | ||
|
|
2d025ef6b4 | ||
|
|
20516bb99e | ||
|
|
3192b03f97 | ||
|
|
0956a34430 | ||
|
|
ac34bfec67 | ||
|
|
9d765ecb25 | ||
|
|
dc1a9f1d66 | ||
|
|
d12a06dc0a | ||
|
|
1ff51ffdb1 | ||
|
|
1c00c0f0b2 | ||
|
|
5136c7fe6e | ||
|
|
e2c45d7089 | ||
|
|
7f7e06f416 | ||
|
|
ad03da3822 | ||
|
|
07e735b654 | ||
|
|
999c7b8754 | ||
|
|
c5ed5cb0c0 | ||
|
|
9f5f6f8f99 | ||
|
|
4c36328104 | ||
|
|
7171e6ccea | ||
|
|
2a59b09ebe | ||
|
|
9e16ce8253 | ||
|
|
f22266c44e | ||
|
|
75cbe288ef | ||
|
|
70e593c589 | ||
|
|
f86385f70b | ||
|
|
d0762100b0 | ||
|
|
40ec7a2796 | ||
|
|
10b240fd31 | ||
|
|
91ffe99e03 | ||
|
|
c992857618 | ||
|
|
4bba84f096 | ||
|
|
17c3ac89e7 | ||
|
|
cde69883a1 | ||
|
|
e6a94aa569 | ||
|
|
840b393c06 | ||
|
|
56ef0aa7c8 | ||
|
|
dcf409f8e7 | ||
|
|
1237cce65d | ||
|
|
d182820fa7 | ||
|
|
0c65342889 | ||
|
|
e8d0057710 | ||
|
|
3e9e27e98f | ||
|
|
6f2240aefd | ||
|
|
bd60c11bd8 | ||
|
|
38f6207f88 | ||
|
|
dd05b7f67f | ||
|
|
67ee87522a | ||
|
|
3f6d00d387 | ||
|
|
7ef2270ee7 | ||
|
|
456bbc02c8 | ||
|
|
1d4ea00d12 | ||
|
|
abf8150b2e | ||
|
|
2d7dc71b6f | ||
|
|
7d5fb5df3f | ||
|
|
28d146bed6 | ||
|
|
9506c860f6 | ||
|
|
baa88a1c14 | ||
|
|
d28948b143 | ||
|
|
a8c912ead6 | ||
|
|
24896427fc | ||
|
|
b5f52bf01c | ||
|
|
8105f91a02 | ||
|
|
b8b8dd5c15 | ||
|
|
9466dae4e5 | ||
|
|
5234bff579 | ||
|
|
51a01ca8a6 | ||
|
|
b8d315ff76 | ||
|
|
bb93686754 | ||
|
|
64ef0ad71a | ||
|
|
0f3c353dd3 | ||
|
|
f616ecf361 | ||
|
|
2ee4f9f34e | ||
|
|
c89ec5af1e | ||
|
|
0e38c5f39c | ||
|
|
7080a28efc | ||
|
|
fda2bf9c92 | ||
|
|
63e46e5f8d | ||
|
|
d6a13f4440 | ||
|
|
18c2676084 | ||
|
|
9387f7333e | ||
|
|
2f8134a7ff | ||
|
|
408e8e9f44 | ||
|
|
0af467d18f | ||
|
|
e5565a793e | ||
|
|
2bc8db9ca5 | ||
|
|
3848849013 | ||
|
|
0992ada2fe | ||
|
|
a3b0d8631f | ||
|
|
d7d13721d3 | ||
|
|
a351e74fe9 | ||
|
|
6e4f70b817 | ||
|
|
faea46710c | ||
|
|
5521910de7 | ||
|
|
3ff95d9074 | ||
|
|
1bae5dfff6 | ||
|
|
0c3fe52ef7 | ||
|
|
1f75ce30df | ||
|
|
0c898bdb07 | ||
|
|
660645c742 | ||
|
|
af02478ba0 | ||
|
|
337dcde9fa | ||
|
|
324e22accf | ||
|
|
dfb598cf33 | ||
|
|
3c0ed0309a | ||
|
|
5e0fe4c77c | ||
|
|
173cca5413 | ||
|
|
8beec4f0e7 | ||
|
|
45af2b1742 | ||
|
|
1398fac3f1 | ||
|
|
8b33975944 | ||
|
|
dfb12f0628 |
No files matched your search
@@ -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:
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
================================================================================
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -842,4 +842,4 @@ void expireEntryFat::popfrontExpireEntry()
|
||||
serverAssert(res == DICT_OK);
|
||||
}
|
||||
m_vecexpireEntries.erase(m_vecexpireEntries.begin());
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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,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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -26,6 +26,7 @@ TEST_MODULES = \
|
||||
keyspace_events.so \
|
||||
blockedclient.so \
|
||||
getkeys.so \
|
||||
zset.so \
|
||||
timers.so
|
||||
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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]
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in new issue
Block a user