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
d375595d
Unverified
Commit
d375595d
authored
Apr 27, 2022
by
Oran Agra
Committed by
GitHub
Apr 27, 2022
Browse files
Merge pull request #10652 from oranagra/redis-7.0.0
Redis 7.0.0
parents
fb4e0d40
c1f30206
Changes
124
Expand all
Show whitespace changes
Inline
Side-by-side
src/anet.c
View file @
d375595d
...
...
@@ -49,6 +49,8 @@
#include "anet.h"
#include "config.h"
#define UNUSED(x) (void)(x)
static
void
anetSetError
(
char
*
err
,
const
char
*
fmt
,
...)
{
va_list
ap
;
...
...
@@ -680,3 +682,18 @@ error:
close
(
fds
[
1
]);
return
-
1
;
}
int
anetSetSockMarkId
(
char
*
err
,
int
fd
,
uint32_t
id
)
{
#ifdef HAVE_SOCKOPTMARKID
if
(
setsockopt
(
fd
,
SOL_SOCKET
,
SOCKOPTMARKID
,
(
void
*
)
&
id
,
sizeof
(
id
))
==
-
1
)
{
anetSetError
(
err
,
"setsockopt: %s"
,
strerror
(
errno
));
return
ANET_ERR
;
}
return
ANET_OK
;
#else
UNUSED
(
fd
);
UNUSED
(
id
);
anetSetError
(
err
,
"anetSetSockMarkid unsupported on this platform"
);
return
ANET_OK
;
#endif
}
src/anet.h
View file @
d375595d
...
...
@@ -73,5 +73,6 @@ int anetKeepAlive(char *err, int fd, int interval);
int
anetFormatAddr
(
char
*
fmt
,
size_t
fmt_len
,
char
*
ip
,
int
port
);
int
anetFormatFdAddr
(
int
fd
,
char
*
buf
,
size_t
buf_len
,
int
fd_to_str_type
);
int
anetPipe
(
int
fds
[
2
],
int
read_flags
,
int
write_flags
);
int
anetSetSockMarkId
(
char
*
err
,
int
fd
,
uint32_t
id
);
#endif
src/aof.c
View file @
d375595d
...
...
@@ -87,7 +87,7 @@ void aofManifestFreeAndUpdate(aofManifest *am);
#define RDB_FORMAT_SUFFIX ".rdb"
#define AOF_FORMAT_SUFFIX ".aof"
#define MANIFEST_NAME_SUFFIX ".manifest"
#define
MANIFEST_TEMP
_NAME_PREFIX "temp
_
"
#define
TEMP_FILE
_NAME_PREFIX
"temp
-
"
/* AOF manifest key. */
#define AOF_MANIFEST_KEY_FILE_NAME "file"
...
...
@@ -169,7 +169,7 @@ sds getAofManifestFileName() {
}
sds
getTempAofManifestFileName
()
{
return
sdscatprintf
(
sdsempty
(),
"%s%s%s"
,
MANIFEST_TEMP
_NAME_PREFIX
,
return
sdscatprintf
(
sdsempty
(),
"%s%s%s"
,
TEMP_FILE
_NAME_PREFIX
,
server
.
aof_filename
,
MANIFEST_NAME_SUFFIX
);
}
...
...
@@ -462,6 +462,12 @@ sds getNewIncrAofName(aofManifest *am) {
return
ai
->
file_name
;
}
/* Get temp INCR type AOF name. */
sds
getTempIncrAofName
()
{
return
sdscatprintf
(
sdsempty
(),
"%s%s%s"
,
TEMP_FILE_NAME_PREFIX
,
server
.
aof_filename
,
INCR_FILE_SUFFIX
);
}
/* Get the last INCR AOF name or create a new one. */
sds
getLastIncrAofName
(
aofManifest
*
am
)
{
serverAssert
(
am
!=
NULL
);
...
...
@@ -674,6 +680,17 @@ int aofDelHistoryFiles(void) {
return
persistAofManifest
(
server
.
aof_manifest
);
}
/* Used to clean up temp INCR AOF when AOFRW fails. */
void
aofDelTempIncrAofFile
()
{
sds
aof_filename
=
getTempIncrAofName
();
sds
aof_filepath
=
makePath
(
server
.
aof_dirname
,
aof_filename
);
serverLog
(
LL_NOTICE
,
"Removing the temp incr aof file %s in the background"
,
aof_filename
);
bg_unlink
(
aof_filepath
);
sdsfree
(
aof_filepath
);
sdsfree
(
aof_filename
);
return
;
}
/* Called after `loadDataFromDisk` when redis start. If `server.aof_state` is
* 'AOF_ON', It will do three things:
* 1. Force create a BASE file when redis starts with an empty dataset
...
...
@@ -739,44 +756,52 @@ int aofFileExist(char *filename) {
}
/* Called in `rewriteAppendOnlyFileBackground`. If `server.aof_state`
* is 'AOF_ON'
or 'AOF_WAIT_REWRITE'
, It will do two things:
* is 'AOF_ON', It will do two things:
* 1. Open a new INCR type AOF for writing
* 2. Synchronously update the manifest file to the disk
*
* The above two steps of modification are atomic, that is, if
* any step fails, the entire operation will rollback and returns
* C_ERR, and if all succeeds, it returns C_OK.
*
* If `server.aof_state` is 'AOF_WAIT_REWRITE', It will open a temporary INCR AOF
* file to accumulate data during AOF_WAIT_REWRITE, and it will eventually be
* renamed in the `backgroundRewriteDoneHandler` and written to the manifest file.
* */
int
openNewIncrAofForAppend
(
void
)
{
serverAssert
(
server
.
aof_manifest
!=
NULL
);
int
newfd
;
int
newfd
=
-
1
;
aofManifest
*
temp_am
=
NULL
;
sds
new_aof_name
=
NULL
;
/* Only open new INCR AOF when AOF enabled. */
if
(
server
.
aof_state
==
AOF_OFF
)
return
C_OK
;
/* Dup a temp aof_manifest to modify. */
aofManifest
*
temp_am
=
aofManifestDup
(
server
.
aof_manifest
);
/* Open new AOF. */
sds
new_aof_name
=
getNewIncrAofName
(
temp_am
);
if
(
server
.
aof_state
==
AOF_WAIT_REWRITE
)
{
/* Use a temporary INCR AOF file to accumulate data during AOF_WAIT_REWRITE. */
new_aof_name
=
getTempIncrAofName
();
}
else
{
/* Dup a temp aof_manifest to modify. */
temp_am
=
aofManifestDup
(
server
.
aof_manifest
);
new_aof_name
=
sdsdup
(
getNewIncrAofName
(
temp_am
));
}
sds
new_aof_filepath
=
makePath
(
server
.
aof_dirname
,
new_aof_name
);
newfd
=
open
(
new_aof_filepath
,
O_WRONLY
|
O_TRUNC
|
O_CREAT
,
0644
);
sdsfree
(
new_aof_filepath
);
if
(
newfd
==
-
1
)
{
serverLog
(
LL_WARNING
,
"Can't open the append-only file %s: %s"
,
new_aof_name
,
strerror
(
errno
));
aofManifestFree
(
temp_am
);
return
C_ERR
;
goto
cleanup
;
}
if
(
temp_am
)
{
/* Persist AOF Manifest. */
int
ret
=
persistAofManifest
(
temp_am
);
if
(
ret
==
C_ERR
)
{
close
(
newfd
);
aofManifestFree
(
temp_am
);
return
C_ERR
;
if
(
persistAofManifest
(
temp_am
)
==
C_ERR
)
{
goto
cleanup
;
}
}
sdsfree
(
new_aof_name
);
/* If reaches here, we can safely modify the `server.aof_manifest`
* and `server.aof_fd`. */
...
...
@@ -788,8 +813,14 @@ int openNewIncrAofForAppend(void) {
/* Reset the aof_last_incr_size. */
server
.
aof_last_incr_size
=
0
;
/* Update `server.aof_manifest`. */
aofManifestFreeAndUpdate
(
temp_am
);
if
(
temp_am
)
aofManifestFreeAndUpdate
(
temp_am
);
return
C_OK
;
cleanup:
if
(
new_aof_name
)
sdsfree
(
new_aof_name
);
if
(
newfd
!=
-
1
)
close
(
newfd
);
if
(
temp_am
)
aofManifestFree
(
temp_am
);
return
C_ERR
;
}
/* Whether to limit the execution of Background AOF rewrite.
...
...
@@ -815,38 +846,35 @@ int openNewIncrAofForAppend(void) {
#define AOF_REWRITE_LIMITE_THRESHOLD 3
#define AOF_REWRITE_LIMITE_MAX_MINUTES 60
/* 1 hour */
int
aofRewriteLimited
(
void
)
{
int
limit
=
0
;
static
int
limit_delay_minutes
=
0
;
static
int
next_delay_minutes
=
0
;
static
time_t
next_rewrite_time
=
0
;
unsigned
long
incr_aof_num
=
listLength
(
server
.
aof_manifest
->
incr_aof_list
);
if
(
incr_aof_num
>=
AOF_REWRITE_LIMITE_THRESHOLD
)
{
if
(
server
.
stat_aofrw_consecutive_failures
<
AOF_REWRITE_LIMITE_THRESHOLD
)
{
/* We may be recovering from limited state, so reset all states. */
next_delay_minutes
=
0
;
next_rewrite_time
=
0
;
return
0
;
}
/* if it is in the limiting state, then check if the next_rewrite_time is reached */
if
(
next_rewrite_time
!=
0
)
{
if
(
server
.
unixtime
<
next_rewrite_time
)
{
limit
=
1
;
}
else
{
if
(
limit_delay_minutes
==
0
)
{
limit
=
1
;
limit_delay_minutes
=
1
;
return
1
;
}
else
{
limit_delay_minutes
*=
2
;
next_rewrite_time
=
0
;
return
0
;
}
if
(
limit_delay_minutes
>
AOF_REWRITE_LIMITE_MAX_MINUTES
)
{
limit_delay_minutes
=
AOF_REWRITE_LIMITE_MAX_MINUTES
;
}
next_rewrite_time
=
server
.
unixtime
+
limit_delay_minutes
*
60
;
serverLog
(
LL_WARNING
,
"Background AOF rewrite has repeatedly failed %ld times and triggered the limit, will retry in %d minutes"
,
incr_aof_num
,
limit_delay_minutes
);
}
}
else
{
limit_delay_minutes
=
0
;
next_rewrite_time
=
0
;
next_delay_minutes
=
(
next_delay_minutes
==
0
)
?
1
:
(
next_delay_minutes
*
2
);
if
(
next_delay_minutes
>
AOF_REWRITE_LIMITE_MAX_MINUTES
)
{
next_delay_minutes
=
AOF_REWRITE_LIMITE_MAX_MINUTES
;
}
return
limit
;
next_rewrite_time
=
server
.
unixtime
+
next_delay_minutes
*
60
;
serverLog
(
LL_WARNING
,
"Background AOF rewrite has repeatedly failed and triggered the limit, will retry in %d minutes"
,
next_delay_minutes
);
return
1
;
}
/* ----------------------------------------------------------------------------
...
...
@@ -1265,7 +1293,7 @@ void feedAppendOnlyFile(int dictid, robj **argv, int argc) {
* of re-entering the event loop, so before the client will get a
* positive reply about the operation performed. */
if
(
server
.
aof_state
==
AOF_ON
||
server
.
child_type
==
CHILD_TYPE_AOF
)
(
server
.
aof_state
==
AOF_WAIT_REWRITE
&&
server
.
child_type
==
CHILD_TYPE_AOF
)
)
{
server
.
aof_buf
=
sdscatlen
(
server
.
aof_buf
,
buf
,
sdslen
(
buf
));
}
...
...
@@ -1558,7 +1586,7 @@ int loadAppendOnlyFiles(aofManifest *am) {
serverAssert
(
am
!=
NULL
);
int
status
,
ret
=
C_OK
;
long
long
start
;
off_t
total_size
=
0
;
off_t
total_size
=
0
,
base_size
=
0
;
sds
aof_name
;
int
total_num
,
aof_num
=
0
,
last_file
;
...
...
@@ -1607,6 +1635,7 @@ int loadAppendOnlyFiles(aofManifest *am) {
serverAssert
(
am
->
base_aof_info
->
file_type
==
AOF_FILE_TYPE_BASE
);
aof_name
=
(
char
*
)
am
->
base_aof_info
->
file_name
;
updateLoadingFileName
(
aof_name
);
base_size
=
getAppendOnlyFileSize
(
aof_name
,
NULL
);
last_file
=
++
aof_num
==
total_num
;
start
=
ustime
();
ret
=
loadSingleAppendOnlyFile
(
aof_name
);
...
...
@@ -1659,7 +1688,16 @@ int loadAppendOnlyFiles(aofManifest *am) {
}
server
.
aof_current_size
=
total_size
;
server
.
aof_rewrite_base_size
=
server
.
aof_current_size
;
/* Ideally, the aof_rewrite_base_size variable should hold the size of the
* AOF when the last rewrite ended, this should include the size of the
* incremental file that was created during the rewrite since otherwise we
* risk the next automatic rewrite to happen too soon (or immediately if
* auto-aof-rewrite-percentage is low). However, since we do not persist
* aof_rewrite_base_size information anywhere, we initialize it on restart
* to the size of BASE AOF file. This might cause the first AOFRW to be
* executed early, but that shouldn't be a problem since everything will be
* fine after the first AOFRW. */
server
.
aof_rewrite_base_size
=
base_size
;
server
.
aof_fsync_offset
=
server
.
aof_current_size
;
cleanup:
...
...
@@ -2393,6 +2431,9 @@ void bgrewriteaofCommand(client *c) {
addReplyError
(
c
,
"Background append only file rewriting already in progress"
);
}
else
if
(
hasActiveChildProcess
()
||
server
.
in_exec
)
{
server
.
aof_rewrite_scheduled
=
1
;
/* When manually triggering AOFRW we reset the count
* so that it can be executed immediately. */
server
.
stat_aofrw_consecutive_failures
=
0
;
addReplyStatus
(
c
,
"Background append only file rewriting scheduled"
);
}
else
if
(
rewriteAppendOnlyFileBackground
()
==
C_OK
)
{
addReplyStatus
(
c
,
"Background append only file rewriting started"
);
...
...
@@ -2476,7 +2517,8 @@ void backgroundRewriteDoneHandler(int exitcode, int bysignal) {
if
(
!
bysignal
&&
exitcode
==
0
)
{
char
tmpfile
[
256
];
long
long
now
=
ustime
();
sds
new_base_filename
;
sds
new_base_filepath
=
NULL
;
sds
new_incr_filepath
=
NULL
;
aofManifest
*
temp_am
;
mstime_t
latency
;
...
...
@@ -2493,9 +2535,9 @@ void backgroundRewriteDoneHandler(int exitcode, int bysignal) {
/* Get a new BASE file name and mark the previous (if we have)
* as the HISTORY type. */
new_base_filename
=
getNewBaseFileNameAndMarkPreAsHistory
(
temp_am
);
sds
new_base_filename
=
getNewBaseFileNameAndMarkPreAsHistory
(
temp_am
);
serverAssert
(
new_base_filename
!=
NULL
);
sds
new_base_filepath
=
makePath
(
server
.
aof_dirname
,
new_base_filename
);
new_base_filepath
=
makePath
(
server
.
aof_dirname
,
new_base_filename
);
/* Rename the temporary aof file to 'new_base_filename'. */
latencyStartMonitor
(
latency
);
...
...
@@ -2503,7 +2545,7 @@ void backgroundRewriteDoneHandler(int exitcode, int bysignal) {
serverLog
(
LL_WARNING
,
"Error trying to rename the temporary AOF file %s into %s: %s"
,
tmpfile
,
new_base_file
name
,
new_base_file
path
,
strerror
(
errno
));
aofManifestFree
(
temp_am
);
sdsfree
(
new_base_filepath
);
...
...
@@ -2512,6 +2554,34 @@ void backgroundRewriteDoneHandler(int exitcode, int bysignal) {
latencyEndMonitor
(
latency
);
latencyAddSampleIfNeeded
(
"aof-rename"
,
latency
);
/* Rename the temporary incr aof file to 'new_incr_filename'. */
if
(
server
.
aof_state
==
AOF_WAIT_REWRITE
)
{
/* Get temporary incr aof name. */
sds
temp_incr_aof_name
=
getTempIncrAofName
();
sds
temp_incr_filepath
=
makePath
(
server
.
aof_dirname
,
temp_incr_aof_name
);
sdsfree
(
temp_incr_aof_name
);
/* Get next new incr aof name. */
sds
new_incr_filename
=
getNewIncrAofName
(
temp_am
);
new_incr_filepath
=
makePath
(
server
.
aof_dirname
,
new_incr_filename
);
latencyStartMonitor
(
latency
);
if
(
rename
(
temp_incr_filepath
,
new_incr_filepath
)
==
-
1
)
{
serverLog
(
LL_WARNING
,
"Error trying to rename the temporary incr AOF file %s into %s: %s"
,
temp_incr_filepath
,
new_incr_filepath
,
strerror
(
errno
));
bg_unlink
(
new_base_filepath
);
sdsfree
(
new_base_filepath
);
aofManifestFree
(
temp_am
);
sdsfree
(
temp_incr_filepath
);
sdsfree
(
new_incr_filepath
);
goto
cleanup
;
}
latencyEndMonitor
(
latency
);
latencyAddSampleIfNeeded
(
"aof-rename"
,
latency
);
sdsfree
(
temp_incr_filepath
);
}
/* Change the AOF file type in 'incr_aof_list' from AOF_FILE_TYPE_INCR
* to AOF_FILE_TYPE_HIST, and move them to the 'history_aof_list'. */
markRewrittenIncrAofAsHistory
(
temp_am
);
...
...
@@ -2521,9 +2591,14 @@ void backgroundRewriteDoneHandler(int exitcode, int bysignal) {
bg_unlink
(
new_base_filepath
);
aofManifestFree
(
temp_am
);
sdsfree
(
new_base_filepath
);
if
(
new_incr_filepath
)
{
bg_unlink
(
new_incr_filepath
);
sdsfree
(
new_incr_filepath
);
}
goto
cleanup
;
}
sdsfree
(
new_base_filepath
);
if
(
new_incr_filepath
)
sdsfree
(
new_incr_filepath
);
/* We can safely let `server.aof_manifest` point to 'temp_am' and free the previous one. */
aofManifestFreeAndUpdate
(
temp_am
);
...
...
@@ -2542,6 +2617,7 @@ void backgroundRewriteDoneHandler(int exitcode, int bysignal) {
aofDelHistoryFiles
();
server
.
aof_lastbgrewrite_status
=
C_OK
;
server
.
stat_aofrw_consecutive_failures
=
0
;
serverLog
(
LL_NOTICE
,
"Background AOF rewrite finished successfully"
);
/* Change state from WAIT_REWRITE to ON if needed */
...
...
@@ -2552,14 +2628,17 @@ void backgroundRewriteDoneHandler(int exitcode, int bysignal) {
"Background AOF rewrite signal handler took %lldus"
,
ustime
()
-
now
);
}
else
if
(
!
bysignal
&&
exitcode
!=
0
)
{
server
.
aof_lastbgrewrite_status
=
C_ERR
;
server
.
stat_aofrw_consecutive_failures
++
;
serverLog
(
LL_WARNING
,
"Background AOF rewrite terminated with error"
);
}
else
{
/* SIGUSR1 is whitelisted, so we have a way to kill a child without
* triggering an error condition. */
if
(
bysignal
!=
SIGUSR1
)
if
(
bysignal
!=
SIGUSR1
)
{
server
.
aof_lastbgrewrite_status
=
C_ERR
;
server
.
stat_aofrw_consecutive_failures
++
;
}
serverLog
(
LL_WARNING
,
"Background AOF rewrite terminated by signal %d"
,
bysignal
);
...
...
@@ -2567,6 +2646,12 @@ void backgroundRewriteDoneHandler(int exitcode, int bysignal) {
cleanup:
aofRemoveTempFile
(
server
.
child_pid
);
/* Clear AOF buffer and delete temp incr aof for next rewrite. */
if
(
server
.
aof_state
==
AOF_WAIT_REWRITE
)
{
sdsfree
(
server
.
aof_buf
);
server
.
aof_buf
=
sdsempty
();
aofDelTempIncrAofFile
();
}
server
.
aof_rewrite_time_last
=
time
(
NULL
)
-
server
.
aof_rewrite_time_start
;
server
.
aof_rewrite_time_start
=
-
1
;
/* Schedule a new rewrite if we are waiting for it to switch the AOF ON. */
...
...
src/bitops.c
View file @
d375595d
...
...
@@ -430,7 +430,7 @@ int getBitOffsetFromArgument(client *c, robj *o, uint64_t *offset, int hash, int
if
(
usehash
)
loffset
*=
bits
;
/* Limit offset to server.proto_max_bulk_len (512MB in bytes by default) */
if
(
loffset
<
0
||
(
!
(
c
->
flags
&
CLIENT_MASTER
)
&&
(
loffset
>>
3
)
>=
server
.
proto_max_bulk_len
))
if
(
loffset
<
0
||
(
!
mustObeyClient
(
c
)
&&
(
loffset
>>
3
)
>=
server
.
proto_max_bulk_len
))
{
addReplyError
(
c
,
err
);
return
C_ERR
;
...
...
@@ -1002,7 +1002,7 @@ void bitposCommand(client *c) {
}
}
/* BITFIELD key subcomm
m
and-1 arg ... subcommand-2 arg ... subcommand-N ...
/* BITFIELD key subcommand-1 arg ... subcommand-2 arg ... subcommand-N ...
*
* Supported subcommands:
*
...
...
src/cli_common.c
View file @
d375595d
...
...
@@ -390,7 +390,7 @@ sds escapeJsonString(sds s, const char *p, size_t len) {
case
'\t'
:
s
=
sdscatlen
(
s
,
"
\\
t"
,
2
);
break
;
case
'\b'
:
s
=
sdscatlen
(
s
,
"
\\
b"
,
2
);
break
;
default:
s
=
sdscatprintf
(
s
,
(
*
p
>=
0
&&
*
p
<=
0x1f
)
?
"
\\
u%04x"
:
"%c"
,
*
p
);
s
=
sdscatprintf
(
s
,
*
(
unsigned
char
*
)
p
<=
0x1f
?
"
\\
u%04x"
:
"%c"
,
*
p
);
}
p
++
;
}
...
...
src/cluster.c
View file @
d375595d
...
...
@@ -960,7 +960,6 @@ clusterNode *createClusterNode(char *nodename, int flags) {
memset
(
node
->
slots
,
0
,
sizeof
(
node
->
slots
));
node
->
slot_info_pairs
=
NULL
;
node
->
slot_info_pairs_count
=
0
;
node
->
slot_info_pairs_alloc
=
0
;
node
->
numslots
=
0
;
node
->
numslaves
=
0
;
node
->
slaves
=
NULL
;
...
...
@@ -2507,11 +2506,7 @@ int clusterProcessPacket(clusterLink *link) {
message
=
createStringObject
(
(
char
*
)
hdr
->
data
.
publish
.
msg
.
bulk_data
+
channel_len
,
message_len
);
if
(
type
==
CLUSTERMSG_TYPE_PUBLISHSHARD
)
{
pubsubPublishMessageShard
(
channel
,
message
);
}
else
{
pubsubPublishMessage
(
channel
,
message
);
}
pubsubPublishMessage
(
channel
,
message
,
type
==
CLUSTERMSG_TYPE_PUBLISHSHARD
);
decrRefCount
(
channel
);
decrRefCount
(
message
);
}
...
...
@@ -3200,20 +3195,19 @@ int clusterSendModuleMessageToTarget(const char *target, uint64_t module_id, uin
/* -----------------------------------------------------------------------------
* CLUSTER Pub/Sub support
*
* For now we do very little, just propagating PUBLISH messages across the whole
* If `sharded` is 0:
* For now we do very little, just propagating [S]PUBLISH messages across the whole
* cluster. In the future we'll try to get smarter and avoiding propagating those
* messages to hosts without receives for a given channel.
* Otherwise:
* Publish this message across the slot (primary/replica).
* -------------------------------------------------------------------------- */
void
clusterPropagatePublish
(
robj
*
channel
,
robj
*
message
)
{
void
clusterPropagatePublish
(
robj
*
channel
,
robj
*
message
,
int
sharded
)
{
if
(
!
sharded
)
{
clusterSendPublish
(
NULL
,
channel
,
message
,
CLUSTERMSG_TYPE_PUBLISH
);
}
return
;
}
/* -----------------------------------------------------------------------------
* CLUSTER Pub/Sub shard support
*
* Publish this message across the slot (primary/replica).
* -------------------------------------------------------------------------- */
void
clusterPropagatePublishShard
(
robj
*
channel
,
robj
*
message
)
{
list
*
nodes_for_slot
=
clusterGetNodesServingMySlots
(
server
.
cluster
->
myself
);
if
(
listLength
(
nodes_for_slot
)
!=
0
)
{
listIter
li
;
...
...
@@ -4726,13 +4720,10 @@ void clusterGenNodesSlotsInfo(int filter) {
* or end of slot. */
if
(
i
==
CLUSTER_SLOTS
||
n
!=
server
.
cluster
->
slots
[
i
])
{
if
(
!
(
n
->
flags
&
filter
))
{
if
(
n
->
slot_info_pairs_count
+
2
>
n
->
slot_info_pairs_alloc
)
{
if
(
n
->
slot_info_pairs_alloc
==
0
)
n
->
slot_info_pairs_alloc
=
8
;
else
n
->
slot_info_pairs_alloc
*=
2
;
n
->
slot_info_pairs
=
zrealloc
(
n
->
slot_info_pairs
,
n
->
slot_info_pairs_alloc
*
sizeof
(
uint16_t
));
if
(
!
n
->
slot_info_pairs
)
{
n
->
slot_info_pairs
=
zmalloc
(
2
*
n
->
numslots
*
sizeof
(
uint16_t
));
}
serverAssert
((
n
->
slot_info_pairs_count
+
1
)
<
(
2
*
n
->
numslots
));
n
->
slot_info_pairs
[
n
->
slot_info_pairs_count
++
]
=
start
;
n
->
slot_info_pairs
[
n
->
slot_info_pairs_count
++
]
=
i
-
1
;
}
...
...
@@ -4747,7 +4738,6 @@ void clusterFreeNodesSlotsInfo(clusterNode *n) {
zfree
(
n
->
slot_info_pairs
);
n
->
slot_info_pairs
=
NULL
;
n
->
slot_info_pairs_count
=
0
;
n
->
slot_info_pairs_alloc
=
0
;
}
/* Generate a csv-alike representation of the nodes we are aware of,
...
...
src/cluster.h
View file @
d375595d
...
...
@@ -120,7 +120,6 @@ typedef struct clusterNode {
unsigned
char
slots
[
CLUSTER_SLOTS
/
8
];
/* slots handled by this node */
uint16_t
*
slot_info_pairs
;
/* Slots info represented as (start/end) pair (consecutive index). */
int
slot_info_pairs_count
;
/* Used number of slots in slot_info_pairs */
int
slot_info_pairs_alloc
;
/* Allocated number of slots in slot_info_pairs */
int
numslots
;
/* Number of slots handled by this node */
int
numslaves
;
/* Number of slave nodes, if this is a master */
struct
clusterNode
**
slaves
;
/* pointers to slave nodes */
...
...
@@ -385,8 +384,7 @@ void migrateCloseTimedoutSockets(void);
int
verifyClusterConfigWithData
(
void
);
unsigned
long
getClusterConnectionsCount
(
void
);
int
clusterSendModuleMessageToTarget
(
const
char
*
target
,
uint64_t
module_id
,
uint8_t
type
,
const
char
*
payload
,
uint32_t
len
);
void
clusterPropagatePublish
(
robj
*
channel
,
robj
*
message
);
void
clusterPropagatePublishShard
(
robj
*
channel
,
robj
*
message
);
void
clusterPropagatePublish
(
robj
*
channel
,
robj
*
message
,
int
sharded
);
unsigned
int
keyHashSlot
(
char
*
key
,
int
keylen
);
void
slotToKeyAddEntry
(
dictEntry
*
entry
,
redisDb
*
db
);
void
slotToKeyDelEntry
(
dictEntry
*
entry
,
redisDb
*
db
);
...
...
src/commands.c
View file @
d375595d
This diff is collapsed.
Click to expand it.
src/commands/bitfield.json
View file @
d375595d
...
...
@@ -43,11 +43,15 @@
"type"
:
"key"
,
"key_spec_index"
:
0
},
{
"name"
:
"operation"
,
"type"
:
"oneof"
,
"multiple"
:
"true"
,
"arguments"
:
[
{
"token"
:
"GET"
,
"name"
:
"encoding_offset"
,
"type"
:
"block"
,
"optional"
:
true
,
"arguments"
:
[
{
"name"
:
"encoding"
,
...
...
@@ -59,11 +63,41 @@
}
]
},
{
"name"
:
"write"
,
"type"
:
"block"
,
"arguments"
:
[
{
"token"
:
"OVERFLOW"
,
"name"
:
"wrap_sat_fail"
,
"type"
:
"oneof"
,
"optional"
:
true
,
"arguments"
:
[
{
"name"
:
"wrap"
,
"type"
:
"pure-token"
,
"token"
:
"WRAP"
},
{
"name"
:
"sat"
,
"type"
:
"pure-token"
,
"token"
:
"SAT"
},
{
"name"
:
"fail"
,
"type"
:
"pure-token"
,
"token"
:
"FAIL"
}
]
},
{
"name"
:
"write_operation"
,
"type"
:
"oneof"
,
"arguments"
:
[
{
"token"
:
"SET"
,
"name"
:
"encoding_offset_value"
,
"type"
:
"block"
,
"optional"
:
true
,
"arguments"
:
[
{
"name"
:
"encoding"
,
...
...
@@ -83,7 +117,6 @@
"token"
:
"INCRBY"
,
"name"
:
"encoding_offset_increment"
,
"type"
:
"block"
,
"optional"
:
true
,
"arguments"
:
[
{
"name"
:
"encoding"
,
...
...
@@ -98,27 +131,10 @@
"type"
:
"integer"
}
]
},
{
"token"
:
"OVERFLOW"
,
"name"
:
"wrap_sat_fail"
,
"type"
:
"oneof"
,
"optional"
:
true
,
"arguments"
:
[
{
"name"
:
"wrap"
,
"type"
:
"pure-token"
,
"token"
:
"WRAP"
},
{
"name"
:
"sat"
,
"type"
:
"pure-token"
,
"token"
:
"SAT"
},
{
"name"
:
"fail"
,
"type"
:
"pure-token"
,
"token"
:
"FAIL"
}
]
}
]
}
]
}
...
...
src/commands/bitfield_ro.json
View file @
d375595d
...
...
@@ -43,6 +43,7 @@
"token"
:
"GET"
,
"name"
:
"encoding_offset"
,
"type"
:
"block"
,
"multiple"
:
"true"
,
"arguments"
:
[
{
"name"
:
"encoding"
,
...
...
src/commands/geosearch.json
View file @
d375595d
...
...
@@ -38,17 +38,19 @@
"type"
:
"key"
,
"key_spec_index"
:
0
},
{
"name"
:
"from"
,
"type"
:
"oneof"
,
"arguments"
:
[
{
"token"
:
"FROMMEMBER"
,
"name"
:
"member"
,
"type"
:
"string"
,
"optional"
:
true
"type"
:
"string"
},
{
"token"
:
"FROMLONLAT"
,
"name"
:
"longitude_latitude"
,
"type"
:
"block"
,
"optional"
:
true
,
"arguments"
:
[
{
"name"
:
"longitude"
,
...
...
@@ -59,11 +61,16 @@
"type"
:
"double"
}
]
}
]
},
{
"name"
:
"by"
,
"type"
:
"oneof"
,
"arguments"
:
[
{
"name"
:
"circle"
,
"type"
:
"block"
,
"optional"
:
true
,
"arguments"
:
[
{
"token"
:
"BYRADIUS"
,
...
...
@@ -101,7 +108,6 @@
{
"name"
:
"box"
,
"type"
:
"block"
,
"optional"
:
true
,
"arguments"
:
[
{
"token"
:
"BYBOX"
,
...
...
@@ -139,6 +145,8 @@
]
}
]
}
]
},
{
"name"
:
"order"
,
...
...
src/commands/geosearchstore.json
View file @
d375595d
...
...
@@ -62,17 +62,19 @@
"type"
:
"key"
,
"key_spec_index"
:
1
},
{
"name"
:
"from"
,
"type"
:
"oneof"
,
"arguments"
:
[
{
"token"
:
"FROMMEMBER"
,
"name"
:
"member"
,
"type"
:
"string"
,
"optional"
:
true
"type"
:
"string"
},
{
"token"
:
"FROMLONLAT"
,
"name"
:
"longitude_latitude"
,
"type"
:
"block"
,
"optional"
:
true
,
"arguments"
:
[
{
"name"
:
"longitude"
,
...
...
@@ -83,11 +85,16 @@
"type"
:
"double"
}
]
}
]
},
{
"name"
:
"by"
,
"type"
:
"oneof"
,
"arguments"
:
[
{
"name"
:
"circle"
,
"type"
:
"block"
,
"optional"
:
true
,
"arguments"
:
[
{
"token"
:
"BYRADIUS"
,
...
...
@@ -125,7 +132,6 @@
{
"name"
:
"box"
,
"type"
:
"block"
,
"optional"
:
true
,
"arguments"
:
[
{
"token"
:
"BYBOX"
,
...
...
@@ -163,6 +169,8 @@
]
}
]
}
]
},
{
"name"
:
"order"
,
...
...
src/commands/migrate.json
View file @
d375595d
...
...
@@ -124,13 +124,17 @@
"optional"
:
true
,
"since"
:
"3.0.0"
},
{
"name"
:
"authentication"
,
"type"
:
"oneof"
,
"optional"
:
true
,
"arguments"
:
[
{
"token"
:
"AUTH"
,
"name"
:
"password"
,
"type"
:
"string"
,
"optional"
:
true
,
"since"
:
"4.0.7"
},
{
"token"
:
"AUTH2"
,
...
...
@@ -148,6 +152,8 @@
"type"
:
"string"
}
]
}
]
},
{
"token"
:
"KEYS"
,
...
...
src/commands/module-loadex.json
View file @
d375595d
...
...
@@ -23,6 +23,7 @@
"token"
:
"CONFIG"
,
"type"
:
"block"
,
"multiple"
:
true
,
"multiple_token"
:
true
,
"optional"
:
true
,
"arguments"
:
[
{
...
...
src/commands/set.json
View file @
d375595d
...
...
@@ -65,6 +65,31 @@
"name"
:
"value"
,
"type"
:
"string"
},
{
"name"
:
"condition"
,
"type"
:
"oneof"
,
"optional"
:
true
,
"since"
:
"2.6.12"
,
"arguments"
:
[
{
"name"
:
"nx"
,
"type"
:
"pure-token"
,
"token"
:
"NX"
},
{
"name"
:
"xx"
,
"type"
:
"pure-token"
,
"token"
:
"XX"
}
]
},
{
"name"
:
"get"
,
"token"
:
"GET"
,
"type"
:
"pure-token"
,
"optional"
:
true
,
"since"
:
"6.2.0"
},
{
"name"
:
"expiration"
,
"type"
:
"oneof"
,
...
...
@@ -101,31 +126,6 @@
"since"
:
"6.0.0"
}
]
},
{
"name"
:
"condition"
,
"type"
:
"oneof"
,
"optional"
:
true
,
"since"
:
"2.6.12"
,
"arguments"
:
[
{
"name"
:
"nx"
,
"type"
:
"pure-token"
,
"token"
:
"NX"
},
{
"name"
:
"xx"
,
"type"
:
"pure-token"
,
"token"
:
"XX"
}
]
},
{
"name"
:
"get"
,
"token"
:
"GET"
,
"type"
:
"pure-token"
,
"optional"
:
true
,
"since"
:
"6.2.0"
}
]
}
...
...
src/commands/zrangebylex.json
View file @
d375595d
...
...
@@ -7,7 +7,7 @@
"arity"
:
-4
,
"function"
:
"zrangebylexCommand"
,
"deprecated_since"
:
"6.2.0"
,
"replaced_by"
:
"`ZRANGE` with the `BY
SCORE
` argument"
,
"replaced_by"
:
"`ZRANGE` with the `BY
LEX
` argument"
,
"doc_flags"
:
[
"DEPRECATED"
],
...
...
src/config.c
View file @
d375595d
...
...
@@ -94,6 +94,15 @@ configEnum aof_fsync_enum[] = {
{
NULL
,
0
}
};
configEnum
shutdown_on_sig_enum
[]
=
{
{
"default"
,
0
},
{
"save"
,
SHUTDOWN_SAVE
},
{
"nosave"
,
SHUTDOWN_NOSAVE
},
{
"now"
,
SHUTDOWN_NOW
},
{
"force"
,
SHUTDOWN_FORCE
},
{
NULL
,
0
}
};
configEnum
repl_diskless_load_enum
[]
=
{
{
"disabled"
,
REPL_DISKLESS_LOAD_DISABLED
},
{
"on-empty-db"
,
REPL_DISKLESS_LOAD_WHEN_DB_EMPTY
},
...
...
@@ -143,6 +152,13 @@ configEnum cluster_preferred_endpoint_type_enum[] = {
{
NULL
,
0
}
};
configEnum
propagation_error_behavior_enum
[]
=
{
{
"ignore"
,
PROPAGATION_ERR_BEHAVIOR_IGNORE
},
{
"panic"
,
PROPAGATION_ERR_BEHAVIOR_PANIC
},
{
"panic-on-replicas"
,
PROPAGATION_ERR_BEHAVIOR_PANIC_ON_REPLICAS
},
{
NULL
,
0
}
};
/* Output buffer limits presets. */
clientBufferLimitsConfig
clientBufferLimitsDefaults
[
CLIENT_TYPE_OBUF_COUNT
]
=
{
{
0
,
0
,
0
},
/* normal */
...
...
@@ -276,33 +292,50 @@ static standardConfig *lookupConfig(sds name) {
*----------------------------------------------------------------------------*/
/* Get enum value from name. If there is no match INT_MIN is returned. */
int
configEnumGetValue
(
configEnum
*
ce
,
char
*
name
)
{
while
(
ce
->
name
!=
NULL
)
{
if
(
!
strcasecmp
(
ce
->
name
,
name
))
return
ce
->
val
;
ce
++
;
int
configEnumGetValue
(
configEnum
*
ce
,
sds
*
argv
,
int
argc
,
int
bitflags
)
{
if
(
argc
==
0
||
(
!
bitflags
&&
argc
!=
1
))
return
INT_MIN
;
int
values
=
0
;
for
(
int
i
=
0
;
i
<
argc
;
i
++
)
{
int
matched
=
0
;
for
(
configEnum
*
ceItem
=
ce
;
ceItem
->
name
!=
NULL
;
ceItem
++
)
{
if
(
!
strcasecmp
(
argv
[
i
],
ceItem
->
name
))
{
values
|=
ceItem
->
val
;
matched
=
1
;
}
return
INT_MIN
;
}
/* Get enum name from value. If no match is found NULL is returned. */
const
char
*
configEnumGetName
(
configEnum
*
ce
,
int
val
)
{
while
(
ce
->
name
!=
NULL
)
{
if
(
ce
->
val
==
val
)
return
ce
->
name
;
ce
++
;
}
return
NULL
;
if
(
!
matched
)
return
INT_MIN
;
}
return
values
;
}
/* Wrapper for configEnumGetName() returning "unknown" instead of NULL if
* there is no match. */
const
char
*
configEnumGetNameOrUnknown
(
configEnum
*
ce
,
int
val
)
{
const
char
*
name
=
configEnumGetName
(
ce
,
val
);
return
name
?
name
:
"unknown"
;
/* Get enum name/s from value. If no matches are found "unknown" is returned. */
static
sds
configEnumGetName
(
configEnum
*
ce
,
int
values
,
int
bitflags
)
{
sds
names
=
NULL
;
int
matches
=
0
;
for
(
;
ce
->
name
!=
NULL
;
ce
++
)
{
if
(
values
==
ce
->
val
)
{
/* Short path for perfect match */
sdsfree
(
names
);
return
sdsnew
(
ce
->
name
);
}
if
(
bitflags
&&
(
values
&
ce
->
val
))
{
names
=
names
?
sdscatfmt
(
names
,
" %s"
,
ce
->
name
)
:
sdsnew
(
ce
->
name
);
matches
|=
ce
->
val
;
}
}
if
(
!
names
||
values
!=
matches
)
{
sdsfree
(
names
);
return
sdsnew
(
"unknown"
);
}
return
names
;
}
/* Used for INFO generation. */
const
char
*
evictPolicyToString
(
void
)
{
return
configEnumGetNameOrUnknown
(
maxmemory_policy_enum
,
server
.
maxmemory_policy
);
for
(
configEnum
*
ce
=
maxmemory_policy_enum
;
ce
->
name
!=
NULL
;
ce
++
)
{
if
(
server
.
maxmemory_policy
==
ce
->
val
)
return
ce
->
name
;
}
serverPanic
(
"unknown eviction policy"
);
}
/*-----------------------------------------------------------------------------
...
...
@@ -514,12 +547,15 @@ void loadServerConfigFromString(char *config) {
}
else
if
(
!
strcasecmp
(
argv
[
0
],
"loadmodule"
)
&&
argc
>=
2
)
{
queueLoadModule
(
argv
[
1
],
&
argv
[
2
],
argc
-
2
);
}
else
if
(
strchr
(
argv
[
0
],
'.'
))
{
if
(
argc
!=
2
)
{
if
(
argc
<
2
)
{
err
=
"Module config specified without value"
;
goto
loaderr
;
}
sds
name
=
sdsdup
(
argv
[
0
]);
if
(
!
dictReplace
(
server
.
module_configs_queue
,
name
,
sdsdup
(
argv
[
1
])))
sdsfree
(
name
);
sds
val
=
sdsdup
(
argv
[
1
]);
for
(
int
i
=
2
;
i
<
argc
;
i
++
)
val
=
sdscatfmt
(
val
,
" %S"
,
argv
[
i
]);
if
(
!
dictReplace
(
server
.
module_configs_queue
,
name
,
val
))
sdsfree
(
name
);
}
else
if
(
!
strcasecmp
(
argv
[
0
],
"sentinel"
))
{
/* argc == 1 is handled by main() as we need to enter the sentinel
* mode ASAP. */
...
...
@@ -1297,12 +1333,13 @@ void rewriteConfigOctalOption(struct rewriteConfigState *state, const char *opti
/* Rewrite an enumeration option. It takes as usually state and option name,
* and in addition the enumeration array and the default value for the
* option. */
void
rewriteConfigEnumOption
(
struct
rewriteConfigState
*
state
,
const
char
*
option
,
int
value
,
configEnum
*
ce
,
int
defval
)
{
sds
line
;
const
char
*
name
=
configEnumGetNameOrUnknown
(
ce
,
value
);
int
force
=
value
!=
defval
;
void
rewriteConfigEnumOption
(
struct
rewriteConfigState
*
state
,
const
char
*
option
,
int
value
,
standardConfig
*
config
)
{
int
multiarg
=
config
->
flags
&
MULTI_ARG_CONFIG
;
sds
names
=
configEnumGetName
(
config
->
data
.
enumd
.
enum_value
,
value
,
multiarg
);
sds
line
=
sdscatfmt
(
sdsempty
(),
"%s %s"
,
option
,
names
);
sdsfree
(
names
);
int
force
=
value
!=
config
->
data
.
enumd
.
default_value
;
line
=
sdscatprintf
(
sdsempty
(),
"%s %s"
,
option
,
name
);
rewriteConfigRewriteLine
(
state
,
option
,
line
,
force
);
}
...
...
@@ -1821,10 +1858,16 @@ static int sdsConfigSet(standardConfig *config, sds *argv, int argc, const char
UNUSED
(
argc
);
if
(
config
->
data
.
sds
.
is_valid_fn
&&
!
config
->
data
.
sds
.
is_valid_fn
(
argv
[
0
],
err
))
return
0
;
sds
prev
=
config
->
flags
&
MODULE_CONFIG
?
getModuleStringConfig
(
config
->
privdata
)
:
*
config
->
data
.
sds
.
config
;
sds
new
=
(
config
->
data
.
string
.
convert_empty_to_null
&&
(
sdslen
(
argv
[
0
])
==
0
))
?
NULL
:
argv
[
0
];
/* if prev and new configuration are not equal, set the new one */
if
(
new
!=
prev
&&
(
new
==
NULL
||
prev
==
NULL
||
sdscmp
(
prev
,
new
)))
{
/* If MODULE_CONFIG flag is set, then free temporary prev getModuleStringConfig returned.
* Otherwise, free the actual previous config value Redis held (Same action, different reasons) */
sdsfree
(
prev
);
if
(
config
->
flags
&
MODULE_CONFIG
)
{
return
setModuleStringConfig
(
config
->
privdata
,
new
,
err
);
}
...
...
@@ -1848,7 +1891,7 @@ static sds sdsConfigGet(standardConfig *config) {
static
void
sdsConfigRewrite
(
standardConfig
*
config
,
const
char
*
name
,
struct
rewriteConfigState
*
state
)
{
sds
val
=
config
->
flags
&
MODULE_CONFIG
?
getModuleStringConfig
(
config
->
privdata
)
:
*
config
->
data
.
sds
.
config
;
rewriteConfigSdsOption
(
state
,
name
,
val
,
config
->
data
.
sds
.
default_value
);
if
(
val
)
sdsfree
(
val
);
if
(
(
val
)
&&
(
config
->
flags
&
MODULE_CONFIG
))
sdsfree
(
val
);
}
...
...
@@ -1885,10 +1928,12 @@ static void enumConfigInit(standardConfig *config) {
}
static
int
enumConfigSet
(
standardConfig
*
config
,
sds
*
argv
,
int
argc
,
const
char
**
err
)
{
UNUSED
(
argc
);
int
enumval
=
configEnumGetValue
(
config
->
data
.
enumd
.
enum_value
,
argv
[
0
]);
int
enumval
;
int
bitflags
=
!!
(
config
->
flags
&
MULTI_ARG_CONFIG
);
enumval
=
configEnumGetValue
(
config
->
data
.
enumd
.
enum_value
,
argv
,
argc
,
bitflags
);
if
(
enumval
==
INT_MIN
)
{
sds
enumerr
=
sdsnew
(
"argument must be one of the following: "
);
sds
enumerr
=
sdsnew
(
"argument
(s)
must be one of the following: "
);
configEnum
*
enumNode
=
config
->
data
.
enumd
.
enum_value
;
while
(
enumNode
->
name
!=
NULL
)
{
enumerr
=
sdscatlen
(
enumerr
,
enumNode
->
name
,
...
...
@@ -1919,12 +1964,13 @@ static int enumConfigSet(standardConfig *config, sds *argv, int argc, const char
static
sds
enumConfigGet
(
standardConfig
*
config
)
{
int
val
=
config
->
flags
&
MODULE_CONFIG
?
getModuleEnumConfig
(
config
->
privdata
)
:
*
(
config
->
data
.
enumd
.
config
);
return
sdsnew
(
configEnumGetNameOrUnknown
(
config
->
data
.
enumd
.
enum_value
,
val
));
int
bitflags
=
!!
(
config
->
flags
&
MULTI_ARG_CONFIG
);
return
configEnumGetName
(
config
->
data
.
enumd
.
enum_value
,
val
,
bitflags
);
}
static
void
enumConfigRewrite
(
standardConfig
*
config
,
const
char
*
name
,
struct
rewriteConfigState
*
state
)
{
int
val
=
config
->
flags
&
MODULE_CONFIG
?
getModuleEnumConfig
(
config
->
privdata
)
:
*
(
config
->
data
.
enumd
.
config
);
rewriteConfigEnumOption
(
state
,
name
,
val
,
config
->
data
.
enumd
.
enum_value
,
config
->
data
.
enumd
.
default_value
);
rewriteConfigEnumOption
(
state
,
name
,
val
,
config
);
}
#define createEnumConfig(name, alias, flags, enum, config_addr, default, is_valid, apply) { \
...
...
@@ -2284,6 +2330,16 @@ static int isValidAOFdirname(char *val, const char **err) {
return
1
;
}
static
int
isValidShutdownOnSigFlags
(
int
val
,
const
char
**
err
)
{
/* Individual arguments are validated by createEnumConfig logic.
* We just need to ensure valid combinations here. */
if
(
val
&
SHUTDOWN_NOSAVE
&&
val
&
SHUTDOWN_SAVE
)
{
*
err
=
"shutdown options SAVE and NOSAVE can't be used simultaneously"
;
return
0
;
}
return
1
;
}
static
int
isValidAnnouncedHostname
(
char
*
val
,
const
char
**
err
)
{
if
(
strlen
(
val
)
>=
NET_HOST_STR_LEN
)
{
*
err
=
"Hostnames must be less than "
...
...
@@ -2641,7 +2697,7 @@ static int setConfigOOMScoreAdjValuesOption(standardConfig *config, sds *argv, i
if
(
*
eptr
!=
'\0'
||
val
<
-
2000
||
val
>
2000
)
{
if
(
err
)
*
err
=
"Invalid oom-score-adj-values, elements must be between -2000 and 2000."
;
return
-
1
;
return
0
;
}
values
[
i
]
=
val
;
...
...
@@ -2691,7 +2747,7 @@ static int setConfigNotifyKeyspaceEventsOption(standardConfig *config, sds *argv
}
int
flags
=
keyspaceEventsStringToFlags
(
argv
[
0
]);
if
(
flags
==
-
1
)
{
*
err
=
"Invalid event class character. Use 'Ag$lshzxeKEtmd'."
;
*
err
=
"Invalid event class character. Use 'Ag$lshzxeKEtmd
n
'."
;
return
0
;
}
server
.
notify_keyspace_events
=
flags
;
...
...
@@ -2887,6 +2943,7 @@ standardConfig static_configs[] = {
createBoolConfig
(
"replica-announced"
,
NULL
,
MODIFIABLE_CONFIG
,
server
.
replica_announced
,
1
,
NULL
,
NULL
),
createBoolConfig
(
"latency-tracking"
,
NULL
,
MODIFIABLE_CONFIG
,
server
.
latency_tracking_enabled
,
1
,
NULL
,
NULL
),
createBoolConfig
(
"aof-disable-auto-gc"
,
NULL
,
MODIFIABLE_CONFIG
,
server
.
aof_disable_auto_gc
,
0
,
NULL
,
updateAofAutoGCEnabled
),
createBoolConfig
(
"replica-ignore-disk-write-errors"
,
NULL
,
MODIFIABLE_CONFIG
,
server
.
repl_ignore_disk_write_error
,
0
,
NULL
,
NULL
),
/* String Configs */
createStringConfig
(
"aclfile"
,
NULL
,
IMMUTABLE_CONFIG
,
ALLOW_EMPTY_STRING
,
server
.
acl_filename
,
""
,
NULL
,
NULL
),
...
...
@@ -2928,6 +2985,9 @@ standardConfig static_configs[] = {
createEnumConfig
(
"enable-debug-command"
,
NULL
,
IMMUTABLE_CONFIG
,
protected_action_enum
,
server
.
enable_debug_cmd
,
PROTECTED_ACTION_ALLOWED_NO
,
NULL
,
NULL
),
createEnumConfig
(
"enable-module-command"
,
NULL
,
IMMUTABLE_CONFIG
,
protected_action_enum
,
server
.
enable_module_cmd
,
PROTECTED_ACTION_ALLOWED_NO
,
NULL
,
NULL
),
createEnumConfig
(
"cluster-preferred-endpoint-type"
,
NULL
,
MODIFIABLE_CONFIG
,
cluster_preferred_endpoint_type_enum
,
server
.
cluster_preferred_endpoint_type
,
CLUSTER_ENDPOINT_TYPE_IP
,
NULL
,
NULL
),
createEnumConfig
(
"propagation-error-behavior"
,
NULL
,
MODIFIABLE_CONFIG
,
propagation_error_behavior_enum
,
server
.
propagation_error_behavior
,
PROPAGATION_ERR_BEHAVIOR_IGNORE
,
NULL
,
NULL
),
createEnumConfig
(
"shutdown-on-sigint"
,
NULL
,
MODIFIABLE_CONFIG
|
MULTI_ARG_CONFIG
,
shutdown_on_sig_enum
,
server
.
shutdown_on_sigint
,
0
,
isValidShutdownOnSigFlags
,
NULL
),
createEnumConfig
(
"shutdown-on-sigterm"
,
NULL
,
MODIFIABLE_CONFIG
|
MULTI_ARG_CONFIG
,
shutdown_on_sig_enum
,
server
.
shutdown_on_sigterm
,
0
,
isValidShutdownOnSigFlags
,
NULL
),
/* Integer configs */
createIntConfig
(
"databases"
,
NULL
,
IMMUTABLE_CONFIG
,
1
,
INT_MAX
,
server
.
dbnum
,
16
,
INTEGER_CONFIG
,
NULL
,
NULL
),
...
...
@@ -2971,6 +3031,7 @@ standardConfig static_configs[] = {
/* Unsigned int configs */
createUIntConfig
(
"maxclients"
,
NULL
,
MODIFIABLE_CONFIG
,
1
,
UINT_MAX
,
server
.
maxclients
,
10000
,
INTEGER_CONFIG
,
NULL
,
updateMaxclients
),
createUIntConfig
(
"unixsocketperm"
,
NULL
,
IMMUTABLE_CONFIG
,
0
,
0777
,
server
.
unixsocketperm
,
0
,
OCTAL_CONFIG
,
NULL
,
NULL
),
createUIntConfig
(
"socket-mark-id"
,
NULL
,
IMMUTABLE_CONFIG
,
0
,
UINT_MAX
,
server
.
socket_mark_id
,
0
,
INTEGER_CONFIG
,
NULL
,
NULL
),
/* Unsigned Long configs */
createULongConfig
(
"active-defrag-max-scan-fields"
,
NULL
,
MODIFIABLE_CONFIG
,
1
,
LONG_MAX
,
server
.
active_defrag_max_scan_fields
,
1000
,
INTEGER_CONFIG
,
NULL
,
NULL
),
/* Default: keys with more than 1000 fields will be processed separately */
...
...
src/config.h
View file @
d375595d
...
...
@@ -80,6 +80,10 @@
/* MSG_NOSIGNAL. */
#ifdef __linux__
#define HAVE_MSG_NOSIGNAL 1
#if defined(SO_MARK)
#define HAVE_SOCKOPTMARKID 1
#define SOCKOPTMARKID SO_MARK
#endif
#endif
/* Test for polling API */
...
...
@@ -113,6 +117,20 @@
#define redis_fsync(fd) fsync(fd)
#endif
#if defined(__FreeBSD__)
#if defined(SO_USER_COOKIE)
#define HAVE_SOCKOPTMARKID 1
#define SOCKOPTMARKID SO_USER_COOKIE
#endif
#endif
#if defined(__OpenBSD__)
#if defined(SO_RTABLE)
#define HAVE_SOCKOPTMARKID 1
#define SOCKOPTMARKID SO_RTABLE
#endif
#endif
#if __GNUC__ >= 4
#define redis_unreachable __builtin_unreachable
#else
...
...
src/db.c
View file @
d375595d
...
...
@@ -182,6 +182,7 @@ void dbAdd(redisDb *db, robj *key, robj *val) {
dictSetVal
(
db
->
dict
,
de
,
val
);
signalKeyAsReady
(
db
,
key
,
val
->
type
);
if
(
server
.
cluster_enabled
)
slotToKeyAddEntry
(
de
,
db
);
notifyKeyspaceEvent
(
NOTIFY_NEW
,
"new"
,
key
,
db
->
id
);
}
/* This is a special version of dbAdd() that is used only when loading
...
...
src/debug.c
View file @
d375595d
...
...
@@ -416,6 +416,8 @@ void debugCommand(client *c) {
" Like HTSTATS but for the hash table stored at <key>'s value."
,
"LOADAOF"
,
" Flush the AOF buffers on disk and reload the AOF in memory."
,
"REPLICATE <string>"
,
" Replicates the provided string to replicas, allowing data divergence."
,
#ifdef USE_JEMALLOC
"MALLCTL <key> [<val>]"
,
" Get or set a malloc tuning integer."
,
...
...
@@ -849,6 +851,10 @@ NULL
{
server
.
aof_flush_sleep
=
atoi
(
c
->
argv
[
2
]
->
ptr
);
addReply
(
c
,
shared
.
ok
);
}
else
if
(
!
strcasecmp
(
c
->
argv
[
1
]
->
ptr
,
"replicate"
)
&&
c
->
argc
>=
3
)
{
replicationFeedSlaves
(
server
.
slaves
,
server
.
slaveseldb
,
c
->
argv
+
2
,
c
->
argc
-
2
);
addReply
(
c
,
shared
.
ok
);
}
else
if
(
!
strcasecmp
(
c
->
argv
[
1
]
->
ptr
,
"error"
)
&&
c
->
argc
==
3
)
{
sds
errstr
=
sdsnewlen
(
"-"
,
1
);
...
...
Prev
1
2
3
4
5
6
7
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