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
64c2508e
Unverified
Commit
64c2508e
authored
Nov 21, 2019
by
Salvatore Sanfilippo
Committed by
GitHub
Nov 21, 2019
Browse files
Merge branch 'unstable' into rm_get_server_info
parents
04233097
f1f259de
Changes
44
Expand all
Hide whitespace changes
Inline
Side-by-side
redis.conf
View file @
64c2508e
...
@@ -813,11 +813,11 @@ replica-priority 100
...
@@ -813,11 +813,11 @@ replica-priority 100
# MAXMEMORY POLICY: how Redis will select what to remove when maxmemory
# MAXMEMORY POLICY: how Redis will select what to remove when maxmemory
# is reached. You can select among five behaviors:
# is reached. You can select among five behaviors:
#
#
# volatile-lru -> Evict using approximated LRU
among the
keys with an expire set.
# volatile-lru -> Evict using approximated LRU
, only
keys with an expire set.
# allkeys-lru -> Evict any key using approximated LRU.
# allkeys-lru -> Evict any key using approximated LRU.
# volatile-lfu -> Evict using approximated LFU
among the
keys with an expire set.
# volatile-lfu -> Evict using approximated LFU
, only
keys with an expire set.
# allkeys-lfu -> Evict any key using approximated LFU.
# allkeys-lfu -> Evict any key using approximated LFU.
# volatile-random -> Remove a random key
among the ones with
an expire set.
# volatile-random -> Remove a random key
having
an expire set.
# allkeys-random -> Remove a random key, any key.
# allkeys-random -> Remove a random key, any key.
# volatile-ttl -> Remove the key with the nearest expire time (minor TTL)
# volatile-ttl -> Remove the key with the nearest expire time (minor TTL)
# noeviction -> Don't evict anything, just return an error on write operations.
# noeviction -> Don't evict anything, just return an error on write operations.
...
@@ -872,6 +872,23 @@ replica-priority 100
...
@@ -872,6 +872,23 @@ replica-priority 100
#
#
# replica-ignore-maxmemory yes
# replica-ignore-maxmemory yes
# Redis reclaims expired keys in two ways: upon access when those keys are
# found to be expired, and also in background, in what is called the
# "active expire key". The key space is slowly and interactively scanned
# looking for expired keys to reclaim, so that it is possible to free memory
# of keys that are expired and will never be accessed again in a short time.
#
# The default effort of the expire cycle will try to avoid having more than
# ten percent of expired keys still in memory, and will try to avoid consuming
# more than 25% of total memory and to add latency to the system. However
# it is possible to increase the expire "effort" that is normally set to
# "1", to a greater value, up to the value "10". At its maximum value the
# system will use more CPU, longer cycles (and technically may introduce
# more latency), and will tollerate less already expired keys still present
# in the system. It's a tradeoff betweeen memory, CPU and latecy.
#
# active-expire-effort 1
############################# LAZY FREEING ####################################
############################# LAZY FREEING ####################################
# Redis has two primitives to delete keys. One is called DEL and is a blocking
# Redis has two primitives to delete keys. One is called DEL and is a blocking
...
@@ -1606,10 +1623,6 @@ rdb-save-incremental-fsync yes
...
@@ -1606,10 +1623,6 @@ rdb-save-incremental-fsync yes
########################### ACTIVE DEFRAGMENTATION #######################
########################### ACTIVE DEFRAGMENTATION #######################
#
#
# WARNING THIS FEATURE IS EXPERIMENTAL. However it was stress tested
# even in production and manually tested by multiple engineers for some
# time.
#
# What is active defragmentation?
# What is active defragmentation?
# -------------------------------
# -------------------------------
#
#
...
@@ -1649,7 +1662,7 @@ rdb-save-incremental-fsync yes
...
@@ -1649,7 +1662,7 @@ rdb-save-incremental-fsync yes
# a good idea to leave the defaults untouched.
# a good idea to leave the defaults untouched.
# Enabled active defragmentation
# Enabled active defragmentation
# activedefrag
yes
# activedefrag
no
# Minimum amount of fragmentation waste to start active defrag
# Minimum amount of fragmentation waste to start active defrag
# active-defrag-ignore-bytes 100mb
# active-defrag-ignore-bytes 100mb
...
@@ -1660,11 +1673,13 @@ rdb-save-incremental-fsync yes
...
@@ -1660,11 +1673,13 @@ rdb-save-incremental-fsync yes
# Maximum percentage of fragmentation at which we use maximum effort
# Maximum percentage of fragmentation at which we use maximum effort
# active-defrag-threshold-upper 100
# active-defrag-threshold-upper 100
# Minimal effort for defrag in CPU percentage
# Minimal effort for defrag in CPU percentage, to be used when the lower
# active-defrag-cycle-min 5
# threshold is reached
# active-defrag-cycle-min 1
# Maximal effort for defrag in CPU percentage
# Maximal effort for defrag in CPU percentage, to be used when the upper
# active-defrag-cycle-max 75
# threshold is reached
# active-defrag-cycle-max 25
# Maximum number of set/hash/zset/list fields that will be processed from
# Maximum number of set/hash/zset/list fields that will be processed from
# the main dictionary scan
# the main dictionary scan
...
...
runtest-moduleapi
View file @
64c2508e
...
@@ -21,4 +21,7 @@ $TCLSH tests/test_helper.tcl \
...
@@ -21,4 +21,7 @@ $TCLSH tests/test_helper.tcl \
--single
unit/moduleapi/propagate
\
--single
unit/moduleapi/propagate
\
--single
unit/moduleapi/hooks
\
--single
unit/moduleapi/hooks
\
--single
unit/moduleapi/misc
\
--single
unit/moduleapi/misc
\
--single
unit/moduleapi/blockonkeys
\
--single
unit/moduleapi/scan
\
--single
unit/moduleapi/datatype
\
"
${
@
}
"
"
${
@
}
"
src/adlist.h
View file @
64c2508e
...
@@ -66,7 +66,7 @@ typedef struct list {
...
@@ -66,7 +66,7 @@ typedef struct list {
#define listSetMatchMethod(l,m) ((l)->match = (m))
#define listSetMatchMethod(l,m) ((l)->match = (m))
#define listGetDupMethod(l) ((l)->dup)
#define listGetDupMethod(l) ((l)->dup)
#define listGetFree(l) ((l)->free)
#define listGetFree
Method
(l) ((l)->free)
#define listGetMatchMethod(l) ((l)->match)
#define listGetMatchMethod(l) ((l)->match)
/* Prototypes */
/* Prototypes */
...
...
src/aof.c
View file @
64c2508e
...
@@ -731,7 +731,7 @@ int loadAppendOnlyFile(char *filename) {
...
@@ -731,7 +731,7 @@ int loadAppendOnlyFile(char *filename) {
server
.
aof_state
=
AOF_OFF
;
server
.
aof_state
=
AOF_OFF
;
fakeClient
=
createAOFClient
();
fakeClient
=
createAOFClient
();
startLoadingFile
(
fp
,
filename
);
startLoadingFile
(
fp
,
filename
,
RDBFLAGS_AOF_PREAMBLE
);
/* Check if this AOF file has an RDB preamble. In that case we need to
/* Check if this AOF file has an RDB preamble. In that case we need to
* load the RDB file and later continue loading the AOF tail. */
* load the RDB file and later continue loading the AOF tail. */
...
@@ -746,7 +746,7 @@ int loadAppendOnlyFile(char *filename) {
...
@@ -746,7 +746,7 @@ int loadAppendOnlyFile(char *filename) {
serverLog
(
LL_NOTICE
,
"Reading RDB preamble from AOF file..."
);
serverLog
(
LL_NOTICE
,
"Reading RDB preamble from AOF file..."
);
if
(
fseek
(
fp
,
0
,
SEEK_SET
)
==
-
1
)
goto
readerr
;
if
(
fseek
(
fp
,
0
,
SEEK_SET
)
==
-
1
)
goto
readerr
;
rioInitWithFile
(
&
rdb
,
fp
);
rioInitWithFile
(
&
rdb
,
fp
);
if
(
rdbLoadRio
(
&
rdb
,
NULL
,
1
)
!=
C_OK
)
{
if
(
rdbLoadRio
(
&
rdb
,
RDBFLAGS_AOF_PREAMBLE
,
NULL
)
!=
C_OK
)
{
serverLog
(
LL_WARNING
,
"Error reading the RDB preamble of the AOF file, AOF loading aborted"
);
serverLog
(
LL_WARNING
,
"Error reading the RDB preamble of the AOF file, AOF loading aborted"
);
goto
readerr
;
goto
readerr
;
}
else
{
}
else
{
...
@@ -767,6 +767,7 @@ int loadAppendOnlyFile(char *filename) {
...
@@ -767,6 +767,7 @@ int loadAppendOnlyFile(char *filename) {
if
(
!
(
loops
++
%
1000
))
{
if
(
!
(
loops
++
%
1000
))
{
loadingProgress
(
ftello
(
fp
));
loadingProgress
(
ftello
(
fp
));
processEventsWhileBlocked
();
processEventsWhileBlocked
();
processModuleLoadingProgressEvent
(
1
);
}
}
if
(
fgets
(
buf
,
sizeof
(
buf
),
fp
)
==
NULL
)
{
if
(
fgets
(
buf
,
sizeof
(
buf
),
fp
)
==
NULL
)
{
...
@@ -859,7 +860,7 @@ loaded_ok: /* DB loaded, cleanup and return C_OK to the caller. */
...
@@ -859,7 +860,7 @@ loaded_ok: /* DB loaded, cleanup and return C_OK to the caller. */
fclose
(
fp
);
fclose
(
fp
);
freeFakeClient
(
fakeClient
);
freeFakeClient
(
fakeClient
);
server
.
aof_state
=
old_aof_state
;
server
.
aof_state
=
old_aof_state
;
stopLoading
();
stopLoading
(
1
);
aofUpdateCurrentSize
();
aofUpdateCurrentSize
();
server
.
aof_rewrite_base_size
=
server
.
aof_current_size
;
server
.
aof_rewrite_base_size
=
server
.
aof_current_size
;
server
.
aof_fsync_offset
=
server
.
aof_current_size
;
server
.
aof_fsync_offset
=
server
.
aof_current_size
;
...
@@ -1400,9 +1401,11 @@ int rewriteAppendOnlyFile(char *filename) {
...
@@ -1400,9 +1401,11 @@ int rewriteAppendOnlyFile(char *filename) {
if
(
server
.
aof_rewrite_incremental_fsync
)
if
(
server
.
aof_rewrite_incremental_fsync
)
rioSetAutoSync
(
&
aof
,
REDIS_AUTOSYNC_BYTES
);
rioSetAutoSync
(
&
aof
,
REDIS_AUTOSYNC_BYTES
);
startSaving
(
RDBFLAGS_AOF_PREAMBLE
);
if
(
server
.
aof_use_rdb_preamble
)
{
if
(
server
.
aof_use_rdb_preamble
)
{
int
error
;
int
error
;
if
(
rdbSaveRio
(
&
aof
,
&
error
,
RDB
_SAVE
_AOF_PREAMBLE
,
NULL
)
==
C_ERR
)
{
if
(
rdbSaveRio
(
&
aof
,
&
error
,
RDB
FLAGS
_AOF_PREAMBLE
,
NULL
)
==
C_ERR
)
{
errno
=
error
;
errno
=
error
;
goto
werr
;
goto
werr
;
}
}
...
@@ -1465,15 +1468,18 @@ int rewriteAppendOnlyFile(char *filename) {
...
@@ -1465,15 +1468,18 @@ int rewriteAppendOnlyFile(char *filename) {
if
(
rename
(
tmpfile
,
filename
)
==
-
1
)
{
if
(
rename
(
tmpfile
,
filename
)
==
-
1
)
{
serverLog
(
LL_WARNING
,
"Error moving temp append only file on the final destination: %s"
,
strerror
(
errno
));
serverLog
(
LL_WARNING
,
"Error moving temp append only file on the final destination: %s"
,
strerror
(
errno
));
unlink
(
tmpfile
);
unlink
(
tmpfile
);
stopSaving
(
0
);
return
C_ERR
;
return
C_ERR
;
}
}
serverLog
(
LL_NOTICE
,
"SYNC append only file rewrite performed"
);
serverLog
(
LL_NOTICE
,
"SYNC append only file rewrite performed"
);
stopSaving
(
1
);
return
C_OK
;
return
C_OK
;
werr:
werr:
serverLog
(
LL_WARNING
,
"Write error writing append only file on disk: %s"
,
strerror
(
errno
));
serverLog
(
LL_WARNING
,
"Write error writing append only file on disk: %s"
,
strerror
(
errno
));
fclose
(
fp
);
fclose
(
fp
);
unlink
(
tmpfile
);
unlink
(
tmpfile
);
stopSaving
(
0
);
return
C_ERR
;
return
C_ERR
;
}
}
...
@@ -1760,7 +1766,7 @@ void backgroundRewriteDoneHandler(int exitcode, int bysignal) {
...
@@ -1760,7 +1766,7 @@ void backgroundRewriteDoneHandler(int exitcode, int bysignal) {
server
.
aof_selected_db
=
-
1
;
/* Make sure SELECT is re-issued */
server
.
aof_selected_db
=
-
1
;
/* Make sure SELECT is re-issued */
aofUpdateCurrentSize
();
aofUpdateCurrentSize
();
server
.
aof_rewrite_base_size
=
server
.
aof_current_size
;
server
.
aof_rewrite_base_size
=
server
.
aof_current_size
;
server
.
aof_
current_size
=
server
.
aof_current_size
;
server
.
aof_
fsync_offset
=
server
.
aof_current_size
;
/* Clear regular AOF buffer since its contents was just written to
/* Clear regular AOF buffer since its contents was just written to
* the new AOF from the background rewrite buffer. */
* the new AOF from the background rewrite buffer. */
...
...
src/blocked.c
View file @
64c2508e
...
@@ -514,6 +514,16 @@ void handleClientsBlockedOnKeys(void) {
...
@@ -514,6 +514,16 @@ void handleClientsBlockedOnKeys(void) {
* we can safely call signalKeyAsReady() against this key. */
* we can safely call signalKeyAsReady() against this key. */
dictDelete
(
rl
->
db
->
ready_keys
,
rl
->
key
);
dictDelete
(
rl
->
db
->
ready_keys
,
rl
->
key
);
/* Even if we are not inside call(), increment the call depth
* in order to make sure that keys are expired against a fixed
* reference time, and not against the wallclock time. This
* way we can lookup an object multiple times (BRPOPLPUSH does
* that) without the risk of it being freed in the second
* lookup, invalidating the first one.
* See https://github.com/antirez/redis/pull/6554. */
server
.
fixed_time_expire
++
;
updateCachedTime
(
0
);
/* Serve clients blocked on list key. */
/* Serve clients blocked on list key. */
robj
*
o
=
lookupKeyWrite
(
rl
->
db
,
rl
->
key
);
robj
*
o
=
lookupKeyWrite
(
rl
->
db
,
rl
->
key
);
...
@@ -529,6 +539,7 @@ void handleClientsBlockedOnKeys(void) {
...
@@ -529,6 +539,7 @@ void handleClientsBlockedOnKeys(void) {
* module is trying to accomplish right now. */
* module is trying to accomplish right now. */
serveClientsBlockedOnKeyByModule
(
rl
);
serveClientsBlockedOnKeyByModule
(
rl
);
}
}
server
.
fixed_time_expire
--
;
/* Free this item. */
/* Free this item. */
decrRefCount
(
rl
->
key
);
decrRefCount
(
rl
->
key
);
...
...
src/cluster.c
View file @
64c2508e
...
@@ -4966,7 +4966,7 @@ void restoreCommand(client *c) {
...
@@ -4966,7 +4966,7 @@ void restoreCommand(client *c) {
if
(
!
absttl
)
ttl
+=
mstime
();
if
(
!
absttl
)
ttl
+=
mstime
();
setExpire
(
c
,
c
->
db
,
c
->
argv
[
1
],
ttl
);
setExpire
(
c
,
c
->
db
,
c
->
argv
[
1
],
ttl
);
}
}
objectSetLRUOrLFU
(
obj
,
lfu_freq
,
lru_idle
,
lru_clock
);
objectSetLRUOrLFU
(
obj
,
lfu_freq
,
lru_idle
,
lru_clock
,
1000
);
signalModifiedKey
(
c
->
db
,
c
->
argv
[
1
]);
signalModifiedKey
(
c
->
db
,
c
->
argv
[
1
]);
addReply
(
c
,
shared
.
ok
);
addReply
(
c
,
shared
.
ok
);
server
.
dirty
++
;
server
.
dirty
++
;
...
...
src/config.c
View file @
64c2508e
...
@@ -256,7 +256,7 @@ void loadServerConfigFromString(char *config) {
...
@@ -256,7 +256,7 @@ void loadServerConfigFromString(char *config) {
for
(
configYesNo
*
config
=
configs_yesno
;
config
->
name
!=
NULL
;
config
++
)
{
for
(
configYesNo
*
config
=
configs_yesno
;
config
->
name
!=
NULL
;
config
++
)
{
if
((
!
strcasecmp
(
argv
[
0
],
config
->
name
)
||
if
((
!
strcasecmp
(
argv
[
0
],
config
->
name
)
||
(
config
->
alias
&&
!
strcasecmp
(
argv
[
0
],
config
->
alias
)))
&&
(
config
->
alias
&&
!
strcasecmp
(
argv
[
0
],
config
->
alias
)))
&&
(
argc
==
2
))
(
argc
==
2
))
{
{
if
((
*
(
config
->
config
)
=
yesnotoi
(
argv
[
1
]))
==
-
1
)
{
if
((
*
(
config
->
config
)
=
yesnotoi
(
argv
[
1
]))
==
-
1
)
{
err
=
"argument must be 'yes' or 'no'"
;
goto
loaderr
;
err
=
"argument must be 'yes' or 'no'"
;
goto
loaderr
;
...
@@ -580,6 +580,14 @@ void loadServerConfigFromString(char *config) {
...
@@ -580,6 +580,14 @@ void loadServerConfigFromString(char *config) {
err
=
"active-defrag-max-scan-fields must be positive"
;
err
=
"active-defrag-max-scan-fields must be positive"
;
goto
loaderr
;
goto
loaderr
;
}
}
}
else
if
(
!
strcasecmp
(
argv
[
0
],
"active-expire-effort"
)
&&
argc
==
2
)
{
server
.
active_expire_effort
=
atoi
(
argv
[
1
]);
if
(
server
.
active_expire_effort
<
1
||
server
.
active_expire_effort
>
10
)
{
err
=
"active-expire-effort must be between 1 and 10"
;
goto
loaderr
;
}
}
else
if
(
!
strcasecmp
(
argv
[
0
],
"hash-max-ziplist-entries"
)
&&
argc
==
2
)
{
}
else
if
(
!
strcasecmp
(
argv
[
0
],
"hash-max-ziplist-entries"
)
&&
argc
==
2
)
{
server
.
hash_max_ziplist_entries
=
memtoll
(
argv
[
1
],
NULL
);
server
.
hash_max_ziplist_entries
=
memtoll
(
argv
[
1
],
NULL
);
}
else
if
(
!
strcasecmp
(
argv
[
0
],
"hash-max-ziplist-value"
)
&&
argc
==
2
)
{
}
else
if
(
!
strcasecmp
(
argv
[
0
],
"hash-max-ziplist-value"
)
&&
argc
==
2
)
{
...
@@ -1165,6 +1173,8 @@ void configSetCommand(client *c) {
...
@@ -1165,6 +1173,8 @@ void configSetCommand(client *c) {
"active-defrag-cycle-max"
,
server
.
active_defrag_cycle_max
,
1
,
99
)
{
"active-defrag-cycle-max"
,
server
.
active_defrag_cycle_max
,
1
,
99
)
{
}
config_set_numerical_field
(
}
config_set_numerical_field
(
"active-defrag-max-scan-fields"
,
server
.
active_defrag_max_scan_fields
,
1
,
LONG_MAX
)
{
"active-defrag-max-scan-fields"
,
server
.
active_defrag_max_scan_fields
,
1
,
LONG_MAX
)
{
}
config_set_numerical_field
(
"active-expire-effort"
,
server
.
active_expire_effort
,
1
,
10
)
{
}
config_set_numerical_field
(
}
config_set_numerical_field
(
"auto-aof-rewrite-percentage"
,
server
.
aof_rewrite_perc
,
0
,
INT_MAX
){
"auto-aof-rewrite-percentage"
,
server
.
aof_rewrite_perc
,
0
,
INT_MAX
){
}
config_set_numerical_field
(
}
config_set_numerical_field
(
...
@@ -1478,6 +1488,7 @@ void configGetCommand(client *c) {
...
@@ -1478,6 +1488,7 @@ void configGetCommand(client *c) {
config_get_numerical_field
(
"active-defrag-cycle-min"
,
server
.
active_defrag_cycle_min
);
config_get_numerical_field
(
"active-defrag-cycle-min"
,
server
.
active_defrag_cycle_min
);
config_get_numerical_field
(
"active-defrag-cycle-max"
,
server
.
active_defrag_cycle_max
);
config_get_numerical_field
(
"active-defrag-cycle-max"
,
server
.
active_defrag_cycle_max
);
config_get_numerical_field
(
"active-defrag-max-scan-fields"
,
server
.
active_defrag_max_scan_fields
);
config_get_numerical_field
(
"active-defrag-max-scan-fields"
,
server
.
active_defrag_max_scan_fields
);
config_get_numerical_field
(
"active-expire-effort"
,
server
.
active_expire_effort
);
config_get_numerical_field
(
"auto-aof-rewrite-percentage"
,
config_get_numerical_field
(
"auto-aof-rewrite-percentage"
,
server
.
aof_rewrite_perc
);
server
.
aof_rewrite_perc
);
config_get_numerical_field
(
"auto-aof-rewrite-min-size"
,
config_get_numerical_field
(
"auto-aof-rewrite-min-size"
,
...
@@ -2327,6 +2338,7 @@ int rewriteConfig(char *path) {
...
@@ -2327,6 +2338,7 @@ int rewriteConfig(char *path) {
rewriteConfigNumericalOption
(
state
,
"active-defrag-cycle-min"
,
server
.
active_defrag_cycle_min
,
CONFIG_DEFAULT_DEFRAG_CYCLE_MIN
);
rewriteConfigNumericalOption
(
state
,
"active-defrag-cycle-min"
,
server
.
active_defrag_cycle_min
,
CONFIG_DEFAULT_DEFRAG_CYCLE_MIN
);
rewriteConfigNumericalOption
(
state
,
"active-defrag-cycle-max"
,
server
.
active_defrag_cycle_max
,
CONFIG_DEFAULT_DEFRAG_CYCLE_MAX
);
rewriteConfigNumericalOption
(
state
,
"active-defrag-cycle-max"
,
server
.
active_defrag_cycle_max
,
CONFIG_DEFAULT_DEFRAG_CYCLE_MAX
);
rewriteConfigNumericalOption
(
state
,
"active-defrag-max-scan-fields"
,
server
.
active_defrag_max_scan_fields
,
CONFIG_DEFAULT_DEFRAG_MAX_SCAN_FIELDS
);
rewriteConfigNumericalOption
(
state
,
"active-defrag-max-scan-fields"
,
server
.
active_defrag_max_scan_fields
,
CONFIG_DEFAULT_DEFRAG_MAX_SCAN_FIELDS
);
rewriteConfigNumericalOption
(
state
,
"active-expire-effort"
,
server
.
active_expire_effort
,
CONFIG_DEFAULT_ACTIVE_EXPIRE_EFFORT
);
rewriteConfigYesNoOption
(
state
,
"appendonly"
,
server
.
aof_enabled
,
0
);
rewriteConfigYesNoOption
(
state
,
"appendonly"
,
server
.
aof_enabled
,
0
);
rewriteConfigStringOption
(
state
,
"appendfilename"
,
server
.
aof_filename
,
CONFIG_DEFAULT_AOF_FILENAME
);
rewriteConfigStringOption
(
state
,
"appendfilename"
,
server
.
aof_filename
,
CONFIG_DEFAULT_AOF_FILENAME
);
rewriteConfigEnumOption
(
state
,
"appendfsync"
,
server
.
aof_fsync
,
aof_fsync_enum
,
CONFIG_DEFAULT_AOF_FSYNC
);
rewriteConfigEnumOption
(
state
,
"appendfsync"
,
server
.
aof_fsync
,
aof_fsync_enum
,
CONFIG_DEFAULT_AOF_FSYNC
);
...
...
src/db.c
View file @
64c2508e
...
@@ -151,9 +151,13 @@ robj *lookupKeyRead(redisDb *db, robj *key) {
...
@@ -151,9 +151,13 @@ robj *lookupKeyRead(redisDb *db, robj *key) {
*
*
* Returns the linked value object if the key exists or NULL if the key
* Returns the linked value object if the key exists or NULL if the key
* does not exist in the specified DB. */
* does not exist in the specified DB. */
robj
*
lookupKeyWrite
(
redisDb
*
db
,
robj
*
key
)
{
robj
*
lookupKeyWrite
WithFlags
(
redisDb
*
db
,
robj
*
key
,
int
flags
)
{
expireIfNeeded
(
db
,
key
);
expireIfNeeded
(
db
,
key
);
return
lookupKey
(
db
,
key
,
LOOKUP_NONE
);
return
lookupKey
(
db
,
key
,
flags
);
}
robj
*
lookupKeyWrite
(
redisDb
*
db
,
robj
*
key
)
{
return
lookupKeyWriteWithFlags
(
db
,
key
,
LOOKUP_NONE
);
}
}
robj
*
lookupKeyReadOrReply
(
client
*
c
,
robj
*
key
,
robj
*
reply
)
{
robj
*
lookupKeyReadOrReply
(
client
*
c
,
robj
*
key
,
robj
*
reply
)
{
...
@@ -461,6 +465,29 @@ int getFlushCommandFlags(client *c, int *flags) {
...
@@ -461,6 +465,29 @@ int getFlushCommandFlags(client *c, int *flags) {
return
C_OK
;
return
C_OK
;
}
}
/* Flushes the whole server data set. */
void
flushAllDataAndResetRDB
(
int
flags
)
{
server
.
dirty
+=
emptyDb
(
-
1
,
flags
,
NULL
);
if
(
server
.
rdb_child_pid
!=
-
1
)
killRDBChild
();
if
(
server
.
saveparamslen
>
0
)
{
/* Normally rdbSave() will reset dirty, but we don't want this here
* as otherwise FLUSHALL will not be replicated nor put into the AOF. */
int
saved_dirty
=
server
.
dirty
;
rdbSaveInfo
rsi
,
*
rsiptr
;
rsiptr
=
rdbPopulateSaveInfo
(
&
rsi
);
rdbSave
(
server
.
rdb_filename
,
rsiptr
);
server
.
dirty
=
saved_dirty
;
}
server
.
dirty
++
;
#if defined(USE_JEMALLOC)
/* jemalloc 5 doesn't release pages back to the OS when there's no traffic.
* for large databases, flushdb blocks for long anyway, so a bit more won't
* harm and this way the flush and purge will be synchroneus. */
if
(
!
(
flags
&
EMPTYDB_ASYNC
))
jemalloc_purge
();
#endif
}
/* FLUSHDB [ASYNC]
/* FLUSHDB [ASYNC]
*
*
* Flushes the currently SELECTed Redis DB. */
* Flushes the currently SELECTed Redis DB. */
...
@@ -484,28 +511,9 @@ void flushdbCommand(client *c) {
...
@@ -484,28 +511,9 @@ void flushdbCommand(client *c) {
* Flushes the whole server data set. */
* Flushes the whole server data set. */
void
flushallCommand
(
client
*
c
)
{
void
flushallCommand
(
client
*
c
)
{
int
flags
;
int
flags
;
if
(
getFlushCommandFlags
(
c
,
&
flags
)
==
C_ERR
)
return
;
if
(
getFlushCommandFlags
(
c
,
&
flags
)
==
C_ERR
)
return
;
server
.
dirty
+=
emptyDb
(
-
1
,
flags
,
NULL
);
flushAllDataAndResetRDB
(
flags
);
addReply
(
c
,
shared
.
ok
);
addReply
(
c
,
shared
.
ok
);
if
(
server
.
rdb_child_pid
!=
-
1
)
killRDBChild
();
if
(
server
.
saveparamslen
>
0
)
{
/* Normally rdbSave() will reset dirty, but we don't want this here
* as otherwise FLUSHALL will not be replicated nor put into the AOF. */
int
saved_dirty
=
server
.
dirty
;
rdbSaveInfo
rsi
,
*
rsiptr
;
rsiptr
=
rdbPopulateSaveInfo
(
&
rsi
);
rdbSave
(
server
.
rdb_filename
,
rsiptr
);
server
.
dirty
=
saved_dirty
;
}
server
.
dirty
++
;
#if defined(USE_JEMALLOC)
/* jemalloc 5 doesn't release pages back to the OS when there's no traffic.
* for large databases, flushdb blocks for long anyway, so a bit more won't
* harm and this way the flush and purge will be synchroneus. */
if
(
!
(
flags
&
EMPTYDB_ASYNC
))
jemalloc_purge
();
#endif
}
}
/* This command implements DEL and LAZYDEL. */
/* This command implements DEL and LAZYDEL. */
...
@@ -1069,10 +1077,12 @@ int dbSwapDatabases(long id1, long id2) {
...
@@ -1069,10 +1077,12 @@ int dbSwapDatabases(long id1, long id2) {
db1
->
dict
=
db2
->
dict
;
db1
->
dict
=
db2
->
dict
;
db1
->
expires
=
db2
->
expires
;
db1
->
expires
=
db2
->
expires
;
db1
->
avg_ttl
=
db2
->
avg_ttl
;
db1
->
avg_ttl
=
db2
->
avg_ttl
;
db1
->
expires_cursor
=
db2
->
expires_cursor
;
db2
->
dict
=
aux
.
dict
;
db2
->
dict
=
aux
.
dict
;
db2
->
expires
=
aux
.
expires
;
db2
->
expires
=
aux
.
expires
;
db2
->
avg_ttl
=
aux
.
avg_ttl
;
db2
->
avg_ttl
=
aux
.
avg_ttl
;
db2
->
expires_cursor
=
aux
.
expires_cursor
;
/* Now we need to handle clients blocked on lists: as an effect
/* Now we need to handle clients blocked on lists: as an effect
* of swapping the two DBs, a client that was waiting for list
* of swapping the two DBs, a client that was waiting for list
...
@@ -1188,6 +1198,7 @@ void propagateExpire(redisDb *db, robj *key, int lazy) {
...
@@ -1188,6 +1198,7 @@ void propagateExpire(redisDb *db, robj *key, int lazy) {
/* Check if the key is expired. */
/* Check if the key is expired. */
int
keyIsExpired
(
redisDb
*
db
,
robj
*
key
)
{
int
keyIsExpired
(
redisDb
*
db
,
robj
*
key
)
{
mstime_t
when
=
getExpire
(
db
,
key
);
mstime_t
when
=
getExpire
(
db
,
key
);
mstime_t
now
;
if
(
when
<
0
)
return
0
;
/* No expire for this key */
if
(
when
<
0
)
return
0
;
/* No expire for this key */
...
@@ -1199,8 +1210,26 @@ int keyIsExpired(redisDb *db, robj *key) {
...
@@ -1199,8 +1210,26 @@ int keyIsExpired(redisDb *db, robj *key) {
* only the first time it is accessed and not in the middle of the
* only the first time it is accessed and not in the middle of the
* script execution, making propagation to slaves / AOF consistent.
* script execution, making propagation to slaves / AOF consistent.
* See issue #1525 on Github for more information. */
* See issue #1525 on Github for more information. */
mstime_t
now
=
server
.
lua_caller
?
server
.
lua_time_start
:
mstime
();
if
(
server
.
lua_caller
)
{
now
=
server
.
lua_time_start
;
}
/* If we are in the middle of a command execution, we still want to use
* a reference time that does not change: in that case we just use the
* cached time, that we update before each call in the call() function.
* This way we avoid that commands such as RPOPLPUSH or similar, that
* may re-open the same key multiple times, can invalidate an already
* open object in a next call, if the next call will see the key expired,
* while the first did not. */
else
if
(
server
.
fixed_time_expire
>
0
)
{
now
=
server
.
mstime
;
}
/* For the other cases, we want to use the most fresh time we have. */
else
{
now
=
mstime
();
}
/* The key expired if the current (virtual or real) time is greater
* than the expire time of the key. */
return
now
>
when
;
return
now
>
when
;
}
}
...
...
src/debug.c
View file @
64c2508e
...
@@ -417,7 +417,7 @@ NULL
...
@@ -417,7 +417,7 @@ NULL
}
}
emptyDb
(
-
1
,
EMPTYDB_NO_FLAGS
,
NULL
);
emptyDb
(
-
1
,
EMPTYDB_NO_FLAGS
,
NULL
);
protectClient
(
c
);
protectClient
(
c
);
int
ret
=
rdbLoad
(
server
.
rdb_filename
,
NULL
);
int
ret
=
rdbLoad
(
server
.
rdb_filename
,
NULL
,
RDBFLAGS_NONE
);
unprotectClient
(
c
);
unprotectClient
(
c
);
if
(
ret
!=
C_OK
)
{
if
(
ret
!=
C_OK
)
{
addReplyError
(
c
,
"Error trying to load the RDB dump"
);
addReplyError
(
c
,
"Error trying to load the RDB dump"
);
...
...
src/defrag.c
View file @
64c2508e
...
@@ -919,10 +919,12 @@ int defragLaterItem(dictEntry *de, unsigned long *cursor, long long endtime) {
...
@@ -919,10 +919,12 @@ int defragLaterItem(dictEntry *de, unsigned long *cursor, long long endtime) {
return
0
;
return
0
;
}
}
/* static variables serving defragLaterStep to continue scanning a key from were we stopped last time. */
static
sds
defrag_later_current_key
=
NULL
;
static
unsigned
long
defrag_later_cursor
=
0
;
/* returns 0 if no more work needs to be been done, and 1 if time is up and more work is needed. */
/* returns 0 if no more work needs to be been done, and 1 if time is up and more work is needed. */
int
defragLaterStep
(
redisDb
*
db
,
long
long
endtime
)
{
int
defragLaterStep
(
redisDb
*
db
,
long
long
endtime
)
{
static
sds
current_key
=
NULL
;
static
unsigned
long
cursor
=
0
;
unsigned
int
iterations
=
0
;
unsigned
int
iterations
=
0
;
unsigned
long
long
prev_defragged
=
server
.
stat_active_defrag_hits
;
unsigned
long
long
prev_defragged
=
server
.
stat_active_defrag_hits
;
unsigned
long
long
prev_scanned
=
server
.
stat_active_defrag_scanned
;
unsigned
long
long
prev_scanned
=
server
.
stat_active_defrag_scanned
;
...
@@ -930,16 +932,15 @@ int defragLaterStep(redisDb *db, long long endtime) {
...
@@ -930,16 +932,15 @@ int defragLaterStep(redisDb *db, long long endtime) {
do
{
do
{
/* if we're not continuing a scan from the last call or loop, start a new one */
/* if we're not continuing a scan from the last call or loop, start a new one */
if
(
!
cursor
)
{
if
(
!
defrag_later_
cursor
)
{
listNode
*
head
=
listFirst
(
db
->
defrag_later
);
listNode
*
head
=
listFirst
(
db
->
defrag_later
);
/* Move on to next key */
/* Move on to next key */
if
(
current_key
)
{
if
(
defrag_later_current_key
)
{
serverAssert
(
current_key
==
head
->
value
);
serverAssert
(
defrag_later_current_key
==
head
->
value
);
sdsfree
(
head
->
value
);
listDelNode
(
db
->
defrag_later
,
head
);
listDelNode
(
db
->
defrag_later
,
head
);
cursor
=
0
;
defrag_later_
cursor
=
0
;
current_key
=
NULL
;
defrag_later_
current_key
=
NULL
;
}
}
/* stop if we reached the last one. */
/* stop if we reached the last one. */
...
@@ -948,21 +949,21 @@ int defragLaterStep(redisDb *db, long long endtime) {
...
@@ -948,21 +949,21 @@ int defragLaterStep(redisDb *db, long long endtime) {
return
0
;
return
0
;
/* start a new key */
/* start a new key */
current_key
=
head
->
value
;
defrag_later_
current_key
=
head
->
value
;
cursor
=
0
;
defrag_later_
cursor
=
0
;
}
}
/* each time we enter this function we need to fetch the key from the dict again (if it still exists) */
/* each time we enter this function we need to fetch the key from the dict again (if it still exists) */
dictEntry
*
de
=
dictFind
(
db
->
dict
,
current_key
);
dictEntry
*
de
=
dictFind
(
db
->
dict
,
defrag_later_
current_key
);
key_defragged
=
server
.
stat_active_defrag_hits
;
key_defragged
=
server
.
stat_active_defrag_hits
;
do
{
do
{
int
quit
=
0
;
int
quit
=
0
;
if
(
defragLaterItem
(
de
,
&
cursor
,
endtime
))
if
(
defragLaterItem
(
de
,
&
defrag_later_
cursor
,
endtime
))
quit
=
1
;
/* time is up, we didn't finish all the work */
quit
=
1
;
/* time is up, we didn't finish all the work */
/* Don't start a new BIG key in this loop, this is because the
/* Don't start a new BIG key in this loop, this is because the
* next key can be a list, and scanLaterList must be done in once cycle */
* next key can be a list, and scanLaterList must be done in once cycle */
if
(
!
cursor
)
if
(
!
defrag_later_
cursor
)
quit
=
1
;
quit
=
1
;
/* Once in 16 scan iterations, 512 pointer reallocations, or 64 fields
/* Once in 16 scan iterations, 512 pointer reallocations, or 64 fields
...
@@ -982,7 +983,7 @@ int defragLaterStep(redisDb *db, long long endtime) {
...
@@ -982,7 +983,7 @@ int defragLaterStep(redisDb *db, long long endtime) {
prev_defragged
=
server
.
stat_active_defrag_hits
;
prev_defragged
=
server
.
stat_active_defrag_hits
;
prev_scanned
=
server
.
stat_active_defrag_scanned
;
prev_scanned
=
server
.
stat_active_defrag_scanned
;
}
}
}
while
(
cursor
);
}
while
(
defrag_later_
cursor
);
if
(
key_defragged
!=
server
.
stat_active_defrag_hits
)
if
(
key_defragged
!=
server
.
stat_active_defrag_hits
)
server
.
stat_active_defrag_key_hits
++
;
server
.
stat_active_defrag_key_hits
++
;
else
else
...
@@ -1039,6 +1040,21 @@ void activeDefragCycle(void) {
...
@@ -1039,6 +1040,21 @@ void activeDefragCycle(void) {
mstime_t
latency
;
mstime_t
latency
;
int
quit
=
0
;
int
quit
=
0
;
if
(
!
server
.
active_defrag_enabled
)
{
if
(
server
.
active_defrag_running
)
{
/* if active defrag was disabled mid-run, start from fresh next time. */
server
.
active_defrag_running
=
0
;
if
(
db
)
listEmpty
(
db
->
defrag_later
);
defrag_later_current_key
=
NULL
;
defrag_later_cursor
=
0
;
current_db
=
-
1
;
cursor
=
0
;
db
=
NULL
;
}
return
;
}
if
(
hasActiveChildProcess
())
if
(
hasActiveChildProcess
())
return
;
/* Defragging memory while there's a fork will just do damage. */
return
;
/* Defragging memory while there's a fork will just do damage. */
...
...
src/expire.c
View file @
64c2508e
...
@@ -78,24 +78,63 @@ int activeExpireCycleTryExpire(redisDb *db, dictEntry *de, long long now) {
...
@@ -78,24 +78,63 @@ int activeExpireCycleTryExpire(redisDb *db, dictEntry *de, long long now) {
* it will get more aggressive to avoid that too much memory is used by
* it will get more aggressive to avoid that too much memory is used by
* keys that can be removed from the keyspace.
* keys that can be removed from the keyspace.
*
*
* No more than CRON_DBS_PER_CALL databases are tested at every
* Every expire cycle tests multiple databases: the next call will start
* iteration.
* again from the next db, with the exception of exists for time limit: in that
* case we restart again from the last database we were processing. Anyway
* no more than CRON_DBS_PER_CALL databases are tested at every iteration.
*
*
* This kind of call is used when Redis detects that timelimit_exit is
* The function can perform more or less work, depending on the "type"
* true, so there is more work to do, and we do it more incrementally from
* argument. It can execute a "fast cycle" or a "slow cycle". The slow
* the beforeSleep() function of the event loop.
* cycle is the main way we collect expired cycles: this happens with
* the "server.hz" frequency (usually 10 hertz).
*
*
* Expire cycle type:
* However the slow cycle can exit for timeout, since it used too much time.
* For this reason the function is also invoked to perform a fast cycle
* at every event loop cycle, in the beforeSleep() function. The fast cycle
* will try to perform less work, but will do it much more often.
*
* The following are the details of the two expire cycles and their stop
* conditions:
*
*
* If type is ACTIVE_EXPIRE_CYCLE_FAST the function will try to run a
* If type is ACTIVE_EXPIRE_CYCLE_FAST the function will try to run a
* "fast" expire cycle that takes no longer than EXPIRE_FAST_CYCLE_DURATION
* "fast" expire cycle that takes no longer than EXPIRE_FAST_CYCLE_DURATION
* microseconds, and is not repeated again before the same amount of time.
* microseconds, and is not repeated again before the same amount of time.
* The cycle will also refuse to run at all if the latest slow cycle did not
* terminate because of a time limit condition.
*
*
* If type is ACTIVE_EXPIRE_CYCLE_SLOW, that normal expire cycle is
* If type is ACTIVE_EXPIRE_CYCLE_SLOW, that normal expire cycle is
* executed, where the time limit is a percentage of the REDIS_HZ period
* executed, where the time limit is a percentage of the REDIS_HZ period
* as specified by the ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC define. */
* as specified by the ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC define. In the
* fast cycle, the check of every database is interrupted once the number
* of already expired keys in the database is estimated to be lower than
* a given percentage, in order to avoid doing too much work to gain too
* little memory.
*
* The configured expire "effort" will modify the baseline parameters in
* order to do more work in both the fast and slow expire cycles.
*/
#define ACTIVE_EXPIRE_CYCLE_KEYS_PER_LOOP 20
/* Keys for each DB loop. */
#define ACTIVE_EXPIRE_CYCLE_FAST_DURATION 1000
/* Microseconds. */
#define ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC 25
/* Max % of CPU to use. */
#define ACTIVE_EXPIRE_CYCLE_ACCEPTABLE_STALE 10
/* % of stale keys after which
we do extra efforts. */
void
activeExpireCycle
(
int
type
)
{
void
activeExpireCycle
(
int
type
)
{
/* Adjust the running parameters according to the configured expire
* effort. The default effort is 1, and the maximum configurable effort
* is 10. */
unsigned
long
effort
=
server
.
active_expire_effort
-
1
,
/* Rescale from 0 to 9. */
config_keys_per_loop
=
ACTIVE_EXPIRE_CYCLE_KEYS_PER_LOOP
+
ACTIVE_EXPIRE_CYCLE_KEYS_PER_LOOP
/
4
*
effort
,
config_cycle_fast_duration
=
ACTIVE_EXPIRE_CYCLE_FAST_DURATION
+
ACTIVE_EXPIRE_CYCLE_FAST_DURATION
/
4
*
effort
,
config_cycle_slow_time_perc
=
ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC
+
2
*
effort
,
config_cycle_acceptable_stale
=
ACTIVE_EXPIRE_CYCLE_ACCEPTABLE_STALE
-
effort
;
/* This function has some global state in order to continue the work
/* This function has some global state in order to continue the work
* incrementally across calls. */
* incrementally across calls. */
static
unsigned
int
current_db
=
0
;
/* Last DB tested. */
static
unsigned
int
current_db
=
0
;
/* Last DB tested. */
...
@@ -113,10 +152,16 @@ void activeExpireCycle(int type) {
...
@@ -113,10 +152,16 @@ void activeExpireCycle(int type) {
if
(
type
==
ACTIVE_EXPIRE_CYCLE_FAST
)
{
if
(
type
==
ACTIVE_EXPIRE_CYCLE_FAST
)
{
/* Don't start a fast cycle if the previous cycle did not exit
/* Don't start a fast cycle if the previous cycle did not exit
* for time limit. Also don't repeat a fast cycle for the same period
* for time limit, unless the percentage of estimated stale keys is
* too high. Also never repeat a fast cycle for the same period
* as the fast cycle total duration itself. */
* as the fast cycle total duration itself. */
if
(
!
timelimit_exit
)
return
;
if
(
!
timelimit_exit
&&
if
(
start
<
last_fast_cycle
+
ACTIVE_EXPIRE_CYCLE_FAST_DURATION
*
2
)
return
;
server
.
stat_expired_stale_perc
<
config_cycle_acceptable_stale
)
return
;
if
(
start
<
last_fast_cycle
+
(
long
long
)
config_cycle_fast_duration
*
2
)
return
;
last_fast_cycle
=
start
;
last_fast_cycle
=
start
;
}
}
...
@@ -130,16 +175,16 @@ void activeExpireCycle(int type) {
...
@@ -130,16 +175,16 @@ void activeExpireCycle(int type) {
if
(
dbs_per_call
>
server
.
dbnum
||
timelimit_exit
)
if
(
dbs_per_call
>
server
.
dbnum
||
timelimit_exit
)
dbs_per_call
=
server
.
dbnum
;
dbs_per_call
=
server
.
dbnum
;
/* We can use at max
ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC
percentage of CPU
time
/* We can use at max
'config_cycle_slow_time_perc'
percentage of CPU
* per iteration. Since this function gets called with a frequency of
*
time
per iteration. Since this function gets called with a frequency of
* server.hz times per second, the following is the max amount of
* server.hz times per second, the following is the max amount of
* microseconds we can spend in this function. */
* microseconds we can spend in this function. */
timelimit
=
1000000
*
ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC
/
server
.
hz
/
100
;
timelimit
=
config_cycle_slow_time_perc
*
1000000
/
server
.
hz
/
100
;
timelimit_exit
=
0
;
timelimit_exit
=
0
;
if
(
timelimit
<=
0
)
timelimit
=
1
;
if
(
timelimit
<=
0
)
timelimit
=
1
;
if
(
type
==
ACTIVE_EXPIRE_CYCLE_FAST
)
if
(
type
==
ACTIVE_EXPIRE_CYCLE_FAST
)
timelimit
=
ACTIVE_EXPIRE_CYCLE_FAST_DURATION
;
/* in microseconds. */
timelimit
=
config_cycle_fast_duration
;
/* in microseconds. */
/* Accumulate some global stats as we expire keys, to have some idea
/* Accumulate some global stats as we expire keys, to have some idea
* about the number of keys that are already logically expired, but still
* about the number of keys that are already logically expired, but still
...
@@ -148,7 +193,9 @@ void activeExpireCycle(int type) {
...
@@ -148,7 +193,9 @@ void activeExpireCycle(int type) {
long
total_expired
=
0
;
long
total_expired
=
0
;
for
(
j
=
0
;
j
<
dbs_per_call
&&
timelimit_exit
==
0
;
j
++
)
{
for
(
j
=
0
;
j
<
dbs_per_call
&&
timelimit_exit
==
0
;
j
++
)
{
int
expired
;
/* Expired and checked in a single loop. */
unsigned
long
expired
,
sampled
;
redisDb
*
db
=
server
.
db
+
(
current_db
%
server
.
dbnum
);
redisDb
*
db
=
server
.
db
+
(
current_db
%
server
.
dbnum
);
/* Increment the DB now so we are sure if we run out of time
/* Increment the DB now so we are sure if we run out of time
...
@@ -172,8 +219,8 @@ void activeExpireCycle(int type) {
...
@@ -172,8 +219,8 @@ void activeExpireCycle(int type) {
slots
=
dictSlots
(
db
->
expires
);
slots
=
dictSlots
(
db
->
expires
);
now
=
mstime
();
now
=
mstime
();
/* When there are less than 1% filled slots
getting random
/* When there are less than 1% filled slots
, sampling the key
*
keys
is expensive, so stop here waiting for better times...
*
space
is expensive, so stop here waiting for better times...
* The dictionary will be resized asap. */
* The dictionary will be resized asap. */
if
(
num
&&
slots
>
DICT_HT_INITIAL_SIZE
&&
if
(
num
&&
slots
>
DICT_HT_INITIAL_SIZE
&&
(
num
*
100
/
slots
<
1
))
break
;
(
num
*
100
/
slots
<
1
))
break
;
...
@@ -181,27 +228,58 @@ void activeExpireCycle(int type) {
...
@@ -181,27 +228,58 @@ void activeExpireCycle(int type) {
/* The main collection cycle. Sample random keys among keys
/* The main collection cycle. Sample random keys among keys
* with an expire set, checking for expired ones. */
* with an expire set, checking for expired ones. */
expired
=
0
;
expired
=
0
;
sampled
=
0
;
ttl_sum
=
0
;
ttl_sum
=
0
;
ttl_samples
=
0
;
ttl_samples
=
0
;
if
(
num
>
ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP
)
if
(
num
>
config_keys_per_loop
)
num
=
ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP
;
num
=
config_keys_per_loop
;
while
(
num
--
)
{
/* Here we access the low level representation of the hash table
dictEntry
*
de
;
* for speed concerns: this makes this code coupled with dict.c,
long
long
ttl
;
* but it hardly changed in ten years.
*
if
((
de
=
dictGetRandomKey
(
db
->
expires
))
==
NULL
)
break
;
* Note that certain places of the hash table may be empty,
ttl
=
dictGetSignedIntegerVal
(
de
)
-
now
;
* so we want also a stop condition about the number of
if
(
activeExpireCycleTryExpire
(
db
,
de
,
now
))
expired
++
;
* buckets that we scanned. However scanning for free buckets
if
(
ttl
>
0
)
{
* is very fast: we are in the cache line scanning a sequential
/* We want the average TTL of keys yet not expired. */
* array of NULL pointers, so we can scan a lot more buckets
ttl_sum
+=
ttl
;
* than keys in the same time. */
ttl_samples
++
;
long
max_buckets
=
num
*
20
;
long
checked_buckets
=
0
;
while
(
sampled
<
num
&&
checked_buckets
<
max_buckets
)
{
for
(
int
table
=
0
;
table
<
2
;
table
++
)
{
if
(
table
==
1
&&
!
dictIsRehashing
(
db
->
expires
))
break
;
unsigned
long
idx
=
db
->
expires_cursor
;
idx
&=
db
->
expires
->
ht
[
table
].
sizemask
;
dictEntry
*
de
=
db
->
expires
->
ht
[
table
].
table
[
idx
];
long
long
ttl
;
/* Scan the current bucket of the current table. */
checked_buckets
++
;
while
(
de
)
{
/* Get the next entry now since this entry may get
* deleted. */
dictEntry
*
e
=
de
;
de
=
de
->
next
;
ttl
=
dictGetSignedIntegerVal
(
e
)
-
now
;
if
(
activeExpireCycleTryExpire
(
db
,
e
,
now
))
expired
++
;
if
(
ttl
>
0
)
{
/* We want the average TTL of keys yet
* not expired. */
ttl_sum
+=
ttl
;
ttl_samples
++
;
}
sampled
++
;
}
}
}
total_sampled
++
;
db
->
expires_cursor
++
;
}
}
total_expired
+=
expired
;
total_expired
+=
expired
;
total_sampled
+=
sampled
;
/* Update the average TTL stats for this database. */
/* Update the average TTL stats for this database. */
if
(
ttl_samples
)
{
if
(
ttl_samples
)
{
...
@@ -225,12 +303,14 @@ void activeExpireCycle(int type) {
...
@@ -225,12 +303,14 @@ void activeExpireCycle(int type) {
break
;
break
;
}
}
}
}
/* We don't repeat the cycle if there are less than 25% of keys
/* We don't repeat the cycle for the current database if there are
* found expired in the current DB. */
* an acceptable amount of stale keys (logically expired but yet
}
while
(
expired
>
ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP
/
4
);
* not reclained). */
}
while
((
expired
*
100
/
sampled
)
>
config_cycle_acceptable_stale
);
}
}
elapsed
=
ustime
()
-
start
;
elapsed
=
ustime
()
-
start
;
server
.
stat_expire_cycle_time_used
+=
elapsed
;
latencyAddSampleIfNeeded
(
"expire-cycle"
,
elapsed
/
1000
);
latencyAddSampleIfNeeded
(
"expire-cycle"
,
elapsed
/
1000
);
/* Update our estimate of keys existing but yet to be expired.
/* Update our estimate of keys existing but yet to be expired.
...
...
src/mkreleasehdr.sh
View file @
64c2508e
...
@@ -3,7 +3,7 @@ GIT_SHA1=`(git show-ref --head --hash=8 2> /dev/null || echo 00000000) | head -n
...
@@ -3,7 +3,7 @@ GIT_SHA1=`(git show-ref --head --hash=8 2> /dev/null || echo 00000000) | head -n
GIT_DIRTY
=
`
git diff
--no-ext-diff
2> /dev/null |
wc
-l
`
GIT_DIRTY
=
`
git diff
--no-ext-diff
2> /dev/null |
wc
-l
`
BUILD_ID
=
`
uname
-n
`
"-"
`
date
+%s
`
BUILD_ID
=
`
uname
-n
`
"-"
`
date
+%s
`
if
[
-n
"
$SOURCE_DATE_EPOCH
"
]
;
then
if
[
-n
"
$SOURCE_DATE_EPOCH
"
]
;
then
BUILD_ID
=
$(
date
-u
-d
"@
$SOURCE_DATE_EPOCH
"
+%s 2>/dev/null
||
date
-u
-r
"
$SOURCE_DATE_EPOCH
"
+%s 2>/dev/null
||
date
-u
%s
)
BUILD_ID
=
$(
date
-u
-d
"@
$SOURCE_DATE_EPOCH
"
+%s 2>/dev/null
||
date
-u
-r
"
$SOURCE_DATE_EPOCH
"
+%s 2>/dev/null
||
date
-u
+
%s
)
fi
fi
test
-f
release.h
||
touch
release.h
test
-f
release.h
||
touch
release.h
(
cat
release.h |
grep
SHA1 |
grep
$GIT_SHA1
)
&&
\
(
cat
release.h |
grep
SHA1 |
grep
$GIT_SHA1
)
&&
\
...
...
src/module.c
View file @
64c2508e
This diff is collapsed.
Click to expand it.
src/networking.c
View file @
64c2508e
...
@@ -530,7 +530,7 @@ void addReplyHumanLongDouble(client *c, long double d) {
...
@@ -530,7 +530,7 @@ void addReplyHumanLongDouble(client *c, long double d) {
decrRefCount
(
o
);
decrRefCount
(
o
);
}
else
{
}
else
{
char
buf
[
MAX_LONG_DOUBLE_CHARS
];
char
buf
[
MAX_LONG_DOUBLE_CHARS
];
int
len
=
ld2string
(
buf
,
sizeof
(
buf
),
d
,
1
);
int
len
=
ld2string
(
buf
,
sizeof
(
buf
),
d
,
LD_STR_HUMAN
);
addReplyProto
(
c
,
","
,
1
);
addReplyProto
(
c
,
","
,
1
);
addReplyProto
(
c
,
buf
,
len
);
addReplyProto
(
c
,
buf
,
len
);
addReplyProto
(
c
,
"
\r\n
"
,
2
);
addReplyProto
(
c
,
"
\r\n
"
,
2
);
...
@@ -1118,6 +1118,11 @@ void freeClient(client *c) {
...
@@ -1118,6 +1118,11 @@ void freeClient(client *c) {
if
(
c
->
flags
&
CLIENT_SLAVE
&&
listLength
(
server
.
slaves
)
==
0
)
if
(
c
->
flags
&
CLIENT_SLAVE
&&
listLength
(
server
.
slaves
)
==
0
)
server
.
repl_no_slaves_since
=
server
.
unixtime
;
server
.
repl_no_slaves_since
=
server
.
unixtime
;
refreshGoodSlavesCount
();
refreshGoodSlavesCount
();
/* Fire the replica change modules event. */
if
(
c
->
replstate
==
SLAVE_STATE_ONLINE
)
moduleFireServerEvent
(
REDISMODULE_EVENT_REPLICA_CHANGE
,
REDISMODULE_SUBEVENT_REPLICA_CHANGE_OFFLINE
,
NULL
);
}
}
/* Master/slave cleanup Case 2:
/* Master/slave cleanup Case 2:
...
...
src/object.c
View file @
64c2508e
...
@@ -178,7 +178,7 @@ robj *createStringObjectFromLongLongForValue(long long value) {
...
@@ -178,7 +178,7 @@ robj *createStringObjectFromLongLongForValue(long long value) {
* The 'humanfriendly' option is used for INCRBYFLOAT and HINCRBYFLOAT. */
* The 'humanfriendly' option is used for INCRBYFLOAT and HINCRBYFLOAT. */
robj
*
createStringObjectFromLongDouble
(
long
double
value
,
int
humanfriendly
)
{
robj
*
createStringObjectFromLongDouble
(
long
double
value
,
int
humanfriendly
)
{
char
buf
[
MAX_LONG_DOUBLE_CHARS
];
char
buf
[
MAX_LONG_DOUBLE_CHARS
];
int
len
=
ld2string
(
buf
,
sizeof
(
buf
),
value
,
humanfriendly
);
int
len
=
ld2string
(
buf
,
sizeof
(
buf
),
value
,
humanfriendly
?
LD_STR_HUMAN
:
LD_STR_AUTO
);
return
createStringObject
(
buf
,
len
);
return
createStringObject
(
buf
,
len
);
}
}
...
@@ -1201,19 +1201,20 @@ sds getMemoryDoctorReport(void) {
...
@@ -1201,19 +1201,20 @@ sds getMemoryDoctorReport(void) {
* The lru_idle and lru_clock args are only relevant if policy
* The lru_idle and lru_clock args are only relevant if policy
* is MAXMEMORY_FLAG_LRU.
* is MAXMEMORY_FLAG_LRU.
* Either or both of them may be <0, in that case, nothing is set. */
* Either or both of them may be <0, in that case, nothing is set. */
void
objectSetLRUOrLFU
(
robj
*
val
,
long
long
lfu_freq
,
long
long
lru_idle
,
int
objectSetLRUOrLFU
(
robj
*
val
,
long
long
lfu_freq
,
long
long
lru_idle
,
long
long
lru_clock
)
{
long
long
lru_clock
,
int
lru_multiplier
)
{
if
(
server
.
maxmemory_policy
&
MAXMEMORY_FLAG_LFU
)
{
if
(
server
.
maxmemory_policy
&
MAXMEMORY_FLAG_LFU
)
{
if
(
lfu_freq
>=
0
)
{
if
(
lfu_freq
>=
0
)
{
serverAssert
(
lfu_freq
<=
255
);
serverAssert
(
lfu_freq
<=
255
);
val
->
lru
=
(
LFUGetTimeInMinutes
()
<<
8
)
|
lfu_freq
;
val
->
lru
=
(
LFUGetTimeInMinutes
()
<<
8
)
|
lfu_freq
;
return
1
;
}
}
}
else
if
(
lru_idle
>=
0
)
{
}
else
if
(
lru_idle
>=
0
)
{
/* Provided LRU idle time is in seconds. Scale
/* Provided LRU idle time is in seconds. Scale
* according to the LRU clock resolution this Redis
* according to the LRU clock resolution this Redis
* instance was compiled with (normally 1000 ms, so the
* instance was compiled with (normally 1000 ms, so the
* below statement will expand to lru_idle*1000/1000. */
* below statement will expand to lru_idle*1000/1000. */
lru_idle
=
lru_idle
*
1000
/
LRU_CLOCK_RESOLUTION
;
lru_idle
=
lru_idle
*
lru_multiplier
/
LRU_CLOCK_RESOLUTION
;
long
lru_abs
=
lru_clock
-
lru_idle
;
/* Absolute access time. */
long
lru_abs
=
lru_clock
-
lru_idle
;
/* Absolute access time. */
/* If the LRU field underflows (since LRU it is a wrapping
/* If the LRU field underflows (since LRU it is a wrapping
* clock), the best we can do is to provide a large enough LRU
* clock), the best we can do is to provide a large enough LRU
...
@@ -1223,7 +1224,9 @@ void objectSetLRUOrLFU(robj *val, long long lfu_freq, long long lru_idle,
...
@@ -1223,7 +1224,9 @@ void objectSetLRUOrLFU(robj *val, long long lfu_freq, long long lru_idle,
if
(
lru_abs
<
0
)
if
(
lru_abs
<
0
)
lru_abs
=
(
lru_clock
+
(
LRU_CLOCK_MAX
/
2
))
%
LRU_CLOCK_MAX
;
lru_abs
=
(
lru_clock
+
(
LRU_CLOCK_MAX
/
2
))
%
LRU_CLOCK_MAX
;
val
->
lru
=
lru_abs
;
val
->
lru
=
lru_abs
;
return
1
;
}
}
return
0
;
}
}
/* ======================= The OBJECT and MEMORY commands =================== */
/* ======================= The OBJECT and MEMORY commands =================== */
...
...
src/rax.c
View file @
64c2508e
...
@@ -1673,6 +1673,7 @@ int raxSeek(raxIterator *it, const char *op, unsigned char *ele, size_t len) {
...
@@ -1673,6 +1673,7 @@ int raxSeek(raxIterator *it, const char *op, unsigned char *ele, size_t len) {
* node, but will be our match, representing the key "f".
* node, but will be our match, representing the key "f".
*
*
* So in that case, we don't seek backward. */
* So in that case, we don't seek backward. */
it
->
data
=
raxGetData
(
it
->
node
);
}
else
{
}
else
{
if
(
gt
&&
!
raxIteratorNextStep
(
it
,
0
))
return
0
;
if
(
gt
&&
!
raxIteratorNextStep
(
it
,
0
))
return
0
;
if
(
lt
&&
!
raxIteratorPrevStep
(
it
,
0
))
return
0
;
if
(
lt
&&
!
raxIteratorPrevStep
(
it
,
0
))
return
0
;
...
@@ -1791,7 +1792,7 @@ int raxCompare(raxIterator *iter, const char *op, unsigned char *key, size_t key
...
@@ -1791,7 +1792,7 @@ int raxCompare(raxIterator *iter, const char *op, unsigned char *key, size_t key
if
(
eq
&&
key_len
==
iter
->
key_len
)
return
1
;
if
(
eq
&&
key_len
==
iter
->
key_len
)
return
1
;
else
if
(
lt
)
return
iter
->
key_len
<
key_len
;
else
if
(
lt
)
return
iter
->
key_len
<
key_len
;
else
if
(
gt
)
return
iter
->
key_len
>
key_len
;
else
if
(
gt
)
return
iter
->
key_len
>
key_len
;
return
0
;
else
return
0
;
/* Avoid warning, just 'eq' is handled before. */
}
else
if
(
cmp
>
0
)
{
}
else
if
(
cmp
>
0
)
{
return
gt
?
1
:
0
;
return
gt
?
1
:
0
;
}
else
/* (cmp < 0) */
{
}
else
/* (cmp < 0) */
{
...
...
src/rdb.c
View file @
64c2508e
...
@@ -1080,9 +1080,9 @@ ssize_t rdbSaveAuxFieldStrInt(rio *rdb, char *key, long long val) {
...
@@ -1080,9 +1080,9 @@ ssize_t rdbSaveAuxFieldStrInt(rio *rdb, char *key, long long val) {
}
}
/* Save a few default AUX fields with information about the RDB generated. */
/* Save a few default AUX fields with information about the RDB generated. */
int
rdbSaveInfoAuxFields
(
rio
*
rdb
,
int
flags
,
rdbSaveInfo
*
rsi
)
{
int
rdbSaveInfoAuxFields
(
rio
*
rdb
,
int
rdb
flags
,
rdbSaveInfo
*
rsi
)
{
int
redis_bits
=
(
sizeof
(
void
*
)
==
8
)
?
64
:
32
;
int
redis_bits
=
(
sizeof
(
void
*
)
==
8
)
?
64
:
32
;
int
aof_preamble
=
(
flags
&
RDB
_SAVE
_AOF_PREAMBLE
)
!=
0
;
int
aof_preamble
=
(
rdb
flags
&
RDB
FLAGS
_AOF_PREAMBLE
)
!=
0
;
/* Add a few fields about the state when the RDB was created. */
/* Add a few fields about the state when the RDB was created. */
if
(
rdbSaveAuxFieldStrStr
(
rdb
,
"redis-ver"
,
REDIS_VERSION
)
==
-
1
)
return
-
1
;
if
(
rdbSaveAuxFieldStrStr
(
rdb
,
"redis-ver"
,
REDIS_VERSION
)
==
-
1
)
return
-
1
;
...
@@ -1150,7 +1150,7 @@ ssize_t rdbSaveSingleModuleAux(rio *rdb, int when, moduleType *mt) {
...
@@ -1150,7 +1150,7 @@ ssize_t rdbSaveSingleModuleAux(rio *rdb, int when, moduleType *mt) {
* When the function returns C_ERR and if 'error' is not NULL, the
* When the function returns C_ERR and if 'error' is not NULL, the
* integer pointed by 'error' is set to the value of errno just after the I/O
* integer pointed by 'error' is set to the value of errno just after the I/O
* error. */
* error. */
int
rdbSaveRio
(
rio
*
rdb
,
int
*
error
,
int
flags
,
rdbSaveInfo
*
rsi
)
{
int
rdbSaveRio
(
rio
*
rdb
,
int
*
error
,
int
rdb
flags
,
rdbSaveInfo
*
rsi
)
{
dictIterator
*
di
=
NULL
;
dictIterator
*
di
=
NULL
;
dictEntry
*
de
;
dictEntry
*
de
;
char
magic
[
10
];
char
magic
[
10
];
...
@@ -1162,7 +1162,7 @@ int rdbSaveRio(rio *rdb, int *error, int flags, rdbSaveInfo *rsi) {
...
@@ -1162,7 +1162,7 @@ int rdbSaveRio(rio *rdb, int *error, int flags, rdbSaveInfo *rsi) {
rdb
->
update_cksum
=
rioGenericUpdateChecksum
;
rdb
->
update_cksum
=
rioGenericUpdateChecksum
;
snprintf
(
magic
,
sizeof
(
magic
),
"REDIS%04d"
,
RDB_VERSION
);
snprintf
(
magic
,
sizeof
(
magic
),
"REDIS%04d"
,
RDB_VERSION
);
if
(
rdbWriteRaw
(
rdb
,
magic
,
9
)
==
-
1
)
goto
werr
;
if
(
rdbWriteRaw
(
rdb
,
magic
,
9
)
==
-
1
)
goto
werr
;
if
(
rdbSaveInfoAuxFields
(
rdb
,
flags
,
rsi
)
==
-
1
)
goto
werr
;
if
(
rdbSaveInfoAuxFields
(
rdb
,
rdb
flags
,
rsi
)
==
-
1
)
goto
werr
;
if
(
rdbSaveModulesAux
(
rdb
,
REDISMODULE_AUX_BEFORE_RDB
)
==
-
1
)
goto
werr
;
if
(
rdbSaveModulesAux
(
rdb
,
REDISMODULE_AUX_BEFORE_RDB
)
==
-
1
)
goto
werr
;
for
(
j
=
0
;
j
<
server
.
dbnum
;
j
++
)
{
for
(
j
=
0
;
j
<
server
.
dbnum
;
j
++
)
{
...
@@ -1199,7 +1199,7 @@ int rdbSaveRio(rio *rdb, int *error, int flags, rdbSaveInfo *rsi) {
...
@@ -1199,7 +1199,7 @@ int rdbSaveRio(rio *rdb, int *error, int flags, rdbSaveInfo *rsi) {
/* When this RDB is produced as part of an AOF rewrite, move
/* When this RDB is produced as part of an AOF rewrite, move
* accumulated diff from parent to child while rewriting in
* accumulated diff from parent to child while rewriting in
* order to have a smaller final write. */
* order to have a smaller final write. */
if
(
flags
&
RDB
_SAVE
_AOF_PREAMBLE
&&
if
(
rdb
flags
&
RDB
FLAGS
_AOF_PREAMBLE
&&
rdb
->
processed_bytes
>
processed
+
AOF_READ_DIFF_INTERVAL_BYTES
)
rdb
->
processed_bytes
>
processed
+
AOF_READ_DIFF_INTERVAL_BYTES
)
{
{
processed
=
rdb
->
processed_bytes
;
processed
=
rdb
->
processed_bytes
;
...
@@ -1254,18 +1254,21 @@ werr:
...
@@ -1254,18 +1254,21 @@ werr:
int
rdbSaveRioWithEOFMark
(
rio
*
rdb
,
int
*
error
,
rdbSaveInfo
*
rsi
)
{
int
rdbSaveRioWithEOFMark
(
rio
*
rdb
,
int
*
error
,
rdbSaveInfo
*
rsi
)
{
char
eofmark
[
RDB_EOF_MARK_SIZE
];
char
eofmark
[
RDB_EOF_MARK_SIZE
];
startSaving
(
RDBFLAGS_REPLICATION
);
getRandomHexChars
(
eofmark
,
RDB_EOF_MARK_SIZE
);
getRandomHexChars
(
eofmark
,
RDB_EOF_MARK_SIZE
);
if
(
error
)
*
error
=
0
;
if
(
error
)
*
error
=
0
;
if
(
rioWrite
(
rdb
,
"$EOF:"
,
5
)
==
0
)
goto
werr
;
if
(
rioWrite
(
rdb
,
"$EOF:"
,
5
)
==
0
)
goto
werr
;
if
(
rioWrite
(
rdb
,
eofmark
,
RDB_EOF_MARK_SIZE
)
==
0
)
goto
werr
;
if
(
rioWrite
(
rdb
,
eofmark
,
RDB_EOF_MARK_SIZE
)
==
0
)
goto
werr
;
if
(
rioWrite
(
rdb
,
"
\r\n
"
,
2
)
==
0
)
goto
werr
;
if
(
rioWrite
(
rdb
,
"
\r\n
"
,
2
)
==
0
)
goto
werr
;
if
(
rdbSaveRio
(
rdb
,
error
,
RDB
_SAVE
_NONE
,
rsi
)
==
C_ERR
)
goto
werr
;
if
(
rdbSaveRio
(
rdb
,
error
,
RDB
FLAGS
_NONE
,
rsi
)
==
C_ERR
)
goto
werr
;
if
(
rioWrite
(
rdb
,
eofmark
,
RDB_EOF_MARK_SIZE
)
==
0
)
goto
werr
;
if
(
rioWrite
(
rdb
,
eofmark
,
RDB_EOF_MARK_SIZE
)
==
0
)
goto
werr
;
stopSaving
(
1
);
return
C_OK
;
return
C_OK
;
werr:
/* Write error. */
werr:
/* Write error. */
/* Set 'error' only if not already set by rdbSaveRio() call. */
/* Set 'error' only if not already set by rdbSaveRio() call. */
if
(
error
&&
*
error
==
0
)
*
error
=
errno
;
if
(
error
&&
*
error
==
0
)
*
error
=
errno
;
stopSaving
(
0
);
return
C_ERR
;
return
C_ERR
;
}
}
...
@@ -1291,11 +1294,12 @@ int rdbSave(char *filename, rdbSaveInfo *rsi) {
...
@@ -1291,11 +1294,12 @@ int rdbSave(char *filename, rdbSaveInfo *rsi) {
}
}
rioInitWithFile
(
&
rdb
,
fp
);
rioInitWithFile
(
&
rdb
,
fp
);
startSaving
(
RDBFLAGS_NONE
);
if
(
server
.
rdb_save_incremental_fsync
)
if
(
server
.
rdb_save_incremental_fsync
)
rioSetAutoSync
(
&
rdb
,
REDIS_AUTOSYNC_BYTES
);
rioSetAutoSync
(
&
rdb
,
REDIS_AUTOSYNC_BYTES
);
if
(
rdbSaveRio
(
&
rdb
,
&
error
,
RDB
_SAVE
_NONE
,
rsi
)
==
C_ERR
)
{
if
(
rdbSaveRio
(
&
rdb
,
&
error
,
RDB
FLAGS
_NONE
,
rsi
)
==
C_ERR
)
{
errno
=
error
;
errno
=
error
;
goto
werr
;
goto
werr
;
}
}
...
@@ -1317,6 +1321,7 @@ int rdbSave(char *filename, rdbSaveInfo *rsi) {
...
@@ -1317,6 +1321,7 @@ int rdbSave(char *filename, rdbSaveInfo *rsi) {
cwdp
?
cwdp
:
"unknown"
,
cwdp
?
cwdp
:
"unknown"
,
strerror
(
errno
));
strerror
(
errno
));
unlink
(
tmpfile
);
unlink
(
tmpfile
);
stopSaving
(
0
);
return
C_ERR
;
return
C_ERR
;
}
}
...
@@ -1324,12 +1329,14 @@ int rdbSave(char *filename, rdbSaveInfo *rsi) {
...
@@ -1324,12 +1329,14 @@ int rdbSave(char *filename, rdbSaveInfo *rsi) {
server
.
dirty
=
0
;
server
.
dirty
=
0
;
server
.
lastsave
=
time
(
NULL
);
server
.
lastsave
=
time
(
NULL
);
server
.
lastbgsave_status
=
C_OK
;
server
.
lastbgsave_status
=
C_OK
;
stopSaving
(
1
);
return
C_OK
;
return
C_OK
;
werr:
werr:
serverLog
(
LL_WARNING
,
"Write error saving DB on disk: %s"
,
strerror
(
errno
));
serverLog
(
LL_WARNING
,
"Write error saving DB on disk: %s"
,
strerror
(
errno
));
fclose
(
fp
);
fclose
(
fp
);
unlink
(
tmpfile
);
unlink
(
tmpfile
);
stopSaving
(
0
);
return
C_ERR
;
return
C_ERR
;
}
}
...
@@ -1918,23 +1925,33 @@ robj *rdbLoadObject(int rdbtype, rio *rdb, robj *key) {
...
@@ -1918,23 +1925,33 @@ robj *rdbLoadObject(int rdbtype, rio *rdb, robj *key) {
/* Mark that we are loading in the global state and setup the fields
/* Mark that we are loading in the global state and setup the fields
* needed to provide loading stats. */
* needed to provide loading stats. */
void
startLoading
(
size_t
size
)
{
void
startLoading
(
size_t
size
,
int
rdbflags
)
{
/* Load the DB */
/* Load the DB */
server
.
loading
=
1
;
server
.
loading
=
1
;
server
.
loading_start_time
=
time
(
NULL
);
server
.
loading_start_time
=
time
(
NULL
);
server
.
loading_loaded_bytes
=
0
;
server
.
loading_loaded_bytes
=
0
;
server
.
loading_total_bytes
=
size
;
server
.
loading_total_bytes
=
size
;
/* Fire the loading modules start event. */
int
subevent
;
if
(
rdbflags
&
RDBFLAGS_AOF_PREAMBLE
)
subevent
=
REDISMODULE_SUBEVENT_LOADING_AOF_START
;
else
if
(
rdbflags
&
RDBFLAGS_REPLICATION
)
subevent
=
REDISMODULE_SUBEVENT_LOADING_REPL_START
;
else
subevent
=
REDISMODULE_SUBEVENT_LOADING_RDB_START
;
moduleFireServerEvent
(
REDISMODULE_EVENT_LOADING
,
subevent
,
NULL
);
}
}
/* Mark that we are loading in the global state and setup the fields
/* Mark that we are loading in the global state and setup the fields
* needed to provide loading stats.
* needed to provide loading stats.
* 'filename' is optional and used for rdb-check on error */
* 'filename' is optional and used for rdb-check on error */
void
startLoadingFile
(
FILE
*
fp
,
char
*
filename
)
{
void
startLoadingFile
(
FILE
*
fp
,
char
*
filename
,
int
rdbflags
)
{
struct
stat
sb
;
struct
stat
sb
;
if
(
fstat
(
fileno
(
fp
),
&
sb
)
==
-
1
)
if
(
fstat
(
fileno
(
fp
),
&
sb
)
==
-
1
)
sb
.
st_size
=
0
;
sb
.
st_size
=
0
;
rdbFileBeingLoaded
=
filename
;
rdbFileBeingLoaded
=
filename
;
startLoading
(
sb
.
st_size
);
startLoading
(
sb
.
st_size
,
rdbflags
);
}
}
/* Refresh the loading progress info */
/* Refresh the loading progress info */
...
@@ -1945,9 +1962,37 @@ void loadingProgress(off_t pos) {
...
@@ -1945,9 +1962,37 @@ void loadingProgress(off_t pos) {
}
}
/* Loading finished */
/* Loading finished */
void
stopLoading
(
void
)
{
void
stopLoading
(
int
success
)
{
server
.
loading
=
0
;
server
.
loading
=
0
;
rdbFileBeingLoaded
=
NULL
;
rdbFileBeingLoaded
=
NULL
;
/* Fire the loading modules end event. */
moduleFireServerEvent
(
REDISMODULE_EVENT_LOADING
,
success
?
REDISMODULE_SUBEVENT_LOADING_ENDED:
REDISMODULE_SUBEVENT_LOADING_FAILED
,
NULL
);
}
void
startSaving
(
int
rdbflags
)
{
/* Fire the persistence modules end event. */
int
subevent
;
if
(
rdbflags
&
RDBFLAGS_AOF_PREAMBLE
)
subevent
=
REDISMODULE_SUBEVENT_PERSISTENCE_AOF_START
;
else
if
(
getpid
()
!=
server
.
pid
)
subevent
=
REDISMODULE_SUBEVENT_PERSISTENCE_RDB_START
;
else
subevent
=
REDISMODULE_SUBEVENT_PERSISTENCE_SYNC_RDB_START
;
moduleFireServerEvent
(
REDISMODULE_EVENT_PERSISTENCE
,
subevent
,
NULL
);
}
void
stopSaving
(
int
success
)
{
/* Fire the persistence modules end event. */
moduleFireServerEvent
(
REDISMODULE_EVENT_PERSISTENCE
,
success
?
REDISMODULE_SUBEVENT_PERSISTENCE_ENDED:
REDISMODULE_SUBEVENT_PERSISTENCE_FAILED
,
NULL
);
}
}
/* Track loading progress in order to serve client's from time to time
/* Track loading progress in order to serve client's from time to time
...
@@ -1961,17 +2006,18 @@ void rdbLoadProgressCallback(rio *r, const void *buf, size_t len) {
...
@@ -1961,17 +2006,18 @@ void rdbLoadProgressCallback(rio *r, const void *buf, size_t len) {
/* The DB can take some non trivial amount of time to load. Update
/* The DB can take some non trivial amount of time to load. Update
* our cached time since it is used to create and update the last
* our cached time since it is used to create and update the last
* interaction time with clients and for other important things. */
* interaction time with clients and for other important things. */
updateCachedTime
();
updateCachedTime
(
0
);
if
(
server
.
masterhost
&&
server
.
repl_state
==
REPL_STATE_TRANSFER
)
if
(
server
.
masterhost
&&
server
.
repl_state
==
REPL_STATE_TRANSFER
)
replicationSendNewlineToMaster
();
replicationSendNewlineToMaster
();
loadingProgress
(
r
->
processed_bytes
);
loadingProgress
(
r
->
processed_bytes
);
processEventsWhileBlocked
();
processEventsWhileBlocked
();
processModuleLoadingProgressEvent
(
0
);
}
}
}
}
/* Load an RDB file from the rio stream 'rdb'. On success C_OK is returned,
/* Load an RDB file from the rio stream 'rdb'. On success C_OK is returned,
* otherwise C_ERR is returned and 'errno' is set accordingly. */
* otherwise C_ERR is returned and 'errno' is set accordingly. */
int
rdbLoadRio
(
rio
*
rdb
,
rdbSaveInfo
*
rsi
,
int
loading_aof
)
{
int
rdbLoadRio
(
rio
*
rdb
,
int
rdbflags
,
rdbSaveInfo
*
rsi
)
{
uint64_t
dbid
;
uint64_t
dbid
;
int
type
,
rdbver
;
int
type
,
rdbver
;
redisDb
*
db
=
server
.
db
+
0
;
redisDb
*
db
=
server
.
db
+
0
;
...
@@ -2182,7 +2228,7 @@ int rdbLoadRio(rio *rdb, rdbSaveInfo *rsi, int loading_aof) {
...
@@ -2182,7 +2228,7 @@ int rdbLoadRio(rio *rdb, rdbSaveInfo *rsi, int loading_aof) {
* received from the master. In the latter case, the master is
* received from the master. In the latter case, the master is
* responsible for key expiry. If we would expire keys here, the
* responsible for key expiry. If we would expire keys here, the
* snapshot taken by the master may not be reflected on the slave. */
* snapshot taken by the master may not be reflected on the slave. */
if
(
server
.
masterhost
==
NULL
&&
!
loading_aof
&&
expiretime
!=
-
1
&&
expiretime
<
now
)
{
if
(
server
.
masterhost
==
NULL
&&
!
(
rdbflags
&
RDBFLAGS_AOF_PREAMBLE
)
&&
expiretime
!=
-
1
&&
expiretime
<
now
)
{
decrRefCount
(
key
);
decrRefCount
(
key
);
decrRefCount
(
val
);
decrRefCount
(
val
);
}
else
{
}
else
{
...
@@ -2193,7 +2239,7 @@ int rdbLoadRio(rio *rdb, rdbSaveInfo *rsi, int loading_aof) {
...
@@ -2193,7 +2239,7 @@ int rdbLoadRio(rio *rdb, rdbSaveInfo *rsi, int loading_aof) {
if
(
expiretime
!=
-
1
)
setExpire
(
NULL
,
db
,
key
,
expiretime
);
if
(
expiretime
!=
-
1
)
setExpire
(
NULL
,
db
,
key
,
expiretime
);
/* Set usage information (for eviction). */
/* Set usage information (for eviction). */
objectSetLRUOrLFU
(
val
,
lfu_freq
,
lru_idle
,
lru_clock
);
objectSetLRUOrLFU
(
val
,
lfu_freq
,
lru_idle
,
lru_clock
,
1000
);
/* Decrement the key refcount since dbAdd() will take its
/* Decrement the key refcount since dbAdd() will take its
* own reference. */
* own reference. */
...
@@ -2243,17 +2289,17 @@ eoferr:
...
@@ -2243,17 +2289,17 @@ eoferr:
*
*
* If you pass an 'rsi' structure initialied with RDB_SAVE_OPTION_INIT, the
* If you pass an 'rsi' structure initialied with RDB_SAVE_OPTION_INIT, the
* loading code will fiil the information fields in the structure. */
* loading code will fiil the information fields in the structure. */
int
rdbLoad
(
char
*
filename
,
rdbSaveInfo
*
rsi
)
{
int
rdbLoad
(
char
*
filename
,
rdbSaveInfo
*
rsi
,
int
rdbflags
)
{
FILE
*
fp
;
FILE
*
fp
;
rio
rdb
;
rio
rdb
;
int
retval
;
int
retval
;
if
((
fp
=
fopen
(
filename
,
"r"
))
==
NULL
)
return
C_ERR
;
if
((
fp
=
fopen
(
filename
,
"r"
))
==
NULL
)
return
C_ERR
;
startLoadingFile
(
fp
,
filename
);
startLoadingFile
(
fp
,
filename
,
rdbflags
);
rioInitWithFile
(
&
rdb
,
fp
);
rioInitWithFile
(
&
rdb
,
fp
);
retval
=
rdbLoadRio
(
&
rdb
,
rsi
,
0
);
retval
=
rdbLoadRio
(
&
rdb
,
r
dbflags
,
r
si
);
fclose
(
fp
);
fclose
(
fp
);
stopLoading
();
stopLoading
(
retval
==
C_OK
);
return
retval
;
return
retval
;
}
}
...
...
src/rdb.h
View file @
64c2508e
...
@@ -121,8 +121,10 @@
...
@@ -121,8 +121,10 @@
#define RDB_LOAD_PLAIN (1<<1)
#define RDB_LOAD_PLAIN (1<<1)
#define RDB_LOAD_SDS (1<<2)
#define RDB_LOAD_SDS (1<<2)
#define RDB_SAVE_NONE 0
/* flags on the purpose of rdb save or load */
#define RDB_SAVE_AOF_PREAMBLE (1<<0)
#define RDBFLAGS_NONE 0
#define RDBFLAGS_AOF_PREAMBLE (1<<0)
#define RDBFLAGS_REPLICATION (1<<1)
int
rdbSaveType
(
rio
*
rdb
,
unsigned
char
type
);
int
rdbSaveType
(
rio
*
rdb
,
unsigned
char
type
);
int
rdbLoadType
(
rio
*
rdb
);
int
rdbLoadType
(
rio
*
rdb
);
...
@@ -135,7 +137,7 @@ uint64_t rdbLoadLen(rio *rdb, int *isencoded);
...
@@ -135,7 +137,7 @@ uint64_t rdbLoadLen(rio *rdb, int *isencoded);
int
rdbLoadLenByRef
(
rio
*
rdb
,
int
*
isencoded
,
uint64_t
*
lenptr
);
int
rdbLoadLenByRef
(
rio
*
rdb
,
int
*
isencoded
,
uint64_t
*
lenptr
);
int
rdbSaveObjectType
(
rio
*
rdb
,
robj
*
o
);
int
rdbSaveObjectType
(
rio
*
rdb
,
robj
*
o
);
int
rdbLoadObjectType
(
rio
*
rdb
);
int
rdbLoadObjectType
(
rio
*
rdb
);
int
rdbLoad
(
char
*
filename
,
rdbSaveInfo
*
rsi
);
int
rdbLoad
(
char
*
filename
,
rdbSaveInfo
*
rsi
,
int
rdbflags
);
int
rdbSaveBackground
(
char
*
filename
,
rdbSaveInfo
*
rsi
);
int
rdbSaveBackground
(
char
*
filename
,
rdbSaveInfo
*
rsi
);
int
rdbSaveToSlavesSockets
(
rdbSaveInfo
*
rsi
);
int
rdbSaveToSlavesSockets
(
rdbSaveInfo
*
rsi
);
void
rdbRemoveTempFile
(
pid_t
childpid
);
void
rdbRemoveTempFile
(
pid_t
childpid
);
...
@@ -154,7 +156,8 @@ int rdbSaveBinaryDoubleValue(rio *rdb, double val);
...
@@ -154,7 +156,8 @@ int rdbSaveBinaryDoubleValue(rio *rdb, double val);
int
rdbLoadBinaryDoubleValue
(
rio
*
rdb
,
double
*
val
);
int
rdbLoadBinaryDoubleValue
(
rio
*
rdb
,
double
*
val
);
int
rdbSaveBinaryFloatValue
(
rio
*
rdb
,
float
val
);
int
rdbSaveBinaryFloatValue
(
rio
*
rdb
,
float
val
);
int
rdbLoadBinaryFloatValue
(
rio
*
rdb
,
float
*
val
);
int
rdbLoadBinaryFloatValue
(
rio
*
rdb
,
float
*
val
);
int
rdbLoadRio
(
rio
*
rdb
,
rdbSaveInfo
*
rsi
,
int
loading_aof
);
int
rdbLoadRio
(
rio
*
rdb
,
int
rdbflags
,
rdbSaveInfo
*
rsi
);
int
rdbSaveRio
(
rio
*
rdb
,
int
*
error
,
int
rdbflags
,
rdbSaveInfo
*
rsi
);
rdbSaveInfo
*
rdbPopulateSaveInfo
(
rdbSaveInfo
*
rsi
);
rdbSaveInfo
*
rdbPopulateSaveInfo
(
rdbSaveInfo
*
rsi
);
#endif
#endif
src/redis-check-rdb.c
View file @
64c2508e
...
@@ -202,7 +202,7 @@ int redis_check_rdb(char *rdbfilename, FILE *fp) {
...
@@ -202,7 +202,7 @@ int redis_check_rdb(char *rdbfilename, FILE *fp) {
}
}
expiretime
=
-
1
;
expiretime
=
-
1
;
startLoadingFile
(
fp
,
rdbfilename
);
startLoadingFile
(
fp
,
rdbfilename
,
RDBFLAGS_NONE
);
while
(
1
)
{
while
(
1
)
{
robj
*
key
,
*
val
;
robj
*
key
,
*
val
;
...
@@ -316,7 +316,7 @@ int redis_check_rdb(char *rdbfilename, FILE *fp) {
...
@@ -316,7 +316,7 @@ int redis_check_rdb(char *rdbfilename, FILE *fp) {
}
}
if
(
closefile
)
fclose
(
fp
);
if
(
closefile
)
fclose
(
fp
);
stopLoading
();
stopLoading
(
1
);
return
0
;
return
0
;
eoferr:
/* unexpected end of file is handled here with a fatal exit */
eoferr:
/* unexpected end of file is handled here with a fatal exit */
...
@@ -327,7 +327,7 @@ eoferr: /* unexpected end of file is handled here with a fatal exit */
...
@@ -327,7 +327,7 @@ eoferr: /* unexpected end of file is handled here with a fatal exit */
}
}
err:
err:
if
(
closefile
)
fclose
(
fp
);
if
(
closefile
)
fclose
(
fp
);
stopLoading
();
stopLoading
(
0
);
return
1
;
return
1
;
}
}
...
...
src/redismodule.h
View file @
64c2508e
...
@@ -18,6 +18,10 @@
...
@@ -18,6 +18,10 @@
#define REDISMODULE_READ (1<<0)
#define REDISMODULE_READ (1<<0)
#define REDISMODULE_WRITE (1<<1)
#define REDISMODULE_WRITE (1<<1)
/* RedisModule_OpenKey extra flags for the 'mode' argument.
* Avoid touching the LRU/LFU of the key when opened. */
#define REDISMODULE_OPEN_KEY_NOTOUCH (1<<16)
#define REDISMODULE_LIST_HEAD 0
#define REDISMODULE_LIST_HEAD 0
#define REDISMODULE_LIST_TAIL 1
#define REDISMODULE_LIST_TAIL 1
...
@@ -29,6 +33,7 @@
...
@@ -29,6 +33,7 @@
#define REDISMODULE_KEYTYPE_SET 4
#define REDISMODULE_KEYTYPE_SET 4
#define REDISMODULE_KEYTYPE_ZSET 5
#define REDISMODULE_KEYTYPE_ZSET 5
#define REDISMODULE_KEYTYPE_MODULE 6
#define REDISMODULE_KEYTYPE_MODULE 6
#define REDISMODULE_KEYTYPE_STREAM 7
/* Reply types. */
/* Reply types. */
#define REDISMODULE_REPLY_UNKNOWN -1
#define REDISMODULE_REPLY_UNKNOWN -1
...
@@ -181,6 +186,8 @@ typedef uint64_t RedisModuleTimerID;
...
@@ -181,6 +186,8 @@ typedef uint64_t RedisModuleTimerID;
#define REDISMODULE_EVENT_REPLICA_CHANGE 6
#define REDISMODULE_EVENT_REPLICA_CHANGE 6
#define REDISMODULE_EVENT_MASTER_LINK_CHANGE 7
#define REDISMODULE_EVENT_MASTER_LINK_CHANGE 7
#define REDISMODULE_EVENT_CRON_LOOP 8
#define REDISMODULE_EVENT_CRON_LOOP 8
#define REDISMODULE_EVENT_MODULE_CHANGE 9
#define REDISMODULE_EVENT_LOADING_PROGRESS 10
typedef
struct
RedisModuleEvent
{
typedef
struct
RedisModuleEvent
{
uint64_t
id
;
/* REDISMODULE_EVENT_... defines. */
uint64_t
id
;
/* REDISMODULE_EVENT_... defines. */
...
@@ -226,18 +233,28 @@ static const RedisModuleEvent
...
@@ -226,18 +233,28 @@ static const RedisModuleEvent
RedisModuleEvent_MasterLinkChange
=
{
RedisModuleEvent_MasterLinkChange
=
{
REDISMODULE_EVENT_MASTER_LINK_CHANGE
,
REDISMODULE_EVENT_MASTER_LINK_CHANGE
,
1
1
},
RedisModuleEvent_ModuleChange
=
{
REDISMODULE_EVENT_MODULE_CHANGE
,
1
},
RedisModuleEvent_LoadingProgress
=
{
REDISMODULE_EVENT_LOADING_PROGRESS
,
1
};
};
/* Those are values that are used for the 'subevent' callback argument. */
/* Those are values that are used for the 'subevent' callback argument. */
#define REDISMODULE_SUBEVENT_PERSISTENCE_RDB_START 0
#define REDISMODULE_SUBEVENT_PERSISTENCE_RDB_START 0
#define REDISMODULE_SUBEVENT_PERSISTENCE_RDB_END 1
#define REDISMODULE_SUBEVENT_PERSISTENCE_AOF_START 1
#define REDISMODULE_SUBEVENT_PERSISTENCE_AOF_START 2
#define REDISMODULE_SUBEVENT_PERSISTENCE_SYNC_RDB_START 2
#define REDISMODULE_SUBEVENT_PERSISTENCE_AOF_END 3
#define REDISMODULE_SUBEVENT_PERSISTENCE_ENDED 3
#define REDISMODULE_SUBEVENT_PERSISTENCE_FAILED 4
#define REDISMODULE_SUBEVENT_LOADING_RDB_START 0
#define REDISMODULE_SUBEVENT_LOADING_RDB_START 0
#define REDISMODULE_SUBEVENT_LOADING_RDB_END 1
#define REDISMODULE_SUBEVENT_LOADING_AOF_START 1
#define REDISMODULE_SUBEVENT_LOADING_AOF_START 2
#define REDISMODULE_SUBEVENT_LOADING_REPL_START 2
#define REDISMODULE_SUBEVENT_LOADING_AOF_END 3
#define REDISMODULE_SUBEVENT_LOADING_ENDED 3
#define REDISMODULE_SUBEVENT_LOADING_FAILED 4
#define REDISMODULE_SUBEVENT_CLIENT_CHANGE_CONNECTED 0
#define REDISMODULE_SUBEVENT_CLIENT_CHANGE_CONNECTED 0
#define REDISMODULE_SUBEVENT_CLIENT_CHANGE_DISCONNECTED 1
#define REDISMODULE_SUBEVENT_CLIENT_CHANGE_DISCONNECTED 1
...
@@ -245,12 +262,21 @@ static const RedisModuleEvent
...
@@ -245,12 +262,21 @@ static const RedisModuleEvent
#define REDISMODULE_SUBEVENT_MASTER_LINK_UP 0
#define REDISMODULE_SUBEVENT_MASTER_LINK_UP 0
#define REDISMODULE_SUBEVENT_MASTER_LINK_DOWN 1
#define REDISMODULE_SUBEVENT_MASTER_LINK_DOWN 1
#define REDISMODULE_SUBEVENT_REPLICA_CHANGE_CONNECTED 0
#define REDISMODULE_SUBEVENT_REPLICA_CHANGE_ONLINE 0
#define REDISMODULE_SUBEVENT_REPLICA_CHANGE_DISCONNECTED 1
#define REDISMODULE_SUBEVENT_REPLICA_CHANGE_OFFLINE 1
#define REDISMODULE_EVENT_REPLROLECHANGED_NOW_MASTER 0
#define REDISMODULE_EVENT_REPLROLECHANGED_NOW_REPLICA 1
#define REDISMODULE_SUBEVENT_FLUSHDB_START 0
#define REDISMODULE_SUBEVENT_FLUSHDB_START 0
#define REDISMODULE_SUBEVENT_FLUSHDB_END 1
#define REDISMODULE_SUBEVENT_FLUSHDB_END 1
#define REDISMODULE_SUBEVENT_MODULE_LOADED 0
#define REDISMODULE_SUBEVENT_MODULE_UNLOADED 1
#define REDISMODULE_SUBEVENT_LOADING_PROGRESS_RDB 0
#define REDISMODULE_SUBEVENT_LOADING_PROGRESS_AOF 1
/* RedisModuleClientInfo flags. */
/* RedisModuleClientInfo flags. */
#define REDISMODULE_CLIENTINFO_FLAG_SSL (1<<0)
#define REDISMODULE_CLIENTINFO_FLAG_SSL (1<<0)
#define REDISMODULE_CLIENTINFO_FLAG_PUBSUB (1<<1)
#define REDISMODULE_CLIENTINFO_FLAG_PUBSUB (1<<1)
...
@@ -286,6 +312,22 @@ typedef struct RedisModuleClientInfo {
...
@@ -286,6 +312,22 @@ typedef struct RedisModuleClientInfo {
#define RedisModuleClientInfo RedisModuleClientInfoV1
#define RedisModuleClientInfo RedisModuleClientInfoV1
#define REDISMODULE_REPLICATIONINFO_VERSION 1
typedef
struct
RedisModuleReplicationInfo
{
uint64_t
version
;
/* Not used since this structure is never passed
from the module to the core right now. Here
for future compatibility. */
int
master
;
/* true if master, false if replica */
char
*
masterhost
;
/* master instance hostname for NOW_REPLICA */
int
masterport
;
/* master instance port for NOW_REPLICA */
char
*
replid1
;
/* Main replication ID */
char
*
replid2
;
/* Secondary replication ID */
uint64_t
repl1_offset
;
/* Main replication offset */
uint64_t
repl2_offset
;
/* Offset of replid2 validity */
}
RedisModuleReplicationInfoV1
;
#define RedisModuleReplicationInfo RedisModuleReplicationInfoV1
#define REDISMODULE_FLUSHINFO_VERSION 1
#define REDISMODULE_FLUSHINFO_VERSION 1
typedef
struct
RedisModuleFlushInfo
{
typedef
struct
RedisModuleFlushInfo
{
uint64_t
version
;
/* Not used since this structure is never passed
uint64_t
version
;
/* Not used since this structure is never passed
...
@@ -297,6 +339,39 @@ typedef struct RedisModuleFlushInfo {
...
@@ -297,6 +339,39 @@ typedef struct RedisModuleFlushInfo {
#define RedisModuleFlushInfo RedisModuleFlushInfoV1
#define RedisModuleFlushInfo RedisModuleFlushInfoV1
#define REDISMODULE_MODULE_CHANGE_VERSION 1
typedef
struct
RedisModuleModuleChange
{
uint64_t
version
;
/* Not used since this structure is never passed
from the module to the core right now. Here
for future compatibility. */
const
char
*
module_name
;
/* Name of module loaded or unloaded. */
int32_t
module_version
;
/* Module version. */
}
RedisModuleModuleChangeV1
;
#define RedisModuleModuleChange RedisModuleModuleChangeV1
#define REDISMODULE_CRON_LOOP_VERSION 1
typedef
struct
RedisModuleCronLoopInfo
{
uint64_t
version
;
/* Not used since this structure is never passed
from the module to the core right now. Here
for future compatibility. */
int32_t
hz
;
/* Approximate number of events per second. */
}
RedisModuleCronLoopV1
;
#define RedisModuleCronLoop RedisModuleCronLoopV1
#define REDISMODULE_LOADING_PROGRESS_VERSION 1
typedef
struct
RedisModuleLoadingProgressInfo
{
uint64_t
version
;
/* Not used since this structure is never passed
from the module to the core right now. Here
for future compatibility. */
int32_t
hz
;
/* Approximate number of events per second. */
int32_t
progress
;
/* Approximate progress between 0 and 1024, or -1
* if unknown. */
}
RedisModuleLoadingProgressV1
;
#define RedisModuleLoadingProgress RedisModuleLoadingProgressV1
/* ------------------------- End of common defines ------------------------ */
/* ------------------------- End of common defines ------------------------ */
#ifndef REDISMODULE_CORE
#ifndef REDISMODULE_CORE
...
@@ -319,6 +394,7 @@ typedef struct RedisModuleCommandFilterCtx RedisModuleCommandFilterCtx;
...
@@ -319,6 +394,7 @@ typedef struct RedisModuleCommandFilterCtx RedisModuleCommandFilterCtx;
typedef
struct
RedisModuleCommandFilter
RedisModuleCommandFilter
;
typedef
struct
RedisModuleCommandFilter
RedisModuleCommandFilter
;
typedef
struct
RedisModuleInfoCtx
RedisModuleInfoCtx
;
typedef
struct
RedisModuleInfoCtx
RedisModuleInfoCtx
;
typedef
struct
RedisModuleServerInfoData
RedisModuleServerInfoData
;
typedef
struct
RedisModuleServerInfoData
RedisModuleServerInfoData
;
typedef
struct
RedisModuleScanCursor
RedisModuleScanCursor
;
typedef
int
(
*
RedisModuleCmdFunc
)(
RedisModuleCtx
*
ctx
,
RedisModuleString
**
argv
,
int
argc
);
typedef
int
(
*
RedisModuleCmdFunc
)(
RedisModuleCtx
*
ctx
,
RedisModuleString
**
argv
,
int
argc
);
typedef
void
(
*
RedisModuleDisconnectFunc
)(
RedisModuleCtx
*
ctx
,
RedisModuleBlockedClient
*
bc
);
typedef
void
(
*
RedisModuleDisconnectFunc
)(
RedisModuleCtx
*
ctx
,
RedisModuleBlockedClient
*
bc
);
...
@@ -336,6 +412,8 @@ typedef void (*RedisModuleTimerProc)(RedisModuleCtx *ctx, void *data);
...
@@ -336,6 +412,8 @@ typedef void (*RedisModuleTimerProc)(RedisModuleCtx *ctx, void *data);
typedef
void
(
*
RedisModuleCommandFilterFunc
)
(
RedisModuleCommandFilterCtx
*
filter
);
typedef
void
(
*
RedisModuleCommandFilterFunc
)
(
RedisModuleCommandFilterCtx
*
filter
);
typedef
void
(
*
RedisModuleForkDoneHandler
)
(
int
exitcode
,
int
bysignal
,
void
*
user_data
);
typedef
void
(
*
RedisModuleForkDoneHandler
)
(
int
exitcode
,
int
bysignal
,
void
*
user_data
);
typedef
void
(
*
RedisModuleInfoFunc
)(
RedisModuleInfoCtx
*
ctx
,
int
for_crash_report
);
typedef
void
(
*
RedisModuleInfoFunc
)(
RedisModuleInfoCtx
*
ctx
,
int
for_crash_report
);
typedef
void
(
*
RedisModuleScanCB
)(
RedisModuleCtx
*
ctx
,
RedisModuleString
*
keyname
,
RedisModuleKey
*
key
,
void
*
privdata
);
typedef
void
(
*
RedisModuleScanKeyCB
)(
RedisModuleKey
*
key
,
RedisModuleString
*
field
,
RedisModuleString
*
value
,
void
*
privdata
);
#define REDISMODULE_TYPE_METHOD_VERSION 2
#define REDISMODULE_TYPE_METHOD_VERSION 2
typedef
struct
RedisModuleTypeMethods
{
typedef
struct
RedisModuleTypeMethods
{
...
@@ -385,6 +463,7 @@ size_t REDISMODULE_API_FUNC(RedisModule_CallReplyLength)(RedisModuleCallReply *r
...
@@ -385,6 +463,7 @@ size_t REDISMODULE_API_FUNC(RedisModule_CallReplyLength)(RedisModuleCallReply *r
RedisModuleCallReply
*
REDISMODULE_API_FUNC
(
RedisModule_CallReplyArrayElement
)(
RedisModuleCallReply
*
reply
,
size_t
idx
);
RedisModuleCallReply
*
REDISMODULE_API_FUNC
(
RedisModule_CallReplyArrayElement
)(
RedisModuleCallReply
*
reply
,
size_t
idx
);
RedisModuleString
*
REDISMODULE_API_FUNC
(
RedisModule_CreateString
)(
RedisModuleCtx
*
ctx
,
const
char
*
ptr
,
size_t
len
);
RedisModuleString
*
REDISMODULE_API_FUNC
(
RedisModule_CreateString
)(
RedisModuleCtx
*
ctx
,
const
char
*
ptr
,
size_t
len
);
RedisModuleString
*
REDISMODULE_API_FUNC
(
RedisModule_CreateStringFromLongLong
)(
RedisModuleCtx
*
ctx
,
long
long
ll
);
RedisModuleString
*
REDISMODULE_API_FUNC
(
RedisModule_CreateStringFromLongLong
)(
RedisModuleCtx
*
ctx
,
long
long
ll
);
RedisModuleString
*
REDISMODULE_API_FUNC
(
RedisModule_CreateStringFromLongDouble
)(
RedisModuleCtx
*
ctx
,
long
double
ld
,
int
humanfriendly
);
RedisModuleString
*
REDISMODULE_API_FUNC
(
RedisModule_CreateStringFromString
)(
RedisModuleCtx
*
ctx
,
const
RedisModuleString
*
str
);
RedisModuleString
*
REDISMODULE_API_FUNC
(
RedisModule_CreateStringFromString
)(
RedisModuleCtx
*
ctx
,
const
RedisModuleString
*
str
);
RedisModuleString
*
REDISMODULE_API_FUNC
(
RedisModule_CreateStringPrintf
)(
RedisModuleCtx
*
ctx
,
const
char
*
fmt
,
...);
RedisModuleString
*
REDISMODULE_API_FUNC
(
RedisModule_CreateStringPrintf
)(
RedisModuleCtx
*
ctx
,
const
char
*
fmt
,
...);
void
REDISMODULE_API_FUNC
(
RedisModule_FreeString
)(
RedisModuleCtx
*
ctx
,
RedisModuleString
*
str
);
void
REDISMODULE_API_FUNC
(
RedisModule_FreeString
)(
RedisModuleCtx
*
ctx
,
RedisModuleString
*
str
);
...
@@ -402,9 +481,11 @@ int REDISMODULE_API_FUNC(RedisModule_ReplyWithEmptyString)(RedisModuleCtx *ctx);
...
@@ -402,9 +481,11 @@ int REDISMODULE_API_FUNC(RedisModule_ReplyWithEmptyString)(RedisModuleCtx *ctx);
int
REDISMODULE_API_FUNC
(
RedisModule_ReplyWithVerbatimString
)(
RedisModuleCtx
*
ctx
,
const
char
*
buf
,
size_t
len
);
int
REDISMODULE_API_FUNC
(
RedisModule_ReplyWithVerbatimString
)(
RedisModuleCtx
*
ctx
,
const
char
*
buf
,
size_t
len
);
int
REDISMODULE_API_FUNC
(
RedisModule_ReplyWithNull
)(
RedisModuleCtx
*
ctx
);
int
REDISMODULE_API_FUNC
(
RedisModule_ReplyWithNull
)(
RedisModuleCtx
*
ctx
);
int
REDISMODULE_API_FUNC
(
RedisModule_ReplyWithDouble
)(
RedisModuleCtx
*
ctx
,
double
d
);
int
REDISMODULE_API_FUNC
(
RedisModule_ReplyWithDouble
)(
RedisModuleCtx
*
ctx
,
double
d
);
int
REDISMODULE_API_FUNC
(
RedisModule_ReplyWithLongDouble
)(
RedisModuleCtx
*
ctx
,
long
double
d
);
int
REDISMODULE_API_FUNC
(
RedisModule_ReplyWithCallReply
)(
RedisModuleCtx
*
ctx
,
RedisModuleCallReply
*
reply
);
int
REDISMODULE_API_FUNC
(
RedisModule_ReplyWithCallReply
)(
RedisModuleCtx
*
ctx
,
RedisModuleCallReply
*
reply
);
int
REDISMODULE_API_FUNC
(
RedisModule_StringToLongLong
)(
const
RedisModuleString
*
str
,
long
long
*
ll
);
int
REDISMODULE_API_FUNC
(
RedisModule_StringToLongLong
)(
const
RedisModuleString
*
str
,
long
long
*
ll
);
int
REDISMODULE_API_FUNC
(
RedisModule_StringToDouble
)(
const
RedisModuleString
*
str
,
double
*
d
);
int
REDISMODULE_API_FUNC
(
RedisModule_StringToDouble
)(
const
RedisModuleString
*
str
,
double
*
d
);
int
REDISMODULE_API_FUNC
(
RedisModule_StringToLongDouble
)(
const
RedisModuleString
*
str
,
long
double
*
d
);
void
REDISMODULE_API_FUNC
(
RedisModule_AutoMemory
)(
RedisModuleCtx
*
ctx
);
void
REDISMODULE_API_FUNC
(
RedisModule_AutoMemory
)(
RedisModuleCtx
*
ctx
);
int
REDISMODULE_API_FUNC
(
RedisModule_Replicate
)(
RedisModuleCtx
*
ctx
,
const
char
*
cmdname
,
const
char
*
fmt
,
...);
int
REDISMODULE_API_FUNC
(
RedisModule_Replicate
)(
RedisModuleCtx
*
ctx
,
const
char
*
cmdname
,
const
char
*
fmt
,
...);
int
REDISMODULE_API_FUNC
(
RedisModule_ReplicateVerbatim
)(
RedisModuleCtx
*
ctx
);
int
REDISMODULE_API_FUNC
(
RedisModule_ReplicateVerbatim
)(
RedisModuleCtx
*
ctx
);
...
@@ -417,6 +498,9 @@ char *REDISMODULE_API_FUNC(RedisModule_StringDMA)(RedisModuleKey *key, size_t *l
...
@@ -417,6 +498,9 @@ char *REDISMODULE_API_FUNC(RedisModule_StringDMA)(RedisModuleKey *key, size_t *l
int
REDISMODULE_API_FUNC
(
RedisModule_StringTruncate
)(
RedisModuleKey
*
key
,
size_t
newlen
);
int
REDISMODULE_API_FUNC
(
RedisModule_StringTruncate
)(
RedisModuleKey
*
key
,
size_t
newlen
);
mstime_t
REDISMODULE_API_FUNC
(
RedisModule_GetExpire
)(
RedisModuleKey
*
key
);
mstime_t
REDISMODULE_API_FUNC
(
RedisModule_GetExpire
)(
RedisModuleKey
*
key
);
int
REDISMODULE_API_FUNC
(
RedisModule_SetExpire
)(
RedisModuleKey
*
key
,
mstime_t
expire
);
int
REDISMODULE_API_FUNC
(
RedisModule_SetExpire
)(
RedisModuleKey
*
key
,
mstime_t
expire
);
void
REDISMODULE_API_FUNC
(
RedisModule_ResetDataset
)(
int
restart_aof
,
int
async
);
unsigned
long
long
REDISMODULE_API_FUNC
(
RedisModule_DbSize
)(
RedisModuleCtx
*
ctx
);
RedisModuleString
*
REDISMODULE_API_FUNC
(
RedisModule_RandomKey
)(
RedisModuleCtx
*
ctx
);
int
REDISMODULE_API_FUNC
(
RedisModule_ZsetAdd
)(
RedisModuleKey
*
key
,
double
score
,
RedisModuleString
*
ele
,
int
*
flagsptr
);
int
REDISMODULE_API_FUNC
(
RedisModule_ZsetAdd
)(
RedisModuleKey
*
key
,
double
score
,
RedisModuleString
*
ele
,
int
*
flagsptr
);
int
REDISMODULE_API_FUNC
(
RedisModule_ZsetIncrby
)(
RedisModuleKey
*
key
,
double
score
,
RedisModuleString
*
ele
,
int
*
flagsptr
,
double
*
newscore
);
int
REDISMODULE_API_FUNC
(
RedisModule_ZsetIncrby
)(
RedisModuleKey
*
key
,
double
score
,
RedisModuleString
*
ele
,
int
*
flagsptr
,
double
*
newscore
);
int
REDISMODULE_API_FUNC
(
RedisModule_ZsetScore
)(
RedisModuleKey
*
key
,
RedisModuleString
*
ele
,
double
*
score
);
int
REDISMODULE_API_FUNC
(
RedisModule_ZsetScore
)(
RedisModuleKey
*
key
,
RedisModuleString
*
ele
,
double
*
score
);
...
@@ -436,10 +520,12 @@ int REDISMODULE_API_FUNC(RedisModule_IsKeysPositionRequest)(RedisModuleCtx *ctx)
...
@@ -436,10 +520,12 @@ int REDISMODULE_API_FUNC(RedisModule_IsKeysPositionRequest)(RedisModuleCtx *ctx)
void
REDISMODULE_API_FUNC
(
RedisModule_KeyAtPos
)(
RedisModuleCtx
*
ctx
,
int
pos
);
void
REDISMODULE_API_FUNC
(
RedisModule_KeyAtPos
)(
RedisModuleCtx
*
ctx
,
int
pos
);
unsigned
long
long
REDISMODULE_API_FUNC
(
RedisModule_GetClientId
)(
RedisModuleCtx
*
ctx
);
unsigned
long
long
REDISMODULE_API_FUNC
(
RedisModule_GetClientId
)(
RedisModuleCtx
*
ctx
);
int
REDISMODULE_API_FUNC
(
RedisModule_GetClientInfoById
)(
void
*
ci
,
uint64_t
id
);
int
REDISMODULE_API_FUNC
(
RedisModule_GetClientInfoById
)(
void
*
ci
,
uint64_t
id
);
int
REDISMODULE_API_FUNC
(
RedisModule_PublishMessage
)(
RedisModuleCtx
*
ctx
,
RedisModuleString
*
channel
,
RedisModuleString
*
message
);
int
REDISMODULE_API_FUNC
(
RedisModule_GetContextFlags
)(
RedisModuleCtx
*
ctx
);
int
REDISMODULE_API_FUNC
(
RedisModule_GetContextFlags
)(
RedisModuleCtx
*
ctx
);
void
*
REDISMODULE_API_FUNC
(
RedisModule_PoolAlloc
)(
RedisModuleCtx
*
ctx
,
size_t
bytes
);
void
*
REDISMODULE_API_FUNC
(
RedisModule_PoolAlloc
)(
RedisModuleCtx
*
ctx
,
size_t
bytes
);
RedisModuleType
*
REDISMODULE_API_FUNC
(
RedisModule_CreateDataType
)(
RedisModuleCtx
*
ctx
,
const
char
*
name
,
int
encver
,
RedisModuleTypeMethods
*
typemethods
);
RedisModuleType
*
REDISMODULE_API_FUNC
(
RedisModule_CreateDataType
)(
RedisModuleCtx
*
ctx
,
const
char
*
name
,
int
encver
,
RedisModuleTypeMethods
*
typemethods
);
int
REDISMODULE_API_FUNC
(
RedisModule_ModuleTypeSetValue
)(
RedisModuleKey
*
key
,
RedisModuleType
*
mt
,
void
*
value
);
int
REDISMODULE_API_FUNC
(
RedisModule_ModuleTypeSetValue
)(
RedisModuleKey
*
key
,
RedisModuleType
*
mt
,
void
*
value
);
void
*
REDISMODULE_API_FUNC
(
RedisModule_ModuleTypeReplaceValue
)(
RedisModuleKey
*
key
,
RedisModuleType
*
mt
,
void
*
new_value
);
RedisModuleType
*
REDISMODULE_API_FUNC
(
RedisModule_ModuleTypeGetType
)(
RedisModuleKey
*
key
);
RedisModuleType
*
REDISMODULE_API_FUNC
(
RedisModule_ModuleTypeGetType
)(
RedisModuleKey
*
key
);
void
*
REDISMODULE_API_FUNC
(
RedisModule_ModuleTypeGetValue
)(
RedisModuleKey
*
key
);
void
*
REDISMODULE_API_FUNC
(
RedisModule_ModuleTypeGetValue
)(
RedisModuleKey
*
key
);
int
REDISMODULE_API_FUNC
(
RedisModule_IsIOError
)(
RedisModuleIO
*
io
);
int
REDISMODULE_API_FUNC
(
RedisModule_IsIOError
)(
RedisModuleIO
*
io
);
...
@@ -458,6 +544,10 @@ void REDISMODULE_API_FUNC(RedisModule_SaveDouble)(RedisModuleIO *io, double valu
...
@@ -458,6 +544,10 @@ void REDISMODULE_API_FUNC(RedisModule_SaveDouble)(RedisModuleIO *io, double valu
double
REDISMODULE_API_FUNC
(
RedisModule_LoadDouble
)(
RedisModuleIO
*
io
);
double
REDISMODULE_API_FUNC
(
RedisModule_LoadDouble
)(
RedisModuleIO
*
io
);
void
REDISMODULE_API_FUNC
(
RedisModule_SaveFloat
)(
RedisModuleIO
*
io
,
float
value
);
void
REDISMODULE_API_FUNC
(
RedisModule_SaveFloat
)(
RedisModuleIO
*
io
,
float
value
);
float
REDISMODULE_API_FUNC
(
RedisModule_LoadFloat
)(
RedisModuleIO
*
io
);
float
REDISMODULE_API_FUNC
(
RedisModule_LoadFloat
)(
RedisModuleIO
*
io
);
void
REDISMODULE_API_FUNC
(
RedisModule_SaveLongDouble
)(
RedisModuleIO
*
io
,
long
double
value
);
long
double
REDISMODULE_API_FUNC
(
RedisModule_LoadLongDouble
)(
RedisModuleIO
*
io
);
void
*
REDISMODULE_API_FUNC
(
RedisModule_LoadDataTypeFromString
)(
const
RedisModuleString
*
str
,
const
RedisModuleType
*
mt
);
RedisModuleString
*
REDISMODULE_API_FUNC
(
RedisModule_SaveDataTypeToString
)(
RedisModuleCtx
*
ctx
,
void
*
data
,
const
RedisModuleType
*
mt
);
void
REDISMODULE_API_FUNC
(
RedisModule_Log
)(
RedisModuleCtx
*
ctx
,
const
char
*
level
,
const
char
*
fmt
,
...);
void
REDISMODULE_API_FUNC
(
RedisModule_Log
)(
RedisModuleCtx
*
ctx
,
const
char
*
level
,
const
char
*
fmt
,
...);
void
REDISMODULE_API_FUNC
(
RedisModule_LogIOError
)(
RedisModuleIO
*
io
,
const
char
*
levelstr
,
const
char
*
fmt
,
...);
void
REDISMODULE_API_FUNC
(
RedisModule_LogIOError
)(
RedisModuleIO
*
io
,
const
char
*
levelstr
,
const
char
*
fmt
,
...);
void
REDISMODULE_API_FUNC
(
RedisModule__Assert
)(
const
char
*
estr
,
const
char
*
file
,
int
line
);
void
REDISMODULE_API_FUNC
(
RedisModule__Assert
)(
const
char
*
estr
,
const
char
*
file
,
int
line
);
...
@@ -511,9 +601,18 @@ long long REDISMODULE_API_FUNC(RedisModule_ServerInfoGetFieldSigned)(RedisModule
...
@@ -511,9 +601,18 @@ long long REDISMODULE_API_FUNC(RedisModule_ServerInfoGetFieldSigned)(RedisModule
unsigned
long
long
REDISMODULE_API_FUNC
(
RedisModule_ServerInfoGetFieldUnsigned
)(
RedisModuleServerInfoData
*
data
,
const
char
*
field
,
int
*
out_err
);
unsigned
long
long
REDISMODULE_API_FUNC
(
RedisModule_ServerInfoGetFieldUnsigned
)(
RedisModuleServerInfoData
*
data
,
const
char
*
field
,
int
*
out_err
);
double
REDISMODULE_API_FUNC
(
RedisModule_ServerInfoGetFieldDouble
)(
RedisModuleServerInfoData
*
data
,
const
char
*
field
,
int
*
out_err
);
double
REDISMODULE_API_FUNC
(
RedisModule_ServerInfoGetFieldDouble
)(
RedisModuleServerInfoData
*
data
,
const
char
*
field
,
int
*
out_err
);
int
REDISMODULE_API_FUNC
(
RedisModule_SubscribeToServerEvent
)(
RedisModuleCtx
*
ctx
,
RedisModuleEvent
event
,
RedisModuleEventCallback
callback
);
int
REDISMODULE_API_FUNC
(
RedisModule_SubscribeToServerEvent
)(
RedisModuleCtx
*
ctx
,
RedisModuleEvent
event
,
RedisModuleEventCallback
callback
);
int
REDISMODULE_API_FUNC
(
RedisModule_SetLRU
)(
RedisModuleKey
*
key
,
mstime_t
lru_idle
);
int
REDISMODULE_API_FUNC
(
RedisModule_GetLRU
)(
RedisModuleKey
*
key
,
mstime_t
*
lru_idle
);
int
REDISMODULE_API_FUNC
(
RedisModule_SetLFU
)(
RedisModuleKey
*
key
,
long
long
lfu_freq
);
int
REDISMODULE_API_FUNC
(
RedisModule_GetLFU
)(
RedisModuleKey
*
key
,
long
long
*
lfu_freq
);
RedisModuleBlockedClient
*
REDISMODULE_API_FUNC
(
RedisModule_BlockClientOnKeys
)(
RedisModuleCtx
*
ctx
,
RedisModuleCmdFunc
reply_callback
,
RedisModuleCmdFunc
timeout_callback
,
void
(
*
free_privdata
)(
RedisModuleCtx
*
,
void
*
),
long
long
timeout_ms
,
RedisModuleString
**
keys
,
int
numkeys
,
void
*
privdata
);
RedisModuleBlockedClient
*
REDISMODULE_API_FUNC
(
RedisModule_BlockClientOnKeys
)(
RedisModuleCtx
*
ctx
,
RedisModuleCmdFunc
reply_callback
,
RedisModuleCmdFunc
timeout_callback
,
void
(
*
free_privdata
)(
RedisModuleCtx
*
,
void
*
),
long
long
timeout_ms
,
RedisModuleString
**
keys
,
int
numkeys
,
void
*
privdata
);
void
REDISMODULE_API_FUNC
(
RedisModule_SignalKeyAsReady
)(
RedisModuleCtx
*
ctx
,
RedisModuleString
*
key
);
void
REDISMODULE_API_FUNC
(
RedisModule_SignalKeyAsReady
)(
RedisModuleCtx
*
ctx
,
RedisModuleString
*
key
);
RedisModuleString
*
REDISMODULE_API_FUNC
(
RedisModule_GetBlockedClientReadyKey
)(
RedisModuleCtx
*
ctx
);
RedisModuleString
*
REDISMODULE_API_FUNC
(
RedisModule_GetBlockedClientReadyKey
)(
RedisModuleCtx
*
ctx
);
RedisModuleScanCursor
*
REDISMODULE_API_FUNC
(
RedisModule_ScanCursorCreate
)();
void
REDISMODULE_API_FUNC
(
RedisModule_ScanCursorRestart
)(
RedisModuleScanCursor
*
cursor
);
void
REDISMODULE_API_FUNC
(
RedisModule_ScanCursorDestroy
)(
RedisModuleScanCursor
*
cursor
);
int
REDISMODULE_API_FUNC
(
RedisModule_Scan
)(
RedisModuleCtx
*
ctx
,
RedisModuleScanCursor
*
cursor
,
RedisModuleScanCB
fn
,
void
*
privdata
);
int
REDISMODULE_API_FUNC
(
RedisModule_ScanKey
)(
RedisModuleKey
*
key
,
RedisModuleScanCursor
*
cursor
,
RedisModuleScanKeyCB
fn
,
void
*
privdata
);
/* Experimental APIs */
/* Experimental APIs */
#ifdef REDISMODULE_EXPERIMENTAL_API
#ifdef REDISMODULE_EXPERIMENTAL_API
...
@@ -559,6 +658,8 @@ int REDISMODULE_API_FUNC(RedisModule_CommandFilterArgDelete)(RedisModuleCommandF
...
@@ -559,6 +658,8 @@ int REDISMODULE_API_FUNC(RedisModule_CommandFilterArgDelete)(RedisModuleCommandF
int
REDISMODULE_API_FUNC
(
RedisModule_Fork
)(
RedisModuleForkDoneHandler
cb
,
void
*
user_data
);
int
REDISMODULE_API_FUNC
(
RedisModule_Fork
)(
RedisModuleForkDoneHandler
cb
,
void
*
user_data
);
int
REDISMODULE_API_FUNC
(
RedisModule_ExitFromChild
)(
int
retcode
);
int
REDISMODULE_API_FUNC
(
RedisModule_ExitFromChild
)(
int
retcode
);
int
REDISMODULE_API_FUNC
(
RedisModule_KillForkChild
)(
int
child_pid
);
int
REDISMODULE_API_FUNC
(
RedisModule_KillForkChild
)(
int
child_pid
);
float
REDISMODULE_API_FUNC
(
RedisModule_GetUsedMemoryRatio
)();
size_t
REDISMODULE_API_FUNC
(
RedisModule_MallocSize
)(
void
*
ptr
);
#endif
#endif
#define RedisModule_IsAOFClient(id) ((id) == UINT64_MAX)
#define RedisModule_IsAOFClient(id) ((id) == UINT64_MAX)
...
@@ -592,6 +693,7 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int
...
@@ -592,6 +693,7 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int
REDISMODULE_GET_API
(
ReplyWithNull
);
REDISMODULE_GET_API
(
ReplyWithNull
);
REDISMODULE_GET_API
(
ReplyWithCallReply
);
REDISMODULE_GET_API
(
ReplyWithCallReply
);
REDISMODULE_GET_API
(
ReplyWithDouble
);
REDISMODULE_GET_API
(
ReplyWithDouble
);
REDISMODULE_GET_API
(
ReplyWithLongDouble
);
REDISMODULE_GET_API
(
GetSelectedDb
);
REDISMODULE_GET_API
(
GetSelectedDb
);
REDISMODULE_GET_API
(
SelectDb
);
REDISMODULE_GET_API
(
SelectDb
);
REDISMODULE_GET_API
(
OpenKey
);
REDISMODULE_GET_API
(
OpenKey
);
...
@@ -602,6 +704,7 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int
...
@@ -602,6 +704,7 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int
REDISMODULE_GET_API
(
ListPop
);
REDISMODULE_GET_API
(
ListPop
);
REDISMODULE_GET_API
(
StringToLongLong
);
REDISMODULE_GET_API
(
StringToLongLong
);
REDISMODULE_GET_API
(
StringToDouble
);
REDISMODULE_GET_API
(
StringToDouble
);
REDISMODULE_GET_API
(
StringToLongDouble
);
REDISMODULE_GET_API
(
Call
);
REDISMODULE_GET_API
(
Call
);
REDISMODULE_GET_API
(
CallReplyProto
);
REDISMODULE_GET_API
(
CallReplyProto
);
REDISMODULE_GET_API
(
FreeCallReply
);
REDISMODULE_GET_API
(
FreeCallReply
);
...
@@ -613,6 +716,7 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int
...
@@ -613,6 +716,7 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int
REDISMODULE_GET_API
(
CreateStringFromCallReply
);
REDISMODULE_GET_API
(
CreateStringFromCallReply
);
REDISMODULE_GET_API
(
CreateString
);
REDISMODULE_GET_API
(
CreateString
);
REDISMODULE_GET_API
(
CreateStringFromLongLong
);
REDISMODULE_GET_API
(
CreateStringFromLongLong
);
REDISMODULE_GET_API
(
CreateStringFromLongDouble
);
REDISMODULE_GET_API
(
CreateStringFromString
);
REDISMODULE_GET_API
(
CreateStringFromString
);
REDISMODULE_GET_API
(
CreateStringPrintf
);
REDISMODULE_GET_API
(
CreateStringPrintf
);
REDISMODULE_GET_API
(
FreeString
);
REDISMODULE_GET_API
(
FreeString
);
...
@@ -627,6 +731,9 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int
...
@@ -627,6 +731,9 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int
REDISMODULE_GET_API
(
StringTruncate
);
REDISMODULE_GET_API
(
StringTruncate
);
REDISMODULE_GET_API
(
GetExpire
);
REDISMODULE_GET_API
(
GetExpire
);
REDISMODULE_GET_API
(
SetExpire
);
REDISMODULE_GET_API
(
SetExpire
);
REDISMODULE_GET_API
(
ResetDataset
);
REDISMODULE_GET_API
(
DbSize
);
REDISMODULE_GET_API
(
RandomKey
);
REDISMODULE_GET_API
(
ZsetAdd
);
REDISMODULE_GET_API
(
ZsetAdd
);
REDISMODULE_GET_API
(
ZsetIncrby
);
REDISMODULE_GET_API
(
ZsetIncrby
);
REDISMODULE_GET_API
(
ZsetScore
);
REDISMODULE_GET_API
(
ZsetScore
);
...
@@ -649,6 +756,7 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int
...
@@ -649,6 +756,7 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int
REDISMODULE_GET_API
(
PoolAlloc
);
REDISMODULE_GET_API
(
PoolAlloc
);
REDISMODULE_GET_API
(
CreateDataType
);
REDISMODULE_GET_API
(
CreateDataType
);
REDISMODULE_GET_API
(
ModuleTypeSetValue
);
REDISMODULE_GET_API
(
ModuleTypeSetValue
);
REDISMODULE_GET_API
(
ModuleTypeReplaceValue
);
REDISMODULE_GET_API
(
ModuleTypeGetType
);
REDISMODULE_GET_API
(
ModuleTypeGetType
);
REDISMODULE_GET_API
(
ModuleTypeGetValue
);
REDISMODULE_GET_API
(
ModuleTypeGetValue
);
REDISMODULE_GET_API
(
IsIOError
);
REDISMODULE_GET_API
(
IsIOError
);
...
@@ -666,6 +774,10 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int
...
@@ -666,6 +774,10 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int
REDISMODULE_GET_API
(
LoadDouble
);
REDISMODULE_GET_API
(
LoadDouble
);
REDISMODULE_GET_API
(
SaveFloat
);
REDISMODULE_GET_API
(
SaveFloat
);
REDISMODULE_GET_API
(
LoadFloat
);
REDISMODULE_GET_API
(
LoadFloat
);
REDISMODULE_GET_API
(
SaveLongDouble
);
REDISMODULE_GET_API
(
LoadLongDouble
);
REDISMODULE_GET_API
(
SaveDataTypeToString
);
REDISMODULE_GET_API
(
LoadDataTypeFromString
);
REDISMODULE_GET_API
(
EmitAOF
);
REDISMODULE_GET_API
(
EmitAOF
);
REDISMODULE_GET_API
(
Log
);
REDISMODULE_GET_API
(
Log
);
REDISMODULE_GET_API
(
LogIOError
);
REDISMODULE_GET_API
(
LogIOError
);
...
@@ -720,10 +832,20 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int
...
@@ -720,10 +832,20 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int
REDISMODULE_GET_API
(
ServerInfoGetFieldUnsigned
);
REDISMODULE_GET_API
(
ServerInfoGetFieldUnsigned
);
REDISMODULE_GET_API
(
ServerInfoGetFieldDouble
);
REDISMODULE_GET_API
(
ServerInfoGetFieldDouble
);
REDISMODULE_GET_API
(
GetClientInfoById
);
REDISMODULE_GET_API
(
GetClientInfoById
);
REDISMODULE_GET_API
(
PublishMessage
);
REDISMODULE_GET_API
(
SubscribeToServerEvent
);
REDISMODULE_GET_API
(
SubscribeToServerEvent
);
REDISMODULE_GET_API
(
SetLRU
);
REDISMODULE_GET_API
(
GetLRU
);
REDISMODULE_GET_API
(
SetLFU
);
REDISMODULE_GET_API
(
GetLFU
);
REDISMODULE_GET_API
(
BlockClientOnKeys
);
REDISMODULE_GET_API
(
BlockClientOnKeys
);
REDISMODULE_GET_API
(
SignalKeyAsReady
);
REDISMODULE_GET_API
(
SignalKeyAsReady
);
REDISMODULE_GET_API
(
GetBlockedClientReadyKey
);
REDISMODULE_GET_API
(
GetBlockedClientReadyKey
);
REDISMODULE_GET_API
(
ScanCursorCreate
);
REDISMODULE_GET_API
(
ScanCursorRestart
);
REDISMODULE_GET_API
(
ScanCursorDestroy
);
REDISMODULE_GET_API
(
Scan
);
REDISMODULE_GET_API
(
ScanKey
);
#ifdef REDISMODULE_EXPERIMENTAL_API
#ifdef REDISMODULE_EXPERIMENTAL_API
REDISMODULE_GET_API
(
GetThreadSafeContext
);
REDISMODULE_GET_API
(
GetThreadSafeContext
);
...
@@ -767,6 +889,8 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int
...
@@ -767,6 +889,8 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int
REDISMODULE_GET_API
(
Fork
);
REDISMODULE_GET_API
(
Fork
);
REDISMODULE_GET_API
(
ExitFromChild
);
REDISMODULE_GET_API
(
ExitFromChild
);
REDISMODULE_GET_API
(
KillForkChild
);
REDISMODULE_GET_API
(
KillForkChild
);
REDISMODULE_GET_API
(
GetUsedMemoryRatio
);
REDISMODULE_GET_API
(
MallocSize
);
#endif
#endif
if
(
RedisModule_IsModuleNameBusy
&&
RedisModule_IsModuleNameBusy
(
name
))
return
REDISMODULE_ERR
;
if
(
RedisModule_IsModuleNameBusy
&&
RedisModule_IsModuleNameBusy
(
name
))
return
REDISMODULE_ERR
;
...
...
Prev
1
2
3
Next
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