Compare commits

...
28 Commits
Author SHA1 Message Date
Tomasz Poradowski c59c9365be changed to 5.0.14 in readme 2021-10-18 00:39:33 +02:00
Tomasz Poradowski c1e23f5e83 Changed version to 5.0.10 in readme 2020-11-08 20:26:22 +01:00
Tomasz Poradowski 05971a7a22 Merge pull request #89 from tporadowski/win-5.0
5.0.10
2020-11-08 20:21:49 +01:00
tporadowski 1c047b6866 v5.0.10 release notes 2020-11-08 15:58:30 +01:00
tporadowski 94a8021d33 Redis for Windows version 5.0.10 2020-11-08 15:48:51 +01:00
tporadowski 4a341aecd8 turned off active defragmentation in jemalloc
- jemalloc is now configured in similar way as in original Redis
- active defragmentation does not work properly anymore, needs
  investigation, so is turned off by default
2020-11-08 12:05:05 +01:00
tporadowski 053081a222 adding overlooked test from 5.0.10 2020-11-08 12:04:51 +01:00
tporadowski 8229c562e3 added missing jemalloc/bin folder 2020-11-08 10:09:09 +01:00
tporadowski 1d2e5a6e74 ported changes from redis/5.0.10 2020-11-04 14:39:22 +01:00
tporadowski 380e7df718 corected Redis add-on to jemalloc (iget_defrag_hint) 2020-11-04 13:33:35 +01:00
tporadowski 7ced02a356 added clean-up for tests run under Cygwin
- certain tests (using "debug restart") cause additional processes to be
  spawned and not tracked due to changed process ID (Windows-specific
  behaviour), so we need to clean them up when running tests under Cygwin
2020-11-04 09:26:17 +01:00
tporadowski 1e7ca901c9 added clean-up for tests run under Cygwin
- certain tests (using "debug restart") cause additional processes to be
  spawned and not tracked due to changed process ID (Windows-specific
  behaviour), so we need to clean them up when running tests under Cygwin
2020-10-28 18:24:56 +01:00
tporadowski 623f5e655c Merge branch 'issue-75-sentinel-options' into develop 2020-08-31 13:43:45 +02:00
tporadowski 3144475d4a added missing sentinel options
- "known-replica" (equivalent to "known-slave")
- "rename-command"
2020-08-31 13:42:20 +02:00
tporadowski cfc8ac1fd9 Merge branch 'jemalloc-redis-customizations' into develop 2020-07-02 22:18:30 +02:00
tporadowski 76a46c3cdd Merge branch 'jemalloc-redis-customizations' into win-5.0 2020-07-02 22:17:54 +02:00
tporadowski e6673e44c7 added jemalloc 5.2.1 customizations for Redis 2020-07-02 22:16:09 +02:00
Tomasz Poradowski 8c762d92ba Merge pull request #66 from paviad/aviad
Fix include path
2020-06-24 13:49:45 +02:00
Aviad Pineles 6a48dd7340 fix include path 2020-06-24 12:05:23 +03:00
Tomasz Poradowski 9680d1b462 Update issue templates 2020-06-22 09:34:31 +02:00
tporadowski 514999c46e Merge branch 'inconsistent-sentinel-nosave' into win-5.0 2020-06-18 12:11:12 +02:00
tporadowski e29885f13a ensure SHUTDOWN_NOSAVE in Sentinel mode
- enforcing of SHUTDOWN_NOSAVE flag in one place to make it consistent
  when running in Sentinel mode
2020-06-18 12:10:20 +02:00
tporadowski 3bf92ad060 Merge branch 'bugfix/sentinel-sigint-crash' into develop 2020-06-17 21:45:23 +02:00
tporadowski 8f38cf7f0d Merge branch 'bugfix/sentinel-sigint-crash' into win-5.0 2020-06-17 21:44:40 +02:00
tporadowski 7ce82ac723 prevent EXCEPTION_INT_DIVIDE_BY_ZERO
- when server is shutting down via ctrl+c in Sentinel mode - prevent
  crash in EnsureMEmoryIsMapped
- fixes #62
2020-06-17 21:42:47 +02:00
Tomasz Poradowski 7f7bbed8e6 Update issue templates 2020-05-02 21:19:26 +02:00
Tomasz Poradowski 91b369b0ea Updated readme 2020-05-02 20:41:55 +02:00
Tomasz Poradowski 0008486b75 Merge pull request #57 from tporadowski/win-5.0
5.0.9 release
2020-05-02 20:38:56 +02:00
59 changed files with 6401 additions and 130 deletions
+30
View File
@@ -0,0 +1,30 @@
---
name: Bug report
about: Create a report about a problem with Redis for Windows
title: ''
labels: ''
assignees: ''
---
**Describe the bug/issue**
A clear and concise description of what the bug/issue is.
**To Reproduce**
Please provide more information about:
- version of Redis for Windows you are using
- configuration of your instance if it's not out-of-the-box one (i.e. persistence type)
- typical workload handled by your instance
- any other details that might be helpful in reproducing the issue.
**Crash report**
If Redis generated a crash report - please paste it here.
**INFO output**
If possible - please provide output of `INFO` command that might be helpful in analyzing your issue.
**Event Log**
Please check your system's Event Log to see if there are additional details logged related to this issue.
**Additional context**
Please provide Windows version you are using, mode in which you are starting Redis (standalone, cluster, Sentinel), etc.
+114
View File
@@ -11,6 +11,120 @@ CRITICAL: There is a critical bug affecting MOST USERS. Upgrade ASAP.
SECURITY: There are security fixes in the release.
--------------------------------------------------------------------------------
================================================================================
Redis 5.0.10 Released Mon Oct 26 09:21:49 IST 2020
================================================================================
Upgrade urgency: SECURITY if you use an affected platform (see below).
Otherwise the upgrade urgency is MODERATE.
This release fixes a potential heap overflow when using a heap allocator other
than jemalloc or glibc's malloc. See:
https://github.com/redis/redis/pull/7963
Other fixes in this release:
* Avoid case of Lua scripts being consistently aborted due to OOM
* XPENDING will not update consumer's seen-time
* A blocked XREADGROUP didn't propagated the XSETID to replicas / AOF
* UNLINK support for streams
* RESTORE ABSTTL won't store expired keys into the DB
* Hide AUTH from MONITOR
* Cluster: reduce spurious PFAIL/FAIL states upon delayed PONG receival
* Cluster: Fix case of clusters mixing accidentally by gossip
* Cluster: Allow blocked XREAD on a cluster replica
* Cluster: Optimize memory usage CLUSTER SLOTS command
* RedisModule_ValueLength support for stream data type
* Minor fixes in redis-check-rdb and redis-cli
* Fix redis-check-rdb support for modules aux data
* Add fsync in replica when full RDB payload was received
Full list of commits:
Yossi Gottlieb in commit ce0d74d8f:
Fix wrong zmalloc_size() assumption. (#7963)
1 file changed, 3 deletions(-)
Yossi Gottlieb in commit 066699240:
Backport Lua 5.2.2 stack overflow fix. (#7733)
1 file changed, 1 insertion(+), 1 deletion(-)
WuYunlong in commit 8a90c7ef3:
Add fsync to readSyncBulkPayload(). (#7839)
1 file changed, 11 insertions(+)
Ariel Shtul in commit f0df2bb3c:
Fix redis-check-rdb support for modules aux data (#7826)
3 files changed, 21 insertions(+), 1 deletion(-)
hwware in commit 7add2a412:
fix memory leak in sentinel connection sharing
1 file changed, 1 insertion(+)
Oran Agra in commit 315e648f8:
Allow blocked XREAD on a cluster replica (#7881)
3 files changed, 100 insertions(+), 2 deletions(-)
guybe7 in commit 4967ee94e:
Modules: Invalidate saved_oparray after use (#7688)
1 file changed, 2 insertions(+)
antirez in commit 065003e8f:
Modules: remove spurious call from moduleHandleBlockedClients().
1 file changed, 1 deletion(-)
Angus Pearson in commit 6cdf62928:
Fix broken interval and repeat bahaviour in redis-cli (incluing cluster mode)
1 file changed, 11 insertions(+), 6 deletions(-)
antirez in commit cb6a4971c:
Cluster: introduce data_received field.
2 files changed, 27 insertions(+), 10 deletions(-)
Madelyn Olson in commit 83f4de865:
Hide AUTH from monitor
1 file changed, 1 insertion(+), 1 deletion(-)
Guy Benoish in commit 3ba08d185:
Support streams in general module API functions
3 files changed, 11 insertions(+), 1 deletion(-)
Itamar Haber in commit 109c0635c:
Expands lazyfree's effort estimate to include Streams (#5794)
1 file changed, 24 insertions(+)
huangzhw in commit 235210d5b:
defrag.c activeDefragSdsListAndDict when defrag sdsele, We can't use (#7492)
1 file changed, 1 insertion(+), 1 deletion(-)
Oran Agra in commit fdd3162fe:
RESTORE ABSTTL skip expired keys - leak (#7511)
1 file changed, 1 insertion(+)
Oran Agra in commit 6139d6d18:
RESTORE ABSTTL won't store expired keys into the db (#7472)
4 files changed, 45 insertions(+), 15 deletions(-)
Liu Zhen in commit 0f502c58d:
fix clusters mixing accidentally by gossip
1 file changed, 10 insertions(+), 2 deletions(-)
Guy Benoish in commit 37fd50718:
XPENDING should not update consumer's seen-time
4 files changed, 30 insertions(+), 18 deletions(-)
antirez in commit a3ca53e4a:
Also use propagate() in streamPropagateGroupID().
1 file changed, 11 insertions(+), 1 deletion(-)
yanhui13 in commit 7a62eb96e:
optimize the output of cluster slots
1 file changed, 7 insertions(+), 4 deletions(-)
srzhao in commit 0efb93d0c:
Check OOM at script start to get stable lua OOM state.
3 files changed, 11 insertions(+), 4 deletions(-)
================================================================================
Redis 5.0.9 Released Thu Apr 17 12:41:00 CET 2020
================================================================================
+3 -3
View File
@@ -1,6 +1,6 @@
# Redis 5.0.9 for Windows
# Redis 5.0.14 for Windows
Branch [win-5.0 branch](https://github.com/tporadowski/redis/tree/win-5.0) at the moment provides version of Redis 5.0.9. It will be released shortly!
You can find the release of **Redis 5.0.14 for Windows** on [releases page](https://github.com/tporadowski/redis/releases). Please test it and [report any issues](https://github.com/tporadowski/redis/wiki/Submitting-an-Issue), thanks in advance!
## Redis 4.0.14 for Windows
@@ -8,7 +8,7 @@ You can find the release of **Redis 4.0.14 for Windows** on [releases page](http
**DISCLAIMER**
At the moment [win-4.0.14 branch](https://github.com/tporadowski/redis/tree/win-4.0.14) provides a **stable port of [Redis 4.0.14](https://github.com/antirez/redis/releases/tag/4.0.14) for Windows x64** merged with archived port of [win-3.2.100 version](https://github.com/MicrosoftArchive/redis/releases/tag/win-3.2.100) from MS Open Tech team. Since the latter is no longer maintained - the sources were merged by hand, projects updated to Visual Studio 2019 (v16.2.5) and any findings (mostly via unit tests) were fixed.
At the moment [win-4.0.14 branch](https://github.com/tporadowski/redis/tree/win-4.0.14) provides a **stable port of [Redis 4.0.14](https://github.com/antirez/redis/releases/tag/4.0.14) for Windows x64** and [win-5.0 branch](https://github.com/tporadowski/redis/tree/win-5.0) provides a **stable port of [Redis 5.0.14](https://github.com/redis/redis/releases/tag/5.0.14) for Windows x64**, both merged with archived port of [win-3.2.100 version](https://github.com/MicrosoftArchive/redis/releases/tag/win-3.2.100) from MS Open Tech team. Since the latter is no longer maintained - the sources were merged by hand, projects updated to Visual Studio 2019 (v16.2.5) and any findings (mostly via unit tests) were fixed.
You can find the original description of what this fork provides, how it evolved, what are its requirements, etc. on Wiki: https://github.com/tporadowski/redis/wiki/Old-MSOpenTech-redis-README.md
+10
View File
@@ -6,6 +6,16 @@ For release notes related to original Redis project - please see 00-RELEASENOTES
--------------------------------------------------------
2020-11-08: Redis 5.0.10 for Windows
https://github.com/tporadowski/redis/releases/tag/v5.0.10
Bugfix/maintenance release of Redis for Windows, updated to be in sync with
redis/5.0.10 (https://github.com/redis/redis/releases/tag/5.0.10)
NOTE: active memory defragmentation feature ("activedefrag" option) is turned OFF.
--------------------------------------------------------
2020-05-02: Redis 5.0.9 for Windows
https://github.com/tporadowski/redis/releases/tag/v5.0.9
+13
View File
@@ -42,6 +42,19 @@ the following additional steps:
changed, otherwise you could just copy the old implementation if you are
upgrading just to a similar version of Jemalloc.
Jemalloc for Redis for Windows
---
In order to reconfigure `jemalloc` for Redis for Windows - please follow the steps from `msvc/ReadMe.txt` file. Due to memory allocation tracking in Windows
port - options `--with-lg-page` and `--with-lg-hugepage` must be set to the same value (which is now `22` and it defines a `1 << 22` page size = 4MB).
`jemalloc` has been confiured with:
```
sh -c "CC=cl ./autogen.sh --with-lg-quantum=3 --with-lg-page=22 --with-lg-hugepage=22 --with-version=5.2.1-0-g6619f70ffc9b53ba5d3b38c8c3d5676905242c87"
```
**NOTE**: active defragmentation is **switched OFF** for now as the Redis-specific modification that supports that feature seems to not work properly (either in jemalooc 5.2.1 or together with memory allocation code specific to Windows port of Redis).
Geohash
---
+83
View File
@@ -0,0 +1,83 @@
#!/bin/sh
usage() {
cat <<EOF
Usage:
@BINDIR@/jemalloc-config <option>
Options:
--help | -h : Print usage.
--version : Print jemalloc version.
--revision : Print shared library revision number.
--config : Print configure options used to build jemalloc.
--prefix : Print installation directory prefix.
--bindir : Print binary installation directory.
--datadir : Print data installation directory.
--includedir : Print include installation directory.
--libdir : Print library installation directory.
--mandir : Print manual page installation directory.
--cc : Print compiler used to build jemalloc.
--cflags : Print compiler flags used to build jemalloc.
--cppflags : Print preprocessor flags used to build jemalloc.
--cxxflags : Print C++ compiler flags used to build jemalloc.
--ldflags : Print library flags used to build jemalloc.
--libs : Print libraries jemalloc was linked against.
EOF
}
prefix="@prefix@"
exec_prefix="@exec_prefix@"
case "$1" in
--help | -h)
usage
exit 0
;;
--version)
echo "@jemalloc_version@"
;;
--revision)
echo "@rev@"
;;
--config)
echo "@CONFIG@"
;;
--prefix)
echo "@PREFIX@"
;;
--bindir)
echo "@BINDIR@"
;;
--datadir)
echo "@DATADIR@"
;;
--includedir)
echo "@INCLUDEDIR@"
;;
--libdir)
echo "@LIBDIR@"
;;
--mandir)
echo "@MANDIR@"
;;
--cc)
echo "@CC@"
;;
--cflags)
echo "@CFLAGS@"
;;
--cppflags)
echo "@CPPFLAGS@"
;;
--cxxflags)
echo "@CXXFLAGS@"
;;
--ldflags)
echo "@LDFLAGS@ @EXTRA_LDFLAGS@"
;;
--libs)
echo "@LIBS@"
;;
*)
usage
exit 1
esac
+9
View File
@@ -0,0 +1,9 @@
#!/bin/sh
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
@LD_PRELOAD_VAR@=${libdir}/libjemalloc.@SOREV@
export @LD_PRELOAD_VAR@
exec "$@"
+5625
View File
File diff suppressed because it is too large Load Diff
@@ -173,7 +173,7 @@
* Minimum allocation alignment is 2^LG_QUANTUM bytes (ignoring tiny size
* classes).
*/
/* #undef LG_QUANTUM */
#define LG_QUANTUM 3
/* One page is 2^LG_PAGE bytes. */
#define LG_PAGE 22
@@ -219,4 +219,32 @@ ixalloc(tsdn_t *tsdn, void *ptr, size_t oldsize, size_t size, size_t extra,
newsize);
}
JEMALLOC_ALWAYS_INLINE int
iget_defrag_hint(tsdn_t *tsdn, void* ptr, int *bin_util, int *run_util) {
int defrag = 0;
rtree_ctx_t rtree_ctx_fallback;
rtree_ctx_t *rtree_ctx = tsdn_rtree_ctx(tsdn, &rtree_ctx_fallback);
szind_t szind;
bool is_slab;
rtree_szind_slab_read(tsdn, &extents_rtree, rtree_ctx, (uintptr_t)ptr, true, &szind, &is_slab);
if (likely(is_slab)) {
/* Small allocation. */
extent_t *slab = iealloc(tsdn, ptr);
arena_t *arena = extent_arena_get(slab);
szind_t binind = extent_szind_get(slab);
bin_t *bin = arena->bins[binind].bin_shards;
malloc_mutex_lock(tsdn, &bin->lock);
/* don't bother moving allocations from the slab currently used for new allocations */
if (slab != bin->slabcur) {
const bin_info_t *bin_info = &bin_infos[binind];
size_t availregs = bin_info->nregs * bin->stats.curslabs;
*bin_util = ((long long)bin->stats.curregs<<16) / availregs;
*run_util = ((long long)(bin_info->nregs - extent_nfree_get(slab))<<16) / bin_info->nregs;
defrag = 1;
}
malloc_mutex_unlock(tsdn, &bin->lock);
}
return defrag;
}
#endif /* JEMALLOC_INTERNAL_INLINES_C_H */
@@ -16,7 +16,7 @@ BEGIN {
je_malloc_stats_print \
je_malloc_usable_size \
je_mallocx \
je_smallocx_ea6b3e973b477b8061e0076bb257dbd7f3faa756 \
je_smallocx_6619f70ffc9b53ba5d3b38c8c3d5676905242c87 \
je_nallocx \
je_posix_memalign \
je_rallocx \
@@ -16,7 +16,7 @@ BEGIN {
jet_malloc_stats_print \
jet_malloc_usable_size \
jet_mallocx \
jet_smallocx_ea6b3e973b477b8061e0076bb257dbd7f3faa756 \
jet_smallocx_6619f70ffc9b53ba5d3b38c8c3d5676905242c87 \
jet_nallocx \
jet_posix_memalign \
jet_rallocx \
@@ -11,7 +11,7 @@
#define je_malloc_stats_print JEMALLOC_N(malloc_stats_print)
#define je_malloc_usable_size JEMALLOC_N(malloc_usable_size)
#define je_mallocx JEMALLOC_N(mallocx)
#define je_smallocx_ea6b3e973b477b8061e0076bb257dbd7f3faa756 JEMALLOC_N(smallocx_ea6b3e973b477b8061e0076bb257dbd7f3faa756)
#define je_smallocx_6619f70ffc9b53ba5d3b38c8c3d5676905242c87 JEMALLOC_N(smallocx_6619f70ffc9b53ba5d3b38c8c3d5676905242c87)
#define je_nallocx JEMALLOC_N(nallocx)
#define je_posix_memalign JEMALLOC_N(posix_memalign)
#define je_rallocx JEMALLOC_N(rallocx)
@@ -11,7 +11,7 @@ malloc_message:je_malloc_message
malloc_stats_print:je_malloc_stats_print
malloc_usable_size:je_malloc_usable_size
mallocx:je_mallocx
smallocx_ea6b3e973b477b8061e0076bb257dbd7f3faa756:je_smallocx_ea6b3e973b477b8061e0076bb257dbd7f3faa756
smallocx_6619f70ffc9b53ba5d3b38c8c3d5676905242c87:je_smallocx_6619f70ffc9b53ba5d3b38c8c3d5676905242c87
nallocx:je_nallocx
posix_memalign:je_posix_memalign
rallocx:je_rallocx
@@ -11,7 +11,7 @@
#undef je_malloc_stats_print
#undef je_malloc_usable_size
#undef je_mallocx
#undef je_smallocx_ea6b3e973b477b8061e0076bb257dbd7f3faa756
#undef je_smallocx_6619f70ffc9b53ba5d3b38c8c3d5676905242c87
#undef je_nallocx
#undef je_posix_memalign
#undef je_rallocx
+11 -6
View File
@@ -72,7 +72,7 @@ extern "C" {
# define je_malloc_stats_print je_malloc_stats_print
# define je_malloc_usable_size je_malloc_usable_size
# define je_mallocx je_mallocx
# define je_smallocx_ea6b3e973b477b8061e0076bb257dbd7f3faa756 je_smallocx_ea6b3e973b477b8061e0076bb257dbd7f3faa756
# define je_smallocx_6619f70ffc9b53ba5d3b38c8c3d5676905242c87 je_smallocx_6619f70ffc9b53ba5d3b38c8c3d5676905242c87
# define je_nallocx je_nallocx
# define je_posix_memalign je_posix_memalign
# define je_rallocx je_rallocx
@@ -88,13 +88,13 @@ extern "C" {
#include <limits.h>
#include <string.h>
#define JEMALLOC_VERSION "5.2.1-0-gea6b3e973b477b8061e0076bb257dbd7f3faa756"
#define JEMALLOC_VERSION "5.2.1-0-g6619f70ffc9b53ba5d3b38c8c3d5676905242c87"
#define JEMALLOC_VERSION_MAJOR 5
#define JEMALLOC_VERSION_MINOR 2
#define JEMALLOC_VERSION_BUGFIX 1
#define JEMALLOC_VERSION_NREV 0
#define JEMALLOC_VERSION_GID "ea6b3e973b477b8061e0076bb257dbd7f3faa756"
#define JEMALLOC_VERSION_GID_IDENT ea6b3e973b477b8061e0076bb257dbd7f3faa756
#define JEMALLOC_VERSION_GID "6619f70ffc9b53ba5d3b38c8c3d5676905242c87"
#define JEMALLOC_VERSION_GID_IDENT 6619f70ffc9b53ba5d3b38c8c3d5676905242c87
#define MALLOCX_LG_ALIGN(la) ((int)(la))
#if LG_SIZEOF_PTR == 2
@@ -212,6 +212,11 @@ extern "C" {
# define JEMALLOC_ALLOCATOR
#endif
/* This version of Jemalloc, modified for Redis, has the je_get_defrag_hint()
* function. */
//[tporadowski] turned off as it no longer works properly and needs further investigation
//#define JEMALLOC_FRAG_HINT
/*
* The je_ prefix on the following public symbol declarations is an artifact
* of namespace management, and should be omitted in application code unless
@@ -381,7 +386,7 @@ struct extent_hooks_s {
# define malloc_stats_print je_malloc_stats_print
# define malloc_usable_size je_malloc_usable_size
# define mallocx je_mallocx
# define smallocx_ea6b3e973b477b8061e0076bb257dbd7f3faa756 je_smallocx_ea6b3e973b477b8061e0076bb257dbd7f3faa756
# define smallocx_6619f70ffc9b53ba5d3b38c8c3d5676905242c87 je_smallocx_6619f70ffc9b53ba5d3b38c8c3d5676905242c87
# define nallocx je_nallocx
# define posix_memalign je_posix_memalign
# define rallocx je_rallocx
@@ -412,7 +417,7 @@ struct extent_hooks_s {
# undef je_malloc_stats_print
# undef je_malloc_usable_size
# undef je_mallocx
# undef je_smallocx_ea6b3e973b477b8061e0076bb257dbd7f3faa756
# undef je_smallocx_6619f70ffc9b53ba5d3b38c8c3d5676905242c87
# undef je_nallocx
# undef je_posix_memalign
# undef je_rallocx
+9 -4
View File
@@ -2,15 +2,15 @@
#include <stdbool.h>
#include <stdint.h>
#include <limits.h>
#include <strings.h>
#include <string.h>
#define JEMALLOC_VERSION "5.2.1-0-gea6b3e973b477b8061e0076bb257dbd7f3faa756"
#define JEMALLOC_VERSION "5.2.1-0-g6619f70ffc9b53ba5d3b38c8c3d5676905242c87"
#define JEMALLOC_VERSION_MAJOR 5
#define JEMALLOC_VERSION_MINOR 2
#define JEMALLOC_VERSION_BUGFIX 1
#define JEMALLOC_VERSION_NREV 0
#define JEMALLOC_VERSION_GID "ea6b3e973b477b8061e0076bb257dbd7f3faa756"
#define JEMALLOC_VERSION_GID_IDENT ea6b3e973b477b8061e0076bb257dbd7f3faa756
#define JEMALLOC_VERSION_GID "6619f70ffc9b53ba5d3b38c8c3d5676905242c87"
#define JEMALLOC_VERSION_GID_IDENT 6619f70ffc9b53ba5d3b38c8c3d5676905242c87
#define MALLOCX_LG_ALIGN(la) ((int)(la))
#if LG_SIZEOF_PTR == 2
@@ -127,3 +127,8 @@
# define JEMALLOC_RESTRICT_RETURN
# define JEMALLOC_ALLOCATOR
#endif
/* This version of Jemalloc, modified for Redis, has the je_get_defrag_hint()
* function. */
//[tporadowski] turned off as it no longer works properly and needs further investigation
//#define JEMALLOC_FRAG_HINT
+6 -1
View File
@@ -2,7 +2,7 @@
#include <stdbool.h>
#include <stdint.h>
#include <limits.h>
#include <strings.h>
#include <string.h>
#define JEMALLOC_VERSION "@jemalloc_version@"
#define JEMALLOC_VERSION_MAJOR @jemalloc_version_major@
@@ -127,3 +127,8 @@
# define JEMALLOC_RESTRICT_RETURN
# define JEMALLOC_ALLOCATOR
#endif
/* This version of Jemalloc, modified for Redis, has the je_get_defrag_hint()
* function. */
//[tporadowski] turned off as it no longer works properly and needs further investigation
//#define JEMALLOC_FRAG_HINT
+2 -2
View File
@@ -22,7 +22,7 @@
# define malloc_stats_print je_malloc_stats_print
# define malloc_usable_size je_malloc_usable_size
# define mallocx je_mallocx
# define smallocx_ea6b3e973b477b8061e0076bb257dbd7f3faa756 je_smallocx_ea6b3e973b477b8061e0076bb257dbd7f3faa756
# define smallocx_6619f70ffc9b53ba5d3b38c8c3d5676905242c87 je_smallocx_6619f70ffc9b53ba5d3b38c8c3d5676905242c87
# define nallocx je_nallocx
# define posix_memalign je_posix_memalign
# define rallocx je_rallocx
@@ -53,7 +53,7 @@
# undef je_malloc_stats_print
# undef je_malloc_usable_size
# undef je_mallocx
# undef je_smallocx_ea6b3e973b477b8061e0076bb257dbd7f3faa756
# undef je_smallocx_6619f70ffc9b53ba5d3b38c8c3d5676905242c87
# undef je_nallocx
# undef je_posix_memalign
# undef je_rallocx
+2 -2
View File
@@ -22,7 +22,7 @@
# define malloc_stats_print jet_malloc_stats_print
# define malloc_usable_size jet_malloc_usable_size
# define mallocx jet_mallocx
# define smallocx_ea6b3e973b477b8061e0076bb257dbd7f3faa756 jet_smallocx_ea6b3e973b477b8061e0076bb257dbd7f3faa756
# define smallocx_6619f70ffc9b53ba5d3b38c8c3d5676905242c87 jet_smallocx_6619f70ffc9b53ba5d3b38c8c3d5676905242c87
# define nallocx jet_nallocx
# define posix_memalign jet_posix_memalign
# define rallocx jet_rallocx
@@ -53,7 +53,7 @@
# undef jet_malloc_stats_print
# undef jet_malloc_usable_size
# undef jet_mallocx
# undef jet_smallocx_ea6b3e973b477b8061e0076bb257dbd7f3faa756
# undef jet_smallocx_6619f70ffc9b53ba5d3b38c8c3d5676905242c87
# undef jet_nallocx
# undef jet_posix_memalign
# undef jet_rallocx
+1 -1
View File
@@ -17,7 +17,7 @@
# define je_malloc_stats_print je_malloc_stats_print
# define je_malloc_usable_size je_malloc_usable_size
# define je_mallocx je_mallocx
# define je_smallocx_ea6b3e973b477b8061e0076bb257dbd7f3faa756 je_smallocx_ea6b3e973b477b8061e0076bb257dbd7f3faa756
# define je_smallocx_6619f70ffc9b53ba5d3b38c8c3d5676905242c87 je_smallocx_6619f70ffc9b53ba5d3b38c8c3d5676905242c87
# define je_nallocx je_nallocx
# define je_posix_memalign je_posix_memalign
# define je_rallocx je_rallocx
+12
View File
@@ -3920,3 +3920,15 @@ jemalloc_postfork_child(void) {
}
/******************************************************************************/
/* Helps the application decide if a pointer is worth re-allocating in order to reduce fragmentation.
* returns 0 if the allocation is in the currently active run,
* or when it is not causing any frag issue (large or huge bin)
* returns the bin utilization and run utilization both in fixed point 16:16.
* If the application decides to re-allocate it should use MALLOCX_TCACHE_NONE when doing so. */
JEMALLOC_EXPORT int JEMALLOC_NOTHROW
je_get_defrag_hint(void* ptr, int *bin_util, int *run_util) {
assert(ptr != NULL);
return iget_defrag_hint(TSDN_NULL, ptr, bin_util, run_util);
}
+1 -1
View File
@@ -274,7 +274,7 @@ int luaD_precall (lua_State *L, StkId func, int nresults) {
CallInfo *ci;
StkId st, base;
Proto *p = cl->p;
luaD_checkstack(L, p->maxstacksize);
luaD_checkstack(L, p->maxstacksize + p->numparams);
func = restorestack(L, funcr);
if (!p->is_vararg) { /* no varargs? */
base = func + 1;
+4 -4
View File
@@ -50,8 +50,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 5,0,9
PRODUCTVERSION 5,0,9
FILEVERSION 5,0,10
PRODUCTVERSION 5,0,10
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -68,10 +68,10 @@ BEGIN
BEGIN
VALUE "CompanyName", "Poradowski.com Tomasz Poradowski"
VALUE "FileDescription", "Redis for Windows, based on MS OpenTech port."
VALUE "FileVersion", "5.0.9"
VALUE "FileVersion", "5.0.10"
VALUE "LegalCopyright", "Copyright (C) 2006-2018 Salvatore Sanfilippo, Microsoft Open Technologies Inc., Tomasz Poradowski"
VALUE "ProductName", "Redis for Windows"
VALUE "ProductVersion", "5.0.9"
VALUE "ProductVersion", "5.0.10"
END
END
BLOCK "VarFileInfo"
+1 -1
View File
@@ -182,7 +182,7 @@ copy /Y $(OutputPath)redis-server.pdb $(OutputPath)redis-check-aof.pdb</Command>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PreprocessorDefinitions>USE_JEMALLOC;_OFF_T_DEFINED;_WIN32;LACKS_STDLIB_H;NDEBUG;_CONSOLE;__x86_64__;%(PreprocessorDefinitions);_WIN32_WINNT=0x0501</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir)..\deps\lua\src;$(SolutionDir)..\deps\geohash-int;$(SolutionDir)..\deps\hiredis;$(SolutionDir)..\deps\jemalloc-5.2.1\include..\deps\jemalloc-5.2.1\include\msvc_compat</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SolutionDir)..\deps\lua\src;$(SolutionDir)..\deps\geohash-int;$(SolutionDir)..\deps\hiredis;$(SolutionDir)..\deps\jemalloc-5.2.1\include;..\deps\jemalloc-5.2.1\include\msvc_compat</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+1 -1
View File
@@ -21,7 +21,7 @@
<Product Id="*"
Name="Redis on Windows"
Language="1033"
Version="5.0.9"
Version="5.0.10"
Manufacturer="Poradowski.com"
UpgradeCode="{05410198-7212-4FC4-B7C8-AFEFC3DA0FBC}">
<Package InstallerVersion="200"
+1 -1
View File
@@ -3,7 +3,7 @@
<metadata>
<id>redis-64</id>
<title>Redis 64-bit</title>
<version>5.0.9</version>
<version>5.0.10</version>
<authors>Alexis Campailla, Enrico Giordani, Jonathan Pickett</authors>
<owners>Microsoft Open Technologies, Inc.</owners>
<description>A porting of Redis on Windows 64-bit.
+1 -1
View File
@@ -3,7 +3,7 @@
<metadata>
<id>redis-64</id>
<title>Redis 64-bit</title>
<version>5.0.9</version>
<version>5.0.10</version>
<authors>Alexis Campailla, Enrico Giordani, Jonathan Pickett</authors>
<owners>Microsoft Open Technologies, Inc.</owners>
<description>A porting of Redis on Windows 64-bit.
+6 -4
View File
@@ -289,20 +289,22 @@ public:
subCommands = RedisParameterMapper
{
{ "monitor", &fp4 }, // sentinel monitor [master name] [ip] [port] [quorum]
{ "auth-pass", &fp2 }, // sentinel auth-pass [master name] [password]
{ "down-after-milliseconds", &fp2 }, // sentinel down-after-milliseconds [master name] [milliseconds]
{ "parallel-syncs", &fp2 }, // sentinel parallel-syncs [master name] [number]
{ "failover-timeout", &fp2 }, // sentinel failover-timeout [master name] [number]
{ "parallel-syncs", &fp2 }, // sentinel parallel-syncs [master name] [number]
{ "notification-script", &fp2 }, // sentinel notification-script [master name] [scriptPath]
{ "client-reconfig-script", &fp2 }, // sentinel client-reconfig-script [master name] [scriptPath]
{ "config-epoch", &fp2 }, // sentinel config-epoch [name] [epoch]
{ "auth-pass", &fp2 }, // sentinel auth-pass [master name] [password]
{ "current-epoch", &fp1 }, // sentinel current-epoch <epoch>
{ "myid", &fp1 }, // sentinel myid <id>
{ "config-epoch", &fp2 }, // sentinel config-epoch [name] [epoch]
{ "leader-epoch", &fp2 }, // sentinel leader-epoch [name] [epoch]
{ "known-slave", &fp3 }, // sentinel known-slave <name> <ip> <port>
{ "known-replica", &fp3 }, // sentinel known-slave <name> <ip> <port>
{ "known-sentinel", &fp4 }, // sentinel known-sentinel <name> <ip> <port> [runid]
{ "rename-command", &fp3 }, // sentinel rename-command <name> <command> <renamed-command>
{ "announce-ip", &fp1 }, // sentinel announce-ip <ip>
{ "announce-port", &fp1 }, // sentinel announce-port <port>
{ "myid", &fp1 }, // sentinel myid <id>
{ "deny-scripts-reconfig", &fp1 } // sentinel deny-scripts-reconfig [yes/no]
};
}
+6
View File
@@ -29,6 +29,12 @@ namespace Globals
/* This function is used to force the VEH on the entire size of the buffer length,
* in the event that the buffer crosses the memory page boundaries */
void EnsureMemoryIsMapped(const void *buffer, size_t size) {
//[tporadowski/#62] when this is called from main process - Globals::pageSize is not initialized,
// so prevent EXCEPTION_INT_DIVIDE_BY_ZERO
if (Globals::pageSize == 0) {
return;
}
char* pFirstByte = (char*) buffer;
char* pLastByte = (char*) buffer + size - 1;
char* pFirstPage = pFirstByte - ((size_t) pFirstByte % Globals::pageSize);
+3 -2
View File
@@ -101,6 +101,7 @@
#include "Win32_EventLog.h"
#include <jemalloc/jemalloc.h>
#include <jemalloc/internal/jemalloc_internal_defs.h>
#include <algorithm>
#include <string>
@@ -163,9 +164,9 @@ extern "C"
PORT_LONGLONG memtoll(const char *p, int *err); // Forward def from util.h
}
const size_t cAllocationGranularity = 1 << 22; // 4MB per heap block (matches the default allocation threshold of jemalloc)
const size_t cAllocationGranularity = 1 << LG_PAGE; // 4MB per heap block (matches the default allocation threshold of jemalloc)
#ifdef _WIN64
const int cMaxBlocks = 1 << 18; // 4MB * 256K heap blocks = 1TB
const int cMaxBlocks = 1 << (40 - LG_PAGE); // 4MB * 256K heap blocks = 1TB
#else
const int cMaxBlocks = 1 << 8; // 4MB * 256 heap blocks = 1GB
#endif
+1 -1
View File
@@ -452,7 +452,7 @@ void handleClientsBlockedOnKeys(void) {
if (group) {
consumer = streamLookupConsumer(group,
receiver->bpop.xread_consumer->ptr,
1);
SLC_NONE);
noack = receiver->bpop.xread_group_noack;
}
+74 -23
View File
@@ -755,6 +755,7 @@ clusterNode *createClusterNode(char *nodename, int flags) {
node->slaves = NULL;
node->slaveof = NULL;
node->ping_sent = node->pong_received = 0;
node->data_received = 0;
node->fail_time = 0;
node->link = NULL;
memset(node->ip,0,sizeof(node->ip));
@@ -1468,7 +1469,10 @@ void clusterProcessGossipSection(clusterMsg *hdr, clusterLink *link) {
}
} else {
/* If it's not in NOADDR state and we don't have it, we
* start a handshake process against this IP/PORT pairs.
* add it to our trusted dict with exact nodeid and flag.
* Note that we cannot simply start a handshake against
* this IP/PORT pairs, since IP/PORT can be reused already,
* otherwise we risk joining another cluster.
*
* Note that we require that the sender of this gossip message
* is a well known node in our cluster, otherwise we risk
@@ -1477,7 +1481,12 @@ void clusterProcessGossipSection(clusterMsg *hdr, clusterLink *link) {
!(flags & CLUSTER_NODE_NOADDR) &&
!clusterBlacklistExists(g->nodename))
{
clusterStartHandshake(g->ip,ntohs(g->port),ntohs(g->cport));
clusterNode *node;
node = createClusterNode(g->nodename, flags);
memcpy(node->ip,g->ip,NET_IP_STR_LEN);
node->port = ntohs(g->port);
node->cport = ntohs(g->cport);
clusterAddNode(node);
}
}
@@ -1684,6 +1693,7 @@ int clusterProcessPacket(clusterLink *link) {
clusterMsg *hdr = (clusterMsg*) link->rcvbuf;
uint32_t totlen = ntohl(hdr->totlen);
uint16_t type = ntohs(hdr->type);
mstime_t now = mstime();
if (type < CLUSTERMSG_TYPE_COUNT)
server.cluster->stats_bus_messages_received[type]++;
@@ -1747,6 +1757,13 @@ int clusterProcessPacket(clusterLink *link) {
/* Check if the sender is a known node. */
sender = clusterLookupNode(hdr->sender);
/* Update the last time we saw any data from this node. We
* use this in order to avoid detecting a timeout from a node that
* is just sending a lot of data in the cluster bus, for instance
* because of Pub/Sub. */
if (sender) sender->data_received = now;
if (sender && !nodeInHandshake(sender)) {
/* Update our curretEpoch if we see a newer epoch in the cluster. */
senderCurrentEpoch = ntohu64(hdr->currentEpoch);
@@ -1761,7 +1778,7 @@ int clusterProcessPacket(clusterLink *link) {
}
/* Update the replication offset info for this node. */
sender->repl_offset = ntohu64(hdr->offset);
sender->repl_offset_time = mstime();
sender->repl_offset_time = now;
/* If we are a slave performing a manual failover and our master
* sent its offset while already paused, populate the MF state. */
if (server.cluster->mf_end &&
@@ -1875,7 +1892,7 @@ int clusterProcessPacket(clusterLink *link) {
* address. */
serverLog(LL_DEBUG,"PONG contains mismatching sender ID. About node %.40s added %d ms ago, having flags %d",
link->node->name,
(int)(mstime()-(link->node->ctime)),
(int)(now-(link->node->ctime)),
link->node->flags);
link->node->flags |= CLUSTER_NODE_NOADDR;
link->node->ip[0] = '\0';
@@ -1910,7 +1927,7 @@ int clusterProcessPacket(clusterLink *link) {
/* Update our info about the node */
if (link->node && type == CLUSTERMSG_TYPE_PONG) {
link->node->pong_received = mstime();
link->node->pong_received = now;
link->node->ping_sent = 0;
/* The PFAIL condition can be reversed without external
@@ -2057,7 +2074,7 @@ int clusterProcessPacket(clusterLink *link) {
"FAIL message received from %.40s about %.40s",
hdr->sender, hdr->data.fail.about.nodename);
failing->flags |= CLUSTER_NODE_FAIL;
failing->fail_time = mstime();
failing->fail_time = now;
failing->flags &= ~CLUSTER_NODE_PFAIL;
clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG|
CLUSTER_TODO_UPDATE_STATE);
@@ -2110,9 +2127,9 @@ int clusterProcessPacket(clusterLink *link) {
/* Manual failover requested from slaves. Initialize the state
* accordingly. */
resetManualFailover();
server.cluster->mf_end = mstime() + CLUSTER_MF_TIMEOUT;
server.cluster->mf_end = now + CLUSTER_MF_TIMEOUT;
server.cluster->mf_slave = sender;
pauseClients(mstime()+(CLUSTER_MF_TIMEOUT*2));
pauseClients(now+(CLUSTER_MF_TIMEOUT*CLUSTER_MF_PAUSE_MULT));
serverLog(LL_WARNING,"Manual failover requested by replica %.40s.",
sender->name);
} else if (type == CLUSTERMSG_TYPE_UPDATE) {
@@ -3558,7 +3575,6 @@ void clusterCron(void) {
while((de = dictNext(di)) != NULL) {
clusterNode *node = dictGetVal(de);
now = mstime(); /* Use an updated time at every iteration. */
mstime_t delay;
if (node->flags &
(CLUSTER_NODE_MYSELF|CLUSTER_NODE_NOADDR|CLUSTER_NODE_HANDSHAKE))
@@ -3582,7 +3598,7 @@ void clusterCron(void) {
this_slaves = okslaves;
}
/* If we are waiting for the PONG more than half the cluster
/* If we are not receiving any data for more than half the cluster
* timeout, reconnect the link: maybe there is a connection
* issue even if the node is alive. */
if (node->link && /* is connected */
@@ -3591,7 +3607,9 @@ void clusterCron(void) {
node->ping_sent && /* we already sent a ping */
node->pong_received < node->ping_sent && /* still waiting pong */
/* and we are waiting for the pong more than timeout/2 */
now - node->ping_sent > server.cluster_node_timeout/2)
now - node->ping_sent > server.cluster_node_timeout/2 &&
/* and in such interval we are not seeing any traffic at all. */
now - node->data_received > server.cluster_node_timeout/2)
{
/* Disconnect the link, it will be reconnected automatically. */
freeClusterLink(node->link);
@@ -3626,7 +3644,13 @@ void clusterCron(void) {
/* Compute the delay of the PONG. Note that if we already received
* the PONG, then node->ping_sent is zero, so can't reach this
* code at all. */
delay = now - node->ping_sent;
mstime_t delay = now - node->ping_sent;
/* We consider every incoming data as proof of liveness, since
* our cluster bus link is also used for data: under heavy data
* load pong delays are possible. */
mstime_t data_delay = now - node->data_received;
if (data_delay < delay) delay = data_delay;
if (delay > server.cluster_node_timeout) {
/* Timeout reached. Set the node as possibly failing if it is
@@ -4220,11 +4244,17 @@ void clusterReplyMultiBulkSlots(client *c) {
while((de = dictNext(di)) != NULL) {
clusterNode *node = dictGetVal(de);
int j = 0, start = -1;
int i, nested_elements = 0;
/* Skip slaves (that are iterated when producing the output of their
* master) and masters not serving any slot. */
if (!nodeIsMaster(node) || node->numslots == 0) continue;
for(i = 0; i < node->numslaves; i++) {
if (nodeFailed(node->slaves[i])) continue;
nested_elements++;
}
for (j = 0; j < CLUSTER_SLOTS; j++) {
int bit, i;
@@ -4232,8 +4262,7 @@ void clusterReplyMultiBulkSlots(client *c) {
if (start == -1) start = j;
}
if (start != -1 && (!bit || j == CLUSTER_SLOTS-1)) {
int nested_elements = 3; /* slots (2) + master addr (1). */
void *nested_replylen = addDeferredMultiBulkLength(c);
addReplyMultiBulkLen(c, nested_elements + 3); /* slots (2) + master addr (1). */
if (bit && j == CLUSTER_SLOTS-1) j++;
@@ -4263,9 +4292,7 @@ void clusterReplyMultiBulkSlots(client *c) {
addReplyBulkCString(c, node->slaves[i]->ip);
addReplyLongLong(c, node->slaves[i]->port);
addReplyBulkCBuffer(c, node->slaves[i]->name, CLUSTER_NAMELEN);
nested_elements++;
}
setDeferredMultiBulkLength(c, nested_replylen, nested_elements);
num_masters++;
}
}
@@ -4979,7 +5006,8 @@ void restoreCommand(client *c) {
}
/* Make sure this key does not already exist here... */
if (!replace && lookupKeyWrite(c->db,c->argv[1]) != NULL) {
robj *key = c->argv[1];
if (!replace && lookupKeyWrite(c->db,key) != NULL) {
addReply(c,shared.busykeyerr);
return;
}
@@ -5001,23 +5029,37 @@ void restoreCommand(client *c) {
rioInitWithBuffer(&payload,c->argv[3]->ptr);
if (((type = rdbLoadObjectType(&payload)) == -1) ||
((obj = rdbLoadObject(type,&payload,c->argv[1])) == NULL))
((obj = rdbLoadObject(type,&payload,key)) == NULL))
{
addReplyError(c,"Bad data format");
return;
}
/* Remove the old key if needed. */
if (replace) dbDelete(c->db,c->argv[1]);
int deleted = 0;
if (replace)
deleted = dbDelete(c->db,key);
if (ttl && !absttl) ttl+=mstime();
if (ttl && checkAlreadyExpired(ttl)) {
if (deleted) {
rewriteClientCommandVector(c,2,shared.del,key);
signalModifiedKey(c->db,key);
notifyKeyspaceEvent(NOTIFY_GENERIC,"del",key,c->db->id);
server.dirty++;
}
decrRefCount(obj);
addReply(c, shared.ok);
return;
}
/* Create the key and set the TTL if any */
dbAdd(c->db,c->argv[1],obj);
dbAdd(c->db,key,obj);
if (ttl) {
if (!absttl) ttl+=mstime();
setExpire(c,c->db,c->argv[1],ttl);
setExpire(c,c->db,key,ttl);
}
objectSetLRUOrLFU(obj,lfu_freq,lru_idle,lru_clock);
signalModifiedKey(c->db,c->argv[1]);
signalModifiedKey(c->db,key);
addReply(c,shared.ok);
server.dirty++;
}
@@ -5797,6 +5839,15 @@ int clusterRedirectBlockedClientIfNeeded(client *c) {
int slot = keyHashSlot((char*)key->ptr, (int)sdslen(key->ptr)); WIN_PORT_FIX /* cast (int) */
clusterNode *node = server.cluster->slots[slot];
/* if the client is read-only and attempting to access key that our
* replica can handle, allow it. */
if ((c->flags & CLIENT_READONLY) &&
(c->lastcmd->flags & CMD_READONLY) &&
nodeIsSlave(myself) && myself->slaveof == node)
{
node = myself;
}
/* We send an error and unblock the client if:
* 1) The slot is unassigned, emitting a cluster down error.
* 2) The slot is not handled by this node, nor being imported. */
+1
View File
@@ -128,6 +128,7 @@ typedef struct clusterNode {
tables. */
mstime_t ping_sent; /* Unix time we sent latest ping */
mstime_t pong_received; /* Unix time we received the pong */
mstime_t data_received; /* Unix time we received any data */
mstime_t fail_time; /* Unix time when FAIL flag was set */
mstime_t voted_time; /* Last time we voted for a slave of this master */
mstime_t repl_offset_time; /* Unix time we received offset for this node */
-8
View File
@@ -857,14 +857,6 @@ void shutdownCommand(client *c) {
return;
}
}
/* When SHUTDOWN is called while the server is loading a dataset in
* memory we need to make sure no attempt is performed to save
* the dataset on shutdown (otherwise it could overwrite the current DB
* with half-read data).
*
* Also when in Sentinel mode clear the SAVE flag and force NOSAVE. */
if (server.loading || server.sentinel_mode)
flags = (flags & ~SHUTDOWN_SAVE) | SHUTDOWN_NOSAVE;
if (prepareForShutdown(flags) == C_OK) exit(0);
addReplyError(c,"Errors trying to SHUTDOWN. Check logs.");
}
+1 -1
View File
@@ -355,7 +355,7 @@ PORT_LONG activeDefragSdsListAndDict(list *l, dict *d, int dict_val_type) {
sdsele = ln->value;
if ((newsds = activeDefragSds(sdsele))) {
/* When defragging an sds value, we need to update the dict key */
uint64_t hash = dictGetHash(d, sdsele);
uint64_t hash = dictGetHash(d, newsds);
replaceSateliteDictKeyPtrAndOrDefragDictEntry(d, sdsele, newsds, hash, &defragged);
ln->value = newsds;
defragged++;
+11 -7
View File
@@ -391,6 +391,16 @@ void flushSlaveKeysWithExpireList(void) {
}
}
int checkAlreadyExpired(PORT_LONGLONG when) {
/* EXPIRE with negative TTL, or EXPIREAT with a timestamp into the past
* should never be executed as a DEL when load the AOF or in the context
* of a slave instance.
*
* Instead we add the already expired key to the database with expire time
* (possibly in the past) and wait for an explicit DEL from the master. */
return (when <= mstime() && !server.loading && !server.masterhost);
}
/*-----------------------------------------------------------------------------
* Expires Commands
*----------------------------------------------------------------------------*/
@@ -418,13 +428,7 @@ void expireGenericCommand(client *c, PORT_LONGLONG basetime, int unit) {
return;
}
/* EXPIRE with negative TTL, or EXPIREAT with a timestamp into the past
* should never be executed as a DEL when load the AOF or in the context
* of a slave instance.
*
* Instead we take the other branch of the IF statement setting an expire
* (possibly in the past) and wait for an explicit DEL from the master. */
if (when <= mstime() && !server.loading && !server.masterhost) {
if (checkAlreadyExpired(when)) {
robj *aux;
int deleted = server.lazyfree_lazy_expire ? dbAsyncDelete(c->db,key) :
+24
View File
@@ -45,6 +45,30 @@ size_t lazyfreeGetFreeEffort(robj *obj) {
} else if (obj->type == OBJ_HASH && obj->encoding == OBJ_ENCODING_HT) {
dict *ht = obj->ptr;
return dictSize(ht);
} else if (obj->type == OBJ_STREAM) {
size_t effort = 0;
stream *s = obj->ptr;
/* Make a best effort estimate to maintain constant runtime. Every macro
* node in the Stream is one allocation. */
effort += s->rax->numnodes;
/* Every consumer group is an allocation and so are the entries in its
* PEL. We use size of the first group's PEL as an estimate for all
* others. */
if (s->cgroups) {
raxIterator ri;
streamCG *cg;
raxStart(&ri,s->cgroups);
raxSeek(&ri,"^",NULL,0);
/* There must be at least one group so the following should always
* work. */
serverAssert(raxNext(&ri));
cg = ri.data;
effort += raxSize(s->cgroups)*(1+raxSize(cg->pel));
raxStop(&ri);
}
return effort;
} else {
return 1; /* Everything else is a single allocation. */
}
+13 -4
View File
@@ -485,7 +485,8 @@ int moduleDelKeyIfEmpty(RedisModuleKey *key) {
case OBJ_LIST: isempty = listTypeLength(o) == 0; break;
case OBJ_SET: isempty = setTypeSize(o) == 0; break;
case OBJ_ZSET: isempty = zsetLength(o) == 0; break;
case OBJ_HASH : isempty = hashTypeLength(o) == 0; break;
case OBJ_HASH: isempty = hashTypeLength(o) == 0; break;
case OBJ_STREAM: isempty = streamLength(o) == 0; break;
default: isempty = 0;
}
@@ -556,6 +557,8 @@ void moduleHandlePropagationAfterCommandCallback(RedisModuleCtx *ctx) {
redisOpArrayFree(&server.also_propagate);
/* Restore the previous oparray in case of nexted use of the API. */
server.also_propagate = ctx->saved_oparray;
/* We're done with saved_oparray, let's invalidate it. */
redisOpArrayInit(&ctx->saved_oparray);
}
}
@@ -1698,6 +1701,7 @@ int RM_KeyType(RedisModuleKey *key) {
case OBJ_ZSET: return REDISMODULE_KEYTYPE_ZSET;
case OBJ_HASH: return REDISMODULE_KEYTYPE_HASH;
case OBJ_MODULE: return REDISMODULE_KEYTYPE_MODULE;
/* case OBJ_STREAM: return REDISMODULE_KEYTYPE_STREAM; - don't wanna add new API to 5.0 */
default: return 0;
}
}
@@ -1715,6 +1719,7 @@ size_t RM_ValueLength(RedisModuleKey *key) {
case OBJ_SET: return setTypeSize(key->value);
case OBJ_ZSET: return zsetLength(key->value);
case OBJ_HASH: return hashTypeLength(key->value);
case OBJ_STREAM: return streamLength(key->value);
default: return 0;
}
}
@@ -3907,7 +3912,6 @@ void moduleHandleBlockedClients(void) {
ctx.client = bc->client;
ctx.blocked_client = bc;
bc->reply_callback(&ctx,(void**)c->argv,c->argc);
moduleHandlePropagationAfterCommandCallback(&ctx);
moduleFreeContext(&ctx);
}
@@ -5355,9 +5359,14 @@ int moduleLoad(const char *path, void **module_argv, int module_argc) {
}
/* Redis module loaded! Register it. */
WIN32_ONLY(if (TRUE) {)
#ifdef _WIN32
#pragma warning(push)
#pragma warning(disable: 6011)
#endif
dictAdd(modules,ctx.module->name,ctx.module);
WIN32_ONLY(})
#ifdef _WIN32
#pragma warning(pop)
#endif
ctx.module->handle = handle;
serverLog(LL_NOTICE,"Module '%s' loaded from %s",ctx.module->name,path);
moduleFreeContext(&ctx);
+7 -4
View File
@@ -62,6 +62,7 @@ extern int rdbCheckMode;
void rdbCheckError(const char *fmt, ...);
void rdbCheckSetError(const char *fmt, ...);
WIN32_ONLY(__declspec(noreturn))
void rdbCheckThenExit(int linenum, char *reason, ...) {
va_list ap;
char msg[1024];
@@ -1000,10 +1001,10 @@ ssize_t rdbSaveObject(rio *rdb, robj *o, robj *key) {
* to call the right module during loading. */
int retval = rdbSaveLen(rdb,mt->id);
if (retval == -1) return -1;
io.bytes += retval;
/* Then write the module-specific representation + EOF marker. */
moduleInitIOContext(io,mt,rdb,key);
io.bytes += retval;
mt->rdb_save(&io,mv->value);
retval = rdbSaveLen(rdb,RDB_MODULE_OPCODE_EOF);
if (retval == -1)
@@ -1126,6 +1127,9 @@ ssize_t rdbSaveSingleModuleAux(rio *rdb, int when, moduleType *mt) {
/* Save a module-specific aux value. */
RedisModuleIO io;
int retval = rdbSaveType(rdb, RDB_OPCODE_MODULE_AUX);
if (retval == -1) return -1;
moduleInitIOContext(io,mt,rdb,NULL); WIN_PORT_FIX /*moved earlier before first usage of "io"*/
io.bytes += retval;
/* Write the "module" identifier as prefix, so that we'll be able
* to call the right module during loading. */
@@ -1144,7 +1148,6 @@ ssize_t rdbSaveSingleModuleAux(rio *rdb, int when, moduleType *mt) {
io.bytes += retval;
/* Then write the module-specific representation + EOF marker. */
moduleInitIOContext(io,mt,rdb,NULL);
mt->aux_save(&io,when);
retval = rdbSaveLen(rdb,RDB_MODULE_OPCODE_EOF);
if (retval == -1)
@@ -1812,8 +1815,8 @@ robj *rdbLoadObject(int rdbtype, rio *rdb, robj *key) {
rdbExitReportCorruptRDB(
"Error reading the consumer name from Stream group");
}
streamConsumer *consumer = streamLookupConsumer(cgroup,cname,
1);
streamConsumer *consumer =
streamLookupConsumer(cgroup,cname,SLC_NONE);
sdsfree(cname);
consumer->seen_time = rdbLoadMillisecondTime(rdb,RDB_VERSION);
+1
View File
@@ -146,6 +146,7 @@ robj *rdbLoadObject(int type, rio *rdb, robj *key);
void backgroundSaveDoneHandler(int exitcode, int bysignal);
int rdbSaveKeyValuePair(rio *rdb, robj *key, robj *val, PORT_LONGLONG expiretime);
ssize_t rdbSaveSingleModuleAux(rio *rdb, int when, moduleType *mt);
robj *rdbLoadCheckModuleValue(rio *rdb, char *modulename);
robj *rdbLoadStringObject(rio *rdb);
ssize_t rdbSaveStringObject(rio *rdb, robj *obj);
ssize_t rdbSaveRawString(rio *rdb, unsigned char *s, size_t len);
+18 -1
View File
@@ -70,6 +70,7 @@ struct {
#define RDB_CHECK_DOING_CHECK_SUM 5
#define RDB_CHECK_DOING_READ_LEN 6
#define RDB_CHECK_DOING_READ_AUX 7
#define RDB_CHECK_DOING_READ_MODULE_AUX 8
char *rdb_check_doing_string[] = {
"start",
@@ -79,7 +80,8 @@ char *rdb_check_doing_string[] = {
"read-object-value",
"check-sum",
"read-len",
"read-aux"
"read-aux",
"read-module-aux"
};
char *rdb_type_string[] = {
@@ -284,6 +286,21 @@ int redis_check_rdb(char *rdbfilename, FILE *fp) {
decrRefCount(auxkey);
decrRefCount(auxval);
continue; /* Read type again. */
} else if (type == RDB_OPCODE_MODULE_AUX) {
/* AUX: Auxiliary data for modules. */
uint64_t moduleid, when_opcode, when;
rdbstate.doing = RDB_CHECK_DOING_READ_MODULE_AUX;
if ((moduleid = rdbLoadLen(&rdb,NULL)) == RDB_LENERR) goto eoferr;
if ((when_opcode = rdbLoadLen(&rdb,NULL)) == RDB_LENERR) goto eoferr;
if ((when = rdbLoadLen(&rdb,NULL)) == RDB_LENERR) goto eoferr;
char name[10];
moduleTypeNameByID(name,moduleid);
rdbCheckInfo("MODULE AUX for: %s", name);
robj *o = rdbLoadCheckModuleValue(&rdb,name);
decrRefCount(o);
continue; /* Read type again. */
} else {
if (!rdbIsObjectType(type)) {
rdbCheckError("Invalid object type: %d", type);
+7 -1
View File
@@ -1193,7 +1193,7 @@ static int cliSendCommand(int argc, char **argv, PORT_LONG repeat) {
for (j = 0; j < argc; j++)
argvlen[j] = sdslen(argv[j]);
while(repeat-- > 0) {
while(repeat < 0 || repeat-- > 0) {
redisAppendCommandArgv(context,argc,(const char**)argv,argvlen);
while (config.monitor_mode) {
if (cliReadReply(output_raw) != REDIS_OK) exit(1);
@@ -1228,6 +1228,11 @@ static int cliSendCommand(int argc, char **argv, PORT_LONG repeat) {
cliSelect();
}
}
if (config.cluster_reissue_command){
/* If we need to reissue the command, break to prevent a
further 'repeat' number of dud interations */
break;
}
if (config.interval) usleep(config.interval);
fflush(stdout); /* Make it grep friendly */
}
@@ -6080,6 +6085,7 @@ static void getRDB(void) {
}
close(s); /* Close the file descriptor ASAP as fsync() may take time. */
fsync(fd);
close(fd);
fprintf(stderr,"Transfer finished with success.\n");
exit(0);
}
+11
View File
@@ -1412,6 +1412,17 @@ void readSyncBulkPayload(aeEventLoop *el, int fd, void *privdata, int mask) {
rdbRemoveTempFile(server.rdb_child_pid);
}
/* Make sure the new file (also used for persistence) is fully synced
* (not covered by earlier calls to rdb_fsync_range). */
if (fsync(server.repl_transfer_fd) == -1) {
serverLog(LL_WARNING,
"Failed trying to sync the temp DB to disk in "
"MASTER <-> REPLICA synchronization: %s",
strerror(errno));
cancelReplicationHandshake();
return;
}
if (rename(server.repl_transfer_tmpfile,server.rdb_filename) == -1) {
serverLog(LL_WARNING,"Failed trying to rename the temp DB into dump.rdb in MASTER <-> REPLICA synchronization: %s", IF_WIN32(wsa_strerror(errno),strerror(errno)));
cancelReplicationHandshake();
+3 -4
View File
@@ -524,12 +524,11 @@ int luaRedisGenericCommand(lua_State *lua, int raise_error) {
!server.loading && /* Don't care about mem if loading. */
!server.masterhost && /* Slave must execute the script. */
server.lua_write_dirty == 0 && /* Script had no side effects so far. */
server.lua_oom && /* Detected OOM when script start. */
(cmd->flags & CMD_DENYOOM))
{
if (getMaxmemoryState(NULL,NULL,NULL,NULL) != C_OK) {
luaPushError(lua, shared.oomerr->ptr);
goto cleanup;
}
luaPushError(lua, shared.oomerr->ptr);
goto cleanup;
}
if (cmd->flags & CMD_RANDOM) server.lua_random_dirty = 1;
+1
View File
@@ -1212,6 +1212,7 @@ int sentinelTryConnectionSharing(sentinelRedisInstance *ri) {
releaseInstanceLink(ri->link,NULL);
ri->link = match->link;
match->link->refcount++;
dictReleaseIterator(di);
return C_OK;
}
dictReleaseIterator(di);
+17 -1
View File
@@ -244,7 +244,7 @@ struct redisCommand redisCommandTable[] = {
{"keys",keysCommand,2,"rS",0,NULL,0,0,0,0,0},
{"scan",scanCommand,-2,"rR",0,NULL,0,0,0,0,0},
{"dbsize",dbsizeCommand,1,"rF",0,NULL,0,0,0,0,0},
{"auth",authCommand,2,"sltF",0,NULL,0,0,0,0,0},
{"auth",authCommand,2,"sltMF",0,NULL,0,0,0,0,0},
{"ping",pingCommand,-1,"tF",0,NULL,0,0,0,0,0},
{"echo",echoCommand,2,"F",0,NULL,0,0,0,0,0},
{"save",saveCommand,1,"as",0,NULL,0,0,0,0,0},
@@ -2747,6 +2747,13 @@ int processCommand(client *c) {
addReply(c, shared.oomerr);
return C_OK;
}
/* Save out_of_memory result at script start, otherwise if we check OOM
* untill first write within script, memory used by lua stack and
* arguments might interfere. */
if (c->cmd->proc == evalCommand || c->cmd->proc == evalShaCommand) {
server.lua_oom = out_of_memory;
}
}
/* Don't accept write commands if there are problems persisting on disk
@@ -2874,6 +2881,15 @@ void closeListeningSockets(int unlink_unix_socket) {
}
int prepareForShutdown(int flags) {
/* When SHUTDOWN is called while the server is loading a dataset in
* memory we need to make sure no attempt is performed to save
* the dataset on shutdown (otherwise it could overwrite the current DB
* with half-read data).
*
* Also when in Sentinel mode clear the SAVE flag and force NOSAVE. */
if (server.loading || server.sentinel_mode)
flags = (flags & ~SHUTDOWN_SAVE) | SHUTDOWN_NOSAVE;
int save = flags & SHUTDOWN_SAVE;
int nosave = flags & SHUTDOWN_NOSAVE;
+2
View File
@@ -1292,6 +1292,7 @@ struct redisServer {
execution. */
int lua_kill; /* Kill the script if true. */
int lua_always_replicate_commands; /* Default replication type. */
int lua_oom; /* OOM detected when script start? */
/* Lazy free */
int lazyfree_lazy_eviction;
int lazyfree_lazy_expire;
@@ -1853,6 +1854,7 @@ void propagateExpire(redisDb *db, robj *key, int lazy);
int expireIfNeeded(redisDb *db, robj *key);
PORT_LONGLONG getExpire(redisDb *db, robj *key);
void setExpire(client *c, redisDb *db, robj *key, PORT_LONGLONG when);
int checkAlreadyExpired(PORT_LONGLONG when);
#ifdef _WIN32
time_t getExpireForSave(redisDb *db, robj *key);
#endif
+7 -1
View File
@@ -96,15 +96,21 @@ typedef struct sreamPropInfo {
/* Prototypes of exported APIs. */
struct client;
/* Flags for streamLookupConsumer */
#define SLC_NONE 0
#define SLC_NOCREAT (1<<0) /* Do not create the consumer if it doesn't exist */
#define SLC_NOREFRESH (1<<1) /* Do not update consumer's seen-time */
stream *streamNew(void);
void freeStream(stream *s);
PORT_ULONG streamLength(const robj *subject);
size_t streamReplyWithRange(client *c, stream *s, streamID *start, streamID *end, size_t count, int rev, streamCG *group, streamConsumer *consumer, int flags, streamPropInfo *spi);
void streamIteratorStart(streamIterator *si, stream *s, streamID *start, streamID *end, int rev);
int streamIteratorGetID(streamIterator *si, streamID *id, int64_t *numfields);
void streamIteratorGetField(streamIterator *si, unsigned char **fieldptr, unsigned char **valueptr, int64_t *fieldlen, int64_t *valuelen);
void streamIteratorStop(streamIterator *si);
streamCG *streamLookupCG(stream *s, sds groupname);
streamConsumer *streamLookupConsumer(streamCG *cg, sds name, int create);
streamConsumer *streamLookupConsumer(streamCG *cg, sds name, int flags);
streamCG *streamCreateCG(stream *s, char *name, size_t namelen, streamID *id);
streamNACK *streamCreateNACK(streamConsumer *consumer);
void streamDecodeID(void *buf, streamID *id);
+37 -14
View File
@@ -82,6 +82,12 @@ void streamIncrID(streamID *id) {
}
}
/* Return the length of a stream. */
PORT_ULONG streamLength(const robj *subject) {
stream *s = subject->ptr;
return s->length;
}
/* Generate the next stream item ID given the previous one. If the current
* milliseconds Unix time is greater than the previous one, just use this
* as time part and start with sequence part of zero. Otherwise we use the
@@ -842,6 +848,11 @@ void streamPropagateXCLAIM(client *c, robj *key, streamCG *group, robj *groupnam
argv[11] = createStringObject("JUSTID",6);
argv[12] = createStringObject("LASTID",6);
argv[13] = createObjectFromStreamID(&group->last_id);
/* We use progagate() because this code path is not always called from
* the command execution context. Moreover this will just alter the
* consumer group state, and we don't need MULTI/EXEC wrapping because
* there is no message state cross-message atomicity required. */
propagate(server.xclaimCommand,c->db->id,argv,14,PROPAGATE_AOF|PROPAGATE_REPL);
decrRefCount(argv[0]);
decrRefCount(argv[3]);
@@ -869,7 +880,12 @@ void streamPropagateGroupID(client *c, robj *key, streamCG *group, robj *groupna
argv[2] = key;
argv[3] = groupname;
argv[4] = createObjectFromStreamID(&group->last_id);
alsoPropagate(server.xgroupCommand,c->db->id,argv,5,PROPAGATE_AOF|PROPAGATE_REPL);
/* We use progagate() because this code path is not always called from
* the command execution context. Moreover this will just alter the
* consumer group state, and we don't need MULTI/EXEC wrapping because
* there is no message state cross-message atomicity required. */
propagate(server.xgroupCommand,c->db->id,argv,5,PROPAGATE_AOF|PROPAGATE_REPL);
decrRefCount(argv[0]);
decrRefCount(argv[1]);
decrRefCount(argv[4]);
@@ -1564,7 +1580,8 @@ void xreadCommand(client *c) {
addReplyBulk(c,c->argv[streams_arg+i]);
streamConsumer *consumer = NULL;
if (groups) consumer = streamLookupConsumer(groups[i],
consumername->ptr,1);
consumername->ptr,
SLC_NONE);
streamPropInfo spi = {c->argv[i+streams_arg],groupname};
int flags = 0;
if (noack) flags |= STREAM_RWR_NOACK;
@@ -1697,7 +1714,9 @@ streamCG *streamLookupCG(stream *s, sds groupname) {
* consumer does not exist it is automatically created as a side effect
* of calling this function, otherwise its last seen time is updated and
* the existing consumer reference returned. */
streamConsumer *streamLookupConsumer(streamCG *cg, sds name, int create) {
streamConsumer *streamLookupConsumer(streamCG *cg, sds name, int flags) {
int create = !(flags & SLC_NOCREAT);
int refresh = !(flags & SLC_NOREFRESH);
streamConsumer *consumer = raxFind(cg->consumers,(unsigned char*)name,
sdslen(name));
if (consumer == raxNotFound) {
@@ -1708,7 +1727,7 @@ streamConsumer *streamLookupConsumer(streamCG *cg, sds name, int create) {
raxInsert(cg->consumers,(unsigned char*)name,sdslen(name),
consumer,NULL);
}
consumer->seen_time = mstime();
if (refresh) consumer->seen_time = mstime();
return consumer;
}
@@ -1716,7 +1735,8 @@ streamConsumer *streamLookupConsumer(streamCG *cg, sds name, int create) {
* may have pending messages: they are removed from the PEL, and the number
* of pending messages "lost" is returned. */
uint64_t streamDelConsumer(streamCG *cg, sds name) {
streamConsumer *consumer = streamLookupConsumer(cg,name,0);
streamConsumer *consumer =
streamLookupConsumer(cg,name,SLC_NOCREAT|SLC_NOREFRESH);
if (consumer == NULL) return 0;
uint64_t retval = raxSize(consumer->pel);
@@ -2047,15 +2067,18 @@ void xpendingCommand(client *c) {
}
/* XPENDING <key> <group> <start> <stop> <count> [<consumer>] variant. */
else {
streamConsumer *consumer = consumername ?
streamLookupConsumer(group,consumername->ptr,0):
NULL;
streamConsumer *consumer = NULL;
if (consumername) {
consumer = streamLookupConsumer(group,
consumername->ptr,
SLC_NOCREAT|SLC_NOREFRESH);
/* If a consumer name was mentioned but it does not exist, we can
* just return an empty array. */
if (consumername && consumer == NULL) {
addReplyMultiBulkLen(c,0);
return;
/* If a consumer name was mentioned but it does not exist, we can
* just return an empty array. */
if (consumer == NULL) {
addReplyMultiBulkLen(c,0);
return;
}
}
rax *pel = consumer ? consumer->pel : group->pel;
@@ -2317,7 +2340,7 @@ void xclaimCommand(client *c) {
raxRemove(nack->consumer->pel,buf,sizeof(buf),NULL);
/* Update the consumer and idle time. */
if (consumer == NULL)
consumer = streamLookupConsumer(group,c->argv[3]->ptr,1);
consumer = streamLookupConsumer(group,c->argv[3]->ptr,SLC_NONE);
nack->consumer = consumer;
nack->delivery_time = deliverytime;
/* Set the delivery attempts counter if given, otherwise
+1 -1
View File
@@ -1 +1 @@
#define REDIS_VERSION "5.0.9"
#define REDIS_VERSION "5.0.10"
+1 -3
View File
@@ -33,6 +33,7 @@
#include "Win32_Interop/win32_types.h"
#include "Win32_Interop/win32fixes.h"
#include "Win32_Interop/Win32_QFork.h"
#include "Win32_Interop/Win32_PThread.h"
#endif
#include <stdio.h>
@@ -188,9 +189,6 @@ void *zrealloc(void *ptr, size_t size) {
size_t zmalloc_size(void *ptr) {
void *realptr = (char*)ptr-PREFIX_SIZE;
size_t size = *((size_t*)realptr);
/* Assume at least that all the allocations are padded at sizeof(long) by
* the underlying allocator. */
if (size&(sizeof(PORT_LONG)-1)) size += sizeof(PORT_LONG)-(size&(sizeof(PORT_LONG)-1));
return size+PREFIX_SIZE;
}
size_t zmalloc_usable(void *ptr) {
+6 -2
View File
@@ -51,7 +51,7 @@
#endif
#elif defined(USE_JEMALLOC)
#define ZMALLOC_LIB ("jemalloc-" __xstr(JEMALLOC_VERSION_MAJOR) "." __xstr(JEMALLOC_VERSION_MINOR) "." __xstr(JEMALLOC_VERSION_BUGFIX))
#define ZMALLOC_LIB ("jemalloc-" __xstr(JEMALLOC_VERSION_MAJOR) "." __xstr(JEMALLOC_VERSION_MINOR) "." __xstr(JEMALLOC_VERSION_BUGFIX) "-redis")
#include <jemalloc/jemalloc.h>
#if (JEMALLOC_VERSION_MAJOR == 2 && JEMALLOC_VERSION_MINOR >= 1) || (JEMALLOC_VERSION_MAJOR > 2)
#define HAVE_MALLOC_SIZE 1
@@ -64,11 +64,15 @@
#include <malloc/malloc.h>
#define HAVE_MALLOC_SIZE 1
#define zmalloc_size(p) malloc_size(p)
#endif
#ifndef ZMALLOC_LIB
#define ZMALLOC_LIB "libc"
#ifdef __GLIBC__
#include <malloc.h>
#define HAVE_MALLOC_SIZE 1
#define zmalloc_size(p) malloc_usable_size(p)
#endif
#endif
/* We can enable the Redis defrag capabilities only if we are using Jemalloc
@@ -0,0 +1,70 @@
# Check basic transactions on a replica.
source "../tests/includes/init-tests.tcl"
test "Create a primary with a replica" {
create_cluster 1 1
}
test "Cluster should start ok" {
assert_cluster_state ok
}
set primary [Rn 0]
set replica [Rn 1]
test "Cant read from replica without READONLY" {
$primary SET a 1
catch {$replica GET a} err
assert {[string range $err 0 4] eq {MOVED}}
}
test "Can read from replica after READONLY" {
$replica READONLY
assert {[$replica GET a] eq {1}}
}
test "Can preform HSET primary and HGET from replica" {
$primary HSET h a 1
$primary HSET h b 2
$primary HSET h c 3
assert {[$replica HGET h a] eq {1}}
assert {[$replica HGET h b] eq {2}}
assert {[$replica HGET h c] eq {3}}
}
# didn't cherry pick b120366d4 to 5.0 yet
#test "Can MULTI-EXEC transaction of HGET operations from replica" {
# $replica MULTI
# assert {[$replica HGET h a] eq {QUEUED}}
# assert {[$replica HGET h b] eq {QUEUED}}
# assert {[$replica HGET h c] eq {QUEUED}}
# assert {[$replica EXEC] eq {1 2 3}}
#}
test "MULTI-EXEC with write operations is MOVED" {
$replica MULTI
catch {$replica HSET h b 4} err
assert {[string range $err 0 4] eq {MOVED}}
catch {$replica exec} err
assert {[string range $err 0 8] eq {EXECABORT}}
}
test "read-only blocking operations from replica" {
set rd [redis_deferring_client redis 1]
$rd readonly
$rd read
$rd XREAD BLOCK 0 STREAMS k 0
wait_for_condition 1000 50 {
[RI 1 blocked_clients] eq {1}
} else {
fail "client wasn't blocked"
}
$primary XADD k * foo bar
set res [$rd read]
set res [lindex [lindex [lindex [lindex $res 0] 1] 0] 1]
assert {$res eq {foo bar}}
$rd close
}
+21 -2
View File
@@ -350,10 +350,16 @@ proc S {n args} {
[dict get $s link] {*}$args
}
# Returns a Redis instance by index.
# Example:
# [Rn 0] info
proc Rn {n} {
return [dict get [lindex $::redis_instances $n] link]
}
# Like R but to chat with Redis instances.
proc R {n args} {
set r [lindex $::redis_instances $n]
[dict get $r link] {*}$args
[Rn $n] {*}$args
}
proc get_info_field {info field} {
@@ -532,3 +538,16 @@ proc restart_instance {type id} {
}
}
proc redis_deferring_client {type id} {
set port [get_instance_attrib $type $id port]
set host [get_instance_attrib $type $id host]
set client [redis $host $port 1]
return $client
}
proc redis_client {type id} {
set port [get_instance_attrib $type $id port]
set host [get_instance_attrib $type $id host]
set client [redis $host $port 0]
return $client
}
+16
View File
@@ -180,6 +180,12 @@ start_server {} {
}
set new_sync_count [status $R($master_id) sync_full]
assert {$sync_count == $new_sync_count}
if {$::uses_cygwin} {
# read Windows PID from "INFO" to be cleaned up at the end
set pid [status $R($slave_id) process_id]
lappend ::winpids $pid
}
}
test "PSYNC2: Replica RDB restart with EVALSHA in backlog issue #4483" {
@@ -227,6 +233,12 @@ start_server {} {
incr retry -1
}
if {$::uses_cygwin} {
# read Windows PID from "INFO" to be cleaned up at the end
set pid [status $R($slave_id) process_id]
lappend ::winpids $pid
}
# The master should be back at 4 slaves eventually
wait_for_condition 50 1000 {
[status $R($master_id) connected_slaves] == 4
@@ -250,3 +262,7 @@ start_server {} {
}
}}}}}
# clean up any additional processes started by "debug restart" under Windows
# when running tests from Cygwin
cygwin_clean_up
+38 -11
View File
@@ -96,30 +96,41 @@ if { $tcl_platform(platform) != "windows" } {
}
}
proc windows_is_alive config {
set pid [dict get $config pid]
set mfilter {PID eq }
append mfilter $pid
if { [string first $pid [exec tasklist.exe -FI ${mfilter}]] != -1 } {
return 1
} else {
return 0
}
}
proc windows_kill_proc config {
set pid [dict get $config pid]
catch {exec taskkill.exe /F /T /PID $pid}
}
proc windows_kill_proc2 pid {
catch {exec taskkill.exe /F /T /PID $pid}
}
if { $tcl_platform(platform) == "windows" } {
proc is_alive config {
set pid [dict get $config pid]
set mfilter {PID eq }
append mfilter $pid
if { [string first $pid [exec tasklist.exe -FI ${mfilter}]] != -1 } {
return 1
} else {
return 0
}
return [windows_is_alive $config]
}
}
if { $tcl_platform(platform) == "windows" } {
proc kill_proc config {
set pid [dict get $config pid]
catch {exec taskkill.exe -F -T -PID $pid}
windows_kill_proc $config
}
}
if { $tcl_platform(platform) == "windows" } {
proc kill_proc2 pid {
catch {exec taskkill.exe -F -T -PID $pid}
windows_kill_proc2 $pid
}
}
@@ -389,3 +400,19 @@ proc start_server {options {code undefined}} {
set _ $srv
}
}
proc cygwin_clean_up {} {
# clean up any new processes started with "debug restart" using Windows-specific tools
foreach newpid $::winpids {
set config [dict create "pid" $newpid]
if {$::verbose} { puts "Checking if WINPID=$newpid is still alive" }
while {[windows_is_alive $config]} {
if {$::verbose} { puts "Trying to stop server with WINPID=$newpid" }
windows_kill_proc $config
after 1000
}
}
set ::winpids {}
}
+12
View File
@@ -454,6 +454,18 @@ proc print_help_screen {} {
} "\n"]
}
# [tporadowski] "debug restart" command in Redis for Windows causes a new process
# with new PID to be started, so we need to properly clean this up when running tests
# from Cygwin
set ::winpids {}
set ::uses_cygwin 0
if {$::tcl_platform(platform) == "unix"} {
set uname [exec uname -s]
if {[string first "CYGWIN" $uname] != -1} {
set ::uses_cygwin 1
}
}
# parse arguments
for {set j 0} {$j < [llength $argv]} {incr j} {
set opt [lindex $argv $j]
+12 -1
View File
@@ -36,7 +36,18 @@ start_server {tags {"dump"}} {
assert {$ttl >= 2900 && $ttl <= 3100}
r get foo
} {bar}
test {RESTORE with ABSTTL in the past} {
r set foo bar
set encoded [r dump foo]
set now [clock milliseconds]
r debug set-active-expire 0
r restore foo [expr $now-3000] $encoded absttl REPLACE
catch {r debug object foo} e
r debug set-active-expire 1
set e
} {ERR no such key}
test {RESTORE can set LRU} {
r set foo bar
set encoded [r dump foo]