Compare commits
69
Commits
No files matched your search
@@ -1 +0,0 @@
|
||||
.gitea/CODEOWNERS linguist-detectable=false
|
||||
@@ -1,3 +0,0 @@
|
||||
# Pull requests request review from the eligible staff team(s).
|
||||
# One approval from either an Admin or Developer satisfies branch protection.
|
||||
* @trueog/Admins @trueog/Developers
|
||||
@@ -49,6 +49,8 @@ Join us on [Slack](https://docs.keydb.dev/slack/)
|
||||
|
||||
Learn more using KeyDB's extensive [documentation](https://docs.keydb.dev)
|
||||
|
||||
Post to our [Community Forum](https://community.keydb.dev)
|
||||
|
||||
See the [KeyDB Roadmap](https://docs.keydb.dev/docs/coming-soon) to see what's in store
|
||||
|
||||
|
||||
@@ -78,7 +80,7 @@ The minimum number of clients on a thread before KeyDB assigns new connections t
|
||||
```
|
||||
replica-weighting-factor 2
|
||||
```
|
||||
KeyDB will attempt to balance clients across threads evenly; However, replica clients are usually much more expensive than a normal client, and so KeyDB will try to assign fewer clients to threads with a replica. The weighting factor below is intended to help tune this behavior. A replica weighting factor of 2 means we treat a replica as the equivalent of two normal clients. Adjusting this value may improve performance when replication is used. The best weighting is workload specific - e.g. read heavy workloads should set this to 1. Very write heavy workloads may benefit from higher numbers.
|
||||
KeyDB will attempt to balance clients across threads evenly; However, replica clients are usually much more expensive than a normal client, and so KeyDB will try to assign fewer clients to threads with a replica. The weighting factor below is intented to help tune this behavior. A replica weighting factor of 2 means we treat a replica as the equivalent of two normal clients. Adjusting this value may improve performance when replication is used. The best weighting is workload specific - e.g. read heavy workloads should set this to 1. Very write heavy workloads may benefit from higher numbers.
|
||||
|
||||
```
|
||||
active-client-balancing yes
|
||||
|
||||
+2
-2
@@ -21,13 +21,13 @@ machamp:
|
||||
parent: make-build
|
||||
# https://github.sc-corp.net/Snapchat/img/tree/master/keydb/ubuntu-20-04
|
||||
builder_image: us.gcr.io/snapchat-build-artifacts/prod/snapchat/img/keydb/keydb-ubuntu-20-04@sha256:cf869a3f5d1de1e1d976bb906689c37b7031938eb68661b844a38c532f27248c
|
||||
command: ./runtest --clients 4 --verbose --tls
|
||||
command: ./runtest --clients 4 --verbose
|
||||
cluster-test:
|
||||
type: cmd
|
||||
parent: make-build
|
||||
# https://github.sc-corp.net/Snapchat/img/tree/master/keydb/ubuntu-20-04
|
||||
builder_image: us.gcr.io/snapchat-build-artifacts/prod/snapchat/img/keydb/keydb-ubuntu-20-04@sha256:cf869a3f5d1de1e1d976bb906689c37b7031938eb68661b844a38c532f27248c
|
||||
command: ./runtest-cluster --tls
|
||||
command: ./runtest-cluster
|
||||
sentinel-test:
|
||||
type: cmd
|
||||
parent: make-build
|
||||
|
||||
Vendored
-6
@@ -34,17 +34,11 @@ ifneq ($(shell sh -c '[ -f .make-ldflags ] && cat .make-ldflags || echo none'),
|
||||
endif
|
||||
|
||||
distclean:
|
||||
ifneq ($(USE_SYSTEM_HIREDIS),yes)
|
||||
-(cd hiredis && $(MAKE) clean) > /dev/null || true
|
||||
endif
|
||||
-(cd linenoise && $(MAKE) clean) > /dev/null || true
|
||||
-(cd lua && $(MAKE) clean) > /dev/null || true
|
||||
ifneq ($(USE_SYSTEM_JEMALLOC),yes)
|
||||
-(cd jemalloc && [ -f Makefile ] && $(MAKE) distclean) > /dev/null || true
|
||||
endif
|
||||
ifneq ($(USE_SYSTEM_ROCKSDB),yes)
|
||||
-(cd rocksdb && $(MAKE) clean) > /dev/null || true
|
||||
endif
|
||||
-(cd hdr_histogram && $(MAKE) clean) > /dev/null || true
|
||||
-(rm -f .make-*)
|
||||
|
||||
|
||||
-4
@@ -42,8 +42,6 @@
|
||||
#ifndef HIREDIS_SDS_COMPAT
|
||||
#define HIREDIS_SDS_COMPAT
|
||||
|
||||
#ifndef USE_SYSTEM_HIREDIS
|
||||
|
||||
#define sds hisds
|
||||
|
||||
#define sdslen hi_sdslen
|
||||
@@ -93,6 +91,4 @@
|
||||
#define sdsull2str hi_sdsull2str
|
||||
#define sdsupdatelen hi_sdsupdatelen
|
||||
|
||||
#endif /* !USE_SYSTEM_HIREDIS */
|
||||
|
||||
#endif /* HIREDIS_SDS_COMPAT */
|
||||
Vendored
+1
-1
Submodule deps/rocksdb updated: 39d56d5ad7...444b3f4845.
@@ -0,0 +1,84 @@
|
||||
From: Chris Lamb <lamby@debian.org>
|
||||
Date: Wed, 3 Oct 2018 19:24:16 +0100
|
||||
Subject: Add support for a USE_SYSTEM_HIREDIS flag.
|
||||
|
||||
---
|
||||
deps/Makefile | 2 ++
|
||||
src/Makefile | 19 ++++++++++++++-----
|
||||
2 files changed, 16 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/deps/Makefile b/deps/Makefile
|
||||
index 2ed7736..d6b8e3e 100644
|
||||
--- a/deps/Makefile
|
||||
+++ b/deps/Makefile
|
||||
@@ -33,7 +33,9 @@ ifneq ($(shell sh -c '[ -f .make-ldflags ] && cat .make-ldflags || echo none'),
|
||||
endif
|
||||
|
||||
distclean:
|
||||
+ifneq ($(USE_SYSTEM_HIREDIS),yes)
|
||||
-(cd hiredis && $(MAKE) clean) > /dev/null || true
|
||||
+endif
|
||||
-(cd linenoise && $(MAKE) clean) > /dev/null || true
|
||||
ifneq ($(USE_SYSTEM_LUA),yes)
|
||||
-(cd lua && $(MAKE) clean) > /dev/null || true
|
||||
diff --git a/src/Makefile b/src/Makefile
|
||||
index 49085f2..9e7e6f1 100644
|
||||
--- a/src/Makefile
|
||||
+++ b/src/Makefile
|
||||
@@ -16,7 +16,7 @@ release_hdr := $(shell sh -c './mkreleasehdr.sh')
|
||||
uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')
|
||||
uname_M := $(shell sh -c 'uname -m 2>/dev/null || echo not')
|
||||
OPTIMIZATION?=-O2
|
||||
-DEPENDENCY_TARGETS=hiredis linenoise
|
||||
+DEPENDENCY_TARGETS=linenoise
|
||||
NODEPS:=clean distclean
|
||||
|
||||
# Default settings
|
||||
@@ -107,7 +107,7 @@ endif
|
||||
endif
|
||||
endif
|
||||
# Include paths to dependencies
|
||||
-FINAL_CFLAGS+= -I../deps/hiredis -I../deps/linenoise
|
||||
+FINAL_CFLAGS+= -I../deps/linenoise
|
||||
|
||||
ifeq ($(MALLOC),tcmalloc)
|
||||
FINAL_CFLAGS+= -DUSE_TCMALLOC
|
||||
@@ -139,6 +139,15 @@ else
|
||||
FINAL_LIBS := ../deps/lua/src/liblua.a $(FINAL_LIBS)
|
||||
endif
|
||||
|
||||
+ifeq ($(USE_SYSTEM_HIREDIS),yes)
|
||||
+ FINAL_LIBS+= -lhiredis
|
||||
+ FINAL_CFLAGS+= -I/usr/include/hiredis
|
||||
+else
|
||||
+ DEPENDENCY_TARGETS += hiredis
|
||||
+ FINAL_LIBS+= ../deps/hiredis/libhiredis.a
|
||||
+ FINAL_CFLAGS+= -I../deps/hiredis
|
||||
+endif
|
||||
+
|
||||
REDIS_CC=$(QUIET_CC)$(CC) $(FINAL_CFLAGS) $(CPPFLAGS)
|
||||
REDIS_LD=$(QUIET_LINK)$(CC) $(FINAL_LDFLAGS)
|
||||
REDIS_INSTALL=$(QUIET_INSTALL)$(INSTALL)
|
||||
@@ -210,7 +219,7 @@ endif
|
||||
|
||||
# redis-server
|
||||
$(REDIS_SERVER_NAME): $(REDIS_SERVER_OBJ)
|
||||
- $(REDIS_LD) -o $@ $^ ../deps/hiredis/libhiredis.a $(FINAL_LIBS)
|
||||
+ $(REDIS_LD) -o $@ $^ $(FINAL_LIBS)
|
||||
|
||||
# redis-sentinel
|
||||
$(REDIS_SENTINEL_NAME): $(REDIS_SERVER_NAME)
|
||||
@@ -226,11 +235,11 @@ $(REDIS_CHECK_AOF_NAME): $(REDIS_SERVER_NAME)
|
||||
|
||||
# redis-cli
|
||||
$(REDIS_CLI_NAME): $(REDIS_CLI_OBJ)
|
||||
- $(REDIS_LD) -o $@ $^ ../deps/hiredis/libhiredis.a ../deps/linenoise/linenoise.o $(FINAL_LIBS)
|
||||
+ $(REDIS_LD) -o $@ $^ ../deps/linenoise/linenoise.o $(FINAL_LIBS)
|
||||
|
||||
# redis-benchmark
|
||||
$(REDIS_BENCHMARK_NAME): $(REDIS_BENCHMARK_OBJ)
|
||||
- $(REDIS_LD) -o $@ $^ ../deps/hiredis/libhiredis.a $(FINAL_LIBS)
|
||||
+ $(REDIS_LD) -o $@ $^ $(FINAL_LIBS)
|
||||
|
||||
dict-benchmark: dict.c zmalloc.c sds.c siphash.c
|
||||
$(REDIS_CC) $(FINAL_CFLAGS) $^ -D DICT_BENCHMARK_MAIN -o $@ $(FINAL_LIBS)
|
||||
@@ -0,0 +1,107 @@
|
||||
From: Chris Lamb <lamby@debian.org>
|
||||
Date: Sat, 25 Aug 2018 17:52:13 +0200
|
||||
Subject: Add support for USE_SYSTEM_JEMALLOC flag.
|
||||
|
||||
https://github.com/antirez/redis/pull/5279
|
||||
---
|
||||
deps/Makefile | 2 ++
|
||||
src/Makefile | 5 +++++
|
||||
src/object.c | 5 +++++
|
||||
src/zmalloc.c | 10 ++++++++++
|
||||
src/zmalloc.h | 4 ++++
|
||||
5 files changed, 26 insertions(+)
|
||||
|
||||
diff --git a/deps/Makefile b/deps/Makefile
|
||||
index eb35c1e..1342fac 100644
|
||||
--- a/deps/Makefile
|
||||
+++ b/deps/Makefile
|
||||
@@ -36,7 +36,9 @@ distclean:
|
||||
-(cd hiredis && $(MAKE) clean) > /dev/null || true
|
||||
-(cd linenoise && $(MAKE) clean) > /dev/null || true
|
||||
-(cd lua && $(MAKE) clean) > /dev/null || true
|
||||
+ifneq ($(USE_SYSTEM_JEMALLOC),yes)
|
||||
-(cd jemalloc && [ -f Makefile ] && $(MAKE) distclean) > /dev/null || true
|
||||
+endif
|
||||
-(rm -f .make-*)
|
||||
|
||||
.PHONY: distclean
|
||||
diff --git a/src/Makefile b/src/Makefile
|
||||
index 0ff6e8b..51363fe 100644
|
||||
--- a/src/Makefile
|
||||
+++ b/src/Makefile
|
||||
@@ -120,10 +120,15 @@ ifeq ($(MALLOC),tcmalloc_minimal)
|
||||
endif
|
||||
|
||||
ifeq ($(MALLOC),jemalloc)
|
||||
+ifeq ($(USE_SYSTEM_JEMALLOC),yes)
|
||||
+ FINAL_CFLAGS+= -DUSE_JEMALLOC -I/usr/include/jemalloc/include
|
||||
+ FINAL_LIBS := -ljemalloc $(FINAL_LIBS)
|
||||
+else
|
||||
DEPENDENCY_TARGETS+= jemalloc
|
||||
FINAL_CFLAGS+= -DUSE_JEMALLOC -I../deps/jemalloc/include
|
||||
FINAL_LIBS := ../deps/jemalloc/lib/libjemalloc.a $(FINAL_LIBS)
|
||||
endif
|
||||
+endif
|
||||
|
||||
REDIS_CC=$(QUIET_CC)$(CC) $(FINAL_CFLAGS) $(CPPFLAGS)
|
||||
REDIS_LD=$(QUIET_LINK)$(CC) $(FINAL_LDFLAGS)
|
||||
diff --git a/src/object.c b/src/object.c
|
||||
index 6987e1e..e49c2c2 100644
|
||||
--- a/src/object.c
|
||||
+++ b/src/object.c
|
||||
@@ -36,6 +36,11 @@
|
||||
#define strtold(a,b) ((long double)strtod((a),(b)))
|
||||
#endif
|
||||
|
||||
+#if defined(USE_JEMALLOC) && (USE_SYSTEM_JEMALLOC == yes)
|
||||
+#define je_mallctl mallctl
|
||||
+#define je_malloc_stats_print malloc_stats_print
|
||||
+#endif
|
||||
+
|
||||
/* ===================== Creation and parsing of objects ==================== */
|
||||
|
||||
robj *createObject(int type, void *ptr) {
|
||||
diff --git a/src/zmalloc.c b/src/zmalloc.c
|
||||
index 2482f51..80e6571 100644
|
||||
--- a/src/zmalloc.c
|
||||
+++ b/src/zmalloc.c
|
||||
@@ -63,6 +63,15 @@ void zlibc_free(void *ptr) {
|
||||
#define realloc(ptr,size) tc_realloc(ptr,size)
|
||||
#define free(ptr) tc_free(ptr)
|
||||
#elif defined(USE_JEMALLOC)
|
||||
+#if USE_SYSTEM_JEMALLOC == yes
|
||||
+#define malloc(size) malloc(size)
|
||||
+#define calloc(count,size) calloc(count,size)
|
||||
+#define realloc(ptr,size) realloc(ptr,size)
|
||||
+#define free(ptr) free(ptr)
|
||||
+#define mallocx(size,flags) mallocx(size,flags)
|
||||
+#define dallocx(ptr,flags) dallocx(ptr,flags)
|
||||
+#define je_mallctl mallctl
|
||||
+#else
|
||||
#define malloc(size) je_malloc(size)
|
||||
#define calloc(count,size) je_calloc(count,size)
|
||||
#define realloc(ptr,size) je_realloc(ptr,size)
|
||||
@@ -70,6 +79,7 @@ void zlibc_free(void *ptr) {
|
||||
#define mallocx(size,flags) je_mallocx(size,flags)
|
||||
#define dallocx(ptr,flags) je_dallocx(ptr,flags)
|
||||
#endif
|
||||
+#endif
|
||||
|
||||
#define update_zmalloc_stat_alloc(__n) do { \
|
||||
size_t _n = (__n); \
|
||||
diff --git a/src/zmalloc.h b/src/zmalloc.h
|
||||
index 6fb19b0..62ccf29 100644
|
||||
--- a/src/zmalloc.h
|
||||
+++ b/src/zmalloc.h
|
||||
@@ -50,7 +50,11 @@
|
||||
#include <jemalloc/jemalloc.h>
|
||||
#if (JEMALLOC_VERSION_MAJOR == 2 && JEMALLOC_VERSION_MINOR >= 1) || (JEMALLOC_VERSION_MAJOR > 2)
|
||||
#define HAVE_MALLOC_SIZE 1
|
||||
+#if USE_SYSTEM_JEMALLOC == yes
|
||||
+#define zmalloc_size(p) malloc_usable_size(p)
|
||||
+#else
|
||||
#define zmalloc_size(p) je_malloc_usable_size(p)
|
||||
+#endif
|
||||
#else
|
||||
#error "Newer version of jemalloc required"
|
||||
#endif
|
||||
@@ -2,5 +2,7 @@
|
||||
#debian-packaging/0003-dpkg-buildflags.patch
|
||||
#debian-packaging/0007-Set-Debian-configuration-defaults.patch
|
||||
#0010-Use-get_current_dir_name-over-PATHMAX-etc.patch
|
||||
#0010-Add-support-for-USE_SYSTEM_JEMALLOC-flag.patch
|
||||
#0011-Add-support-for-a-USE_SYSTEM_LUA-flag.patch
|
||||
#0007-Add-support-for-a-USE_SYSTEM_HIREDIS-flag.patch
|
||||
#test
|
||||
@@ -1,86 +1,3 @@
|
||||
keydb (6:6.3.4-1distribution_placeholder) codename_placeholder; urgency=medium
|
||||
|
||||
* Add keydb_modstatsd, a module for providing keydb stats to a local statsd server. Can be found under src/modules/keydb_modstatsd
|
||||
* Fixed FreeBSD compile(Thanks to @bra-fsn)
|
||||
* Fixed a bug in s3 bucket config that blocked startup(Thanks to Alexandre Chichmanian)
|
||||
* Fixed a bug causing crash if keys command is called after a blocking command (Fixes issues #659, #605, #532)
|
||||
* Added proper error checking of replica configs, now KeyDB will throw an error if replica-of config is passed before active-replica or multimaster configs
|
||||
* Fixed double free bug in lazy free
|
||||
* Added "overload-protect-percent" config, when enabled this will load shed clients whenever CPU usage exceeds configured value
|
||||
* Added "availability-zone" config, this can be passed any string which will then be reported by info command
|
||||
* Updated eviction logic to account for total system memory availability using sysinfo
|
||||
* Fixed a bug where repl-backlog-size config was modified in keydb.conf with the runtime value during config rewrite
|
||||
* Fixed a possible deadlock when running CLIENT KILL with large number of clients
|
||||
* Fixed a bug where KeyDB would overcommit memory during fork BG save
|
||||
* Fixed a bug with disk repl_backlog causing double free
|
||||
* Fixed integer overflow issue in the temp rdb file naming (Thanks to @karthyuom)
|
||||
* Fixed compile issue with GCC 13.1.1 (Thanks to @michieldwitte)
|
||||
* Removed expireset and restored redis expire behaviour
|
||||
* Fixed a bug causing forked processes to hang, specifically affecting RDB and AOF(Fixes issues #675, #619)
|
||||
* Added "CLUSTER REPLICATE NO ONE" to turn a replica into an empty primary
|
||||
* Added RDB-less full sync, can be enabled with config 'enable-keydb-fastsync'
|
||||
* Added "flash-disable-key-cache" config to disable key cache which stores every key(but not value) in memory
|
||||
* Moved cluster slot to key map to being stored by storage provider, rather than in memory
|
||||
* Moved expires to be stored by storage provider, rather than in memory
|
||||
* Enabled expiry/eviction from storage provider, previously only data stored in memory could be expired/evicted(Fixes #645 along with the 2 previous updates)
|
||||
* Fixed a bug where swapdb result was not recovered after keydb restarts in FLASH mode (Thanks to @karthyuom)
|
||||
* Fixed double free bug when fast sync was canceled early
|
||||
* Fixed a bug where a temp rdb file with zero bytes is generated in flash mode (Thanks to @karthyuom)
|
||||
* Fixed a bug where flash CF options are being reset to default after flushall (Thanks to @karthyuom)(Fixes issue #717)
|
||||
* Updated debug reload command to work with flash
|
||||
* Added support for KEYDB_PASSWORD env variable(Thanks to @einar-pexip)
|
||||
* Compile with flash in Dockerfile(Thanks to @der-eismann)
|
||||
* Fix broken redis-cli symlink (Thanks to @pimvandenbroek)
|
||||
* Use tini for alpine docker(Thanks to @rofafor)
|
||||
|
||||
-- Malavan Sotheeswaran <msotheeswaran@snapchat.com> Sun, 29 Oct 2023 8:39:21 +0000
|
||||
|
||||
keydb (6:6.3.3-1distribution_placeholder) codename_placeholder; urgency=medium
|
||||
|
||||
* To help accelerate our development efforts for KeyDB, this will be the last release containing support for Centos 7, Ubuntu 16.04, Ubuntu 18.04, Debian 9 and 32-bit builds
|
||||
* This release contains fixes for 11 issues along with improvements to the KeyDB FLASH feature:
|
||||
* Fixed race condition with expireset access (Issue #597)
|
||||
* Fixed keys command with lua, and added keydb as an alternative to redis as lua variable to access db (Issue #562 and #594)
|
||||
* Fixed hang in aof child (Issue #554)
|
||||
* Fixed leaking fds from RDB save (Issue #453 and #584)
|
||||
* Added config for S3 RDB load/save (Issue #584)
|
||||
* Enabled active defrag during forkless background save to improve average memory efficiency (Issue #460)
|
||||
* Fixed crash with fork background save during replication (Issue #567)
|
||||
* RocksDB has been updated to v7.9.2
|
||||
* Fixed missing slot_to_key map in FLASH cluster mode (Issue #574)
|
||||
* Added keyspace notifications for keys loaded from FLASH at startup
|
||||
* Fixed race condition in prefetchKeysAsync with FLASH enabled (Issue #571)
|
||||
* Fixed integer overflow in rand family of commands(Issue #631, #632, #633)
|
||||
* Fixed bad value in hincrbyfloat(Issue #634)
|
||||
* Fixed OOM hang in rand family of commands(Issue #635)
|
||||
* Added config to limit count of return values in rand family of commands(Issue #636)
|
||||
|
||||
-- Ben Schermel <ben@eqalpha.com> Tue, 18 Apr 2023 10:00:37 +0000
|
||||
|
||||
keydb (6:6.3.2-1distribution_placeholder) codename_placeholder; urgency=medium
|
||||
|
||||
* This release contains Beta level support for KeyDB FLASH, new ASYNC commands, latency improvements and a number of bug fixes.
|
||||
* KeyDB FLASH is included as a Beta feature. FLASH allows KeyDB to persist data to the storage medium it is written to, avoiding the need for AOF/RDB files. KeyDB uses rocksdb as the persistent storage provider and can be enabled with config "storage-provider flash /path/to/rocksdb/output". Read more at https://docs.keydb.dev/docs/flash/
|
||||
* In addition to GET/MGET, ASYNC support has been added for the following commands: HGET, HMGET, HKEYS, HVALS, HGETALL, HSCAN and can be enable with config "enable-async-commands yes”
|
||||
* Packaging support for Ubuntu 22.04 (Jammy) and Debian 12 (Bookworm) has been included with this release
|
||||
* Added new soft shutdown feature, can be enabled with config "soft-shutdown yes".
|
||||
* If soft shutdown is enabled, instead of shutting down right away, the server will wait until all clients have disconnected, and will reject all new connection attempts.
|
||||
* Fixed memory leak with tls certificates when tls allowlist is enabled
|
||||
* Fixed bug in rdb load with flash enabled to ensure all dbs are safe to load (previously only checked db[0])
|
||||
* Fixed race conditions in rdb load and replication
|
||||
* Fixed memory access of rdb file after it should have been deleted
|
||||
* Fixed integer overflow bug in flash(Issue #486)
|
||||
* Improve TLS latency by queueing new commands before executing instead of after
|
||||
* Removed O(n) count of memory usage from info command(replaced by O(1) estimate)
|
||||
* Improved latency of clearing large number of flash DBs(Thanks to Paul Chen for this fix)(Issue #516)
|
||||
* replaced sprintf with snprintf to avoid potential security bugs
|
||||
* Fixed bug where a failed move due to key already existing in move target would result in the key being removed from move source(Thanks to Paul Chen for this fix)(Issue #497)
|
||||
* Fixed usage of deprecated OpenSSL api in OpenSSL v>3.0.1(Issue #392)
|
||||
* Imported security fixes from Redis (CVE-2023-22458 CVE-2022-35977)
|
||||
* Other fixed issues: #480 #477 #454 #452 #303 #425 #492 #541
|
||||
|
||||
-- Ben Schermel <ben@eqalpha.com> Fri, 20 Jan 2023 20:00:37 +0000
|
||||
|
||||
keydb (6:6.3.1-1distribution_placeholder) codename_placeholder; urgency=medium
|
||||
|
||||
* This point release contains fixes to bugs related to expires, active-rep, and rdb saving
|
||||
|
||||
@@ -53,7 +53,7 @@ RUN set -eux; \
|
||||
grep -E '^ *createBoolConfig[(]"protected-mode",.*, *1 *,.*[)],$' ./src/config.cpp; \
|
||||
sed -ri 's!^( *createBoolConfig[(]"protected-mode",.*, *)1( *,.*[)],)$!\10\2!' ./src/config.cpp; \
|
||||
grep -E '^ *createBoolConfig[(]"protected-mode",.*, *0 *,.*[)],$' ./src/config.cpp; \
|
||||
make -j$(nproc) BUILD_TLS=yes ENABLE_FLASH=yes; \
|
||||
make -j$(nproc) BUILD_TLS=yes; \
|
||||
cd src; \
|
||||
strip keydb-cli keydb-benchmark keydb-check-rdb keydb-check-aof keydb-diagnostic-tool keydb-sentinel keydb-server; \
|
||||
mv keydb-server keydb-cli keydb-benchmark keydb-check-rdb keydb-check-aof keydb-diagnostic-tool keydb-sentinel /usr/local/bin/; \
|
||||
@@ -83,7 +83,6 @@ RUN \
|
||||
sed -i 's/^\(logfile .*\)$/# \1/' /etc/keydb/keydb.conf; \
|
||||
sed -i 's/protected-mode yes/protected-mode no/g' /etc/keydb/keydb.conf; \
|
||||
sed -i 's/^\(bind .*\)$/# \1/' /etc/keydb/keydb.conf; \
|
||||
cd /usr/local/bin; \
|
||||
ln -s keydb-cli redis-cli; \
|
||||
cd /etc/keydb; \
|
||||
ln -s keydb.conf redis.conf; \
|
||||
@@ -97,10 +96,6 @@ RUN set -eux; \
|
||||
echo 'if [ "${1#-}" != "$1" ] || [ "${1%.conf}" != "$1" ]; then' >> /usr/local/bin/docker-entrypoint.sh; \
|
||||
echo ' set -- keydb-server "$@"' >> /usr/local/bin/docker-entrypoint.sh; \
|
||||
echo 'fi' >> /usr/local/bin/docker-entrypoint.sh; \
|
||||
echo '# if KEYDB_PASSWORD is set, add it to the arguments' >> /usr/local/bin/docker-entrypoint.sh; \
|
||||
echo 'if [ -n "$KEYDB_PASSWORD" ]; then' >> /usr/local/bin/docker-entrypoint.sh; \
|
||||
echo ' set -- "$@" --requirepass "${KEYDB_PASSWORD}"' >> /usr/local/bin/docker-entrypoint.sh; \
|
||||
echo 'fi' >> /usr/local/bin/docker-entrypoint.sh; \
|
||||
echo "# allow the container to be started with `--user`" >> /usr/local/bin/docker-entrypoint.sh; \
|
||||
echo 'if [ "$1" = "keydb-server" -a "$(id -u)" = "0" ]; then' >> /usr/local/bin/docker-entrypoint.sh; \
|
||||
echo " find . \! -user keydb -exec chown keydb '{}' +" >> /usr/local/bin/docker-entrypoint.sh; \
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
FROM alpine:3.18
|
||||
FROM alpine:3.12
|
||||
# add our user and group first to make sure their IDs get assigned consistently, regardless of whatever dependencies get added
|
||||
RUN addgroup -S -g 1000 keydb && adduser -S -G keydb -u 999 keydb
|
||||
RUN mkdir -p /etc/keydb
|
||||
ARG BRANCH
|
||||
RUN set -eux; \
|
||||
\
|
||||
apk add --no-cache su-exec tini; \
|
||||
apk add --no-cache su-exec; \
|
||||
apk add --no-cache --virtual .build-deps \
|
||||
coreutils \
|
||||
gcc \
|
||||
@@ -32,7 +32,7 @@ RUN set -eux; \
|
||||
grep -E '^ *createBoolConfig[(]"protected-mode",.*, *1 *,.*[)],$' ./src/config.cpp; \
|
||||
sed -ri 's!^( *createBoolConfig[(]"protected-mode",.*, *)1( *,.*[)],)$!\10\2!' ./src/config.cpp; \
|
||||
grep -E '^ *createBoolConfig[(]"protected-mode",.*, *0 *,.*[)],$' ./src/config.cpp; \
|
||||
make -j$(nproc) BUILD_TLS=yes ENABLE_FLASH=yes; \
|
||||
make -j$(nproc) BUILD_TLS=yes; \
|
||||
cd src; \
|
||||
strip keydb-cli keydb-benchmark keydb-check-rdb keydb-check-aof keydb-diagnostic-tool keydb-sentinel keydb-server; \
|
||||
mv keydb-server keydb-cli keydb-benchmark keydb-check-rdb keydb-check-aof keydb-diagnostic-tool keydb-sentinel /usr/local/bin/; \
|
||||
@@ -54,7 +54,6 @@ RUN set -eux; \
|
||||
sed -i 's/^\(logfile .*\)$/# \1/' /etc/keydb/keydb.conf; \
|
||||
sed -i 's/protected-mode yes/protected-mode no/g' /etc/keydb/keydb.conf; \
|
||||
sed -i 's/^\(bind .*\)$/# \1/' /etc/keydb/keydb.conf; \
|
||||
cd /usr/local/bin; \
|
||||
ln -s keydb-cli redis-cli; \
|
||||
cd /etc/keydb; \
|
||||
ln -s keydb.conf redis.conf; \
|
||||
@@ -68,10 +67,6 @@ RUN set -eux; \
|
||||
echo 'if [ "${1#-}" != "$1" ] || [ "${1%.conf}" != "$1" ]; then' >> /usr/local/bin/docker-entrypoint.sh; \
|
||||
echo ' set -- keydb-server "$@"' >> /usr/local/bin/docker-entrypoint.sh; \
|
||||
echo 'fi' >> /usr/local/bin/docker-entrypoint.sh; \
|
||||
echo '# if KEYDB_PASSWORD is set, add it to the arguments' >> /usr/local/bin/docker-entrypoint.sh; \
|
||||
echo 'if [ -n "$KEYDB_PASSWORD" ]; then' >> /usr/local/bin/docker-entrypoint.sh; \
|
||||
echo ' set -- "$@" --requirepass "${KEYDB_PASSWORD}"' >> /usr/local/bin/docker-entrypoint.sh; \
|
||||
echo 'fi' >> /usr/local/bin/docker-entrypoint.sh; \
|
||||
echo "# allow the container to be started with `--user`" >> /usr/local/bin/docker-entrypoint.sh; \
|
||||
echo 'if [ "$1" = "keydb-server" -a "$(id -u)" = "0" ]; then' >> /usr/local/bin/docker-entrypoint.sh; \
|
||||
echo " find . \! -user keydb -exec chown keydb '{}' +" >> /usr/local/bin/docker-entrypoint.sh; \
|
||||
@@ -81,6 +76,6 @@ RUN set -eux; \
|
||||
chmod +x /usr/local/bin/docker-entrypoint.sh
|
||||
VOLUME /data
|
||||
WORKDIR /data
|
||||
ENTRYPOINT ["tini", "--", "docker-entrypoint.sh"]
|
||||
ENTRYPOINT ["docker-entrypoint.sh"]
|
||||
EXPOSE 6379
|
||||
CMD ["keydb-server", "/etc/keydb/keydb.conf"]
|
||||
@@ -5,7 +5,10 @@ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
version=$(grep KEYDB_REAL_VERSION $DIR/../../src/version.h | awk '{ printf $3 }' | tr -d \")
|
||||
release=1 # by default this will always be 1 for keydb version structure. If build release version needs to be update you can modify here
|
||||
arch=$(uname -m)
|
||||
dist=$(rpm --eval '%{?dist}')
|
||||
dist=el$(rpm -q --queryformat '%{VERSION}' centos-release | cut -d. -f1)
|
||||
if [[ "$dist" == "elpackage centos-release is not installed" ]]; then
|
||||
dist=el$(rpm -q --queryformat '%{VERSION}' centos-linux-release | cut -d. -f1)
|
||||
fi
|
||||
|
||||
if [[ "$arch" != "aarch64" ]] && [[ "$arch" != "x86_64" ]]; then
|
||||
echo "This script is only valid and tested for aarch64 and x86_64 architectures. You are trying to use: $arch"
|
||||
@@ -36,8 +39,8 @@ sed -i -E "1a\Version : $version" $DIR/keydb_build/keydb.spec
|
||||
sed -i '3d' $DIR/keydb_build/keydb.spec
|
||||
sed -i -E "2a\Release : $release%{?dist}" $DIR/keydb_build/keydb.spec
|
||||
|
||||
mkdir -p /root/rpmbuild/BUILDROOT/keydb-$version-$release$dist.$arch
|
||||
cp -r $DIR/keydb_build/keydb_rpm/* /root/rpmbuild/BUILDROOT/keydb-$version-$release$dist.$arch/
|
||||
mkdir -p /root/rpmbuild/BUILDROOT/keydb-$version-$release.$dist.$arch
|
||||
cp -r $DIR/keydb_build/keydb_rpm/* /root/rpmbuild/BUILDROOT/keydb-$version-$release.$dist.$arch/
|
||||
rpmbuild -bb $DIR/keydb_build/keydb.spec
|
||||
mv /root/rpmbuild/RPMS/$arch/* $DIR/rpm_files_generated
|
||||
|
||||
|
||||
+1
-1
@@ -44,7 +44,7 @@ public:
|
||||
endWriteBatch();
|
||||
}
|
||||
|
||||
virtual std::vector<std::string> getExpirationCandidates(unsigned int count) = 0;
|
||||
virtual std::vector<std::string> getExpirationCandidates(unsigned int count, long long time) = 0;
|
||||
virtual std::vector<std::string> getEvictionCandidates(unsigned int count) = 0;
|
||||
virtual void setExpire(const char *key, size_t cchKey, long long expire) = 0;
|
||||
virtual void removeExpire(const char *key, size_t cchKey, long long expire) = 0;
|
||||
|
||||
+8
-48
@@ -20,7 +20,7 @@ release_hdr := $(shell sh -c './mkreleasehdr.sh')
|
||||
uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')
|
||||
uname_M := $(shell sh -c 'uname -m 2>/dev/null || echo not')
|
||||
OPTIMIZATION?=-O2 -flto
|
||||
DEPENDENCY_TARGETS=linenoise lua hdr_histogram
|
||||
DEPENDENCY_TARGETS=hiredis linenoise lua hdr_histogram
|
||||
NODEPS:=clean distclean
|
||||
|
||||
# Default settings
|
||||
@@ -73,19 +73,12 @@ ifneq ($(strip $(SANITIZE)),)
|
||||
endif
|
||||
|
||||
ifeq ($(ENABLE_FLASH),yes)
|
||||
STORAGE_OBJ+= storage/rocksdb.o storage/rocksdbfactory.o
|
||||
ifeq ($(USE_SYSTEM_ROCKSDB),yes)
|
||||
FINAL_LIBS+= $(shell pkg-config --libs rocksdb)
|
||||
FINAL_CXXFLAGS+= $(shell pkg-config --cflags rocksdb) -DENABLE_ROCKSDB
|
||||
|
||||
else
|
||||
FINAL_LIBS+= -lz -lcrypto -lbz2 -lzstd -llz4 -lsnappy
|
||||
CXXFLAGS+= -I../deps/rocksdb/include/ -DENABLE_ROCKSDB
|
||||
FINAL_CXXFLAGS+= -I../deps/rocksdb/include/
|
||||
STORAGE_OBJ+= storage/rocksdb.o storage/rocksdbfactory.o
|
||||
FINAL_LIBS+= ../deps/rocksdb/librocksdb.a
|
||||
DEPENDENCY_TARGETS+= rocksdb
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
ifeq ($(CHECKED),true)
|
||||
@@ -274,14 +267,8 @@ ifdef OPENSSL_PREFIX
|
||||
endif
|
||||
|
||||
# Include paths to dependencies
|
||||
FINAL_CFLAGS+= -I../deps/linenoise -I../deps/lua/src -I../deps/hdr_histogram
|
||||
FINAL_CXXFLAGS+= -I../deps/linenoise -I../deps/lua/src -I../deps/hdr_histogram
|
||||
|
||||
ifeq ($(USE_SYSTEM_CONCURRENTQUEUE),yes)
|
||||
FINAL_CXXFLAGS+= -I/usr/include/concurrentqueue/moodycamel
|
||||
else
|
||||
FINAL_CXXFLAGS+= -I../deps/concurrentqueue
|
||||
endif
|
||||
FINAL_CFLAGS+= -I../deps/hiredis -I../deps/linenoise -I../deps/lua/src -I../deps/hdr_histogram
|
||||
FINAL_CXXFLAGS+= -I../deps/hiredis -I../deps/linenoise -I../deps/lua/src -I../deps/hdr_histogram -I../deps/rocksdb/include/ -I../deps/concurrentqueue
|
||||
|
||||
# Determine systemd support and/or build preference (defaulting to auto-detection)
|
||||
BUILD_WITH_SYSTEMD=no
|
||||
@@ -324,17 +311,11 @@ ifeq ($(MALLOC),tcmalloc_minimal)
|
||||
endif
|
||||
|
||||
ifeq ($(MALLOC),jemalloc)
|
||||
ifeq ($(USE_SYSTEM_JEMALLOC),yes)
|
||||
FINAL_CFLAGS+= -DUSE_JEMALLOC $(shell $(PKG_CONFIG) --cflags jemalloc)
|
||||
FINAL_CXXFLAGS+= -DUSE_JEMALLOC $(shell $(PKG_CONFIG) --cflags jemalloc)
|
||||
FINAL_LIBS := $(shell $(PKG_CONFIG) --libs jemalloc) $(FINAL_LIBS)
|
||||
else
|
||||
DEPENDENCY_TARGETS+= jemalloc
|
||||
FINAL_CFLAGS+= -DUSE_JEMALLOC -I../deps/jemalloc/include
|
||||
FINAL_CXXFLAGS+= -DUSE_JEMALLOC -I../deps/jemalloc/include
|
||||
FINAL_LIBS := ../deps/jemalloc/lib/libjemalloc.a $(FINAL_LIBS)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(MALLOC),memkind)
|
||||
DEPENDENCY_TARGETS+= memkind
|
||||
@@ -343,22 +324,6 @@ ifeq ($(MALLOC),memkind)
|
||||
FINAL_LIBS := ../deps/memkind/src/.libs/libmemkind.a -lnuma $(FINAL_LIBS)
|
||||
endif
|
||||
|
||||
ifeq ($(USE_SYSTEM_HIREDIS),yes)
|
||||
HIREDIS_CFLAGS := $(shell $(PKG_CONFIG) --cflags hiredis) -DUSE_SYSTEM_HIREDIS=1
|
||||
FINAL_CFLAGS+= $(HIREDIS_CFLAGS)
|
||||
FINAL_CXXFLAGS+= $(HIREDIS_CFLAGS)
|
||||
FINAL_LIBS+= $(shell $(PKG_CONFIG) --libs hiredis)
|
||||
ifeq ($(BUILD_TLS),yes)
|
||||
HIREDIS_TLS_CFLAGS := $(shell $(PKG_CONFIG) --cflags hiredis_ssl)
|
||||
FINAL_CFLAGS+= $(HIREDIS_TLS_CFLAGS)
|
||||
FINAL_CXXFLAGS+= $(HIREDIS_TLS_CFLAGS)
|
||||
FINAL_LIBS+= $(shell $(PKG_CONFIG) --libs hiredis_ssl)
|
||||
endif
|
||||
else
|
||||
DEPENDENCY_TARGETS+= hiredis
|
||||
FINAL_CFLAGS+= -I../deps/hiredis
|
||||
FINAL_CXXFLAGS+= -I../deps/hiredis
|
||||
FINAL_LIBS+=../deps/hiredis/libhiredis.a
|
||||
ifeq ($(BUILD_TLS),yes)
|
||||
FINAL_CFLAGS+=-DUSE_OPENSSL $(OPENSSL_CFLAGS)
|
||||
FINAL_CXXFLAGS+=-DUSE_OPENSSL $(OPENSSL_CXXFLAGS)
|
||||
@@ -377,7 +342,6 @@ else
|
||||
endif
|
||||
FINAL_LIBS += ../deps/hiredis/libhiredis_ssl.a $(LIBSSL_LIBS) $(LIBCRYPTO_LIBS)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifndef V
|
||||
define MAKE_INSTALL
|
||||
@@ -394,7 +358,6 @@ endif
|
||||
OS := $(shell cat /etc/os-release | grep ID= | head -n 1 | cut -d'=' -f2)
|
||||
ifeq ($(OS),alpine)
|
||||
FINAL_CXXFLAGS+=-DUNW_LOCAL_ONLY
|
||||
FINAL_CXXFLAGS+=-DALPINE
|
||||
FINAL_LIBS += -lunwind
|
||||
endif
|
||||
|
||||
@@ -450,12 +413,9 @@ persist-settings: distclean
|
||||
echo STD=$(STD) >> .make-settings
|
||||
echo WARN=$(WARN) >> .make-settings
|
||||
echo OPT=$(OPT) >> .make-settings
|
||||
echo USE_SYSTEM_CONCURRENTQUEUE=$(USE_SYSTEM_CONCURRENTQUEUE) >> .make-settings
|
||||
echo MALLOC=$(MALLOC) >> .make-settings
|
||||
echo USE_SYSTEM_JEMALLOC=$(USE_SYSTEM_JEMALLOC) >> .make-settings
|
||||
echo BUILD_TLS=$(BUILD_TLS) >> .make-settings
|
||||
echo USE_SYSTEMD=$(USE_SYSTEMD) >> .make-settings
|
||||
echo USE_SYSTEM_HIREDIS=$(USE_SYSTEM_HIREDIS) >> .make-settings
|
||||
echo CFLAGS=$(CFLAGS) >> .make-settings
|
||||
echo CXXFLAGS=$(CXXFLAGS) >> .make-settings
|
||||
echo LDFLAGS=$(LDFLAGS) >> .make-settings
|
||||
@@ -485,7 +445,7 @@ endif
|
||||
|
||||
# keydb-server
|
||||
$(REDIS_SERVER_NAME): $(REDIS_SERVER_OBJ) $(KEYDB_SERVER_OBJ)
|
||||
$(REDIS_LD) -o $@ $^ ../deps/lua/src/liblua.a $(FINAL_LIBS)
|
||||
$(REDIS_LD) -o $@ $^ ../deps/hiredis/libhiredis.a ../deps/lua/src/liblua.a $(FINAL_LIBS)
|
||||
|
||||
# keydb-sentinel
|
||||
$(REDIS_SENTINEL_NAME): $(REDIS_SERVER_NAME)
|
||||
@@ -501,15 +461,15 @@ $(REDIS_CHECK_AOF_NAME): $(REDIS_SERVER_NAME)
|
||||
|
||||
# keydb-cli
|
||||
$(REDIS_CLI_NAME): $(REDIS_CLI_OBJ)
|
||||
$(REDIS_LD) -o $@ $^ ../deps/linenoise/linenoise.o $(FINAL_LIBS)
|
||||
$(REDIS_LD) -o $@ $^ ../deps/hiredis/libhiredis.a ../deps/linenoise/linenoise.o $(FINAL_LIBS)
|
||||
|
||||
# keydb-benchmark
|
||||
$(REDIS_BENCHMARK_NAME): $(REDIS_BENCHMARK_OBJ)
|
||||
$(REDIS_LD) -o $@ $^ ../deps/hdr_histogram/hdr_histogram.o $(FINAL_LIBS)
|
||||
$(REDIS_LD) -o $@ $^ ../deps/hiredis/libhiredis.a ../deps/hdr_histogram/hdr_histogram.o $(FINAL_LIBS)
|
||||
|
||||
# keydb-diagnostic-tool
|
||||
$(KEYDB_DIAGNOSTIC_NAME): $(KEYDB_DIAGNOSTIC_OBJ)
|
||||
$(REDIS_LD) -o $@ $^ $(FINAL_LIBS)
|
||||
$(REDIS_LD) -o $@ $^ ../deps/hiredis/libhiredis.a $(FINAL_LIBS)
|
||||
|
||||
DEP = $(REDIS_SERVER_OBJ:%.o=%.d) $(KEYDB_SERVER_OBJ:%.o=%.d) $(REDIS_CLI_OBJ:%.o=%.d) $(REDIS_BENCHMARK_OBJ:%.o=%.d)
|
||||
-include $(DEP)
|
||||
|
||||
@@ -136,33 +136,14 @@ void SnapshotPayloadParseState::flushQueuedKeys() {
|
||||
int idb = current_database;
|
||||
serverAssert(vecqueuedKeys.size() == vecqueuedVals.size());
|
||||
auto sizePrev = vecqueuedKeys.size();
|
||||
(*insertsInFlight)++;
|
||||
std::weak_ptr<std::atomic<int>> insertsInFlightTmp = insertsInFlight; // C++ GRRRRRRRRRRRRRRRR, we don't want to capute "this" because that's dangerous
|
||||
if (current_database < cserver.dbnum) {
|
||||
if (g_pserver->m_pstorageFactory) {
|
||||
(*insertsInFlight)++;
|
||||
std::weak_ptr<std::atomic<int>> insertsInFlightTmp = insertsInFlight; // C++ GRRRRRRRRRRRRRRRR, we don't want to capute "this" because that's dangerous
|
||||
g_pserver->asyncworkqueue->AddWorkFunction([idb, vecqueuedKeys = std::move(this->vecqueuedKeys), vecqueuedKeysCb = std::move(this->vecqueuedKeysCb), vecqueuedVals = std::move(this->vecqueuedVals), vecqueuedValsCb = std::move(this->vecqueuedValsCb), insertsInFlightTmp, pallocator = m_spallocator.release()]() mutable {
|
||||
g_pserver->db[idb]->bulkDirectStorageInsert(vecqueuedKeys.data(), vecqueuedKeysCb.data(), vecqueuedVals.data(), vecqueuedValsCb.data(), vecqueuedKeys.size());
|
||||
(*(insertsInFlightTmp.lock()))--;
|
||||
delete pallocator;
|
||||
});
|
||||
} else {
|
||||
for (size_t ival = 0; ival < vecqueuedKeys.size(); ++ival) {
|
||||
size_t offset = 0;
|
||||
auto spexpire = deserializeExpire(vecqueuedVals[ival], vecqueuedValsCb[ival], &offset);
|
||||
auto o = deserializeStoredObject(vecqueuedVals[ival] + offset, vecqueuedValsCb[ival] - offset);
|
||||
sds sdsKey = sdsnewlen(vecqueuedKeys[ival], -static_cast<ssize_t>(vecqueuedKeysCb[ival]));
|
||||
if (dbMerge(g_pserver->db[idb], sdsKey, o, false)) {
|
||||
if (spexpire != nullptr)
|
||||
g_pserver->db[idb]->setExpire(sdsKey, std::move(*spexpire));
|
||||
} else {
|
||||
sdsfree(sdsKey);
|
||||
}
|
||||
}
|
||||
vecqueuedKeys.clear();
|
||||
vecqueuedKeysCb.clear();
|
||||
vecqueuedVals.clear();
|
||||
vecqueuedValsCb.clear();
|
||||
}
|
||||
g_pserver->asyncworkqueue->AddWorkFunction([idb, vecqueuedKeys = std::move(this->vecqueuedKeys), vecqueuedKeysCb = std::move(this->vecqueuedKeysCb), vecqueuedVals = std::move(this->vecqueuedVals), vecqueuedValsCb = std::move(this->vecqueuedValsCb), insertsInFlightTmp, pallocator = m_spallocator.release()]() mutable {
|
||||
g_pserver->db[idb]->bulkDirectStorageInsert(vecqueuedKeys.data(), vecqueuedKeysCb.data(), vecqueuedVals.data(), vecqueuedValsCb.data(), vecqueuedKeys.size());
|
||||
(*(insertsInFlightTmp.lock()))--;
|
||||
delete pallocator;
|
||||
});
|
||||
} else {
|
||||
// else drop the data
|
||||
vecqueuedKeys.clear();
|
||||
|
||||
+1
-1
@@ -51,7 +51,7 @@ public:
|
||||
bool enumerate(IStorage::callback fn) const { return m_spstorage->enumerate(fn); }
|
||||
bool enumerate_hashslot(IStorage::callback fn, unsigned int hashslot) const { return m_spstorage->enumerate_hashslot(fn, hashslot); }
|
||||
|
||||
std::vector<std::string> getExpirationCandidates(unsigned int count) { return m_spstorage->getExpirationCandidates(count); }
|
||||
std::vector<std::string> getExpirationCandidates(unsigned int count, long long time) { return m_spstorage->getExpirationCandidates(count, time); }
|
||||
std::vector<std::string> getEvictionCandidates(unsigned int count) { return m_spstorage->getEvictionCandidates(count); }
|
||||
void setExpire(const char *key, size_t cchKey, long long expire) { m_spstorage->setExpire(key, cchKey, expire); }
|
||||
void removeExpire(const char *key, size_t cchKey, long long expire) { m_spstorage->removeExpire(key, cchKey, expire); }
|
||||
|
||||
+1
-30
@@ -113,8 +113,6 @@ enum class AE_ASYNC_OP
|
||||
PostCppFunction,
|
||||
DeleteFileEvent,
|
||||
CreateFileEvent,
|
||||
PostAsynDBFunction,
|
||||
|
||||
};
|
||||
|
||||
struct aeCommand
|
||||
@@ -127,8 +125,6 @@ struct aeCommand
|
||||
aePostFunctionProc *proc;
|
||||
aeFileProc *fproc;
|
||||
std::function<void()> *pfn;
|
||||
aePostFunctionTokenProc* tproc;
|
||||
|
||||
};
|
||||
void *clientData;
|
||||
};
|
||||
@@ -179,17 +175,6 @@ void aeProcessCmd(aeEventLoop *eventLoop, int fd, void *, int )
|
||||
(*cmd.pfn)();
|
||||
|
||||
delete cmd.pfn;
|
||||
break;
|
||||
}
|
||||
case AE_ASYNC_OP::PostAsynDBFunction:
|
||||
{ //added to support async api IStorage
|
||||
if (cmd.fLock && !ulock.owns_lock()) {
|
||||
g_forkLock.releaseRead();
|
||||
ulock.lock();
|
||||
g_forkLock.acquireRead();
|
||||
}
|
||||
((aePostFunctionTokenProc*)cmd.tproc)(eventLoop,(StorageToken*)cmd.clientData);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -271,20 +256,6 @@ int aePostFunction(aeEventLoop *eventLoop, aePostFunctionProc *proc, void *arg)
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
int aePostFunction(aeEventLoop *eventLoop, aePostFunctionTokenProc *proc, StorageToken *token)
|
||||
{
|
||||
//added to support async api IStorage
|
||||
aeCommand cmd = {};
|
||||
cmd.op = AE_ASYNC_OP::PostAsynDBFunction;
|
||||
cmd.tproc = proc;
|
||||
cmd.clientData = (void*)token;
|
||||
cmd.fLock = true;
|
||||
auto size = write(eventLoop->fdCmdWrite, &cmd, sizeof(cmd));
|
||||
if (size != sizeof(cmd))
|
||||
return AE_ERR;
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
int aePostFunction(aeEventLoop *eventLoop, std::function<void()> fn, bool fLock, bool fForceQueue)
|
||||
{
|
||||
if (eventLoop == g_eventLoopThisThread && !fForceQueue)
|
||||
@@ -890,7 +861,7 @@ void aeReleaseForkLock()
|
||||
|
||||
void aeForkLockInChild()
|
||||
{
|
||||
g_forkLock.setMulti(false);
|
||||
g_forkLock.setNotify(false);
|
||||
}
|
||||
|
||||
int aeThreadOwnsLock()
|
||||
|
||||
@@ -72,15 +72,13 @@ extern "C" {
|
||||
#define AE_NOTUSED(V) ((void) V)
|
||||
|
||||
struct aeEventLoop;
|
||||
|
||||
/* Types and data structures */
|
||||
typedef void aeFileProc(struct aeEventLoop *eventLoop, int fd, void *clientData, int mask);
|
||||
typedef int aeTimeProc(struct aeEventLoop *eventLoop, long long id, void *clientData);
|
||||
typedef void aeEventFinalizerProc(struct aeEventLoop *eventLoop, void *clientData);
|
||||
typedef void aeBeforeSleepProc(struct aeEventLoop *eventLoop);
|
||||
typedef void aePostFunctionProc(void *pvArgs);
|
||||
//added to support async api IStorage
|
||||
struct StorageToken;
|
||||
typedef void aePostFunctionTokenProc(struct aeEventLoop *el, struct StorageToken *token);
|
||||
|
||||
/* File event structure */
|
||||
typedef struct aeFileEvent {
|
||||
@@ -136,8 +134,6 @@ int aePostFunction(aeEventLoop *eventLoop, aePostFunctionProc *proc, void *arg);
|
||||
#ifdef __cplusplus
|
||||
} // EXTERN C
|
||||
int aePostFunction(aeEventLoop *eventLoop, std::function<void()> fn, bool fLock = true, bool fForceQueue = false);
|
||||
//added to support async api IStorage
|
||||
int aePostFunction(aeEventLoop *eventLoop, aePostFunctionTokenProc *proc, StorageToken *token);
|
||||
extern "C" {
|
||||
#endif
|
||||
void aeDeleteEventLoop(aeEventLoop *eventLoop);
|
||||
|
||||
+2
-4
@@ -208,8 +208,7 @@ void unblockClient(client *c) {
|
||||
listDelNode(g_pserver->paused_clients,c->paused_list_node);
|
||||
c->paused_list_node = NULL;
|
||||
} else {
|
||||
serverPanic("Unknown btype %d in unblockClient() for client %llu.",
|
||||
c->btype, (unsigned long long) c->id);
|
||||
serverPanic("Unknown btype in unblockClient().");
|
||||
}
|
||||
|
||||
/* Reset the client for a new query since, for blocking commands
|
||||
@@ -244,8 +243,7 @@ void replyToBlockedClientTimedOut(client *c) {
|
||||
} else if (c->btype == BLOCKED_MODULE) {
|
||||
moduleBlockedClientTimedOut(c);
|
||||
} else {
|
||||
serverPanic("Unknown btype %d in replyToBlockedClientTimedOut() for client %llu.",
|
||||
c->btype, (unsigned long long) c->id);
|
||||
serverPanic("Unknown btype in replyToBlockedClientTimedOut().");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@
|
||||
#include "cli_common.h"
|
||||
#include <errno.h>
|
||||
#include <hiredis.h>
|
||||
#include "sdscompat.h" /* Use hiredis' sds compat header that maps sds calls to their hi_ variants */
|
||||
#include <sdscompat.h> /* Use hiredis' sds compat header that maps sds calls to their hi_ variants */
|
||||
#include <sds.h> /* use sds.h from hiredis, so that only one set of sds functions will be present in the binary */
|
||||
#ifdef USE_OPENSSL
|
||||
#include <openssl/ssl.h>
|
||||
|
||||
+1
-3
@@ -5991,9 +5991,7 @@ clusterNode *getNodeByQuery(client *c, struct redisCommand *cmd, robj **argv, in
|
||||
/* If it is not the first key, make sure it is exactly
|
||||
* the same key as the first we saw. */
|
||||
if (!equalStringObjects(firstkey,thiskey)) {
|
||||
clusterNode* nThisKey = g_pserver->cluster->slots[thisslot];
|
||||
|
||||
if ((slot != thisslot) && (nThisKey != n || migrating_slot || importing_slot || g_pserver->cluster->migrating_slots_to[slot] != nullptr || g_pserver->cluster->importing_slots_from[slot] != nullptr)) {
|
||||
if (slot != thisslot) {
|
||||
/* Error: multiple keys from different slots. */
|
||||
getKeysFreeResult(&result);
|
||||
if (error_code)
|
||||
|
||||
+1
-3
@@ -2946,7 +2946,7 @@ standardConfig configs[] = {
|
||||
createLongLongConfig("latency-monitor-threshold", NULL, MODIFIABLE_CONFIG, 0, LLONG_MAX, g_pserver->latency_monitor_threshold, 0, INTEGER_CONFIG, NULL, NULL),
|
||||
createLongLongConfig("proto-max-bulk-len", NULL, MODIFIABLE_CONFIG, 1024*1024, LLONG_MAX, g_pserver->proto_max_bulk_len, 512ll*1024*1024, MEMORY_CONFIG, NULL, NULL), /* Bulk request max size */
|
||||
createLongLongConfig("stream-node-max-entries", NULL, MODIFIABLE_CONFIG, 0, LLONG_MAX, g_pserver->stream_node_max_entries, 100, INTEGER_CONFIG, NULL, NULL),
|
||||
createLongLongConfig("repl-backlog-size", NULL, MODIFIABLE_CONFIG, 1, LLONG_MAX, g_pserver->repl_backlog_config_size, 1024*1024, MEMORY_CONFIG, NULL, updateReplBacklogSize), /* Default: 1mb */
|
||||
createLongLongConfig("repl-backlog-size", NULL, MODIFIABLE_CONFIG, 1, LLONG_MAX, g_pserver->repl_backlog_size, 1024*1024, MEMORY_CONFIG, NULL, updateReplBacklogSize), /* Default: 1mb */
|
||||
createLongLongConfig("repl-backlog-disk-reserve", NULL, IMMUTABLE_CONFIG, 0, LLONG_MAX, cserver.repl_backlog_disk_size, 0, MEMORY_CONFIG, NULL, NULL),
|
||||
createLongLongConfig("max-snapshot-slip", NULL, MODIFIABLE_CONFIG, 0, 5000, g_pserver->snapshot_slip, 400, 0, NULL, NULL),
|
||||
createLongLongConfig("max-rand-count", NULL, MODIFIABLE_CONFIG, 0, LONG_MAX/2, g_pserver->rand_total_threshold, LONG_MAX/2, 0, NULL, NULL),
|
||||
@@ -2982,8 +2982,6 @@ standardConfig configs[] = {
|
||||
createSDSConfig("availability-zone", NULL, MODIFIABLE_CONFIG, 0, g_pserver->sdsAvailabilityZone, "", NULL, NULL),
|
||||
createIntConfig("overload-protect-percent", NULL, MODIFIABLE_CONFIG, 0, 200, g_pserver->overload_protect_threshold, 0, INTEGER_CONFIG, NULL, NULL),
|
||||
createIntConfig("force-eviction-percent", NULL, MODIFIABLE_CONFIG, 0, 100, g_pserver->force_eviction_percent, 0, INTEGER_CONFIG, NULL, NULL),
|
||||
createBoolConfig("enable-async-rehash", NULL, MODIFIABLE_CONFIG, g_pserver->enable_async_rehash, 1, NULL, NULL),
|
||||
createBoolConfig("enable-keydb-fastsync", NULL, MODIFIABLE_CONFIG, g_pserver->fEnableFastSync, 0, NULL, NULL),
|
||||
|
||||
#ifdef USE_OPENSSL
|
||||
createIntConfig("tls-port", NULL, MODIFIABLE_CONFIG, 0, 65535, g_pserver->tls_port, 0, INTEGER_CONFIG, NULL, updateTLSPort), /* TCP port. */
|
||||
|
||||
+6
-2
@@ -41,10 +41,14 @@
|
||||
|
||||
#define CONFIG_DEFAULT_RDB_FILENAME "dump.rdb"
|
||||
|
||||
/* Define redis_fstat to fstat */
|
||||
/* Define redis_fstat to fstat or fstat64() */
|
||||
#if defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_6)
|
||||
#define redis_fstat fstat64
|
||||
#define redis_stat stat64
|
||||
#else
|
||||
#define redis_fstat fstat
|
||||
#define redis_stat stat
|
||||
|
||||
#endif
|
||||
|
||||
/* Test for proc filesystem */
|
||||
#ifdef __linux__
|
||||
|
||||
+29
-39
@@ -56,6 +56,7 @@ int expireIfNeeded(redisDb *db, robj *key, robj *o);
|
||||
void slotToKeyUpdateKeyCore(const char *key, size_t keylen, int add);
|
||||
|
||||
std::unique_ptr<expireEntry> deserializeExpire(const char *str, size_t cch, size_t *poffset);
|
||||
sds serializeStoredObjectAndExpire(robj_roptr o);
|
||||
|
||||
dictType dictChangeDescType {
|
||||
dictSdsHash, /* hash function */
|
||||
@@ -1723,17 +1724,16 @@ int dbSwapDatabases(int id1, int id2) {
|
||||
id2 < 0 || id2 >= cserver.dbnum) return C_ERR;
|
||||
if (id1 == id2) return C_OK;
|
||||
std::swap(g_pserver->db[id1], g_pserver->db[id2]);
|
||||
|
||||
//swap db's id too, otherwise db does not match its id
|
||||
std::swap(g_pserver->db[id1]->id, g_pserver->db[id2]->id);
|
||||
|
||||
/* Note that we don't swap blocking_keys,
|
||||
* ready_keys and watched_keys, since we want clients to
|
||||
* remain in the same DB they were. so put them back */
|
||||
std::swap(g_pserver->db[id1]->blocking_keys, g_pserver->db[id2]->blocking_keys);
|
||||
std::swap(g_pserver->db[id1]->ready_keys, g_pserver->db[id2]->ready_keys);
|
||||
std::swap(g_pserver->db[id1]->watched_keys, g_pserver->db[id2]->watched_keys);
|
||||
|
||||
/* Don't swap the redisdb id, as it is expected to be same as database index everywhere else.
|
||||
For example, flushdb, master/slave replication, etc. */
|
||||
std::swap(g_pserver->db[id1]->id, g_pserver->db[id2]->id);
|
||||
std::swap(g_pserver->db[id2]->ready_keys, g_pserver->db[id2]->ready_keys);
|
||||
std::swap(g_pserver->db[id2]->watched_keys, g_pserver->db[id2]->watched_keys);
|
||||
|
||||
/* Now we need to handle clients blocked on lists: as an effect
|
||||
* of swapping the two DBs, a client that was waiting for list
|
||||
@@ -1756,11 +1756,7 @@ int dbSwapDatabases(int id1, int id2) {
|
||||
|
||||
/* SWAPDB db1 db2 */
|
||||
void swapdbCommand(client *c) {
|
||||
int id1, id2;
|
||||
|
||||
listNode *ln;
|
||||
listIter li;
|
||||
client *cl;
|
||||
int id1, id2, oriIdx;
|
||||
|
||||
/* Not allowed in cluster mode: we have just DB 0 there. */
|
||||
if (g_pserver->cluster_enabled) {
|
||||
@@ -1777,6 +1773,14 @@ void swapdbCommand(client *c) {
|
||||
"invalid second DB index") != C_OK)
|
||||
return;
|
||||
|
||||
// get client's original db's index
|
||||
for (int idb=0; idb < cserver.dbnum; ++idb) {
|
||||
if (g_pserver->db[idb]->id == c->db->id) {
|
||||
oriIdx = idb;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Swap... */
|
||||
if (dbSwapDatabases(id1,id2) == C_ERR) {
|
||||
addReplyError(c,"DB index is out of range");
|
||||
@@ -1786,29 +1790,18 @@ void swapdbCommand(client *c) {
|
||||
moduleFireServerEvent(REDISMODULE_EVENT_SWAPDB,0,&si);
|
||||
g_pserver->dirty++;
|
||||
|
||||
// Persist the databse index to storage dbid mapping into FLASH for later recovery.
|
||||
// set client's db to original db
|
||||
c->db=g_pserver->db[oriIdx];
|
||||
|
||||
// Persist the databse index to dbid mapping into FLASH for later recovery.
|
||||
if (g_pserver->m_pstorageFactory != nullptr && g_pserver->metadataDb != nullptr) {
|
||||
std::string dbid_key = "db-" + std::to_string(id1);
|
||||
g_pserver->metadataDb->insert(dbid_key.c_str(), dbid_key.length(), &g_pserver->db[id1]->storage_id, sizeof(g_pserver->db[id1]->storage_id), true);
|
||||
g_pserver->metadataDb->insert(dbid_key.c_str(), dbid_key.length(), &g_pserver->db[id1]->id, sizeof(g_pserver->db[id1]->id), true);
|
||||
|
||||
dbid_key = "db-" + std::to_string(id2);
|
||||
g_pserver->metadataDb->insert(dbid_key.c_str(), dbid_key.length(), &g_pserver->db[id2]->storage_id, sizeof(g_pserver->db[id2]->storage_id), true);
|
||||
g_pserver->metadataDb->insert(dbid_key.c_str(), dbid_key.length(), &g_pserver->db[id2]->id, sizeof(g_pserver->db[id2]->id), true);
|
||||
}
|
||||
addReply(c,shared.ok);
|
||||
|
||||
listRewind(g_pserver->clients,&li);
|
||||
while ((ln = listNext(&li)) != NULL) {
|
||||
cl = reinterpret_cast<struct client*>(listNodeValue(ln));
|
||||
std::unique_lock<decltype(cl->lock)> lock(cl->lock);
|
||||
if (cl->db->id == g_pserver->db[id1]->id) {
|
||||
cl->db = g_pserver->db[id2];
|
||||
updateDBWatchedKey(id1, cl);
|
||||
}
|
||||
else if (cl->db->id == g_pserver->db[id2]->id) {
|
||||
cl->db = g_pserver->db[id1];
|
||||
updateDBWatchedKey(id2, cl);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2639,14 +2632,13 @@ void moduleClusterLoadCallback(const char * rgchKey, size_t cchKey, void *data)
|
||||
moduleLoadCallback(rgchKey, cchKey, data);
|
||||
}
|
||||
|
||||
void redisDb::initialize(int id, int storage_id /* default no storage */)
|
||||
void redisDb::initialize(int id)
|
||||
{
|
||||
redisDbPersistentData::initialize();
|
||||
this->blocking_keys = dictCreate(&keylistDictType,NULL);
|
||||
this->ready_keys = dictCreate(&objectKeyPointerValueDictType,NULL);
|
||||
this->watched_keys = dictCreate(&keylistDictType,NULL);
|
||||
this->id = id;
|
||||
this->storage_id = storage_id;
|
||||
this->avg_ttl = 0;
|
||||
this->last_expire_set = 0;
|
||||
this->defrag_later = listCreate();
|
||||
@@ -2658,7 +2650,7 @@ void redisDb::storageProviderInitialize()
|
||||
if (g_pserver->m_pstorageFactory != nullptr)
|
||||
{
|
||||
IStorageFactory::key_load_iterator itr = g_pserver->cluster_enabled ? moduleClusterLoadCallback : moduleLoadCallback;
|
||||
this->setStorageProvider(StorageCache::create(g_pserver->m_pstorageFactory, storage_id, itr, &id));
|
||||
this->setStorageProvider(StorageCache::create(g_pserver->m_pstorageFactory, id, itr, &id));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2711,6 +2703,11 @@ void redisDbPersistentData::prepOverwriteForSnapshot(char *key)
|
||||
auto itr = m_pdbSnapshot->find_cached_threadsafe(key);
|
||||
if (itr.key() != nullptr)
|
||||
{
|
||||
if (itr.val()->FExpires()) {
|
||||
// Note: I'm sure we could handle this, but its too risky at the moment.
|
||||
// There are known bugs doing this with expires
|
||||
return;
|
||||
}
|
||||
sds keyNew = sdsdupshared(itr.key());
|
||||
if (dictAdd(m_pdictTombstone, keyNew, (void*)dictHashKey(m_pdict, key)) != DICT_OK)
|
||||
sdsfree(keyNew);
|
||||
@@ -2748,13 +2745,6 @@ void redisDbPersistentData::clear(void(callback)(void*))
|
||||
if (m_spstorage != nullptr)
|
||||
m_spstorage->clear(callback);
|
||||
dictEmpty(m_pdictTombstone,callback);
|
||||
|
||||
// To avoid issues with async rehash we completly free the old dict and create a fresh one
|
||||
dictRelease(m_pdict);
|
||||
dictRelease(m_pdictTombstone);
|
||||
m_pdict = dictCreate(&dbDictType, this);
|
||||
m_pdictTombstone = dictCreate(&dbTombstoneDictType, this);
|
||||
|
||||
m_pdbSnapshot = nullptr;
|
||||
m_numexpires = 0;
|
||||
}
|
||||
@@ -2890,10 +2880,10 @@ LNotFound:
|
||||
{
|
||||
dictAdd(m_pdict, sdsNewKey, o);
|
||||
|
||||
o->SetFExpires(spexpire != nullptr);
|
||||
if (spexpire != nullptr) {
|
||||
o->expire = std::move(*spexpire);
|
||||
}
|
||||
o->SetFExpires(spexpire != nullptr);
|
||||
g_pserver->stat_storage_provider_read_hits++;
|
||||
} else {
|
||||
sdsfree(sdsNewKey);
|
||||
|
||||
+22
-68
@@ -79,7 +79,6 @@ void printCrashReport(void);
|
||||
void bugReportEnd(int killViaSignal, int sig);
|
||||
void logStackTrace(void *eip, int uplevel);
|
||||
void getTempFileName(char tmpfile[], int tmpfileNum);
|
||||
bool initializeStorageProvider(const char **err);
|
||||
|
||||
/* ================================= Debugging ============================== */
|
||||
|
||||
@@ -309,7 +308,7 @@ void computeDatasetDigest(unsigned char *final) {
|
||||
mixDigest(final,&aux,sizeof(aux));
|
||||
|
||||
/* Iterate this DB writing every entry */
|
||||
db->iterate_threadsafe([final](const char *key, robj_roptr o)->bool {
|
||||
db->iterate_threadsafe([final, db](const char *key, robj_roptr o)->bool {
|
||||
unsigned char digest[20];
|
||||
robj *keyobj;
|
||||
|
||||
@@ -536,75 +535,30 @@ NULL
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (g_pserver->m_pstorageFactory) {
|
||||
protectClient(c);
|
||||
|
||||
for (int idb = 0; idb < cserver.dbnum; ++idb) {
|
||||
if (g_pserver->db[idb]->processChanges(false))
|
||||
g_pserver->db[idb]->commitChanges();
|
||||
g_pserver->db[idb]->storageProviderDelete();
|
||||
}
|
||||
delete g_pserver->metadataDb;
|
||||
|
||||
if (flush) emptyDb(-1,EMPTYDB_NO_FLAGS,NULL);
|
||||
|
||||
delete g_pserver->m_pstorageFactory;
|
||||
|
||||
const char *err;
|
||||
if (!initializeStorageProvider(&err))
|
||||
{
|
||||
serverLog(LL_WARNING, "Failed to initialize storage provider: %s",err);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
g_pserver->metadataDb = g_pserver->m_pstorageFactory->createMetadataDb();
|
||||
for (int idb = 0; idb < cserver.dbnum; ++idb)
|
||||
{
|
||||
int dbid = idb;
|
||||
std::string dbid_key = "db-" + std::to_string(idb);
|
||||
g_pserver->metadataDb->retrieve(dbid_key.c_str(), dbid_key.length(), [&](const char *, size_t, const void *data, size_t){
|
||||
dbid = *(int*)data;
|
||||
});
|
||||
delete g_pserver->db[idb];
|
||||
g_pserver->db[idb] = new (MALLOC_LOCAL) redisDb();
|
||||
g_pserver->db[idb]->initialize(dbid);
|
||||
}
|
||||
|
||||
moduleFireServerEvent(REDISMODULE_EVENT_LOADING, REDISMODULE_SUBEVENT_LOADING_FLASH_START, NULL);
|
||||
for (int idb = 0; idb < cserver.dbnum; ++idb)
|
||||
{
|
||||
g_pserver->db[idb]->storageProviderInitialize();
|
||||
g_pserver->db[idb]->trackChanges(false);
|
||||
}
|
||||
moduleFireServerEvent(REDISMODULE_EVENT_LOADING, REDISMODULE_SUBEVENT_LOADING_ENDED, NULL);
|
||||
|
||||
unprotectClient(c);
|
||||
} else {
|
||||
/* The default behavior is to save the RDB file before loading
|
||||
* it back. */
|
||||
if (save) {
|
||||
rdbSaveInfo rsi, *rsiptr;
|
||||
rsiptr = rdbPopulateSaveInfo(&rsi);
|
||||
if (rdbSave(nullptr, rsiptr) != C_OK) {
|
||||
addReply(c,shared.err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* The default behavior is to remove the current dataset from
|
||||
* memory before loading the RDB file, however when MERGE is
|
||||
* used together with NOFLUSH, we are able to merge two datasets. */
|
||||
if (flush) emptyDb(-1,EMPTYDB_NO_FLAGS,NULL);
|
||||
|
||||
protectClient(c);
|
||||
int ret = rdbLoadFile(g_pserver->rdb_filename,NULL,flags);
|
||||
unprotectClient(c);
|
||||
if (ret != C_OK) {
|
||||
addReplyError(c,"Error trying to load the RDB dump");
|
||||
/* The default behavior is to save the RDB file before loading
|
||||
* it back. */
|
||||
if (save) {
|
||||
rdbSaveInfo rsi, *rsiptr;
|
||||
rsiptr = rdbPopulateSaveInfo(&rsi);
|
||||
if (rdbSave(nullptr, rsiptr) != C_OK) {
|
||||
addReply(c,shared.err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* The default behavior is to remove the current dataset from
|
||||
* memory before loading the RDB file, however when MERGE is
|
||||
* used together with NOFLUSH, we are able to merge two datasets. */
|
||||
if (flush) emptyDb(-1,EMPTYDB_NO_FLAGS,NULL);
|
||||
|
||||
protectClient(c);
|
||||
int ret = rdbLoadFile(g_pserver->rdb_filename,NULL,flags);
|
||||
unprotectClient(c);
|
||||
if (ret != C_OK) {
|
||||
addReplyError(c,"Error trying to load the RDB dump");
|
||||
return;
|
||||
}
|
||||
serverLog(LL_WARNING,"DB reloaded by DEBUG RELOAD");
|
||||
addReply(c,shared.ok);
|
||||
} else if (!strcasecmp(szFromObj(c->argv[1]),"loadaof")) {
|
||||
@@ -1135,7 +1089,7 @@ static void *getMcontextEip(ucontext_t *uc) {
|
||||
#elif defined(__i386__)
|
||||
return (void*) uc->uc_mcontext->__ss.__eip;
|
||||
#else
|
||||
return (void*) uc->uc_mcontext->__ss.__pc;
|
||||
return (void*) uc->uc_mcontext->__ss.__srr0;
|
||||
#endif
|
||||
#elif defined(__APPLE__) && defined(MAC_OS_X_VERSION_10_6)
|
||||
/* OSX >= 10.6 */
|
||||
|
||||
+3
-5
@@ -518,13 +518,11 @@ void pexpireMemberAtCommand(client *c)
|
||||
} while (sampled == 0 ||
|
||||
(expired*100/sampled) > config_cycle_acceptable_stale);
|
||||
} else {
|
||||
long prev_expired;
|
||||
long long now = mstime();
|
||||
long long now;
|
||||
size_t tried = 0;
|
||||
std::vector<std::string> keys;
|
||||
do {
|
||||
prev_expired = total_expired;
|
||||
keys = db->getStorageCache()->getExpirationCandidates(ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP);
|
||||
keys = db->getStorageCache()->getExpirationCandidates(ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP, now);
|
||||
for (std::string key : keys) {
|
||||
robj* keyobj = createStringObject(key.c_str(), key.size());
|
||||
db->find(szFromObj(keyobj));
|
||||
@@ -535,7 +533,7 @@ void pexpireMemberAtCommand(client *c)
|
||||
}
|
||||
total_sampled += keys.size();
|
||||
elapsed = ustime()-start;
|
||||
} while (keys.size() > 0 && (elapsed < timelimit) && (total_expired - prev_expired) > 0);
|
||||
} while (keys.size() > 0 && (elapsed < timelimit));
|
||||
|
||||
if (ustime()-start > timelimit) {
|
||||
timelimit_exit = 1;
|
||||
|
||||
@@ -160,8 +160,6 @@ public:
|
||||
|
||||
expireEntry &operator=(expireEntry &&e)
|
||||
{
|
||||
if (FFat())
|
||||
delete pfatentry();
|
||||
s = e.s;
|
||||
e.s.m_whenAndPtrUnion = 0;
|
||||
e.s.fFat = false;
|
||||
@@ -169,8 +167,6 @@ public:
|
||||
}
|
||||
|
||||
expireEntry &operator=(expireEntry &e) {
|
||||
if (FFat())
|
||||
delete pfatentry();
|
||||
if (e.FFat()) {
|
||||
s.m_whenAndPtrUnion = reinterpret_cast<long long>(new expireEntryFat(*e.pfatentry()));
|
||||
s.fFat = true;
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
#include <deque>
|
||||
extern "C" {
|
||||
#include <sds.h> /* Use hiredis sds. */
|
||||
#include "sdscompat.h"
|
||||
#include <sdscompat.h>
|
||||
#include "hiredis.h"
|
||||
}
|
||||
#include "ae.h"
|
||||
|
||||
@@ -19,7 +19,6 @@ static size_t getMemKey(std::string key) {
|
||||
}
|
||||
return 0;
|
||||
# else
|
||||
(void)key;
|
||||
return 0;
|
||||
# endif
|
||||
}
|
||||
|
||||
+3
-4
@@ -690,9 +690,8 @@ void moduleHandlePropagationAfterCommandCallback(RedisModuleCtx *ctx) {
|
||||
}
|
||||
|
||||
/* Free the context after the user function was called. */
|
||||
void moduleFreeContext(RedisModuleCtx *ctx, bool propogate) {
|
||||
if (propogate)
|
||||
moduleHandlePropagationAfterCommandCallback(ctx);
|
||||
void moduleFreeContext(RedisModuleCtx *ctx) {
|
||||
moduleHandlePropagationAfterCommandCallback(ctx);
|
||||
autoMemoryCollect(ctx);
|
||||
poolAllocRelease(ctx);
|
||||
if (ctx->postponed_arrays) {
|
||||
@@ -7058,7 +7057,7 @@ RedisModuleString *RM_DictPrev(RedisModuleCtx *ctx, RedisModuleDictIter *di, voi
|
||||
/* Compare the element currently pointed by the iterator to the specified
|
||||
* element given by key/keylen, according to the operator 'op' (the set of
|
||||
* valid operators are the same valid for RedisModule_DictIteratorStart).
|
||||
* If the comparison is successful the command returns REDISMODULE_OK
|
||||
* If the comparision is successful the command returns REDISMODULE_OK
|
||||
* otherwise REDISMODULE_ERR is returned.
|
||||
*
|
||||
* This is useful when we want to just emit a lexicographical range, so
|
||||
|
||||
@@ -4,7 +4,7 @@ OBJECT_FILES := modmain.o
|
||||
MODSNAP_CXX_FLAGS := -std=gnu++14
|
||||
|
||||
%.o: %.cpp
|
||||
$(CXX) -o $@ -c $< $(MODULE_FLAGS) -I../../../deps/cpp-statsd-client/include $(MODSNAP_CXX_FLAGS) -g
|
||||
$(CXX) -o $@ -c $< $(MODULE_FLAGS) -I../../../deps/cpp-statsd-client/include $(MODSNAP_CXX_FLAGS)
|
||||
|
||||
modstatsd.so: $(OBJECT_FILES)
|
||||
$(CXX) -shared $(OBJECT_FILES) -o modstatsd.so
|
||||
|
||||
@@ -76,7 +76,7 @@ std::string m_strPrefix { "keydb" };
|
||||
const std::regex g_replica_or_db_info_regex { "^(slave|db)(\\d+)" };
|
||||
const char *g_string_counter_separator = "__";
|
||||
const uint64_t g_stats_buffer_size_bytes = 1600;
|
||||
std::string nodeName;
|
||||
utsname sysName;
|
||||
int unameResult;
|
||||
|
||||
enum class StatsD_Type {
|
||||
@@ -582,7 +582,7 @@ void event_cron_handler(struct RedisModuleCtx *ctx, RedisModuleEvent eid, uint64
|
||||
size_t startTime = ustime();
|
||||
|
||||
#ifdef __linux__
|
||||
/* Log CPU Usage */
|
||||
/* Log CPU Usage */
|
||||
static long long s_mscpuLast = 0;
|
||||
struct rusage self_ru;
|
||||
getrusage(RUSAGE_SELF, &self_ru);
|
||||
@@ -591,7 +591,7 @@ void event_cron_handler(struct RedisModuleCtx *ctx, RedisModuleEvent eid, uint64
|
||||
+ (self_ru.ru_stime.tv_sec * 1000) + (self_ru.ru_stime.tv_usec / 1000);
|
||||
|
||||
|
||||
g_stats->gauge("cpu_load_perc", ((double)(mscpuCur - s_mscpuLast) / ((curTime - lastTime)*1000))*100, false /* prefixOnly */);
|
||||
g_stats->gauge("cpu_load_perc", (double)(mscpuCur - s_mscpuLast) / ((curTime - lastTime)*1000), true /* prefixOnly */);
|
||||
s_mscpuLast = mscpuCur;
|
||||
#endif
|
||||
|
||||
@@ -600,7 +600,7 @@ void event_cron_handler(struct RedisModuleCtx *ctx, RedisModuleEvent eid, uint64
|
||||
|
||||
/* node name */
|
||||
if (unameResult == 0) {
|
||||
g_stats->increment("node_name" + std::string(g_string_counter_separator) + nodeName);
|
||||
g_stats->increment("node_name" + std::string(g_string_counter_separator) + sysName.nodename);
|
||||
}
|
||||
|
||||
/* Log INFO Fields */
|
||||
@@ -653,7 +653,7 @@ void event_cron_handler(struct RedisModuleCtx *ctx, RedisModuleEvent eid, uint64
|
||||
reply = RedisModule_Call(ctx, "dbsize", "");
|
||||
long long keys = RedisModule_CallReplyInteger(reply);
|
||||
RedisModule_FreeCallReply(reply);
|
||||
g_stats->gauge("keys", keys, false /* prefixOnly */);
|
||||
g_stats->gauge("keys", keys);
|
||||
RedisModule_Log(ctx, REDISMODULE_LOGLEVEL_DEBUG, "Emitting metric \"keys\": %llu", keys);
|
||||
g_stats->timing("emit_keys_metric_time_taken_us", ustime() - commandStartTime);
|
||||
|
||||
@@ -672,20 +672,17 @@ extern "C" int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv,
|
||||
RedisModule_AutoMemory(ctx);
|
||||
/* Use pod name if available*/
|
||||
const char *podName = getenv("POD_NAME");
|
||||
utsname sysName;
|
||||
unameResult = uname(&sysName);
|
||||
if (unameResult == 0) {
|
||||
nodeName = std::string(sysName.nodename);
|
||||
std::replace(nodeName.begin(), nodeName.end(), '.', '-');
|
||||
}
|
||||
if (podName != nullptr) {
|
||||
m_strPrefix = podName;
|
||||
std::replace(m_strPrefix.begin(), m_strPrefix.end(), '.', '-');
|
||||
}
|
||||
else if (unameResult == 0) {
|
||||
m_strPrefix = nodeName;
|
||||
unameResult = 1;
|
||||
else {
|
||||
if (unameResult == 0) {
|
||||
m_strPrefix = std::string(sysName.nodename);
|
||||
unameResult = 1;
|
||||
}
|
||||
}
|
||||
std::replace(m_strPrefix.begin(), m_strPrefix.end(), '.', '-');
|
||||
|
||||
for (int iarg = 0; iarg < argc; ++iarg) {
|
||||
size_t len = 0;
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
#ifdef CLIENT
|
||||
extern "C" {
|
||||
#include "sdscompat.h"
|
||||
#include <sdscompat.h>
|
||||
#include <sds.h>
|
||||
}
|
||||
#else
|
||||
@@ -19,7 +19,7 @@ extern "C" {
|
||||
#ifdef MOTD
|
||||
#include <curl/curl.h>
|
||||
|
||||
#if !defined(USE_SYSTEM_HIREDIS) && defined(CLIENT)
|
||||
#ifdef CLIENT
|
||||
extern "C" {
|
||||
__attribute__ ((weak)) hisds hi_sdscatlen(hisds s, const void *t, size_t len) {
|
||||
return sdscatlen(s, t, len);
|
||||
|
||||
@@ -429,24 +429,6 @@ void touchAllWatchedKeysInDb(redisDb *emptied, redisDb *replaced_with) {
|
||||
dictReleaseIterator(di);
|
||||
}
|
||||
|
||||
/* Update the DB of the watchedKey structure incase if the c->db (currently selected DB) is updated.
|
||||
* For example, it may happen during the SWAPDB.
|
||||
* watchForKey() sets the original DB of the watchedKey structure with the c->db
|
||||
* but the c->db can be updated incase of SWAPDB command. */
|
||||
void updateDBWatchedKey(int dbid, client *c) {
|
||||
listIter li;
|
||||
listNode *ln;
|
||||
watchedKey *wk;
|
||||
|
||||
listRewind(c->watched_keys,&li);
|
||||
while((ln = listNext(&li))) {
|
||||
wk = (watchedKey*)listNodeValue(ln);
|
||||
if (wk->db->id == dbid) {
|
||||
wk->db = c->db;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void watchCommand(client *c) {
|
||||
int j;
|
||||
|
||||
|
||||
@@ -163,6 +163,7 @@ client *createClient(connection *conn, int iel) {
|
||||
c->multibulklen = 0;
|
||||
c->bulklen = -1;
|
||||
c->sentlen = 0;
|
||||
c->sentlenAsync = 0;
|
||||
c->flags = 0;
|
||||
c->fPendingAsyncWrite = FALSE;
|
||||
c->fPendingAsyncWriteHandler = FALSE;
|
||||
|
||||
@@ -46,7 +46,6 @@ robj *createObject(int type, void *ptr) {
|
||||
char *oB = (char*)zcalloc(sizeof(robj)+mvccExtraBytes, MALLOC_SHARED);
|
||||
robj *o = reinterpret_cast<robj*>(oB + mvccExtraBytes);
|
||||
|
||||
new (o) redisObject;
|
||||
o->type = type;
|
||||
o->encoding = OBJ_ENCODING_RAW;
|
||||
o->m_ptr = ptr;
|
||||
@@ -419,7 +418,6 @@ void decrRefCount(robj_roptr o) {
|
||||
case OBJ_NESTEDHASH: freeNestedHashObject(o); break;
|
||||
default: serverPanic("Unknown object type"); break;
|
||||
}
|
||||
o->~redisObject();
|
||||
if (g_pserver->fActiveReplica) {
|
||||
zfree(reinterpret_cast<redisObjectExtended*>(o.unsafe_robjcast())-1);
|
||||
} else {
|
||||
|
||||
+1
-1
@@ -2542,7 +2542,7 @@ robj *rdbLoadObject(int rdbtype, rio *rdb, sds key, int *error, uint64_t mvcc_ts
|
||||
* encoding version in the lower 10 bits of the module ID. */
|
||||
void *ptr = mt->rdb_load(&io,moduleid&1023);
|
||||
if (io.ctx) {
|
||||
moduleFreeContext(io.ctx, false /* propogate */);
|
||||
moduleFreeContext(io.ctx);
|
||||
zfree(io.ctx);
|
||||
}
|
||||
|
||||
|
||||
+33
-47
@@ -8,46 +8,38 @@ class readWriteLock {
|
||||
int m_readCount = 0;
|
||||
int m_writeCount = 0;
|
||||
bool m_writeWaiting = false;
|
||||
bool m_multi = true;
|
||||
bool m_notify = true;
|
||||
public:
|
||||
readWriteLock(const char *name) : m_readLock(name), m_writeLock(name) {}
|
||||
|
||||
void acquireRead() {
|
||||
std::unique_lock<fastlock> rm(m_readLock, std::defer_lock);
|
||||
if (m_multi) {
|
||||
rm.lock();
|
||||
while (m_writeCount > 0 || m_writeWaiting)
|
||||
m_cv.wait(rm);
|
||||
}
|
||||
std::unique_lock<fastlock> rm(m_readLock);
|
||||
while (m_writeCount > 0 || m_writeWaiting)
|
||||
m_cv.wait(rm);
|
||||
m_readCount++;
|
||||
}
|
||||
|
||||
bool tryAcquireRead() {
|
||||
std::unique_lock<fastlock> rm(m_readLock, std::defer_lock);
|
||||
if (m_multi) {
|
||||
if (!rm.try_lock())
|
||||
return false;
|
||||
if (m_writeCount > 0 || m_writeWaiting)
|
||||
return false;
|
||||
}
|
||||
if (!rm.try_lock())
|
||||
return false;
|
||||
if (m_writeCount > 0 || m_writeWaiting)
|
||||
return false;
|
||||
m_readCount++;
|
||||
return true;
|
||||
}
|
||||
|
||||
void acquireWrite(bool exclusive = true) {
|
||||
std::unique_lock<fastlock> rm(m_readLock, std::defer_lock);
|
||||
if (m_multi) {
|
||||
rm.lock();
|
||||
m_writeWaiting = true;
|
||||
while (m_readCount > 0)
|
||||
std::unique_lock<fastlock> rm(m_readLock);
|
||||
m_writeWaiting = true;
|
||||
while (m_readCount > 0)
|
||||
m_cv.wait(rm);
|
||||
if (exclusive) {
|
||||
/* Another thread might have the write lock while we have the read lock
|
||||
but won't be able to release it until they can acquire the read lock
|
||||
so release the read lock and try again instead of waiting to avoid deadlock */
|
||||
while(!m_writeLock.try_lock())
|
||||
m_cv.wait(rm);
|
||||
if (exclusive) {
|
||||
/* Another thread might have the write lock while we have the internal lock
|
||||
but won't be able to release it until they can acquire the internal lock
|
||||
so release the internal lock and try again instead of waiting to avoid deadlock */
|
||||
while(!m_writeLock.try_lock())
|
||||
m_cv.wait(rm);
|
||||
}
|
||||
}
|
||||
m_writeCount++;
|
||||
m_writeWaiting = false;
|
||||
@@ -60,38 +52,32 @@ public:
|
||||
|
||||
bool tryAcquireWrite(bool exclusive = true) {
|
||||
std::unique_lock<fastlock> rm(m_readLock, std::defer_lock);
|
||||
if (m_multi) {
|
||||
if (!rm.try_lock())
|
||||
if (!rm.try_lock())
|
||||
return false;
|
||||
if (m_readCount > 0)
|
||||
return false;
|
||||
if (exclusive)
|
||||
if (!m_writeLock.try_lock())
|
||||
return false;
|
||||
if (m_readCount > 0)
|
||||
return false;
|
||||
if (exclusive)
|
||||
if (!m_writeLock.try_lock())
|
||||
return false;
|
||||
}
|
||||
m_writeCount++;
|
||||
return true;
|
||||
}
|
||||
|
||||
void releaseRead() {
|
||||
std::unique_lock<fastlock> rm(m_readLock, std::defer_lock);
|
||||
if (m_multi) {
|
||||
rm.lock();
|
||||
m_cv.notify_all();
|
||||
}
|
||||
std::unique_lock<fastlock> rm(m_readLock);
|
||||
m_readCount--;
|
||||
if (m_notify)
|
||||
m_cv.notify_all();
|
||||
}
|
||||
|
||||
void releaseWrite(bool exclusive = true) {
|
||||
std::unique_lock<fastlock> rm(m_readLock, std::defer_lock);
|
||||
std::unique_lock<fastlock> rm(m_readLock);
|
||||
serverAssert(m_writeCount > 0);
|
||||
if (m_multi) {
|
||||
rm.lock();
|
||||
if (exclusive)
|
||||
m_writeLock.unlock();
|
||||
m_cv.notify_all();
|
||||
}
|
||||
if (exclusive)
|
||||
m_writeLock.unlock();
|
||||
m_writeCount--;
|
||||
if (m_notify)
|
||||
m_cv.notify_all();
|
||||
}
|
||||
|
||||
void downgradeWrite(bool exclusive = true) {
|
||||
@@ -99,8 +85,8 @@ public:
|
||||
acquireRead();
|
||||
}
|
||||
|
||||
void setMulti(bool multi) {
|
||||
m_multi = multi;
|
||||
void setNotify(bool notify) {
|
||||
m_notify = notify;
|
||||
}
|
||||
|
||||
bool hasReader() {
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
#include <pthread.h>
|
||||
#include <string>
|
||||
extern "C" {
|
||||
#include "sdscompat.h" /* Use hiredis' sds compat header that maps sds calls to their hi_ variants */
|
||||
#include <sdscompat.h> /* Use hiredis' sds compat header that maps sds calls to their hi_ variants */
|
||||
#include <sds.h> /* Use hiredis sds. */
|
||||
#include <hiredis.h>
|
||||
}
|
||||
|
||||
+3
-9
@@ -54,7 +54,7 @@
|
||||
#include <openssl/err.h>
|
||||
#include <hiredis_ssl.h>
|
||||
#endif
|
||||
#include "sdscompat.h" /* Use hiredis' sds compat header that maps sds calls to their hi_ variants */
|
||||
#include <sdscompat.h> /* Use hiredis' sds compat header that maps sds calls to their hi_ variants */
|
||||
#include <sds.h> /* use sds.h from hiredis, so that only one set of sds functions will be present in the binary */
|
||||
#include "adlist.h"
|
||||
#include "zmalloc.h"
|
||||
@@ -2524,10 +2524,7 @@ cleanup:
|
||||
|
||||
static int clusterManagerNodeConnect(clusterManagerNode *node) {
|
||||
if (node->context) redisFree(node->context);
|
||||
struct timeval tv;
|
||||
tv.tv_sec = config.cluster_manager_command.timeout / 1000;
|
||||
tv.tv_usec = (config.cluster_manager_command.timeout % 1000) * 1000;
|
||||
node->context = redisConnectWithTimeout(node->ip, node->port, tv);
|
||||
node->context = redisConnect(node->ip, node->port);
|
||||
if (!node->context->err && config.tls) {
|
||||
const char *err = NULL;
|
||||
if (cliSecureConnection(node->context, config.sslconfig, &err) == REDIS_ERR && err) {
|
||||
@@ -5629,10 +5626,7 @@ static int clusterManagerCommandImport(int argc, char **argv) {
|
||||
char *reply_err = NULL;
|
||||
redisReply *src_reply = NULL;
|
||||
// Connect to the source node.
|
||||
struct timeval tv;
|
||||
tv.tv_sec = config.cluster_manager_command.timeout / 1000;
|
||||
tv.tv_usec = (config.cluster_manager_command.timeout % 1000) * 1000;
|
||||
redisContext *src_ctx = redisConnectWithTimeout(src_ip, src_port, tv);
|
||||
redisContext *src_ctx = redisConnect(src_ip, src_port);
|
||||
if (src_ctx->err) {
|
||||
success = 0;
|
||||
fprintf(stderr,"Could not connect to KeyDB at %s:%d: %s.\n", src_ip,
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
#include "cli_common.h"
|
||||
#include "sdscompat.h" /* Use hiredis' sds compat header that maps sds calls to their hi_ variants */
|
||||
#include <sdscompat.h> /* Use hiredis' sds compat header that maps sds calls to their hi_ variants */
|
||||
#include <sds.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
+51
-69
@@ -188,8 +188,6 @@ int bg_unlink(const char *filename) {
|
||||
/* ---------------------------------- MASTER -------------------------------- */
|
||||
|
||||
bool createDiskBacklog() {
|
||||
if (g_pserver->repl_backlog_disk != nullptr)
|
||||
return true; // already exists
|
||||
// Lets create some disk backed pages and add them here
|
||||
std::string path = "./repl-backlog-temp" + std::to_string(gettid());
|
||||
#if (defined __APPLE__ || defined __FreeBSD__)
|
||||
@@ -1019,6 +1017,8 @@ public:
|
||||
void addReplica(client *replica) {
|
||||
replicas.push_back(replica);
|
||||
replicationSetupSlaveForFullResync(replica,getPsyncInitialOffset());
|
||||
// Optimize the socket for bulk transfer
|
||||
//connDisableTcpNoDelay(replica->conn);
|
||||
}
|
||||
|
||||
bool isActive() const { return !replicas.empty(); }
|
||||
@@ -1091,7 +1091,7 @@ public:
|
||||
reply->used += size;
|
||||
}
|
||||
|
||||
void addLongLongWithPrefix(long long val, char prefix) {
|
||||
void addLongWithPrefix(long val, char prefix) {
|
||||
char buf[128];
|
||||
int len;
|
||||
|
||||
@@ -1103,19 +1103,15 @@ public:
|
||||
}
|
||||
|
||||
void addArrayLen(int len) {
|
||||
addLongLongWithPrefix(len, '*');
|
||||
addLongWithPrefix(len, '*');
|
||||
}
|
||||
|
||||
void addLong(long val) {
|
||||
addLongLongWithPrefix(val, ':');
|
||||
}
|
||||
|
||||
void addLongLong(long long val) {
|
||||
addLongLongWithPrefix(val, ':');
|
||||
addLongWithPrefix(val, ':');
|
||||
}
|
||||
|
||||
void addString(const char *s, unsigned long len) {
|
||||
addLongLongWithPrefix(len, '$');
|
||||
addLongWithPrefix(len, '$');
|
||||
addData(s, len);
|
||||
addData("\r\n", 2);
|
||||
}
|
||||
@@ -1151,19 +1147,22 @@ int rdbSaveSnapshotForReplication(rdbSaveInfo *rsi) {
|
||||
// TODO: This needs to be on a background thread
|
||||
int retval = C_OK;
|
||||
serverAssert(GlobalLocksAcquired());
|
||||
serverLog(LL_NOTICE, "Starting fast full sync with target: %s", "disk");
|
||||
serverLog(LL_NOTICE, "Starting storage provider fast full sync with target: %s", "disk");
|
||||
|
||||
std::shared_ptr<replicationBuffer> spreplBuf = std::make_shared<replicationBuffer>();
|
||||
listNode *ln;
|
||||
listIter li;
|
||||
client *replica = nullptr;
|
||||
listRewind(g_pserver->slaves, &li);
|
||||
while ((ln = listNext(&li))) {
|
||||
while (replica == nullptr && (ln = listNext(&li))) {
|
||||
client *replicaCur = (client*)listNodeValue(ln);
|
||||
if ((replicaCur->slave_capa & SLAVE_CAPA_KEYDB_FASTSYNC) && (replicaCur->replstate == SLAVE_STATE_WAIT_BGSAVE_START)) {
|
||||
spreplBuf->addReplica(replicaCur);
|
||||
if ((replicaCur->slave_capa & SLAVE_CAPA_ROCKSDB_SNAPSHOT) && (replicaCur->replstate == SLAVE_STATE_WAIT_BGSAVE_START)) {
|
||||
replica = replicaCur;
|
||||
spreplBuf->addReplica(replica);
|
||||
replicaCur->replstate = SLAVE_STATE_FASTSYNC_TX;
|
||||
}
|
||||
}
|
||||
serverAssert(replica != nullptr);
|
||||
|
||||
spreplBuf->addArrayLen(2); // Two sections: Metadata and databases
|
||||
|
||||
@@ -1178,7 +1177,7 @@ int rdbSaveSnapshotForReplication(rdbSaveInfo *rsi) {
|
||||
spreplBuf->addString(rsi->repl_id, CONFIG_RUN_ID_SIZE);
|
||||
spreplBuf->addArrayLen(2);
|
||||
spreplBuf->addString("repl-offset", 11);
|
||||
spreplBuf->addLongLong(rsi->master_repl_offset);
|
||||
spreplBuf->addLong(rsi->master_repl_offset);
|
||||
|
||||
if (dictSize(g_pserver->lua_scripts)) {
|
||||
dictEntry *de;
|
||||
@@ -1194,13 +1193,13 @@ int rdbSaveSnapshotForReplication(rdbSaveInfo *rsi) {
|
||||
di = NULL; /* So that we don't release it again on error. */
|
||||
}
|
||||
|
||||
std::shared_ptr<std::vector<const redisDbPersistentDataSnapshot*>> spvecsnapshot = std::make_shared<std::vector<const redisDbPersistentDataSnapshot*>>();
|
||||
std::shared_ptr<std::vector<std::unique_ptr<const StorageCache>>> spvecspsnapshot = std::make_shared<std::vector<std::unique_ptr<const StorageCache>>>();
|
||||
for (int idb = 0; idb < cserver.dbnum; ++idb) {
|
||||
spvecsnapshot->emplace_back(g_pserver->db[idb]->createSnapshot(getMvccTstamp(), false));
|
||||
spvecspsnapshot->emplace_back(g_pserver->db[idb]->CloneStorageCache());
|
||||
}
|
||||
aeReleaseLock();
|
||||
|
||||
g_pserver->asyncworkqueue->AddWorkFunction([spreplBuf = std::move(spreplBuf), spvecsnapshot = std::move(spvecsnapshot)]{
|
||||
g_pserver->asyncworkqueue->AddWorkFunction([spreplBuf = std::move(spreplBuf), spvecspsnapshot = std::move(spvecspsnapshot)]{
|
||||
int retval = C_OK;
|
||||
auto timeStart = ustime();
|
||||
auto lastLogTime = timeStart;
|
||||
@@ -1210,16 +1209,15 @@ int rdbSaveSnapshotForReplication(rdbSaveInfo *rsi) {
|
||||
// Databases
|
||||
replBuf.addArrayLen(cserver.dbnum);
|
||||
for (int idb = 0; idb < cserver.dbnum; ++idb) {
|
||||
auto &spsnapshot = (*spvecsnapshot)[idb];
|
||||
size_t snapshotDeclaredCount = spsnapshot->size();
|
||||
auto &spsnapshot = (*spvecspsnapshot)[idb];
|
||||
size_t snapshotDeclaredCount = spsnapshot->count();
|
||||
replBuf.addArrayLen(snapshotDeclaredCount);
|
||||
size_t count = 0;
|
||||
bool result = spsnapshot->iterate_threadsafe([&replBuf, &count, &cbData, &lastLogTime, &cbLastUpdate](const char *strKey, robj_roptr o) -> bool{
|
||||
bool result = spsnapshot->enumerate([&replBuf, &count, &cbData, &lastLogTime, &cbLastUpdate](const char *rgchKey, size_t cchKey, const void *rgchVal, size_t cchVal) -> bool{
|
||||
replBuf.addArrayLen(2);
|
||||
|
||||
replBuf.addString(strKey, sdslen(strKey));
|
||||
sds strT = serializeStoredObjectAndExpire(o);
|
||||
replBuf.addString(strT, sdslen(strT));
|
||||
replBuf.addString(rgchKey, cchKey);
|
||||
replBuf.addString((const char *)rgchVal, cchVal);
|
||||
++count;
|
||||
if ((count % 8092) == 0) {
|
||||
auto curTime = ustime();
|
||||
@@ -1230,8 +1228,7 @@ int rdbSaveSnapshotForReplication(rdbSaveInfo *rsi) {
|
||||
lastLogTime = ustime();
|
||||
}
|
||||
}
|
||||
cbData += sdslen(strKey) + sdslen(strT);
|
||||
sdsfree(strT);
|
||||
cbData += cchKey + cchVal;
|
||||
return replBuf.isActive();
|
||||
});
|
||||
|
||||
@@ -1303,7 +1300,7 @@ int startBgsaveForReplication(int mincapa) {
|
||||
/* Only do rdbSave* when rsiptr is not NULL,
|
||||
* otherwise replica will miss repl-stream-db. */
|
||||
if (rsiptr) {
|
||||
if (mincapa & SLAVE_CAPA_KEYDB_FASTSYNC && FFastSyncEnabled())
|
||||
if (mincapa & SLAVE_CAPA_ROCKSDB_SNAPSHOT && g_pserver->m_pstorageFactory)
|
||||
retval = rdbSaveSnapshotForReplication(rsiptr);
|
||||
else if (socket_target)
|
||||
retval = rdbSaveToSlavesSockets(rsiptr);
|
||||
@@ -1482,7 +1479,7 @@ void syncCommand(client *c) {
|
||||
}
|
||||
|
||||
/* CASE 0: Fast Sync */
|
||||
if (c->slave_capa & SLAVE_CAPA_KEYDB_FASTSYNC && FFastSyncEnabled()) {
|
||||
if ((c->slave_capa & SLAVE_CAPA_ROCKSDB_SNAPSHOT) && g_pserver->m_pstorageFactory) {
|
||||
serverLog(LL_NOTICE,"Fast SYNC on next replication cycle");
|
||||
/* CASE 1: BGSAVE is in progress, with disk target. */
|
||||
} else if (g_pserver->FRdbSaveInProgress() &&
|
||||
@@ -1673,8 +1670,8 @@ void replconfCommand(client *c) {
|
||||
c->slave_capa |= SLAVE_CAPA_PSYNC2;
|
||||
else if (!strcasecmp((const char*)ptrFromObj(c->argv[j+1]), "activeExpire"))
|
||||
c->slave_capa |= SLAVE_CAPA_ACTIVE_EXPIRE;
|
||||
else if (!strcasecmp((const char*)ptrFromObj(c->argv[j+1]), "keydb-fastsync"))
|
||||
c->slave_capa |= SLAVE_CAPA_KEYDB_FASTSYNC;
|
||||
else if (!strcasecmp((const char*)ptrFromObj(c->argv[j+1]), "rocksdb-snapshot-load"))
|
||||
c->slave_capa |= SLAVE_CAPA_ROCKSDB_SNAPSHOT;
|
||||
|
||||
fCapaCommand = true;
|
||||
} else if (!strcasecmp((const char*)ptrFromObj(c->argv[j]),"ack")) {
|
||||
@@ -1739,14 +1736,10 @@ void replconfCommand(client *c) {
|
||||
|
||||
if (fCapaCommand) {
|
||||
sds reply = sdsnew("+OK");
|
||||
if (g_pserver->fActiveReplica) {
|
||||
if (g_pserver->fActiveReplica)
|
||||
reply = sdscat(reply, " active-replica");
|
||||
}
|
||||
if ((c->slave_capa & SLAVE_CAPA_KEYDB_FASTSYNC) && FFastSyncEnabled()) {
|
||||
reply = sdscat(reply, " keydb-fastsync-save");
|
||||
} else {
|
||||
c->slave_capa = (c->slave_capa & (~SLAVE_CAPA_KEYDB_FASTSYNC)); // never try to fast sync for this as they won't expect it
|
||||
}
|
||||
if (g_pserver->m_pstorageFactory && (c->slave_capa & SLAVE_CAPA_ROCKSDB_SNAPSHOT) && !g_pserver->fActiveReplica)
|
||||
reply = sdscat(reply, " rocksdb-snapshot-save");
|
||||
reply = sdscat(reply, "\r\n");
|
||||
addReplySds(c, reply);
|
||||
} else {
|
||||
@@ -2520,7 +2513,6 @@ bool readSnapshotBulkPayload(connection *conn, redisMaster *mi, rdbSaveInfo &rsi
|
||||
}
|
||||
}
|
||||
|
||||
serverAssert(mi->parseState != nullptr);
|
||||
for (int iter = 0; iter < 10; ++iter) {
|
||||
if (mi->parseState->shouldThrottle())
|
||||
return false;
|
||||
@@ -2531,16 +2523,11 @@ bool readSnapshotBulkPayload(connection *conn, redisMaster *mi, rdbSaveInfo &rsi
|
||||
|
||||
auto nread = connRead(conn, mi->bulkreadBuffer+qblen, readlen);
|
||||
if (nread <= 0) {
|
||||
if (connGetState(conn) != CONN_STATE_CONNECTED) {
|
||||
serverLog(LL_WARNING,"I/O error trying to sync with MASTER: %s",
|
||||
(nread == -1) ? strerror(errno) : "connection lost");
|
||||
if (connGetState(conn) != CONN_STATE_CONNECTED)
|
||||
cancelReplicationHandshake(mi, true);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
g_pserver->stat_net_input_bytes += nread;
|
||||
mi->repl_transfer_lastio = g_pserver->unixtime;
|
||||
mi->repl_transfer_read += nread;
|
||||
sdsIncrLen(mi->bulkreadBuffer,nread);
|
||||
|
||||
size_t offset = 0;
|
||||
@@ -2608,16 +2595,12 @@ bool readSnapshotBulkPayload(connection *conn, redisMaster *mi, rdbSaveInfo &rsi
|
||||
if (mi->parseState->depth() != 0)
|
||||
return false;
|
||||
|
||||
long long repl_stream_db = mi->parseState->getMetaDataLongLong("repl-stream-db");
|
||||
if (repl_stream_db < INT_MIN || repl_stream_db > INT_MAX) {
|
||||
throw "Invalid repl_stream_db value";
|
||||
}
|
||||
rsi.repl_stream_db = static_cast<int>(repl_stream_db);
|
||||
static_assert(sizeof(long) == sizeof(long long),"");
|
||||
rsi.repl_stream_db = mi->parseState->getMetaDataLongLong("repl-stream-db");
|
||||
rsi.repl_offset = mi->parseState->getMetaDataLongLong("repl-offset");
|
||||
sds str = mi->parseState->getMetaDataStr("repl-id");
|
||||
if (sdslen(str) == CONFIG_RUN_ID_SIZE) {
|
||||
if (sdslen(str) == CONFIG_RUN_ID_SIZE+1) {
|
||||
memcpy(rsi.repl_id, str, CONFIG_RUN_ID_SIZE+1);
|
||||
rsi.repl_id_is_set = 1;
|
||||
}
|
||||
|
||||
fFinished = true;
|
||||
@@ -3016,7 +2999,7 @@ void readSyncBulkPayload(connection *conn) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mi->isKeydbFastsync) {
|
||||
if (mi->isRocksdbSnapshotRepl) {
|
||||
if (!readSnapshotBulkPayload(conn, mi, rsi))
|
||||
return;
|
||||
} else {
|
||||
@@ -3029,15 +3012,17 @@ void readSyncBulkPayload(connection *conn) {
|
||||
|
||||
/* Final setup of the connected slave <- master link */
|
||||
replicationCreateMasterClient(mi,mi->repl_transfer_s,rsi.repl_stream_db);
|
||||
if (mi->isKeydbFastsync) {
|
||||
if (mi->isRocksdbSnapshotRepl) {
|
||||
/* We need to handle the case where the initial querybuf data was read by fast sync */
|
||||
/* This should match the work readQueryFromClient would do for a master client */
|
||||
mi->master->querybuf = sdscatsds(mi->master->querybuf, mi->bulkreadBuffer);
|
||||
mi->master->pending_querybuf = sdscatsds(mi->master->pending_querybuf, mi->bulkreadBuffer);
|
||||
mi->master->read_reploff += sdslen(mi->bulkreadBuffer);
|
||||
|
||||
sdsfree(mi->bulkreadBuffer);
|
||||
mi->bulkreadBuffer = nullptr;
|
||||
|
||||
mi->master->pending_querybuf = sdscatlen(mi->master->pending_querybuf,
|
||||
mi->master->querybuf,sdslen(mi->master->querybuf));
|
||||
|
||||
mi->master->read_reploff += sdslen(mi->master->querybuf);
|
||||
}
|
||||
mi->repl_transfer_s = nullptr;
|
||||
mi->repl_state = REPL_STATE_CONNECTED;
|
||||
@@ -3076,13 +3061,13 @@ void readSyncBulkPayload(connection *conn) {
|
||||
}
|
||||
|
||||
/* Send the initial ACK immediately to put this replica in online state. */
|
||||
if (usemark || mi->isKeydbFastsync) replicationSendAck(mi);
|
||||
if (usemark || mi->isRocksdbSnapshotRepl) replicationSendAck(mi);
|
||||
|
||||
/* Restart the AOF subsystem now that we finished the sync. This
|
||||
* will trigger an AOF rewrite, and when done will start appending
|
||||
* to the new file. */
|
||||
if (g_pserver->aof_enabled) restartAOFAfterSYNC();
|
||||
if (mi->isKeydbFastsync)
|
||||
if (mi->isRocksdbSnapshotRepl)
|
||||
readQueryFromClient(conn); // There may be querybuf data we just appeneded
|
||||
return;
|
||||
}
|
||||
@@ -3408,15 +3393,15 @@ void parseMasterCapa(redisMaster *mi, sds strcapa)
|
||||
char *pchEnd = szStart;
|
||||
|
||||
mi->isActive = false;
|
||||
mi->isKeydbFastsync = false;
|
||||
mi->isRocksdbSnapshotRepl = false;
|
||||
for (;;)
|
||||
{
|
||||
if (*pchEnd == ' ' || *pchEnd == '\0') {
|
||||
// Parse the word
|
||||
if (strncmp(szStart, "active-replica", pchEnd - szStart) == 0) {
|
||||
mi->isActive = true;
|
||||
} else if (strncmp(szStart, "keydb-fastsync-save", pchEnd - szStart) == 0) {
|
||||
mi->isKeydbFastsync = true;
|
||||
} else if (strncmp(szStart, "rocksdb-snapshot-save", pchEnd - szStart) == 0) {
|
||||
mi->isRocksdbSnapshotRepl = true;
|
||||
}
|
||||
szStart = pchEnd + 1;
|
||||
}
|
||||
@@ -3563,9 +3548,9 @@ retry_connect:
|
||||
"capa","psync2",
|
||||
"capa","activeExpire",
|
||||
};
|
||||
if (FFastSyncEnabled() && g_pserver->repl_diskless_load != REPL_DISKLESS_LOAD_SWAPDB) {
|
||||
if (g_pserver->m_pstorageFactory && !g_pserver->fActiveReplica && g_pserver->repl_diskless_load != REPL_DISKLESS_LOAD_SWAPDB) {
|
||||
veccapabilities.push_back("capa");
|
||||
veccapabilities.push_back("keydb-fastsync");
|
||||
veccapabilities.push_back("rocksdb-snapshot-load");
|
||||
}
|
||||
|
||||
err = sendCommandArgv(conn, veccapabilities.size(), veccapabilities.data(), nullptr);
|
||||
@@ -3748,12 +3733,12 @@ retry_connect:
|
||||
}
|
||||
|
||||
/* Prepare a suitable temp file for bulk transfer */
|
||||
if (!useDisklessLoad() && !mi->isKeydbFastsync) {
|
||||
if (!useDisklessLoad()) {
|
||||
while(maxtries--) {
|
||||
auto dt = std::chrono::system_clock::now().time_since_epoch();
|
||||
auto dtMillisecond = std::chrono::duration_cast<std::chrono::milliseconds>(dt);
|
||||
snprintf(tmpfile,sizeof(tmpfile),
|
||||
"temp-%lld.%ld.rdb",(long long)dtMillisecond.count(),(long int)getpid());
|
||||
"temp-%d.%ld.rdb",(int)dtMillisecond.count(),(long int)getpid());
|
||||
dfd = open(tmpfile,O_CREAT|O_WRONLY|O_EXCL,0644);
|
||||
if (dfd != -1) break;
|
||||
sleep(1);
|
||||
@@ -3877,10 +3862,6 @@ int cancelReplicationHandshake(redisMaster *mi, int reconnect) {
|
||||
delete mi->parseState;
|
||||
mi->parseState = nullptr;
|
||||
}
|
||||
if (mi->bulkreadBuffer) {
|
||||
sdsfree(mi->bulkreadBuffer);
|
||||
mi->bulkreadBuffer = nullptr;
|
||||
}
|
||||
|
||||
if (mi->repl_state == REPL_STATE_TRANSFER) {
|
||||
replicationAbortSyncTransfer(mi);
|
||||
@@ -4346,6 +4327,7 @@ void replicationCacheMaster(redisMaster *mi, client *c) {
|
||||
if (c->flags & CLIENT_MULTI) discardTransaction(c);
|
||||
listEmpty(c->reply);
|
||||
c->sentlen = 0;
|
||||
c->sentlenAsync = 0;
|
||||
c->reply_bytes = 0;
|
||||
c->bufpos = 0;
|
||||
resetClient(c);
|
||||
|
||||
@@ -418,10 +418,7 @@ public:
|
||||
sdsstring &operator=(const sdsstring &other)
|
||||
{
|
||||
sdsfree(m_str);
|
||||
if (other.m_str != nullptr)
|
||||
m_str = sdsdup(other.m_str);
|
||||
else
|
||||
m_str = nullptr;
|
||||
m_str = sdsdup(other.m_str);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
+10
-12
@@ -2137,7 +2137,7 @@ void databasesCron(bool fMainThread) {
|
||||
::dict *dict = g_pserver->db[rehash_db]->dictUnsafeKeyOnly();
|
||||
/* Are we async rehashing? And if so is it time to re-calibrate? */
|
||||
/* The recalibration limit is a prime number to ensure balancing across threads */
|
||||
if (g_pserver->enable_async_rehash && rehashes_per_ms > 0 && async_rehashes < 131 && !cserver.active_defrag_enabled && cserver.cthreads > 1 && dictSize(dict) > 2048 && dictIsRehashing(dict) && !g_pserver->loading && aeLockContention() > 1) {
|
||||
if (rehashes_per_ms > 0 && async_rehashes < 131 && !cserver.active_defrag_enabled && cserver.cthreads > 1 && dictSize(dict) > 2048 && dictIsRehashing(dict) && !g_pserver->loading) {
|
||||
serverTL->rehashCtl = dictRehashAsyncStart(dict, rehashes_per_ms * ((1000 / g_pserver->hz) / 10)); // Estimate 10% CPU time spent in lock contention
|
||||
if (serverTL->rehashCtl)
|
||||
++async_rehashes;
|
||||
@@ -3925,18 +3925,18 @@ void initServer(void) {
|
||||
g_pserver->db[j]->initialize(j);
|
||||
}
|
||||
} else {
|
||||
// Read FLASH metadata and load the appropriate storage dbid into each databse index, as each DB index can have different storage dbid mapped due to the swapdb command.
|
||||
// Read FLASH metadata and load the appropriate dbid into each databse index, as each DB index can have different dbid mapped due to the swapdb command.
|
||||
g_pserver->metadataDb = g_pserver->m_pstorageFactory->createMetadataDb();
|
||||
for (int idb = 0; idb < cserver.dbnum; ++idb)
|
||||
{
|
||||
int storage_dbid = idb;
|
||||
int dbid = idb;
|
||||
std::string dbid_key = "db-" + std::to_string(idb);
|
||||
g_pserver->metadataDb->retrieve(dbid_key.c_str(), dbid_key.length(), [&](const char *, size_t, const void *data, size_t){
|
||||
storage_dbid = *(int*)data;
|
||||
dbid = *(int*)data;
|
||||
});
|
||||
|
||||
g_pserver->db[idb] = new (MALLOC_LOCAL) redisDb();
|
||||
g_pserver->db[idb]->initialize(idb, storage_dbid);
|
||||
g_pserver->db[idb]->initialize(dbid);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5102,8 +5102,8 @@ int processCommand(client *c, int callFlags) {
|
||||
|
||||
sds str = sdsempty();
|
||||
for (int j = 0; j < numkeys; j++) {
|
||||
str = sdscatsds(str, (sds)ptrFromObj(c->argv[keyindex[j]]));
|
||||
str = sdscat(str, " ");
|
||||
sdscatsds(str, (sds)ptrFromObj(c->argv[keyindex[j]]));
|
||||
sdscat(str, " ");
|
||||
}
|
||||
|
||||
if (numkeys > 0)
|
||||
@@ -5663,8 +5663,7 @@ sds genRedisInfoString(const char *section) {
|
||||
"lru_clock:%u\r\n"
|
||||
"executable:%s\r\n"
|
||||
"config_file:%s\r\n"
|
||||
"availability_zone:%s\r\n"
|
||||
"features:%s\r\n",
|
||||
"availability_zone:%s\r\n",
|
||||
KEYDB_SET_VERSION,
|
||||
redisGitSHA1(),
|
||||
strtol(redisGitDirty(),NULL,10) > 0,
|
||||
@@ -5691,8 +5690,7 @@ sds genRedisInfoString(const char *section) {
|
||||
lruclock,
|
||||
cserver.executable ? cserver.executable : "",
|
||||
cserver.configfile ? cserver.configfile : "",
|
||||
g_pserver->sdsAvailabilityZone,
|
||||
"cluster_mget");
|
||||
g_pserver->sdsAvailabilityZone);
|
||||
}
|
||||
|
||||
/* Clients */
|
||||
@@ -7413,7 +7411,7 @@ static void validateConfiguration()
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
g_pserver->repl_backlog_size = g_pserver->repl_backlog_config_size; // this is normally set in the update logic, but not on initial config
|
||||
g_pserver->repl_backlog_config_size = g_pserver->repl_backlog_size; // this is normally set in the update logic, but not on initial config
|
||||
}
|
||||
|
||||
int iAmMaster(void) {
|
||||
|
||||
+6
-15
@@ -620,7 +620,7 @@ typedef enum {
|
||||
#define SLAVE_CAPA_EOF (1<<0) /* Can parse the RDB EOF streaming format. */
|
||||
#define SLAVE_CAPA_PSYNC2 (1<<1) /* Supports PSYNC2 protocol. */
|
||||
#define SLAVE_CAPA_ACTIVE_EXPIRE (1<<2) /* Will the slave perform its own expirations? (Don't send delete) */
|
||||
#define SLAVE_CAPA_KEYDB_FASTSYNC (1<<3)
|
||||
#define SLAVE_CAPA_ROCKSDB_SNAPSHOT (1<<3)
|
||||
|
||||
/* Synchronous read timeout - replica side */
|
||||
#define CONFIG_REPL_SYNCIO_TIMEOUT 5
|
||||
@@ -966,7 +966,6 @@ struct redisObjectExtended {
|
||||
|
||||
typedef struct redisObject {
|
||||
friend redisObject *createEmbeddedStringObject(const char *ptr, size_t len);
|
||||
friend redisObject *createObject(int type, void *ptr);
|
||||
protected:
|
||||
redisObject() {}
|
||||
|
||||
@@ -1325,7 +1324,7 @@ struct redisDb : public redisDbPersistentDataSnapshot
|
||||
|
||||
redisDb() = default;
|
||||
|
||||
void initialize(int id, int storage_id=-1 /* default no storage */);
|
||||
void initialize(int id);
|
||||
void storageProviderInitialize();
|
||||
void storageProviderDelete();
|
||||
virtual ~redisDb();
|
||||
@@ -1389,7 +1388,6 @@ public:
|
||||
dict *ready_keys; /* Blocked keys that received a PUSH */
|
||||
dict *watched_keys; /* WATCHED keys for MULTI/EXEC CAS */
|
||||
int id; /* Database ID */
|
||||
int storage_id; /* Mapped storage provider DB id which is same as the redisdb id above. But, when the database is swapped, the redisdb id above might be swapped to be consistent with the database index (id <-> g_pserver->db[index]) however the storage_id remains unchanged in order to maintain correct mapping to the underlying storage provider DB. This is valid only if there is a storage provider set.*/
|
||||
long long last_expire_set; /* when the last expire was set */
|
||||
double avg_ttl; /* Average TTL, just for stats */
|
||||
list *defrag_later; /* List of key names to attempt to defrag one by one, gradually. */
|
||||
@@ -1611,6 +1609,7 @@ struct client {
|
||||
unsigned long long reply_bytes; /* Tot bytes of objects in reply list. */
|
||||
size_t sentlen; /* Amount of bytes already sent in the current
|
||||
buffer or object being sent. */
|
||||
size_t sentlenAsync; /* same as sentlen buf for async buffers (which are a different stream) */
|
||||
time_t ctime; /* Client creation time. */
|
||||
long duration; /* Current command duration. Used for measuring latency of blocking/non-blocking cmds */
|
||||
time_t lastinteraction; /* Time of the last interaction, used for timeout */
|
||||
@@ -1871,7 +1870,7 @@ struct redisMaster {
|
||||
long long master_initial_offset; /* Master PSYNC offset. */
|
||||
|
||||
bool isActive = false;
|
||||
bool isKeydbFastsync = false;
|
||||
bool isRocksdbSnapshotRepl = false;
|
||||
int repl_state; /* Replication status if the instance is a replica */
|
||||
off_t repl_transfer_size; /* Size of RDB to read from master during sync. */
|
||||
off_t repl_transfer_read; /* Amount of RDB read from master during sync. */
|
||||
@@ -2306,7 +2305,6 @@ struct redisServer {
|
||||
rax *errors; /* Errors table */
|
||||
int activerehashing; /* Incremental rehash in serverCron() */
|
||||
int active_defrag_running; /* Active defragmentation running (holds current scan aggressiveness) */
|
||||
int enable_async_rehash = 1; /* Should we use the async rehash feature? */
|
||||
int cronloops; /* Number of times the cron function run */
|
||||
char runid[CONFIG_RUN_ID_SIZE+1]; /* ID always different at every exec. */
|
||||
int sentinel_mode; /* True if this instance is a Sentinel. */
|
||||
@@ -2688,7 +2686,6 @@ struct redisServer {
|
||||
|
||||
int fActiveReplica; /* Can this replica also be a master? */
|
||||
int fWriteDuringActiveLoad; /* Can this active-replica write during an RDB load? */
|
||||
int fEnableFastSync = false;
|
||||
|
||||
// Format:
|
||||
// Lower 20 bits: a counter incrementing for each command executed in the same millisecond
|
||||
@@ -2920,7 +2917,7 @@ int moduleGetCommandKeysViaAPI(struct redisCommand *cmd, robj **argv, int argc,
|
||||
moduleType *moduleTypeLookupModuleByID(uint64_t id);
|
||||
void moduleTypeNameByID(char *name, uint64_t moduleid);
|
||||
const char *moduleTypeModuleName(moduleType *mt);
|
||||
void moduleFreeContext(struct RedisModuleCtx *ctx, bool propogate = true);
|
||||
void moduleFreeContext(struct RedisModuleCtx *ctx);
|
||||
void unblockClientFromModule(client *c);
|
||||
void moduleHandleBlockedClients(int iel);
|
||||
void moduleBlockedClientTimedOut(client *c);
|
||||
@@ -3115,7 +3112,6 @@ void queueMultiCommand(client *c);
|
||||
void touchWatchedKey(redisDb *db, robj *key);
|
||||
int isWatchedKeyExpired(client *c);
|
||||
void touchAllWatchedKeysInDb(redisDb *emptied, redisDb *replaced_with);
|
||||
void updateDBWatchedKey(int dbid, client *c);
|
||||
void discardTransaction(client *c);
|
||||
void flagTransaction(client *c);
|
||||
void execCommandAbort(client *c, sds error);
|
||||
@@ -3184,7 +3180,6 @@ void trimStringObjectIfNeeded(robj *o);
|
||||
robj *deserializeStoredObject(const void *data, size_t cb);
|
||||
std::unique_ptr<expireEntry> deserializeExpire(const char *str, size_t cch, size_t *poffset);
|
||||
sds serializeStoredObject(robj_roptr o, sds sdsPrefix = nullptr);
|
||||
sds serializeStoredObjectAndExpire(robj_roptr o);
|
||||
|
||||
#define sdsEncodedObject(objptr) (objptr->encoding == OBJ_ENCODING_RAW || objptr->encoding == OBJ_ENCODING_EMBSTR)
|
||||
|
||||
@@ -3926,7 +3921,7 @@ void updateActiveReplicaMastersFromRsi(rdbSaveInfo *rsi);
|
||||
uint64_t getMvccTstamp();
|
||||
void incrementMvccTstamp();
|
||||
|
||||
#if __GNUC__ >= 7 && !defined(NO_DEPRECATE_FREE) && !defined(ALPINE)
|
||||
#if __GNUC__ >= 7 && !defined(NO_DEPRECATE_FREE)
|
||||
[[deprecated]]
|
||||
void *calloc(size_t count, size_t size) noexcept;
|
||||
[[deprecated]]
|
||||
@@ -3974,10 +3969,6 @@ inline int ielFromEventLoop(const aeEventLoop *eventLoop)
|
||||
return iel;
|
||||
}
|
||||
|
||||
inline bool FFastSyncEnabled() {
|
||||
return g_pserver->fEnableFastSync && !g_pserver->fActiveReplica;
|
||||
}
|
||||
|
||||
inline int FCorrectThread(client *c)
|
||||
{
|
||||
return (c->conn == nullptr)
|
||||
|
||||
+1
-5
@@ -587,12 +587,8 @@ bool redisDbPersistentDataSnapshot::iterate_threadsafe_core(std::function<bool(c
|
||||
if (!fKeyOnly)
|
||||
{
|
||||
size_t offset = 0;
|
||||
std::unique_ptr<expireEntry> spexpire = deserializeExpire((const char*)data, cbData, &offset);
|
||||
deserializeExpire((const char*)data, cbData, &offset);
|
||||
o = deserializeStoredObject(reinterpret_cast<const char*>(data)+offset, cbData-offset);
|
||||
o->SetFExpires(spexpire != nullptr);
|
||||
if (spexpire != nullptr) {
|
||||
o->expire = std::move(*spexpire);
|
||||
}
|
||||
}
|
||||
fContinue = fn(sdsKey, o);
|
||||
if (o != nullptr)
|
||||
|
||||
+21
-31
@@ -7,8 +7,6 @@
|
||||
#include "../cluster.h"
|
||||
#include "rocksdbfactor_internal.h"
|
||||
|
||||
template class std::basic_string<char>;
|
||||
|
||||
static const char keyprefix[] = INTERNAL_KEY_PREFIX;
|
||||
|
||||
rocksdb::Options DefaultRocksDBOptions();
|
||||
@@ -26,9 +24,8 @@ bool FInternalKey(const char *key, size_t cch)
|
||||
|
||||
std::string getPrefix(unsigned int hashslot)
|
||||
{
|
||||
HASHSLOT_PREFIX_TYPE slot = HASHSLOT_PREFIX_ENDIAN((HASHSLOT_PREFIX_TYPE)hashslot);
|
||||
char *hash_char = (char *)&slot;
|
||||
return std::string(hash_char, HASHSLOT_PREFIX_BYTES);
|
||||
char *hash_char = (char *)&hashslot;
|
||||
return std::string(hash_char + (sizeof(unsigned int) - 2), 2);
|
||||
}
|
||||
|
||||
std::string prefixKey(const char *key, size_t cchKey)
|
||||
@@ -147,28 +144,16 @@ void RocksDBStorageProvider::retrieve(const char *key, size_t cchKey, callbackSi
|
||||
size_t RocksDBStorageProvider::clear()
|
||||
{
|
||||
size_t celem = count();
|
||||
auto options = m_spdb->GetOptions(m_spcolfamily.get());
|
||||
auto status = m_spdb->DropColumnFamily(m_spcolfamily.get());
|
||||
auto strName = m_spcolfamily->GetName();
|
||||
|
||||
rocksdb::ColumnFamilyHandle *handle = nullptr;
|
||||
rocksdb::ColumnFamilyOptions cf_options(options);
|
||||
|
||||
rocksdb::ColumnFamilyOptions cf_options(m_pfactory->RocksDbOptions());
|
||||
m_spdb->CreateColumnFamily(cf_options, strName, &handle);
|
||||
m_spcolfamily = std::shared_ptr<rocksdb::ColumnFamilyHandle>(handle);
|
||||
|
||||
if (!status.ok())
|
||||
throw status.ToString();
|
||||
|
||||
status = m_spdb->DropColumnFamily(m_spexpirecolfamily.get());
|
||||
strName = m_spexpirecolfamily->GetName();
|
||||
|
||||
m_spdb->CreateColumnFamily(cf_options, strName, &handle);
|
||||
m_spexpirecolfamily = std::shared_ptr<rocksdb::ColumnFamilyHandle>(handle);
|
||||
|
||||
if (!status.ok())
|
||||
throw status.ToString();
|
||||
|
||||
m_count = 0;
|
||||
return celem;
|
||||
}
|
||||
@@ -187,7 +172,7 @@ bool RocksDBStorageProvider::enumerate(callback fn) const
|
||||
if (FInternalKey(it->key().data(), it->key().size()))
|
||||
continue;
|
||||
++count;
|
||||
bool fContinue = fn(it->key().data()+HASHSLOT_PREFIX_BYTES, it->key().size()-HASHSLOT_PREFIX_BYTES, it->value().data(), it->value().size());
|
||||
bool fContinue = fn(it->key().data()+2, it->key().size()-2, it->value().data(), it->value().size());
|
||||
if (!fContinue)
|
||||
break;
|
||||
}
|
||||
@@ -206,17 +191,17 @@ bool RocksDBStorageProvider::enumerate_hashslot(callback fn, unsigned int hashsl
|
||||
std::string prefix = getPrefix(hashslot);
|
||||
std::unique_ptr<rocksdb::Iterator> it = std::unique_ptr<rocksdb::Iterator>(m_spdb->NewIterator(ReadOptions(), m_spcolfamily.get()));
|
||||
size_t count = 0;
|
||||
for (it->Seek(prefix); it->Valid(); it->Next()) {
|
||||
for (it->Seek(prefix.c_str()); it->Valid(); it->Next()) {
|
||||
if (FInternalKey(it->key().data(), it->key().size()))
|
||||
continue;
|
||||
if (HASHSLOT_PREFIX_RECOVER(*(HASHSLOT_PREFIX_TYPE *)it->key().data()) != hashslot)
|
||||
if (strncmp(it->key().data(),prefix.c_str(),2) != 0)
|
||||
break;
|
||||
++count;
|
||||
bool fContinue = fn(it->key().data()+HASHSLOT_PREFIX_BYTES, it->key().size()-HASHSLOT_PREFIX_BYTES, it->value().data(), it->value().size());
|
||||
bool fContinue = fn(it->key().data()+2, it->key().size()-2, it->value().data(), it->value().size());
|
||||
if (!fContinue)
|
||||
break;
|
||||
}
|
||||
bool full_iter = !it->Valid() || (HASHSLOT_PREFIX_RECOVER(*(HASHSLOT_PREFIX_TYPE *)it->key().data()) != hashslot);
|
||||
bool full_iter = !it->Valid() || (strncmp(it->key().data(),prefix.c_str(),2) != 0);
|
||||
if (full_iter && count != g_pserver->cluster->slots_keys_count[hashslot])
|
||||
{
|
||||
printf("WARNING: rocksdb hashslot count mismatch");
|
||||
@@ -230,8 +215,7 @@ void RocksDBStorageProvider::setExpire(const char *key, size_t cchKey, long long
|
||||
{
|
||||
rocksdb::Status status;
|
||||
std::unique_lock<fastlock> l(m_lock);
|
||||
long long beExpire = htobe64(expire);
|
||||
std::string prefix((const char *)&beExpire,sizeof(long long));
|
||||
std::string prefix((const char *)&expire,sizeof(long long));
|
||||
std::string strKey(key, cchKey);
|
||||
if (m_spbatch != nullptr)
|
||||
status = m_spbatch->Put(m_spexpirecolfamily.get(), rocksdb::Slice(prefix + strKey), rocksdb::Slice(strKey));
|
||||
@@ -245,8 +229,7 @@ void RocksDBStorageProvider::removeExpire(const char *key, size_t cchKey, long l
|
||||
{
|
||||
rocksdb::Status status;
|
||||
std::unique_lock<fastlock> l(m_lock);
|
||||
long long beExpire = htobe64(expire);
|
||||
std::string prefix((const char *)&beExpire,sizeof(long long));
|
||||
std::string prefix((const char *)&expire,sizeof(long long));
|
||||
std::string strKey(key, cchKey);
|
||||
std::string fullKey = prefix + strKey;
|
||||
if (!FExpireExists(fullKey))
|
||||
@@ -259,14 +242,21 @@ void RocksDBStorageProvider::removeExpire(const char *key, size_t cchKey, long l
|
||||
throw status.ToString();
|
||||
}
|
||||
|
||||
std::vector<std::string> RocksDBStorageProvider::getExpirationCandidates(unsigned int count)
|
||||
std::vector<std::string> RocksDBStorageProvider::getExpirationCandidates(unsigned int count, long long time)
|
||||
{
|
||||
std::vector<std::string> result;
|
||||
std::unique_ptr<rocksdb::Iterator> it = std::unique_ptr<rocksdb::Iterator>(m_spdb->NewIterator(ReadOptions(), m_spexpirecolfamily.get()));
|
||||
for (it->SeekToFirst(); it->Valid() && result.size() < count; it->Next()) {
|
||||
for (it->SeekToFirst(); it->Valid() && (*((long long *)it->key().data()) < time) && (result.size() < count); it->Next()) {
|
||||
if (FInternalKey(it->key().data(), it->key().size()))
|
||||
continue;
|
||||
result.emplace_back(it->value().data(), it->value().size());
|
||||
rocksdb::Status status;
|
||||
if (m_spbatch)
|
||||
status = m_spbatch->Delete(m_spexpirecolfamily.get(), it->key());
|
||||
else
|
||||
status = m_spdb->Delete(WriteOptions(), m_spexpirecolfamily.get(), it->key());
|
||||
if (!status.ok())
|
||||
throw status.ToString();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -283,11 +273,11 @@ std::vector<std::string> RocksDBStorageProvider::getEvictionCandidates(unsigned
|
||||
for (it->Seek(randomHashSlot()); it->Valid() && result.size() < count; it->Next()) {
|
||||
if (FInternalKey(it->key().data(), it->key().size()))
|
||||
continue;
|
||||
result.emplace_back(it->key().data() + HASHSLOT_PREFIX_BYTES, it->key().size() - HASHSLOT_PREFIX_BYTES);
|
||||
result.emplace_back(it->key().data() + 2, it->key().size() - 2);
|
||||
}
|
||||
} else {
|
||||
std::unique_ptr<rocksdb::Iterator> it = std::unique_ptr<rocksdb::Iterator>(m_spdb->NewIterator(ReadOptions(), m_spexpirecolfamily.get()));
|
||||
for (it->SeekToFirst(); it->Valid() && result.size() < count; it->Next()) {
|
||||
for (it->SeekToFirst(); it->Valid() && result.size() < 16; it->Next()) {
|
||||
if (FInternalKey(it->key().data(), it->key().size()))
|
||||
continue;
|
||||
result.emplace_back(it->value().data(), it->value().size());
|
||||
|
||||
+1
-13
@@ -4,21 +4,9 @@
|
||||
#include "../IStorage.h"
|
||||
#include <rocksdb/db.h>
|
||||
#include <rocksdb/utilities/write_batch_with_index.h>
|
||||
#ifdef __APPLE__
|
||||
#include <libkern/OSByteOrder.h>
|
||||
#define htole16 OSSwapHostToLittleInt16
|
||||
#define le16toh OSSwapLittleToHostInt16
|
||||
#define htobe64 OSSwapHostToBigInt64
|
||||
#else
|
||||
#include <endian.h>
|
||||
#endif
|
||||
#include "../fastlock.h"
|
||||
|
||||
#define INTERNAL_KEY_PREFIX "\x00\x04\x03\x00\x05\x02\x04"
|
||||
#define HASHSLOT_PREFIX_TYPE uint16_t
|
||||
#define HASHSLOT_PREFIX_BYTES sizeof(HASHSLOT_PREFIX_TYPE)
|
||||
#define HASHSLOT_PREFIX_ENDIAN htole16
|
||||
#define HASHSLOT_PREFIX_RECOVER le16toh
|
||||
static const char count_key[] = INTERNAL_KEY_PREFIX "__keydb__count\1";
|
||||
static const char version_key[] = INTERNAL_KEY_PREFIX "__keydb__version\1";
|
||||
static const char meta_key[] = INTERNAL_KEY_PREFIX "__keydb__metadata\1";
|
||||
@@ -48,7 +36,7 @@ public:
|
||||
virtual bool enumerate(callback fn) const override;
|
||||
virtual bool enumerate_hashslot(callback fn, unsigned int hashslot) const override;
|
||||
|
||||
virtual std::vector<std::string> getExpirationCandidates(unsigned int count) override;
|
||||
virtual std::vector<std::string> getExpirationCandidates(unsigned int count, long long time) override;
|
||||
virtual std::vector<std::string> getEvictionCandidates(unsigned int count) override;
|
||||
virtual void setExpire(const char *key, size_t cchKey, long long expire) override;
|
||||
virtual void removeExpire(const char *key, size_t cchKey, long long expire) override;
|
||||
|
||||
@@ -72,7 +72,7 @@ RocksDBStorageFactory::RocksDBStorageFactory(const char *dbfile, int dbnum, cons
|
||||
rocksdb::DB *db = nullptr;
|
||||
|
||||
auto options = RocksDbOptions();
|
||||
options.prefix_extractor.reset(rocksdb::NewFixedPrefixTransform(HASHSLOT_PREFIX_BYTES));
|
||||
options.prefix_extractor.reset(rocksdb::NewFixedPrefixTransform(2));
|
||||
|
||||
for (int idb = 0; idb < dbnum; ++idb)
|
||||
{
|
||||
@@ -196,7 +196,7 @@ IStorage *RocksDBStorageFactory::create(int db, key_load_iterator iter, void *pr
|
||||
printf("\tDatabase %d was not shutdown cleanly, recomputing metrics\n", db);
|
||||
fFirstRealKey = false;
|
||||
if (iter != nullptr)
|
||||
iter(it->key().data()+HASHSLOT_PREFIX_BYTES, it->key().size()-HASHSLOT_PREFIX_BYTES, privdata);
|
||||
iter(it->key().data()+2, it->key().size()-2, privdata);
|
||||
++count;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ public:
|
||||
virtual bool enumerate_hashslot(callback fn, unsigned int hashslot) const override;
|
||||
virtual size_t count() const override;
|
||||
|
||||
virtual std::vector<std::string> getExpirationCandidates(unsigned int) override { return std::vector<std::string>(); }
|
||||
virtual std::vector<std::string> getExpirationCandidates(unsigned int, long long) override { return std::vector<std::string>(); }
|
||||
virtual std::vector<std::string> getEvictionCandidates(unsigned int) override { return std::vector<std::string>(); }
|
||||
virtual void setExpire(const char *, size_t, long long) override {}
|
||||
virtual void removeExpire(const char *, size_t, long long) override {}
|
||||
|
||||
+4
-4
@@ -2036,7 +2036,7 @@ struct zsetopsrc {
|
||||
zset *zs;
|
||||
zskiplistNode *node;
|
||||
} sl;
|
||||
} iterzset;
|
||||
} zset;
|
||||
} iter;
|
||||
};
|
||||
|
||||
@@ -2085,7 +2085,7 @@ void zuiInitIterator(zsetopsrc *op) {
|
||||
/* Sorted sets are traversed in reverse order to optimize for
|
||||
* the insertion of the elements in a new list as in
|
||||
* ZDIFF/ZINTER/ZUNION */
|
||||
iterzset *it = (iterzset*)&op->iter.iterzset;
|
||||
iterzset *it = (iterzset*)&op->iter.zset;
|
||||
if (op->encoding == OBJ_ENCODING_ZIPLIST) {
|
||||
it->zl.zl = (unsigned char*)op->subject->m_ptr;
|
||||
it->zl.eptr = ziplistIndex(it->zl.zl,-2);
|
||||
@@ -2118,7 +2118,7 @@ void zuiClearIterator(zsetopsrc *op) {
|
||||
serverPanic("Unknown set encoding");
|
||||
}
|
||||
} else if (op->type == OBJ_ZSET) {
|
||||
iterzset *it = &op->iter.iterzset;
|
||||
iterzset *it = &op->iter.zset;
|
||||
if (op->encoding == OBJ_ENCODING_ZIPLIST) {
|
||||
UNUSED(it); /* skip */
|
||||
} else if (op->encoding == OBJ_ENCODING_SKIPLIST) {
|
||||
@@ -2194,7 +2194,7 @@ int zuiNext(zsetopsrc *op, zsetopval *val) {
|
||||
serverPanic("Unknown set encoding");
|
||||
}
|
||||
} else if (op->type == OBJ_ZSET) {
|
||||
iterzset *it = &op->iter.iterzset;
|
||||
iterzset *it = &op->iter.zset;
|
||||
if (op->encoding == OBJ_ENCODING_ZIPLIST) {
|
||||
/* No need to check both, but better be explicit. */
|
||||
if (it->zl.eptr == NULL || it->zl.sptr == NULL)
|
||||
|
||||
@@ -584,7 +584,6 @@ start_server {tags {"repl"}} {
|
||||
set master [srv 0 client]
|
||||
$master config set repl-diskless-sync yes
|
||||
$master config set repl-diskless-sync-delay 1
|
||||
$master config set enable-keydb-fastsync no
|
||||
set master_host [srv 0 host]
|
||||
set master_port [srv 0 port]
|
||||
set master_pid [srv 0 pid]
|
||||
@@ -728,8 +727,6 @@ start_server {tags {"repl"}} {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$master config set enable-keydb-fastsync yes
|
||||
}
|
||||
|
||||
if 0 {
|
||||
@@ -870,10 +867,8 @@ test {replicaof right after disconnection} {
|
||||
test {Kill rdb child process if its dumping RDB is not useful} {
|
||||
start_server {tags {"repl"}} {
|
||||
set slave1 [srv 0 client]
|
||||
$slave1 config set enable-keydb-fastsync no
|
||||
start_server {} {
|
||||
set slave2 [srv 0 client]
|
||||
$slave2 config set enable-keydb-fastsync no
|
||||
start_server {} {
|
||||
set master [srv 0 client]
|
||||
set master_host [srv 0 host]
|
||||
|
||||
@@ -81,6 +81,21 @@ if {$::flash_enabled} {
|
||||
}
|
||||
}
|
||||
|
||||
test { EXPIRE reduces used disk space } {
|
||||
r flushall
|
||||
r set testkey foo ex 10
|
||||
r debug flush-storage
|
||||
set used [r debug get-storage-usage]
|
||||
assert_equal {1} [r dbsize]
|
||||
wait_for_condition 50 1000 {
|
||||
[r dbsize] == 0
|
||||
} else {
|
||||
fail "key is not expired"
|
||||
}
|
||||
set after [r debug get-storage-usage]
|
||||
assert {$after < $used}
|
||||
}
|
||||
|
||||
test { SUBKEY EXPIRE persists after cache flush } {
|
||||
r flushall
|
||||
r sadd testkey foo bar baz
|
||||
|
||||
@@ -182,8 +182,6 @@ proc test_slave_buffers {test_name cmd_count payload_len limit_memory pipeline}
|
||||
fail "Replication not started."
|
||||
}
|
||||
|
||||
after 100
|
||||
|
||||
# measure used memory after the slave connected and set maxmemory
|
||||
set orig_used [s -1 used_memory]
|
||||
set orig_client_buf [s -1 mem_clients_normal]
|
||||
|
||||
@@ -51,7 +51,7 @@ if {$::tls} {
|
||||
}
|
||||
}
|
||||
|
||||
test {TLS Audit Log: Able to connect while with SAN having a comprehensive list} {
|
||||
test {TLS: Able to connect while with SAN having a comprehensive list} {
|
||||
start_server {tags {"tls"} overrides {tls-auditlog-blocklist {dummy.keydb.dev san2.keydb.dev other.keydb.dev}}} {
|
||||
catch {r PING} e
|
||||
assert_match {PONG} $e
|
||||
@@ -65,7 +65,7 @@ if {$::tls} {
|
||||
}
|
||||
}
|
||||
|
||||
test {TLS Audit Log: Able to connect while with SAN having a comprehensive list with wildcards} {
|
||||
test {TLS Audit LogTLS: Able to connect while with SAN having a comprehensive list with wildcards} {
|
||||
start_server {tags {"tls"} overrides {tls-auditlog-blocklist {dummy.* san*.dev other.*}}} {
|
||||
catch {r PING} e
|
||||
assert_match {PONG} $e
|
||||
|
||||
Reference in new issue
Block a user