Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
redis
Commits
05833959
Unverified
Commit
05833959
authored
Jun 12, 2022
by
Oran Agra
Committed by
GitHub
Jun 12, 2022
Browse files
Merge pull request #10851 from oranagra/release702
Release 7.0.2
parents
2667c412
1973558b
Changes
12
Hide whitespace changes
Inline
Side-by-side
00-RELEASENOTES
View file @
05833959
...
@@ -11,6 +11,23 @@ CRITICAL: There is a critical bug affecting MOST USERS. Upgrade ASAP.
...
@@ -11,6 +11,23 @@ CRITICAL: There is a critical bug affecting MOST USERS. Upgrade ASAP.
SECURITY: There are security fixes in the release.
SECURITY: There are security fixes in the release.
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
================================================================================
Redis 7.0.2 Released Sunday Jun 12 12:00:00 IST 2022
================================================================================
Upgrade urgency: MODERATE, specifically if you're using a previous release of
Redis 7.0, contains fixes for bugs in previous 7.0 releases.
Bug Fixes
=========
* Fixed SET and BITFIELD commands being wrongly marked movablekeys (#10837)
Regression in 7.0 possibly resulting in excessive roundtrip from cluster clients.
* Fix crash when /proc/sys/vm/overcommit_memory is inaccessible (#10848)
Regression in 7.0.1 resulting in crash on startup on some configurations.
================================================================================
================================================================================
Redis 7.0.1 Released Wed Jun 8 12:00:00 IST 2022
Redis 7.0.1 Released Wed Jun 8 12:00:00 IST 2022
================================================================================
================================================================================
...
@@ -79,8 +96,8 @@ Bug Fixes
...
@@ -79,8 +96,8 @@ Bug Fixes
* Replica fail and retry the PSYNC if the master is unresponsive (#10726)
* Replica fail and retry the PSYNC if the master is unresponsive (#10726)
* Fix ZRANGESTORE crash when zset_max_listpack_entries is 0 (#10767)
* Fix ZRANGESTORE crash when zset_max_listpack_entries is 0 (#10767)
Fixes for issues in previous release
candidate
s of Redis 7.0
Fixes for issues in previous releases of Redis 7.0
--------------------------------------------------
----------
--------------------------------------------------
* CONFIG REWRITE could cause a config change to be dropped for aliased configs (#10811)
* CONFIG REWRITE could cause a config change to be dropped for aliased configs (#10811)
* CONFIG REWRITE would omit rename-command and include lines (#10761)
* CONFIG REWRITE would omit rename-command and include lines (#10761)
...
...
src/module.c
View file @
05833959
...
@@ -1154,15 +1154,10 @@ RedisModuleCommand *moduleCreateCommandProxy(struct RedisModule *module, sds dec
...
@@ -1154,15 +1154,10 @@ RedisModuleCommand *moduleCreateCommandProxy(struct RedisModule *module, sds dec
cp->rediscmd->key_specs[0].fk.range.lastkey = lastkey < 0 ? lastkey : (lastkey-firstkey);
cp->rediscmd->key_specs[0].fk.range.lastkey = lastkey < 0 ? lastkey : (lastkey-firstkey);
cp->rediscmd->key_specs[0].fk.range.keystep = keystep;
cp->rediscmd->key_specs[0].fk.range.keystep = keystep;
cp->rediscmd->key_specs[0].fk.range.limit = 0;
cp->rediscmd->key_specs[0].fk.range.limit = 0;
/* Copy the default range to legacy_range_key_spec */
cp
->
rediscmd
->
legacy_range_key_spec
=
cp
->
rediscmd
->
key_specs
[
0
];
} else {
} else {
cp->rediscmd->key_specs_num = 0;
cp->rediscmd->key_specs_num = 0;
cp
->
rediscmd
->
legacy_range_key_spec
.
begin_search_type
=
KSPEC_BS_INVALID
;
cp
->
rediscmd
->
legacy_range_key_spec
.
find_keys_type
=
KSPEC_FK_INVALID
;
}
}
populateCommand
MovableKeys
(
cp
->
rediscmd
);
populateCommand
LegacyRangeSpec
(cp->rediscmd);
cp->rediscmd->microseconds = 0;
cp->rediscmd->microseconds = 0;
cp->rediscmd->calls = 0;
cp->rediscmd->calls = 0;
cp->rediscmd->rejected_calls = 0;
cp->rediscmd->rejected_calls = 0;
...
@@ -1697,10 +1692,9 @@ int RM_SetCommandInfo(RedisModuleCommand *command, const RedisModuleCommandInfo
...
@@ -1697,10 +1692,9 @@ int RM_SetCommandInfo(RedisModuleCommand *command, const RedisModuleCommandInfo
}
}
}
}
/* Update the legacy (first,last,step) spec used by the COMMAND command,
/* Update the legacy (first,last,step) spec
and "movablekeys" flag
used by the COMMAND command,
* by trying to "glue" consecutive range key specs. */
* by trying to "glue" consecutive range key specs. */
populateCommandLegacyRangeSpec(cmd);
populateCommandLegacyRangeSpec(cmd);
populateCommandMovableKeys
(
cmd
);
}
}
if (info->args) {
if (info->args) {
...
...
src/server.c
View file @
05833959
...
@@ -372,7 +372,7 @@ int dictExpandAllowed(size_t moreMem, double usedRatio) {
...
@@ -372,7 +372,7 @@ int dictExpandAllowed(size_t moreMem, double usedRatio) {
* belonging to the same cluster slot. See the Slot to Key API in cluster.c. */
* belonging to the same cluster slot. See the Slot to Key API in cluster.c. */
size_t
dictEntryMetadataSize
(
dict
*
d
)
{
size_t
dictEntryMetadataSize
(
dict
*
d
)
{
UNUSED
(
d
);
UNUSED
(
d
);
/* NOTICE: this also affect overhead_ht_slot_to_keys in getMemoryOverheadData.
/* NOTICE: this also affect
s
overhead_ht_slot_to_keys in getMemoryOverheadData.
* If we ever add non-cluster related data here, that code must be modified too. */
* If we ever add non-cluster related data here, that code must be modified too. */
return
server
.
cluster_enabled
?
sizeof
(
clusterDictEntryMetadata
)
:
0
;
return
server
.
cluster_enabled
?
sizeof
(
clusterDictEntryMetadata
)
:
0
;
}
}
...
@@ -774,7 +774,7 @@ int clientsCronResizeOutputBuffer(client *c, mstime_t now_ms) {
...
@@ -774,7 +774,7 @@ int clientsCronResizeOutputBuffer(client *c, mstime_t now_ms) {
*
*
* This is how it works. We have an array of CLIENTS_PEAK_MEM_USAGE_SLOTS slots
* This is how it works. We have an array of CLIENTS_PEAK_MEM_USAGE_SLOTS slots
* where we track, for each, the biggest client output and input buffers we
* where we track, for each, the biggest client output and input buffers we
* saw in that slot. Every slot correspond to one of the latest seconds, since
* saw in that slot. Every slot correspond
s
to one of the latest seconds, since
* the array is indexed by doing UNIXTIME % CLIENTS_PEAK_MEM_USAGE_SLOTS.
* the array is indexed by doing UNIXTIME % CLIENTS_PEAK_MEM_USAGE_SLOTS.
*
*
* When we want to know what was recently the peak memory usage, we just scan
* When we want to know what was recently the peak memory usage, we just scan
...
@@ -2643,9 +2643,12 @@ void InitServerLast() {
...
@@ -2643,9 +2643,12 @@ void InitServerLast() {
* By far the most common case is just one range spec (e.g. SET)
* By far the most common case is just one range spec (e.g. SET)
* but some commands' ranges were split into two or more ranges
* but some commands' ranges were split into two or more ranges
* in order to have different flags for different keys (e.g. SMOVE,
* in order to have different flags for different keys (e.g. SMOVE,
* first key is "
read write
", second key is "
write
").
* first key is "
RW ACCESS DELETE
", second key is "
RW INSERT
").
*
*
* This functions uses very basic heuristics and is "best effort":
* Additionally set the CMD_MOVABLE_KEYS flag for commands that may have key
* names in their arguments, but the legacy range spec doesn't cover all of them.
*
* This function uses very basic heuristics and is "best effort":
* 1. Only commands which have only "range" specs are considered.
* 1. Only commands which have only "range" specs are considered.
* 2. Only range specs with keystep of 1 are considered.
* 2. Only range specs with keystep of 1 are considered.
* 3. The order of the range specs must be ascending (i.e.
* 3. The order of the range specs must be ascending (i.e.
...
@@ -2667,15 +2670,26 @@ void InitServerLast() {
...
@@ -2667,15 +2670,26 @@ void InitServerLast() {
void
populateCommandLegacyRangeSpec
(
struct
redisCommand
*
c
)
{
void
populateCommandLegacyRangeSpec
(
struct
redisCommand
*
c
)
{
memset
(
&
c
->
legacy_range_key_spec
,
0
,
sizeof
(
c
->
legacy_range_key_spec
));
memset
(
&
c
->
legacy_range_key_spec
,
0
,
sizeof
(
c
->
legacy_range_key_spec
));
if
(
c
->
key_specs_num
==
0
)
/* Set the movablekeys flag if we have a GETKEYS flag for modules.
* Note that for native redis commands, we always have keyspecs,
* with enough information to rely on for movablekeys. */
if
(
c
->
flags
&
CMD_MODULE_GETKEYS
)
c
->
flags
|=
CMD_MOVABLE_KEYS
;
/* no key-specs, no keys, exit. */
if
(
c
->
key_specs_num
==
0
)
{
return
;
return
;
}
if
(
c
->
key_specs_num
==
1
&&
if
(
c
->
key_specs_num
==
1
&&
c
->
key_specs
[
0
].
begin_search_type
==
KSPEC_BS_INDEX
&&
c
->
key_specs
[
0
].
begin_search_type
==
KSPEC_BS_INDEX
&&
c
->
key_specs
[
0
].
find_keys_type
==
KSPEC_FK_RANGE
)
c
->
key_specs
[
0
].
find_keys_type
==
KSPEC_FK_RANGE
)
{
{
/* Quick win */
/* Quick win
, exactly one range spec.
*/
c
->
legacy_range_key_spec
=
c
->
key_specs
[
0
];
c
->
legacy_range_key_spec
=
c
->
key_specs
[
0
];
/* If it has the incomplete flag, set the movablekeys flag on the command. */
if
(
c
->
key_specs
[
0
].
flags
&
CMD_KEY_INCOMPLETE
)
c
->
flags
|=
CMD_MOVABLE_KEYS
;
return
;
return
;
}
}
...
@@ -2684,11 +2698,23 @@ void populateCommandLegacyRangeSpec(struct redisCommand *c) {
...
@@ -2684,11 +2698,23 @@ void populateCommandLegacyRangeSpec(struct redisCommand *c) {
for
(
int
i
=
0
;
i
<
c
->
key_specs_num
;
i
++
)
{
for
(
int
i
=
0
;
i
<
c
->
key_specs_num
;
i
++
)
{
if
(
c
->
key_specs
[
i
].
begin_search_type
!=
KSPEC_BS_INDEX
||
if
(
c
->
key_specs
[
i
].
begin_search_type
!=
KSPEC_BS_INDEX
||
c
->
key_specs
[
i
].
find_keys_type
!=
KSPEC_FK_RANGE
)
c
->
key_specs
[
i
].
find_keys_type
!=
KSPEC_FK_RANGE
)
{
/* Found an incompatible (non range) spec, skip it, and set the movablekeys flag. */
c
->
flags
|=
CMD_MOVABLE_KEYS
;
continue
;
continue
;
if
(
c
->
key_specs
[
i
].
fk
.
range
.
keystep
!=
1
)
}
return
;
if
(
c
->
key_specs
[
i
].
fk
.
range
.
keystep
!=
1
||
if
(
prev_lastkey
&&
prev_lastkey
!=
c
->
key_specs
[
i
].
bs
.
index
.
pos
-
1
)
(
prev_lastkey
&&
prev_lastkey
!=
c
->
key_specs
[
i
].
bs
.
index
.
pos
-
1
))
return
;
{
/* Found a range spec that's not plain (step of 1) or not consecutive to the previous one.
* Skip it, and we set the movablekeys flag. */
c
->
flags
|=
CMD_MOVABLE_KEYS
;
continue
;
}
if
(
c
->
key_specs
[
i
].
flags
&
CMD_KEY_INCOMPLETE
)
{
/* The spec we're using is incomplete, we can use it, but we also have to set the movablekeys flag. */
c
->
flags
|=
CMD_MOVABLE_KEYS
;
}
firstkey
=
min
(
firstkey
,
c
->
key_specs
[
i
].
bs
.
index
.
pos
);
firstkey
=
min
(
firstkey
,
c
->
key_specs
[
i
].
bs
.
index
.
pos
);
/* Get the absolute index for lastkey (in the "range" spec, lastkey is relative to firstkey) */
/* Get the absolute index for lastkey (in the "range" spec, lastkey is relative to firstkey) */
int
lastkey_abs_index
=
c
->
key_specs
[
i
].
fk
.
range
.
lastkey
;
int
lastkey_abs_index
=
c
->
key_specs
[
i
].
fk
.
range
.
lastkey
;
...
@@ -2696,10 +2722,14 @@ void populateCommandLegacyRangeSpec(struct redisCommand *c) {
...
@@ -2696,10 +2722,14 @@ void populateCommandLegacyRangeSpec(struct redisCommand *c) {
lastkey_abs_index
+=
c
->
key_specs
[
i
].
bs
.
index
.
pos
;
lastkey_abs_index
+=
c
->
key_specs
[
i
].
bs
.
index
.
pos
;
/* For lastkey we use unsigned comparison to handle negative values correctly */
/* For lastkey we use unsigned comparison to handle negative values correctly */
lastkey
=
max
((
unsigned
)
lastkey
,
(
unsigned
)
lastkey_abs_index
);
lastkey
=
max
((
unsigned
)
lastkey
,
(
unsigned
)
lastkey_abs_index
);
prev_lastkey
=
lastkey
;
}
}
if
(
firstkey
==
INT_MAX
)
if
(
firstkey
==
INT_MAX
)
{
/* Couldn't find range specs, the legacy range spec will remain empty, and we set the movablekeys flag. */
c
->
flags
|=
CMD_MOVABLE_KEYS
;
return
;
return
;
}
serverAssert
(
firstkey
!=
0
);
serverAssert
(
firstkey
!=
0
);
serverAssert
(
lastkey
!=
0
);
serverAssert
(
lastkey
!=
0
);
...
@@ -2787,11 +2817,9 @@ void populateCommandStructure(struct redisCommand *c) {
...
@@ -2787,11 +2817,9 @@ void populateCommandStructure(struct redisCommand *c) {
c
->
num_tips
++
;
c
->
num_tips
++
;
c
->
num_args
=
populateArgsStructure
(
c
->
args
);
c
->
num_args
=
populateArgsStructure
(
c
->
args
);
/* Handle the legacy range spec and the "movablekeys" flag (must be done after populating all key specs). */
populateCommandLegacyRangeSpec
(
c
);
populateCommandLegacyRangeSpec
(
c
);
/* Handle the "movablekeys" flag (must be done after populating all key specs). */
populateCommandMovableKeys
(
c
);
/* Assign the ID used for ACL. */
/* Assign the ID used for ACL. */
c
->
id
=
ACLGetCommandID
(
c
->
fullname
);
c
->
id
=
ACLGetCommandID
(
c
->
fullname
);
...
@@ -2812,7 +2840,7 @@ void populateCommandStructure(struct redisCommand *c) {
...
@@ -2812,7 +2840,7 @@ void populateCommandStructure(struct redisCommand *c) {
extern
struct
redisCommand
redisCommandTable
[];
extern
struct
redisCommand
redisCommandTable
[];
/* Populates the Redis Command Table dict from
from
the static table in commands.c
/* Populates the Redis Command Table dict from the static table in commands.c
* which is auto generated from the json files in the commands folder. */
* which is auto generated from the json files in the commands folder. */
void
populateCommandTable
(
void
)
{
void
populateCommandTable
(
void
)
{
int
j
;
int
j
;
...
@@ -3498,31 +3526,6 @@ void afterCommand(client *c) {
...
@@ -3498,31 +3526,6 @@ void afterCommand(client *c) {
}
}
}
}
/* Returns 1 for commands that may have key names in their arguments, but the legacy range
* spec doesn't cover all of them. */
void
populateCommandMovableKeys
(
struct
redisCommand
*
cmd
)
{
int
movablekeys
=
0
;
if
(
cmd
->
getkeys_proc
||
(
cmd
->
flags
&
CMD_MODULE_GETKEYS
))
{
/* Command with getkeys proc */
movablekeys
=
1
;
}
else
{
/* Redis command without getkeys proc, but possibly has
* movable keys because of a keys spec. */
for
(
int
i
=
0
;
i
<
cmd
->
key_specs_num
;
i
++
)
{
if
(
cmd
->
key_specs
[
i
].
begin_search_type
!=
KSPEC_BS_INDEX
||
cmd
->
key_specs
[
i
].
find_keys_type
!=
KSPEC_FK_RANGE
)
{
/* If we have a non-range spec it means we have movable keys */
movablekeys
=
1
;
break
;
}
}
}
if
(
movablekeys
)
cmd
->
flags
|=
CMD_MOVABLE_KEYS
;
}
/* Check if c->cmd exists, fills `err` with details in case it doesn't.
/* Check if c->cmd exists, fills `err` with details in case it doesn't.
* Return 1 if exists. */
* Return 1 if exists. */
int
commandCheckExistence
(
client
*
c
,
sds
*
err
)
{
int
commandCheckExistence
(
client
*
c
,
sds
*
err
)
{
...
@@ -6028,7 +6031,7 @@ static int THPDisable(void) {
...
@@ -6028,7 +6031,7 @@ static int THPDisable(void) {
}
}
void
linuxMemoryWarnings
(
void
)
{
void
linuxMemoryWarnings
(
void
)
{
sds
err_msg
;
sds
err_msg
=
NULL
;
if
(
checkOvercommit
(
&
err_msg
)
<
0
)
{
if
(
checkOvercommit
(
&
err_msg
)
<
0
)
{
serverLog
(
LL_WARNING
,
"WARNING %s"
,
err_msg
);
serverLog
(
LL_WARNING
,
"WARNING %s"
,
err_msg
);
sdsfree
(
err_msg
);
sdsfree
(
err_msg
);
...
@@ -6939,7 +6942,7 @@ int main(int argc, char **argv) {
...
@@ -6939,7 +6942,7 @@ int main(int argc, char **argv) {
serverLog
(
LL_WARNING
,
"Server initialized"
);
serverLog
(
LL_WARNING
,
"Server initialized"
);
#ifdef __linux__
#ifdef __linux__
linuxMemoryWarnings
();
linuxMemoryWarnings
();
sds
err_msg
;
sds
err_msg
=
NULL
;
if
(
checkXenClocksource
(
&
err_msg
)
<
0
)
{
if
(
checkXenClocksource
(
&
err_msg
)
<
0
)
{
serverLog
(
LL_WARNING
,
"WARNING %s"
,
err_msg
);
serverLog
(
LL_WARNING
,
"WARNING %s"
,
err_msg
);
sdsfree
(
err_msg
);
sdsfree
(
err_msg
);
...
...
src/server.h
View file @
05833959
...
@@ -215,7 +215,8 @@ extern int configOOMScoreAdjValuesDefaults[CONFIG_OOM_COUNT];
...
@@ -215,7 +215,8 @@ extern int configOOMScoreAdjValuesDefaults[CONFIG_OOM_COUNT];
#define CMD_MODULE_NO_CLUSTER (1ULL<<22)
/* Deny on Redis Cluster. */
#define CMD_MODULE_NO_CLUSTER (1ULL<<22)
/* Deny on Redis Cluster. */
#define CMD_NO_ASYNC_LOADING (1ULL<<23)
#define CMD_NO_ASYNC_LOADING (1ULL<<23)
#define CMD_NO_MULTI (1ULL<<24)
#define CMD_NO_MULTI (1ULL<<24)
#define CMD_MOVABLE_KEYS (1ULL<<25)
/* populated by populateCommandMovableKeys */
#define CMD_MOVABLE_KEYS (1ULL<<25)
/* The legacy range spec doesn't cover all keys.
* Populated by populateCommandLegacyRangeSpec. */
#define CMD_ALLOW_BUSY ((1ULL<<26))
#define CMD_ALLOW_BUSY ((1ULL<<26))
#define CMD_MODULE_GETCHANNELS (1ULL<<27)
/* Use the modules getchannels interface. */
#define CMD_MODULE_GETCHANNELS (1ULL<<27)
/* Use the modules getchannels interface. */
...
@@ -3550,7 +3551,6 @@ void mixDigest(unsigned char *digest, const void *ptr, size_t len);
...
@@ -3550,7 +3551,6 @@ void mixDigest(unsigned char *digest, const void *ptr, size_t len);
void
xorDigest
(
unsigned
char
*
digest
,
const
void
*
ptr
,
size_t
len
);
void
xorDigest
(
unsigned
char
*
digest
,
const
void
*
ptr
,
size_t
len
);
sds
catSubCommandFullname
(
const
char
*
parent_name
,
const
char
*
sub_name
);
sds
catSubCommandFullname
(
const
char
*
parent_name
,
const
char
*
sub_name
);
void
commandAddSubcommand
(
struct
redisCommand
*
parent
,
struct
redisCommand
*
subcommand
,
const
char
*
declared_name
);
void
commandAddSubcommand
(
struct
redisCommand
*
parent
,
struct
redisCommand
*
subcommand
,
const
char
*
declared_name
);
void
populateCommandMovableKeys
(
struct
redisCommand
*
cmd
);
void
debugDelay
(
int
usec
);
void
debugDelay
(
int
usec
);
void
killIOThreads
(
void
);
void
killIOThreads
(
void
);
void
killThreads
(
void
);
void
killThreads
(
void
);
...
...
src/syscheck.c
View file @
05833959
...
@@ -143,7 +143,7 @@ int checkOvercommit(sds *error_msg) {
...
@@ -143,7 +143,7 @@ int checkOvercommit(sds *error_msg) {
FILE
*
fp
=
fopen
(
"/proc/sys/vm/overcommit_memory"
,
"r"
);
FILE
*
fp
=
fopen
(
"/proc/sys/vm/overcommit_memory"
,
"r"
);
char
buf
[
64
];
char
buf
[
64
];
if
(
!
fp
)
return
-
1
;
if
(
!
fp
)
return
0
;
if
(
fgets
(
buf
,
64
,
fp
)
==
NULL
)
{
if
(
fgets
(
buf
,
64
,
fp
)
==
NULL
)
{
fclose
(
fp
);
fclose
(
fp
);
return
0
;
return
0
;
...
@@ -152,7 +152,7 @@ int checkOvercommit(sds *error_msg) {
...
@@ -152,7 +152,7 @@ int checkOvercommit(sds *error_msg) {
if
(
atoi
(
buf
))
{
if
(
atoi
(
buf
))
{
*
error_msg
=
sdsnew
(
*
error_msg
=
sdsnew
(
"
WARNING
overcommit_memory is set to 0! Background save may fail under low memory condition. "
"overcommit_memory is set to 0! Background save may fail under low memory condition. "
"To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the "
"To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the "
"command 'sysctl vm.overcommit_memory=1' for this to take effect."
);
"command 'sysctl vm.overcommit_memory=1' for this to take effect."
);
return
-
1
;
return
-
1
;
...
@@ -351,7 +351,7 @@ check checks[] = {
...
@@ -351,7 +351,7 @@ check checks[] = {
int
syscheck
(
void
)
{
int
syscheck
(
void
)
{
check
*
cur_check
=
checks
;
check
*
cur_check
=
checks
;
int
ret
=
1
;
int
ret
=
1
;
sds
err_msg
;
sds
err_msg
=
NULL
;
while
(
cur_check
->
check_fn
)
{
while
(
cur_check
->
check_fn
)
{
int
res
=
cur_check
->
check_fn
(
&
err_msg
);
int
res
=
cur_check
->
check_fn
(
&
err_msg
);
printf
(
"[%s]..."
,
cur_check
->
name
);
printf
(
"[%s]..."
,
cur_check
->
name
);
...
...
src/t_stream.c
View file @
05833959
...
@@ -2144,7 +2144,7 @@ void xrevrangeCommand(client *c) {
...
@@ -2144,7 +2144,7 @@ void xrevrangeCommand(client *c) {
xrangeGenericCommand
(
c
,
1
);
xrangeGenericCommand
(
c
,
1
);
}
}
/* XLEN */
/* XLEN
key
*/
void
xlenCommand
(
client
*
c
)
{
void
xlenCommand
(
client
*
c
)
{
robj
*
o
;
robj
*
o
;
if
((
o
=
lookupKeyReadOrReply
(
c
,
c
->
argv
[
1
],
shared
.
czero
))
==
NULL
if
((
o
=
lookupKeyReadOrReply
(
c
,
c
->
argv
[
1
],
shared
.
czero
))
==
NULL
...
@@ -2156,10 +2156,10 @@ void xlenCommand(client *c) {
...
@@ -2156,10 +2156,10 @@ void xlenCommand(client *c) {
/* XREAD [BLOCK <milliseconds>] [COUNT <count>] STREAMS key_1 key_2 ... key_N
/* XREAD [BLOCK <milliseconds>] [COUNT <count>] STREAMS key_1 key_2 ... key_N
* ID_1 ID_2 ... ID_N
* ID_1 ID_2 ... ID_N
*
*
* This function also implements the XREAD
-
GROUP command, which is like XREAD
* This function also implements the XREADGROUP command, which is like XREAD
* but accepting the [GROUP group-name consumer-name] additional option.
* but accepting the [GROUP group-name consumer-name] additional option.
* This is useful because while XREAD is a read command and can be called
* This is useful because while XREAD is a read command and can be called
* on slaves, XREAD
-
GROUP is not. */
* on slaves, XREADGROUP is not. */
#define XREAD_BLOCKED_DEFAULT_COUNT 1000
#define XREAD_BLOCKED_DEFAULT_COUNT 1000
void
xreadCommand
(
client
*
c
)
{
void
xreadCommand
(
client
*
c
)
{
long
long
timeout
=
-
1
;
/* -1 means, no BLOCK argument given. */
long
long
timeout
=
-
1
;
/* -1 means, no BLOCK argument given. */
...
@@ -2566,8 +2566,8 @@ void streamDelConsumer(streamCG *cg, streamConsumer *consumer) {
...
@@ -2566,8 +2566,8 @@ void streamDelConsumer(streamCG *cg, streamConsumer *consumer) {
* Consumer groups commands
* Consumer groups commands
* ----------------------------------------------------------------------- */
* ----------------------------------------------------------------------- */
/* XGROUP CREATE <key> <groupname> <id or $> [MKSTREAM] [ENTRIES
ADDED count
]
/* XGROUP CREATE <key> <groupname> <id or $> [MKSTREAM] [ENTRIES
READ entries_read
]
* XGROUP SETID <key> <groupname> <id or $> [ENTRIES
ADDED count
]
* XGROUP SETID <key> <groupname> <id or $> [ENTRIES
READ entries_read
]
* XGROUP DESTROY <key> <groupname>
* XGROUP DESTROY <key> <groupname>
* XGROUP CREATECONSUMER <key> <groupname> <consumer>
* XGROUP CREATECONSUMER <key> <groupname> <consumer>
* XGROUP DELCONSUMER <key> <groupname> <consumername> */
* XGROUP DELCONSUMER <key> <groupname> <consumername> */
...
@@ -2805,7 +2805,6 @@ void xsetidCommand(client *c) {
...
@@ -2805,7 +2805,6 @@ void xsetidCommand(client *c) {
}
}
/* XACK <key> <group> <id> <id> ... <id>
/* XACK <key> <group> <id> <id> ... <id>
*
* Acknowledge a message as processed. In practical terms we just check the
* Acknowledge a message as processed. In practical terms we just check the
* pending entries list (PEL) of the group, and delete the PEL entry both from
* pending entries list (PEL) of the group, and delete the PEL entry both from
* the group and the consumer (pending messages are referenced in both places).
* the group and the consumer (pending messages are referenced in both places).
...
@@ -3050,7 +3049,7 @@ void xpendingCommand(client *c) {
...
@@ -3050,7 +3049,7 @@ void xpendingCommand(client *c) {
* [IDLE <milliseconds>] [TIME <mstime>] [RETRYCOUNT <count>]
* [IDLE <milliseconds>] [TIME <mstime>] [RETRYCOUNT <count>]
* [FORCE] [JUSTID]
* [FORCE] [JUSTID]
*
*
*
Get
s ownership of one or multiple messages in the Pending Entries List
*
Change
s ownership of one or multiple messages in the Pending Entries List
* of a given stream consumer group.
* of a given stream consumer group.
*
*
* If the message ID (among the specified ones) exists, and its idle
* If the message ID (among the specified ones) exists, and its idle
...
@@ -3316,7 +3315,7 @@ cleanup:
...
@@ -3316,7 +3315,7 @@ cleanup:
/* XAUTOCLAIM <key> <group> <consumer> <min-idle-time> <start> [COUNT <count>] [JUSTID]
/* XAUTOCLAIM <key> <group> <consumer> <min-idle-time> <start> [COUNT <count>] [JUSTID]
*
*
*
Get
s ownership of one or multiple messages in the Pending Entries List
*
Change
s ownership of one or multiple messages in the Pending Entries List
* of a given stream consumer group.
* of a given stream consumer group.
*
*
* For each PEL entry, if its idle time greater or equal to <min-idle-time>,
* For each PEL entry, if its idle time greater or equal to <min-idle-time>,
...
...
src/version.h
View file @
05833959
#define REDIS_VERSION "7.0.
1
"
#define REDIS_VERSION "7.0.
2
"
#define REDIS_VERSION_NUM 0x0007000
1
#define REDIS_VERSION_NUM 0x0007000
2
tests/integration/logging.tcl
View file @
05833959
...
@@ -8,9 +8,12 @@ if {$system_name eq {darwin}} {
...
@@ -8,9 +8,12 @@ if {$system_name eq {darwin}} {
set backtrace_supported 1
set backtrace_supported 1
}
elseif
{
$system
_name eq
{
linux
}}
{
}
elseif
{
$system
_name eq
{
linux
}}
{
# Avoid the test on libmusl, which does not support backtrace
# Avoid the test on libmusl, which does not support backtrace
set ldd
[
exec ldd src/redis-server
]
# and on static binaries
(
ldd exit code 1
)
where we can't detect libmusl
if
{
!
[
string match
{
*libc.*musl*
}
$ldd
]}
{
catch
{
set backtrace_supported 1
set ldd
[
exec ldd src/redis-server
]
if
{
!
[
string match
{
*libc.*musl*
}
$ldd
]}
{
set backtrace_supported 1
}
}
}
}
}
...
...
tests/modules/keyspecs.c
View file @
05833959
...
@@ -18,6 +18,13 @@ int createKspecNone(RedisModuleCtx *ctx) {
...
@@ -18,6 +18,13 @@ int createKspecNone(RedisModuleCtx *ctx) {
return
REDISMODULE_OK
;
return
REDISMODULE_OK
;
}
}
int
createKspecNoneWithGetkeys
(
RedisModuleCtx
*
ctx
)
{
/* A command without keyspecs; only the legacy (first,last,step) triple (MSET like spec), but also has a getkeys callback */
if
(
RedisModule_CreateCommand
(
ctx
,
"kspec.nonewithgetkeys"
,
kspec_impl
,
"getkeys-api"
,
1
,
-
1
,
2
)
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
return
REDISMODULE_OK
;
}
int
createKspecTwoRanges
(
RedisModuleCtx
*
ctx
)
{
int
createKspecTwoRanges
(
RedisModuleCtx
*
ctx
)
{
/* Test that two position/range-based key specs are combined to produce the
/* Test that two position/range-based key specs are combined to produce the
* legacy (first,last,step) values representing both keys. */
* legacy (first,last,step) values representing both keys. */
...
@@ -51,6 +58,39 @@ int createKspecTwoRanges(RedisModuleCtx *ctx) {
...
@@ -51,6 +58,39 @@ int createKspecTwoRanges(RedisModuleCtx *ctx) {
return
REDISMODULE_OK
;
return
REDISMODULE_OK
;
}
}
int
createKspecTwoRangesWithGap
(
RedisModuleCtx
*
ctx
)
{
/* Test that two position/range-based key specs are combined to produce the
* legacy (first,last,step) values representing just one key. */
if
(
RedisModule_CreateCommand
(
ctx
,
"kspec.tworangeswithgap"
,
kspec_impl
,
""
,
0
,
0
,
0
)
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
RedisModuleCommand
*
command
=
RedisModule_GetCommand
(
ctx
,
"kspec.tworangeswithgap"
);
RedisModuleCommandInfo
info
=
{
.
version
=
REDISMODULE_COMMAND_INFO_VERSION
,
.
arity
=
-
2
,
.
key_specs
=
(
RedisModuleCommandKeySpec
[]){
{
.
flags
=
REDISMODULE_CMD_KEY_RO
|
REDISMODULE_CMD_KEY_ACCESS
,
.
begin_search_type
=
REDISMODULE_KSPEC_BS_INDEX
,
.
bs
.
index
.
pos
=
1
,
.
find_keys_type
=
REDISMODULE_KSPEC_FK_RANGE
,
.
fk
.
range
=
{
0
,
1
,
0
}
},
{
.
flags
=
REDISMODULE_CMD_KEY_RW
|
REDISMODULE_CMD_KEY_UPDATE
,
.
begin_search_type
=
REDISMODULE_KSPEC_BS_INDEX
,
.
bs
.
index
.
pos
=
3
,
/* Omitted find_keys_type is shorthand for RANGE {0,1,0} */
},
{
0
}
}
};
if
(
RedisModule_SetCommandInfo
(
command
,
&
info
)
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
return
REDISMODULE_OK
;
}
int
createKspecKeyword
(
RedisModuleCtx
*
ctx
)
{
int
createKspecKeyword
(
RedisModuleCtx
*
ctx
)
{
/* Only keyword-based specs. The legacy triple is wiped and set to (0,0,0). */
/* Only keyword-based specs. The legacy triple is wiped and set to (0,0,0). */
if
(
RedisModule_CreateCommand
(
ctx
,
"kspec.keyword"
,
kspec_impl
,
""
,
3
,
-
1
,
1
)
==
REDISMODULE_ERR
)
if
(
RedisModule_CreateCommand
(
ctx
,
"kspec.keyword"
,
kspec_impl
,
""
,
3
,
-
1
,
1
)
==
REDISMODULE_ERR
)
...
@@ -177,7 +217,9 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
...
@@ -177,7 +217,9 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
return
REDISMODULE_ERR
;
return
REDISMODULE_ERR
;
if
(
createKspecNone
(
ctx
)
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
if
(
createKspecNone
(
ctx
)
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
if
(
createKspecNoneWithGetkeys
(
ctx
)
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
if
(
createKspecTwoRanges
(
ctx
)
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
if
(
createKspecTwoRanges
(
ctx
)
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
if
(
createKspecTwoRangesWithGap
(
ctx
)
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
if
(
createKspecKeyword
(
ctx
)
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
if
(
createKspecKeyword
(
ctx
)
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
if
(
createKspecComplex1
(
ctx
)
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
if
(
createKspecComplex1
(
ctx
)
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
if
(
createKspecComplex2
(
ctx
)
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
if
(
createKspecComplex2
(
ctx
)
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
...
...
tests/unit/introspection-2.tcl
View file @
05833959
...
@@ -176,4 +176,19 @@ start_server {tags {"introspection"}} {
...
@@ -176,4 +176,19 @@ start_server {tags {"introspection"}} {
assert_equal
{{}}
[
r command info get|key
]
assert_equal
{{}}
[
r command info get|key
]
assert_equal
{{}}
[
r command info config|get|key
]
assert_equal
{{}}
[
r command info config|get|key
]
}
}
foreach cmd
{
SET GET MSET BITFIELD LMOVE LPOP BLPOP PING MEMORY MEMORY|USAGE RENAME GEORADIUS_RO
}
{
test
"
$cmd
command will not be marked with movablekeys"
{
set info
[
lindex
[
r command info $cmd
]
0
]
assert_no_match
{
*movablekeys*
}
[
lindex $info 2
]
}
}
foreach cmd
{
ZUNIONSTORE XREAD EVAL SORT SORT_RO MIGRATE GEORADIUS
}
{
test
"
$cmd
command is marked with movablekeys"
{
set info
[
lindex
[
r command info $cmd
]
0
]
assert_match
{
*movablekeys*
}
[
lindex $info 2
]
}
}
}
}
tests/unit/moduleapi/keyspecs.tcl
View file @
05833959
...
@@ -31,6 +31,20 @@ start_server {tags {"modules"}} {
...
@@ -31,6 +31,20 @@ start_server {tags {"modules"}} {
assert_equal
[
r command getkeys kspec.tworanges foo bar baz quux
]
{
foo bar
}
assert_equal
[
r command getkeys kspec.tworanges foo bar baz quux
]
{
foo bar
}
}
}
test
"Module key specs: Two ranges with gap"
{
set reply
[
lindex
[
r command info kspec.tworangeswithgap
]
0
]
# Verify
(
first, last, step
)
and movablekeys
assert_equal
[
lindex $reply 2
]
{
module movablekeys
}
assert_equal
[
lindex $reply 3
]
1
assert_equal
[
lindex $reply 4
]
1
assert_equal
[
lindex $reply 5
]
1
# Verify key-specs
set keyspecs
[
lindex $reply 8
]
assert_equal
[
lindex $keyspecs 0
]
{
flags
{
RO access
}
begin_search
{
type index spec
{
index 1
}}
find_keys
{
type range spec
{
lastkey 0 keystep 1 limit 0
}}}
assert_equal
[
lindex $keyspecs 1
]
{
flags
{
RW update
}
begin_search
{
type index spec
{
index 3
}}
find_keys
{
type range spec
{
lastkey 0 keystep 1 limit 0
}}}
assert_equal
[
r command getkeys kspec.tworangeswithgap foo bar baz quux
]
{
foo baz
}
}
test
"Module key specs: Keyword-only spec clears the legacy triple"
{
test
"Module key specs: Keyword-only spec clears the legacy triple"
{
set reply
[
lindex
[
r command info kspec.keyword
]
0
]
set reply
[
lindex
[
r command info kspec.keyword
]
0
]
# Verify
(
first, last, step
)
and movablekeys
# Verify
(
first, last, step
)
and movablekeys
...
@@ -79,7 +93,7 @@ start_server {tags {"modules"}} {
...
@@ -79,7 +93,7 @@ start_server {tags {"modules"}} {
test
"Module command list filtering"
{
test
"Module command list filtering"
{
;
# Note: we piggyback this tcl file to test the general functionality of command list filtering
;
# Note: we piggyback this tcl file to test the general functionality of command list filtering
set reply
[
r command list filterby module keyspecs
]
set reply
[
r command list filterby module keyspecs
]
assert_equal
[
lsort $reply
]
{
kspec.complex1 kspec.complex2 kspec.keyword kspec.none kspec.
tworanges
}
assert_equal
[
lsort $reply
]
{
kspec.complex1 kspec.complex2 kspec.keyword kspec.none kspec.
nonewithgetkeys kspec.tworanges kspec.tworangeswithgap
}
assert_equal
[
r command getkeys kspec.complex2 foo bar 2 baz quux banana STORE dst dummy MOREKEYS hey ho
]
{
dst foo bar baz quux hey ho
}
assert_equal
[
r command getkeys kspec.complex2 foo bar 2 baz quux banana STORE dst dummy MOREKEYS hey ho
]
{
dst foo bar baz quux hey ho
}
}
}
...
@@ -108,6 +122,20 @@ start_server {tags {"modules"}} {
...
@@ -108,6 +122,20 @@ start_server {tags {"modules"}} {
assert_equal
"This user has no permissions to access the 'write' key"
[
r ACL DRYRUN testuser kspec.tworanges write rw
]
assert_equal
"This user has no permissions to access the 'write' key"
[
r ACL DRYRUN testuser kspec.tworanges write rw
]
}
}
foreach cmd
{
kspec.none kspec.tworanges
}
{
test
"
$cmd
command will not be marked with movablekeys"
{
set info
[
lindex
[
r command info $cmd
]
0
]
assert_no_match
{
*movablekeys*
}
[
lindex $info 2
]
}
}
foreach cmd
{
kspec.keyword kspec.complex1 kspec.complex2 kspec.nonewithgetkeys
}
{
test
"
$cmd
command is marked with movablekeys"
{
set info
[
lindex
[
r command info $cmd
]
0
]
assert_match
{
*movablekeys*
}
[
lindex $info 2
]
}
}
test
"Unload the module - keyspecs"
{
test
"Unload the module - keyspecs"
{
assert_equal
{
OK
}
[
r module unload keyspecs
]
assert_equal
{
OK
}
[
r module unload keyspecs
]
}
}
...
...
utils/generate-module-api-doc.rb
View file @
05833959
...
@@ -20,7 +20,7 @@ def markdown(s)
...
@@ -20,7 +20,7 @@ def markdown(s)
# Add backquotes around RedisModule functions and type where missing.
# Add backquotes around RedisModule functions and type where missing.
l
=
l
.
gsub
(
/(?<!`)RedisModule[A-z]+(?:\*?\(\))?/
){
|
x
|
"`
#{
x
}
`"
}
l
=
l
.
gsub
(
/(?<!`)RedisModule[A-z]+(?:\*?\(\))?/
){
|
x
|
"`
#{
x
}
`"
}
# Add backquotes around c functions like malloc() where missing.
# Add backquotes around c functions like malloc() where missing.
l
=
l
.
gsub
(
/(?<![`A-z])[a-z_]+\(\)/
,
'`\0`'
)
l
=
l
.
gsub
(
/(?<![`A-z
.
])[a-z_]+\(\)/
,
'`\0`'
)
# Add backquotes around macro and var names containing underscores.
# Add backquotes around macro and var names containing underscores.
l
=
l
.
gsub
(
/(?<![`A-z\*])[A-Za-z]+_[A-Za-z0-9_]+/
){
|
x
|
"`
#{
x
}
`"
}
l
=
l
.
gsub
(
/(?<![`A-z\*])[A-Za-z]+_[A-Za-z0-9_]+/
){
|
x
|
"`
#{
x
}
`"
}
# Link URLs preceded by space or newline (not already linked)
# Link URLs preceded by space or newline (not already linked)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment