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
2667c412
Unverified
Commit
2667c412
authored
Jun 08, 2022
by
Oran Agra
Committed by
GitHub
Jun 08, 2022
Browse files
Merge pull request #10829 from oranagra/release-7.0.1
Release 7.0.1
parents
d375595d
595e725d
Changes
110
Show whitespace changes
Inline
Side-by-side
src/commands/fcall_ro.json
View file @
2667c412
...
@@ -11,7 +11,8 @@
...
@@ -11,7 +11,8 @@
"NOSCRIPT"
,
"NOSCRIPT"
,
"SKIP_MONITOR"
,
"SKIP_MONITOR"
,
"NO_MANDATORY_KEYS"
,
"NO_MANDATORY_KEYS"
,
"STALE"
"STALE"
,
"READONLY"
],
],
"acl_categories"
:
[
"acl_categories"
:
[
"SCRIPTING"
"SCRIPTING"
...
...
src/commands/lcs.json
View file @
2667c412
...
@@ -41,7 +41,7 @@
...
@@ -41,7 +41,7 @@
{
{
"name"
:
"key2"
,
"name"
:
"key2"
,
"type"
:
"key"
,
"type"
:
"key"
,
"key_spec_index"
:
1
"key_spec_index"
:
0
},
},
{
{
"name"
:
"len"
,
"name"
:
"len"
,
...
...
src/commands/pfdebug.json
View file @
2667c412
...
@@ -4,7 +4,7 @@
...
@@ -4,7 +4,7 @@
"complexity"
:
"N/A"
,
"complexity"
:
"N/A"
,
"group"
:
"hyperloglog"
,
"group"
:
"hyperloglog"
,
"since"
:
"2.8.9"
,
"since"
:
"2.8.9"
,
"arity"
:
-
3
,
"arity"
:
3
,
"function"
:
"pfdebugCommand"
,
"function"
:
"pfdebugCommand"
,
"doc_flags"
:
[
"doc_flags"
:
[
"SYSCMD"
"SYSCMD"
...
@@ -36,6 +36,17 @@
...
@@ -36,6 +36,17 @@
}
}
}
}
}
}
],
"arguments"
:
[
{
"name"
:
"subcommand"
,
"type"
:
"string"
},
{
"name"
:
"key"
,
"type"
:
"key"
,
"key_spec_index"
:
0
}
]
]
}
}
}
}
src/commands/pubsub-shardchannels.json
View file @
2667c412
{
{
"SHARDCHANNELS"
:
{
"SHARDCHANNELS"
:
{
"summary"
:
"List active shard channels"
,
"summary"
:
"List active shard channels"
,
"complexity"
:
"O(N) where N is the number of active shard channels, and assuming constant time pattern matching (relatively short channels)."
,
"complexity"
:
"O(N) where N is the number of active shard channels, and assuming constant time pattern matching (relatively short
shard
channels)."
,
"group"
:
"pubsub"
,
"group"
:
"pubsub"
,
"since"
:
"7.0.0"
,
"since"
:
"7.0.0"
,
"arity"
:
-2
,
"arity"
:
-2
,
...
...
src/commands/pubsub-shardnumsub.json
View file @
2667c412
{
{
"SHARDNUMSUB"
:
{
"SHARDNUMSUB"
:
{
"summary"
:
"Get the count of subscribers for shard channels"
,
"summary"
:
"Get the count of subscribers for shard channels"
,
"complexity"
:
"O(N) for the SHARDNUMSUB subcommand, where N is the number of requested channels"
,
"complexity"
:
"O(N) for the SHARDNUMSUB subcommand, where N is the number of requested
shard
channels"
,
"group"
:
"pubsub"
,
"group"
:
"pubsub"
,
"since"
:
"7.0.0"
,
"since"
:
"7.0.0"
,
"arity"
:
-2
,
"arity"
:
-2
,
...
@@ -14,7 +14,7 @@
...
@@ -14,7 +14,7 @@
],
],
"arguments"
:
[
"arguments"
:
[
{
{
"name"
:
"channel"
,
"name"
:
"
shard
channel"
,
"type"
:
"string"
,
"type"
:
"string"
,
"optional"
:
true
,
"optional"
:
true
,
"multiple"
:
true
"multiple"
:
true
...
...
src/commands/rename.json
View file @
2667c412
...
@@ -62,7 +62,7 @@
...
@@ -62,7 +62,7 @@
{
{
"name"
:
"newkey"
,
"name"
:
"newkey"
,
"type"
:
"key"
,
"type"
:
"key"
,
"key_spec_index"
:
0
"key_spec_index"
:
1
}
}
]
]
}
}
...
...
src/commands/renamenx.json
View file @
2667c412
...
@@ -67,7 +67,7 @@
...
@@ -67,7 +67,7 @@
{
{
"name"
:
"newkey"
,
"name"
:
"newkey"
,
"type"
:
"key"
,
"type"
:
"key"
,
"key_spec_index"
:
0
"key_spec_index"
:
1
}
}
]
]
}
}
...
...
src/commands/restore-asking.json
View file @
2667c412
...
@@ -6,6 +6,20 @@
...
@@ -6,6 +6,20 @@
"since"
:
"3.0.0"
,
"since"
:
"3.0.0"
,
"arity"
:
-4
,
"arity"
:
-4
,
"function"
:
"restoreCommand"
,
"function"
:
"restoreCommand"
,
"history"
:
[
[
"3.0.0"
,
"Added the `REPLACE` modifier."
],
[
"5.0.0"
,
"Added the `ABSTTL` modifier."
],
[
"5.0.0"
,
"Added the `IDLETIME` and `FREQ` options."
]
],
"doc_flags"
:
[
"doc_flags"
:
[
"SYSCMD"
"SYSCMD"
],
],
...
@@ -37,6 +51,49 @@
...
@@ -37,6 +51,49 @@
}
}
}
}
}
}
],
"arguments"
:
[
{
"name"
:
"key"
,
"type"
:
"key"
,
"key_spec_index"
:
0
},
{
"name"
:
"ttl"
,
"type"
:
"integer"
},
{
"name"
:
"serialized-value"
,
"type"
:
"string"
},
{
"name"
:
"replace"
,
"token"
:
"REPLACE"
,
"type"
:
"pure-token"
,
"optional"
:
true
,
"since"
:
"3.0.0"
},
{
"name"
:
"absttl"
,
"token"
:
"ABSTTL"
,
"type"
:
"pure-token"
,
"optional"
:
true
,
"since"
:
"5.0.0"
},
{
"token"
:
"IDLETIME"
,
"name"
:
"seconds"
,
"type"
:
"integer"
,
"optional"
:
true
,
"since"
:
"5.0.0"
},
{
"token"
:
"FREQ"
,
"name"
:
"frequency"
,
"type"
:
"integer"
,
"optional"
:
true
,
"since"
:
"5.0.0"
}
]
]
}
}
}
}
src/commands/sentinel-slaves.json
0 → 100644
View file @
2667c412
{
"SLAVES"
:
{
"summary"
:
"List the monitored slaves"
,
"complexity"
:
"O(N) where N is the number of slaves"
,
"group"
:
"sentinel"
,
"since"
:
"2.8.0"
,
"arity"
:
3
,
"container"
:
"SENTINEL"
,
"function"
:
"sentinelCommand"
,
"deprecated_since"
:
"5.0.0"
,
"replaced_by"
:
"`SENTINEL REPLICAS`"
,
"doc_flags"
:
[
"DEPRECATED"
],
"command_flags"
:
[
"ADMIN"
,
"SENTINEL"
,
"ONLY_SENTINEL"
],
"arguments"
:
[
{
"name"
:
"master-name"
,
"type"
:
"string"
}
]
}
}
src/commands/spublish.json
View file @
2667c412
...
@@ -15,7 +15,7 @@
...
@@ -15,7 +15,7 @@
],
],
"arguments"
:
[
"arguments"
:
[
{
{
"name"
:
"channel"
,
"name"
:
"
shard
channel"
,
"type"
:
"string"
"type"
:
"string"
},
},
{
{
...
...
src/commands/ssubscribe.json
View file @
2667c412
...
@@ -14,7 +14,7 @@
...
@@ -14,7 +14,7 @@
],
],
"arguments"
:
[
"arguments"
:
[
{
{
"name"
:
"channel"
,
"name"
:
"
shard
channel"
,
"type"
:
"string"
,
"type"
:
"string"
,
"multiple"
:
true
"multiple"
:
true
}
}
...
...
src/commands/sunsubscribe.json
View file @
2667c412
{
{
"SUNSUBSCRIBE"
:
{
"SUNSUBSCRIBE"
:
{
"summary"
:
"Stop listening for messages posted to the given shard channels"
,
"summary"
:
"Stop listening for messages posted to the given shard channels"
,
"complexity"
:
"O(N) where N is the number of clients already subscribed to a channel."
,
"complexity"
:
"O(N) where N is the number of clients already subscribed to a
shard
channel."
,
"group"
:
"pubsub"
,
"group"
:
"pubsub"
,
"since"
:
"7.0.0"
,
"since"
:
"7.0.0"
,
"arity"
:
-1
,
"arity"
:
-1
,
...
@@ -14,7 +14,7 @@
...
@@ -14,7 +14,7 @@
],
],
"arguments"
:
[
"arguments"
:
[
{
{
"name"
:
"channel"
,
"name"
:
"
shard
channel"
,
"type"
:
"string"
,
"type"
:
"string"
,
"optional"
:
true
,
"optional"
:
true
,
"multiple"
:
true
"multiple"
:
true
...
...
src/commands/watch.json
View file @
2667c412
...
@@ -18,6 +18,9 @@
...
@@ -18,6 +18,9 @@
],
],
"key_specs"
:
[
"key_specs"
:
[
{
{
"flags"
:
[
"RO"
],
"begin_search"
:
{
"begin_search"
:
{
"index"
:
{
"index"
:
{
"pos"
:
1
"pos"
:
1
...
...
src/commands/xinfo-stream.json
View file @
2667c412
...
@@ -7,6 +7,10 @@
...
@@ -7,6 +7,10 @@
"arity"
:
-3
,
"arity"
:
-3
,
"container"
:
"XINFO"
,
"container"
:
"XINFO"
,
"history"
:
[
"history"
:
[
[
"6.0.0"
,
"Added the `FULL` modifier."
],
[
[
"7.0.0"
,
"7.0.0"
,
"Added the `max-deleted-entry-id`, `entries-added`, `recorded-first-entry-id`, `entries-read` and `lag` fields"
"Added the `max-deleted-entry-id`, `entries-added`, `recorded-first-entry-id`, `entries-read` and `lag` fields"
...
...
src/config.c
View file @
2667c412
...
@@ -311,18 +311,21 @@ int configEnumGetValue(configEnum *ce, sds *argv, int argc, int bitflags) {
...
@@ -311,18 +311,21 @@ int configEnumGetValue(configEnum *ce, sds *argv, int argc, int bitflags) {
/* Get enum name/s from value. If no matches are found "unknown" is returned. */
/* Get enum name/s from value. If no matches are found "unknown" is returned. */
static
sds
configEnumGetName
(
configEnum
*
ce
,
int
values
,
int
bitflags
)
{
static
sds
configEnumGetName
(
configEnum
*
ce
,
int
values
,
int
bitflags
)
{
sds
names
=
NULL
;
sds
names
=
NULL
;
int
matche
s
=
0
;
int
un
matche
d
=
values
;
for
(
;
ce
->
name
!=
NULL
;
ce
++
)
{
for
(
;
ce
->
name
!=
NULL
;
ce
++
)
{
if
(
values
==
ce
->
val
)
{
/* Short path for perfect match */
if
(
values
==
ce
->
val
)
{
/* Short path for perfect match */
sdsfree
(
names
);
sdsfree
(
names
);
return
sdsnew
(
ce
->
name
);
return
sdsnew
(
ce
->
name
);
}
}
if
(
bitflags
&&
(
values
&
ce
->
val
))
{
/* Note: for bitflags, we want them sorted from high to low, so that if there are several / partially
* overlapping entries, we'll prefer the ones matching more bits. */
if
(
bitflags
&&
ce
->
val
&&
ce
->
val
==
(
unmatched
&
ce
->
val
))
{
names
=
names
?
sdscatfmt
(
names
,
" %s"
,
ce
->
name
)
:
sdsnew
(
ce
->
name
);
names
=
names
?
sdscatfmt
(
names
,
" %s"
,
ce
->
name
)
:
sdsnew
(
ce
->
name
);
matche
s
|
=
ce
->
val
;
un
matche
d
&
=
~
ce
->
val
;
}
}
}
}
if
(
!
names
||
values
!=
matche
s
)
{
if
(
!
names
||
un
matche
d
)
{
sdsfree
(
names
);
sdsfree
(
names
);
return
sdsnew
(
"unknown"
);
return
sdsnew
(
"unknown"
);
}
}
...
@@ -484,10 +487,24 @@ void loadServerConfigFromString(char *config) {
...
@@ -484,10 +487,24 @@ void loadServerConfigFromString(char *config) {
err
=
"wrong number of arguments"
;
err
=
"wrong number of arguments"
;
goto
loaderr
;
goto
loaderr
;
}
}
if
((
config
->
flags
&
MULTI_ARG_CONFIG
)
&&
argc
==
2
&&
sdslen
(
argv
[
1
]))
{
/* For MULTI_ARG_CONFIGs, if we only have one argument, try to split it by spaces.
* Only if the argument is not empty, otherwise something like --save "" will fail.
* So that we can support something like --config "arg1 arg2 arg3". */
sds
*
new_argv
;
int
new_argc
;
new_argv
=
sdssplitargs
(
argv
[
1
],
&
new_argc
);
if
(
!
config
->
interface
.
set
(
config
,
new_argv
,
new_argc
,
&
err
))
{
goto
loaderr
;
}
sdsfreesplitres
(
new_argv
,
new_argc
);
}
else
{
/* Set config using all arguments that follows */
/* Set config using all arguments that follows */
if
(
!
config
->
interface
.
set
(
config
,
&
argv
[
1
],
argc
-
1
,
&
err
))
{
if
(
!
config
->
interface
.
set
(
config
,
&
argv
[
1
],
argc
-
1
,
&
err
))
{
goto
loaderr
;
goto
loaderr
;
}
}
}
sdsfreesplitres
(
argv
,
argc
);
sdsfreesplitres
(
argv
,
argc
);
continue
;
continue
;
...
@@ -1125,10 +1142,21 @@ struct rewriteConfigState *rewriteConfigReadOldFile(char *path) {
...
@@ -1125,10 +1142,21 @@ struct rewriteConfigState *rewriteConfigReadOldFile(char *path) {
/* Not a comment, split into arguments. */
/* Not a comment, split into arguments. */
argv
=
sdssplitargs
(
line
,
&
argc
);
argv
=
sdssplitargs
(
line
,
&
argc
);
if
(
argv
==
NULL
||
(
!
server
.
sentinel_mode
&&
!
lookupConfig
(
argv
[
0
])))
{
/* Apparently the line is unparsable for some reason, for
if
(
argv
==
NULL
||
* instance it may have unbalanced quotes, or may contain a
(
!
lookupConfig
(
argv
[
0
])
&&
* config that doesn't exist anymore. Load it as a comment. */
/* The following is a list of config features that are only supported in
* config file parsing and are not recognized by lookupConfig */
strcasecmp
(
argv
[
0
],
"include"
)
&&
strcasecmp
(
argv
[
0
],
"rename-command"
)
&&
strcasecmp
(
argv
[
0
],
"user"
)
&&
strcasecmp
(
argv
[
0
],
"loadmodule"
)
&&
strcasecmp
(
argv
[
0
],
"sentinel"
)))
{
/* The line is either unparsable for some reason, for
* instance it may have unbalanced quotes, may contain a
* config that doesn't exist anymore, for instance a module that got
* unloaded. Load it as a comment. */
sds
aux
=
sdsnew
(
"# ??? "
);
sds
aux
=
sdsnew
(
"# ??? "
);
aux
=
sdscatsds
(
aux
,
line
);
aux
=
sdscatsds
(
aux
,
line
);
if
(
argv
)
sdsfreesplitres
(
argv
,
argc
);
if
(
argv
)
sdsfreesplitres
(
argv
,
argc
);
...
@@ -1143,18 +1171,13 @@ struct rewriteConfigState *rewriteConfigReadOldFile(char *path) {
...
@@ -1143,18 +1171,13 @@ struct rewriteConfigState *rewriteConfigReadOldFile(char *path) {
* Append the line and populate the option -> line numbers map. */
* Append the line and populate the option -> line numbers map. */
rewriteConfigAppendLine
(
state
,
line
);
rewriteConfigAppendLine
(
state
,
line
);
/* Translate options using the word "slave" to the corresponding name
/* If this is a alias config, replace it with the original name. */
* "replica", before adding such option to the config name -> lines
standardConfig
*
s_conf
=
lookupConfig
(
argv
[
0
]);
* mapping. */
if
(
s_conf
&&
s_conf
->
flags
&
ALIAS_CONFIG
)
{
char
*
p
=
strstr
(
argv
[
0
],
"slave"
);
if
(
p
)
{
sds
alt
=
sdsempty
();
alt
=
sdscatlen
(
alt
,
argv
[
0
],
p
-
argv
[
0
]);
alt
=
sdscatlen
(
alt
,
"replica"
,
7
);
alt
=
sdscatlen
(
alt
,
p
+
5
,
strlen
(
p
+
5
));
sdsfree
(
argv
[
0
]);
sdsfree
(
argv
[
0
]);
argv
[
0
]
=
alt
;
argv
[
0
]
=
sdsnew
(
s_conf
->
alias
)
;
}
}
/* If this is sentinel config, we use sentinel "sentinel <config>" as option
/* If this is sentinel config, we use sentinel "sentinel <config>" as option
to avoid messing up the sequence. */
to avoid messing up the sequence. */
if
(
server
.
sentinel_mode
&&
argc
>
1
&&
!
strcasecmp
(
argv
[
0
],
"sentinel"
))
{
if
(
server
.
sentinel_mode
&&
argc
>
1
&&
!
strcasecmp
(
argv
[
0
],
"sentinel"
))
{
...
@@ -1796,7 +1819,7 @@ static int boolConfigSet(standardConfig *config, sds *argv, int argc, const char
...
@@ -1796,7 +1819,7 @@ static int boolConfigSet(standardConfig *config, sds *argv, int argc, const char
*
(
config
->
data
.
yesno
.
config
)
=
yn
;
*
(
config
->
data
.
yesno
.
config
)
=
yn
;
return
1
;
return
1
;
}
}
return
2
;
return
(
config
->
flags
&
VOLATILE_CONFIG
)
?
1
:
2
;
}
}
static
sds
boolConfigGet
(
standardConfig
*
config
)
{
static
sds
boolConfigGet
(
standardConfig
*
config
)
{
...
@@ -1838,7 +1861,7 @@ static int stringConfigSet(standardConfig *config, sds *argv, int argc, const ch
...
@@ -1838,7 +1861,7 @@ static int stringConfigSet(standardConfig *config, sds *argv, int argc, const ch
zfree
(
prev
);
zfree
(
prev
);
return
1
;
return
1
;
}
}
return
2
;
return
(
config
->
flags
&
VOLATILE_CONFIG
)
?
1
:
2
;
}
}
static
sds
stringConfigGet
(
standardConfig
*
config
)
{
static
sds
stringConfigGet
(
standardConfig
*
config
)
{
...
@@ -1875,7 +1898,7 @@ static int sdsConfigSet(standardConfig *config, sds *argv, int argc, const char
...
@@ -1875,7 +1898,7 @@ static int sdsConfigSet(standardConfig *config, sds *argv, int argc, const char
return
1
;
return
1
;
}
}
if
(
config
->
flags
&
MODULE_CONFIG
&&
prev
)
sdsfree
(
prev
);
if
(
config
->
flags
&
MODULE_CONFIG
&&
prev
)
sdsfree
(
prev
);
return
2
;
return
(
config
->
flags
&
VOLATILE_CONFIG
)
?
1
:
2
;
}
}
static
sds
sdsConfigGet
(
standardConfig
*
config
)
{
static
sds
sdsConfigGet
(
standardConfig
*
config
)
{
...
@@ -1959,7 +1982,7 @@ static int enumConfigSet(standardConfig *config, sds *argv, int argc, const char
...
@@ -1959,7 +1982,7 @@ static int enumConfigSet(standardConfig *config, sds *argv, int argc, const char
*
(
config
->
data
.
enumd
.
config
)
=
enumval
;
*
(
config
->
data
.
enumd
.
config
)
=
enumval
;
return
1
;
return
1
;
}
}
return
2
;
return
(
config
->
flags
&
VOLATILE_CONFIG
)
?
1
:
2
;
}
}
static
sds
enumConfigGet
(
standardConfig
*
config
)
{
static
sds
enumConfigGet
(
standardConfig
*
config
)
{
...
@@ -2155,7 +2178,7 @@ static int numericConfigSet(standardConfig *config, sds *argv, int argc, const c
...
@@ -2155,7 +2178,7 @@ static int numericConfigSet(standardConfig *config, sds *argv, int argc, const c
return
setNumericType
(
config
,
ll
,
err
);
return
setNumericType
(
config
,
ll
,
err
);
}
}
return
2
;
return
(
config
->
flags
&
VOLATILE_CONFIG
)
?
1
:
2
;
}
}
static
sds
numericConfigGet
(
standardConfig
*
config
)
{
static
sds
numericConfigGet
(
standardConfig
*
config
)
{
...
@@ -2592,8 +2615,10 @@ static int setConfigSaveOption(standardConfig *config, sds *argv, int argc, cons
...
@@ -2592,8 +2615,10 @@ static int setConfigSaveOption(standardConfig *config, sds *argv, int argc, cons
int
j
;
int
j
;
/* Special case: treat single arg "" as zero args indicating empty save configuration */
/* Special case: treat single arg "" as zero args indicating empty save configuration */
if
(
argc
==
1
&&
!
strcasecmp
(
argv
[
0
],
""
))
if
(
argc
==
1
&&
!
strcasecmp
(
argv
[
0
],
""
))
{
resetServerSaveParams
();
argc
=
0
;
argc
=
0
;
}
/* Perform sanity check before setting the new config:
/* Perform sanity check before setting the new config:
* - Even number of args
* - Even number of args
...
@@ -3078,15 +3103,15 @@ standardConfig static_configs[] = {
...
@@ -3078,15 +3103,15 @@ standardConfig static_configs[] = {
createEnumConfig
(
"tls-auth-clients"
,
NULL
,
MODIFIABLE_CONFIG
,
tls_auth_clients_enum
,
server
.
tls_auth_clients
,
TLS_CLIENT_AUTH_YES
,
NULL
,
NULL
),
createEnumConfig
(
"tls-auth-clients"
,
NULL
,
MODIFIABLE_CONFIG
,
tls_auth_clients_enum
,
server
.
tls_auth_clients
,
TLS_CLIENT_AUTH_YES
,
NULL
,
NULL
),
createBoolConfig
(
"tls-prefer-server-ciphers"
,
NULL
,
MODIFIABLE_CONFIG
,
server
.
tls_ctx_config
.
prefer_server_ciphers
,
0
,
NULL
,
applyTlsCfg
),
createBoolConfig
(
"tls-prefer-server-ciphers"
,
NULL
,
MODIFIABLE_CONFIG
,
server
.
tls_ctx_config
.
prefer_server_ciphers
,
0
,
NULL
,
applyTlsCfg
),
createBoolConfig
(
"tls-session-caching"
,
NULL
,
MODIFIABLE_CONFIG
,
server
.
tls_ctx_config
.
session_caching
,
1
,
NULL
,
applyTlsCfg
),
createBoolConfig
(
"tls-session-caching"
,
NULL
,
MODIFIABLE_CONFIG
,
server
.
tls_ctx_config
.
session_caching
,
1
,
NULL
,
applyTlsCfg
),
createStringConfig
(
"tls-cert-file"
,
NULL
,
MODIFIABLE_CONFIG
,
EMPTY_STRING_IS_NULL
,
server
.
tls_ctx_config
.
cert_file
,
NULL
,
NULL
,
applyTlsCfg
),
createStringConfig
(
"tls-cert-file"
,
NULL
,
VOLATILE_CONFIG
|
MODIFIABLE_CONFIG
,
EMPTY_STRING_IS_NULL
,
server
.
tls_ctx_config
.
cert_file
,
NULL
,
NULL
,
applyTlsCfg
),
createStringConfig
(
"tls-key-file"
,
NULL
,
MODIFIABLE_CONFIG
,
EMPTY_STRING_IS_NULL
,
server
.
tls_ctx_config
.
key_file
,
NULL
,
NULL
,
applyTlsCfg
),
createStringConfig
(
"tls-key-file"
,
NULL
,
VOLATILE_CONFIG
|
MODIFIABLE_CONFIG
,
EMPTY_STRING_IS_NULL
,
server
.
tls_ctx_config
.
key_file
,
NULL
,
NULL
,
applyTlsCfg
),
createStringConfig
(
"tls-key-file-pass"
,
NULL
,
MODIFIABLE_CONFIG
,
EMPTY_STRING_IS_NULL
,
server
.
tls_ctx_config
.
key_file_pass
,
NULL
,
NULL
,
applyTlsCfg
),
createStringConfig
(
"tls-key-file-pass"
,
NULL
,
MODIFIABLE_CONFIG
,
EMPTY_STRING_IS_NULL
,
server
.
tls_ctx_config
.
key_file_pass
,
NULL
,
NULL
,
applyTlsCfg
),
createStringConfig
(
"tls-client-cert-file"
,
NULL
,
MODIFIABLE_CONFIG
,
EMPTY_STRING_IS_NULL
,
server
.
tls_ctx_config
.
client_cert_file
,
NULL
,
NULL
,
applyTlsCfg
),
createStringConfig
(
"tls-client-cert-file"
,
NULL
,
VOLATILE_CONFIG
|
MODIFIABLE_CONFIG
,
EMPTY_STRING_IS_NULL
,
server
.
tls_ctx_config
.
client_cert_file
,
NULL
,
NULL
,
applyTlsCfg
),
createStringConfig
(
"tls-client-key-file"
,
NULL
,
MODIFIABLE_CONFIG
,
EMPTY_STRING_IS_NULL
,
server
.
tls_ctx_config
.
client_key_file
,
NULL
,
NULL
,
applyTlsCfg
),
createStringConfig
(
"tls-client-key-file"
,
NULL
,
VOLATILE_CONFIG
|
MODIFIABLE_CONFIG
,
EMPTY_STRING_IS_NULL
,
server
.
tls_ctx_config
.
client_key_file
,
NULL
,
NULL
,
applyTlsCfg
),
createStringConfig
(
"tls-client-key-file-pass"
,
NULL
,
MODIFIABLE_CONFIG
,
EMPTY_STRING_IS_NULL
,
server
.
tls_ctx_config
.
client_key_file_pass
,
NULL
,
NULL
,
applyTlsCfg
),
createStringConfig
(
"tls-client-key-file-pass"
,
NULL
,
MODIFIABLE_CONFIG
,
EMPTY_STRING_IS_NULL
,
server
.
tls_ctx_config
.
client_key_file_pass
,
NULL
,
NULL
,
applyTlsCfg
),
createStringConfig
(
"tls-dh-params-file"
,
NULL
,
MODIFIABLE_CONFIG
,
EMPTY_STRING_IS_NULL
,
server
.
tls_ctx_config
.
dh_params_file
,
NULL
,
NULL
,
applyTlsCfg
),
createStringConfig
(
"tls-dh-params-file"
,
NULL
,
VOLATILE_CONFIG
|
MODIFIABLE_CONFIG
,
EMPTY_STRING_IS_NULL
,
server
.
tls_ctx_config
.
dh_params_file
,
NULL
,
NULL
,
applyTlsCfg
),
createStringConfig
(
"tls-ca-cert-file"
,
NULL
,
MODIFIABLE_CONFIG
,
EMPTY_STRING_IS_NULL
,
server
.
tls_ctx_config
.
ca_cert_file
,
NULL
,
NULL
,
applyTlsCfg
),
createStringConfig
(
"tls-ca-cert-file"
,
NULL
,
VOLATILE_CONFIG
|
MODIFIABLE_CONFIG
,
EMPTY_STRING_IS_NULL
,
server
.
tls_ctx_config
.
ca_cert_file
,
NULL
,
NULL
,
applyTlsCfg
),
createStringConfig
(
"tls-ca-cert-dir"
,
NULL
,
MODIFIABLE_CONFIG
,
EMPTY_STRING_IS_NULL
,
server
.
tls_ctx_config
.
ca_cert_dir
,
NULL
,
NULL
,
applyTlsCfg
),
createStringConfig
(
"tls-ca-cert-dir"
,
NULL
,
VOLATILE_CONFIG
|
MODIFIABLE_CONFIG
,
EMPTY_STRING_IS_NULL
,
server
.
tls_ctx_config
.
ca_cert_dir
,
NULL
,
NULL
,
applyTlsCfg
),
createStringConfig
(
"tls-protocols"
,
NULL
,
MODIFIABLE_CONFIG
,
EMPTY_STRING_IS_NULL
,
server
.
tls_ctx_config
.
protocols
,
NULL
,
NULL
,
applyTlsCfg
),
createStringConfig
(
"tls-protocols"
,
NULL
,
MODIFIABLE_CONFIG
,
EMPTY_STRING_IS_NULL
,
server
.
tls_ctx_config
.
protocols
,
NULL
,
NULL
,
applyTlsCfg
),
createStringConfig
(
"tls-ciphers"
,
NULL
,
MODIFIABLE_CONFIG
,
EMPTY_STRING_IS_NULL
,
server
.
tls_ctx_config
.
ciphers
,
NULL
,
NULL
,
applyTlsCfg
),
createStringConfig
(
"tls-ciphers"
,
NULL
,
MODIFIABLE_CONFIG
,
EMPTY_STRING_IS_NULL
,
server
.
tls_ctx_config
.
ciphers
,
NULL
,
NULL
,
applyTlsCfg
),
createStringConfig
(
"tls-ciphersuites"
,
NULL
,
MODIFIABLE_CONFIG
,
EMPTY_STRING_IS_NULL
,
server
.
tls_ctx_config
.
ciphersuites
,
NULL
,
NULL
,
applyTlsCfg
),
createStringConfig
(
"tls-ciphersuites"
,
NULL
,
MODIFIABLE_CONFIG
,
EMPTY_STRING_IS_NULL
,
server
.
tls_ctx_config
.
ciphersuites
,
NULL
,
NULL
,
applyTlsCfg
),
...
...
src/db.c
View file @
2667c412
...
@@ -602,18 +602,11 @@ void flushAllDataAndResetRDB(int flags) {
...
@@ -602,18 +602,11 @@ void flushAllDataAndResetRDB(int flags) {
server
.
dirty
+=
emptyData
(
-
1
,
flags
,
NULL
);
server
.
dirty
+=
emptyData
(
-
1
,
flags
,
NULL
);
if
(
server
.
child_type
==
CHILD_TYPE_RDB
)
killRDBChild
();
if
(
server
.
child_type
==
CHILD_TYPE_RDB
)
killRDBChild
();
if
(
server
.
saveparamslen
>
0
)
{
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
;
rdbSaveInfo
rsi
,
*
rsiptr
;
rsiptr
=
rdbPopulateSaveInfo
(
&
rsi
);
rsiptr
=
rdbPopulateSaveInfo
(
&
rsi
);
rdbSave
(
SLAVE_REQ_NONE
,
server
.
rdb_filename
,
rsiptr
);
rdbSave
(
SLAVE_REQ_NONE
,
server
.
rdb_filename
,
rsiptr
);
server
.
dirty
=
saved_dirty
;
}
}
/* Without that extra dirty++, when db was already empty, FLUSHALL will
* not be replicated nor put into the AOF. */
server
.
dirty
++
;
#if defined(USE_JEMALLOC)
#if defined(USE_JEMALLOC)
/* jemalloc 5 doesn't release pages back to the OS when there's no traffic.
/* 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
* for large databases, flushdb blocks for long anyway, so a bit more won't
...
@@ -632,7 +625,13 @@ void flushdbCommand(client *c) {
...
@@ -632,7 +625,13 @@ void flushdbCommand(client *c) {
if
(
getFlushCommandFlags
(
c
,
&
flags
)
==
C_ERR
)
return
;
if
(
getFlushCommandFlags
(
c
,
&
flags
)
==
C_ERR
)
return
;
/* flushdb should not flush the functions */
/* flushdb should not flush the functions */
server
.
dirty
+=
emptyData
(
c
->
db
->
id
,
flags
|
EMPTYDB_NOFUNCTIONS
,
NULL
);
server
.
dirty
+=
emptyData
(
c
->
db
->
id
,
flags
|
EMPTYDB_NOFUNCTIONS
,
NULL
);
/* Without the forceCommandPropagation, when DB was already empty,
* FLUSHDB will not be replicated nor put into the AOF. */
forceCommandPropagation
(
c
,
PROPAGATE_REPL
|
PROPAGATE_AOF
);
addReply
(
c
,
shared
.
ok
);
addReply
(
c
,
shared
.
ok
);
#if defined(USE_JEMALLOC)
#if defined(USE_JEMALLOC)
/* jemalloc 5 doesn't release pages back to the OS when there's no traffic.
/* 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
* for large databases, flushdb blocks for long anyway, so a bit more won't
...
@@ -650,6 +649,11 @@ void flushallCommand(client *c) {
...
@@ -650,6 +649,11 @@ void flushallCommand(client *c) {
if
(
getFlushCommandFlags
(
c
,
&
flags
)
==
C_ERR
)
return
;
if
(
getFlushCommandFlags
(
c
,
&
flags
)
==
C_ERR
)
return
;
/* flushall should not flush the functions */
/* flushall should not flush the functions */
flushAllDataAndResetRDB
(
flags
|
EMPTYDB_NOFUNCTIONS
);
flushAllDataAndResetRDB
(
flags
|
EMPTYDB_NOFUNCTIONS
);
/* Without the forceCommandPropagation, when DBs were already empty,
* FLUSHALL will not be replicated nor put into the AOF. */
forceCommandPropagation
(
c
,
PROPAGATE_REPL
|
PROPAGATE_AOF
);
addReply
(
c
,
shared
.
ok
);
addReply
(
c
,
shared
.
ok
);
}
}
...
@@ -1080,7 +1084,7 @@ void shutdownCommand(client *c) {
...
@@ -1080,7 +1084,7 @@ void shutdownCommand(client *c) {
return
;
return
;
}
}
if
(
!
(
flags
&
SHUTDOWN_NOSAVE
)
&&
scriptIsTimedout
())
{
if
(
!
(
flags
&
SHUTDOWN_NOSAVE
)
&&
isInsideYieldingLongCommand
())
{
/* Script timed out. Shutdown allowed only with the NOSAVE flag. See
/* Script timed out. Shutdown allowed only with the NOSAVE flag. See
* also processCommand where these errors are returned. */
* also processCommand where these errors are returned. */
if
(
server
.
busy_module_yield_flags
&&
server
.
busy_module_yield_reply
)
{
if
(
server
.
busy_module_yield_flags
&&
server
.
busy_module_yield_reply
)
{
...
@@ -1878,7 +1882,6 @@ int getKeysFromCommandWithSpecs(struct redisCommand *cmd, robj **argv, int argc,
...
@@ -1878,7 +1882,6 @@ int getKeysFromCommandWithSpecs(struct redisCommand *cmd, robj **argv, int argc,
/* Flags indicating that we have a getkeys callback */
/* Flags indicating that we have a getkeys callback */
int
has_module_getkeys
=
cmd
->
flags
&
CMD_MODULE_GETKEYS
;
int
has_module_getkeys
=
cmd
->
flags
&
CMD_MODULE_GETKEYS
;
int
has_native_getkeys
=
!
(
cmd
->
flags
&
CMD_MODULE
)
&&
cmd
->
getkeys_proc
;
/* The key-spec that's auto generated by RM_CreateCommand sets VARIABLE_FLAGS since no flags are given.
/* The key-spec that's auto generated by RM_CreateCommand sets VARIABLE_FLAGS since no flags are given.
* If the module provides getkeys callback, we'll prefer it, but if it didn't, we'll use key-spec anyway. */
* If the module provides getkeys callback, we'll prefer it, but if it didn't, we'll use key-spec anyway. */
...
@@ -1900,14 +1903,14 @@ int getKeysFromCommandWithSpecs(struct redisCommand *cmd, robj **argv, int argc,
...
@@ -1900,14 +1903,14 @@ int getKeysFromCommandWithSpecs(struct redisCommand *cmd, robj **argv, int argc,
/* We use native getkeys as a last resort, since not all these native getkeys provide
/* We use native getkeys as a last resort, since not all these native getkeys provide
* flags properly (only the ones that correspond to INVALID, INCOMPLETE or VARIABLE_FLAGS do.*/
* flags properly (only the ones that correspond to INVALID, INCOMPLETE or VARIABLE_FLAGS do.*/
if
(
has_native_
getkeys
)
if
(
cmd
->
getkeys
_proc
)
return
cmd
->
getkeys_proc
(
cmd
,
argv
,
argc
,
result
);
return
cmd
->
getkeys_proc
(
cmd
,
argv
,
argc
,
result
);
return
0
;
return
0
;
}
}
/* This function returns a sanity check if the command may have keys. */
/* This function returns a sanity check if the command may have keys. */
int
doesCommandHaveKeys
(
struct
redisCommand
*
cmd
)
{
int
doesCommandHaveKeys
(
struct
redisCommand
*
cmd
)
{
return
(
!
(
cmd
->
flags
&
CMD_MODULE
)
&&
cmd
->
getkeys_proc
)
||
/* has getkeys_proc (non modules) */
return
cmd
->
getkeys_proc
||
/* has getkeys_proc (non modules) */
(
cmd
->
flags
&
CMD_MODULE_GETKEYS
)
||
/* module with GETKEYS */
(
cmd
->
flags
&
CMD_MODULE_GETKEYS
)
||
/* module with GETKEYS */
(
getAllKeySpecsFlags
(
cmd
,
1
)
&
CMD_KEY_NOT_KEY
);
/* has at least one key-spec not marked as NOT_KEY */
(
getAllKeySpecsFlags
(
cmd
,
1
)
&
CMD_KEY_NOT_KEY
);
/* has at least one key-spec not marked as NOT_KEY */
}
}
...
@@ -2056,7 +2059,7 @@ int getKeysUsingLegacyRangeSpec(struct redisCommand *cmd, robj **argv, int argc,
...
@@ -2056,7 +2059,7 @@ int getKeysUsingLegacyRangeSpec(struct redisCommand *cmd, robj **argv, int argc,
int
getKeysFromCommand
(
struct
redisCommand
*
cmd
,
robj
**
argv
,
int
argc
,
getKeysResult
*
result
)
{
int
getKeysFromCommand
(
struct
redisCommand
*
cmd
,
robj
**
argv
,
int
argc
,
getKeysResult
*
result
)
{
if
(
cmd
->
flags
&
CMD_MODULE_GETKEYS
)
{
if
(
cmd
->
flags
&
CMD_MODULE_GETKEYS
)
{
return
moduleGetCommandKeysViaAPI
(
cmd
,
argv
,
argc
,
result
);
return
moduleGetCommandKeysViaAPI
(
cmd
,
argv
,
argc
,
result
);
}
else
if
(
!
(
cmd
->
flags
&
CMD_MODULE
)
&&
cmd
->
getkeys_proc
)
{
}
else
if
(
cmd
->
getkeys_proc
)
{
return
cmd
->
getkeys_proc
(
cmd
,
argv
,
argc
,
result
);
return
cmd
->
getkeys_proc
(
cmd
,
argv
,
argc
,
result
);
}
else
{
}
else
{
return
getKeysUsingLegacyRangeSpec
(
cmd
,
argv
,
argc
,
result
);
return
getKeysUsingLegacyRangeSpec
(
cmd
,
argv
,
argc
,
result
);
...
...
src/debug.c
View file @
2667c412
...
@@ -2014,7 +2014,9 @@ void bugReportEnd(int killViaSignal, int sig) {
...
@@ -2014,7 +2014,9 @@ void bugReportEnd(int killViaSignal, int sig) {
"
\n
=== REDIS BUG REPORT END. Make sure to include from START to END. ===
\n\n
"
"
\n
=== REDIS BUG REPORT END. Make sure to include from START to END. ===
\n\n
"
" Please report the crash by opening an issue on github:
\n\n
"
" Please report the crash by opening an issue on github:
\n\n
"
" http://github.com/redis/redis/issues
\n\n
"
" http://github.com/redis/redis/issues
\n\n
"
" If a Redis module was involved, please open in the module's repo instead.
\n\n
"
" Suspect RAM error? Use redis-server --test-memory to verify it.
\n\n
"
" Suspect RAM error? Use redis-server --test-memory to verify it.
\n\n
"
" Some other issues could be detected by redis-server --check-system
\n
"
);
);
/* free(messages); Don't call free() with possibly corrupted memory. */
/* free(messages); Don't call free() with possibly corrupted memory. */
...
...
src/eval.c
View file @
2667c412
...
@@ -285,59 +285,61 @@ void scriptingReset(int async) {
...
@@ -285,59 +285,61 @@ void scriptingReset(int async) {
* EVAL and SCRIPT commands implementation
* EVAL and SCRIPT commands implementation
* ------------------------------------------------------------------------- */
* ------------------------------------------------------------------------- */
/* Define a Lua function with the specified body.
static
void
evalCalcFunctionName
(
int
evalsha
,
sds
script
,
char
*
out_funcname
)
{
* The function name will be generated in the following form:
/* We obtain the script SHA1, then check if this function is already
*
* defined into the Lua state */
* f_<hex sha1 sum>
out_funcname
[
0
]
=
'f'
;
*
out_funcname
[
1
]
=
'_'
;
* The function increments the reference count of the 'body' object as a
if
(
!
evalsha
)
{
* side effect of a successful call.
/* Hash the code if this is an EVAL call */
*
sha1hex
(
out_funcname
+
2
,
script
,
sdslen
(
script
));
* On success a pointer to an SDS string representing the function SHA1 of the
}
else
{
* just added function is returned (and will be valid until the next call
/* We already have the SHA if it is an EVALSHA */
* to scriptingReset() function), otherwise NULL is returned.
int
j
;
*
char
*
sha
=
script
;
* The function handles the fact of being called with a script that already
* exists, and in such a case, it behaves like in the success case.
*
* If 'c' is not NULL, on error the client is informed with an appropriate
* error describing the nature of the problem and the Lua interpreter error. */
sds
luaCreateFunction
(
client
*
c
,
robj
*
body
)
{
char
funcname
[
43
];
dictEntry
*
de
;
uint64_t
script_flags
=
SCRIPT_FLAG_EVAL_COMPAT_MODE
;
funcname
[
0
]
=
'f'
;
funcname
[
1
]
=
'_'
;
sha1hex
(
funcname
+
2
,
body
->
ptr
,
sdslen
(
body
->
ptr
));
if
((
de
=
dictFind
(
lctx
.
lua_scripts
,
funcname
+
2
))
!=
NULL
)
{
/* Convert to lowercase. We don't use tolower since the function
return
dictGetKey
(
de
);
* managed to always show up in the profiler output consuming
* a non trivial amount of time. */
for
(
j
=
0
;
j
<
40
;
j
++
)
out_funcname
[
j
+
2
]
=
(
sha
[
j
]
>=
'A'
&&
sha
[
j
]
<=
'Z'
)
?
sha
[
j
]
+
(
'a'
-
'A'
)
:
sha
[
j
];
out_funcname
[
42
]
=
'\0'
;
}
}
}
/* Handle shebang header in script code */
/* Helper function to try and extract shebang flags from the script body.
* If no shebang is found, return with success and COMPAT mode flag.
* The err arg is optional, can be used to get a detailed error string.
* The out_shebang_len arg is optional, can be used to trim the shebang from the script.
* Returns C_OK on success, and C_ERR on error. */
int
evalExtractShebangFlags
(
sds
body
,
uint64_t
*
out_flags
,
ssize_t
*
out_shebang_len
,
sds
*
err
)
{
ssize_t
shebang_len
=
0
;
ssize_t
shebang_len
=
0
;
if
(
!
strncmp
(
body
->
ptr
,
"#!"
,
2
))
{
uint64_t
script_flags
=
SCRIPT_FLAG_EVAL_COMPAT_MODE
;
if
(
!
strncmp
(
body
,
"#!"
,
2
))
{
int
numparts
,
j
;
int
numparts
,
j
;
char
*
shebang_end
=
strchr
(
body
->
ptr
,
'\n'
);
char
*
shebang_end
=
strchr
(
body
,
'\n'
);
if
(
shebang_end
==
NULL
)
{
if
(
shebang_end
==
NULL
)
{
addReplyError
(
c
,
"Invalid script shebang"
);
if
(
err
)
return
NULL
;
*
err
=
sdsnew
(
"Invalid script shebang"
);
return
C_ERR
;
}
}
shebang_len
=
shebang_end
-
(
char
*
)
body
->
ptr
;
shebang_len
=
shebang_end
-
body
;
sds
shebang
=
sdsnewlen
(
body
->
ptr
,
shebang_len
);
sds
shebang
=
sdsnewlen
(
body
,
shebang_len
);
sds
*
parts
=
sdssplitargs
(
shebang
,
&
numparts
);
sds
*
parts
=
sdssplitargs
(
shebang
,
&
numparts
);
sdsfree
(
shebang
);
sdsfree
(
shebang
);
if
(
!
parts
||
numparts
==
0
)
{
if
(
!
parts
||
numparts
==
0
)
{
addReplyError
(
c
,
"Invalid engine in script shebang"
);
if
(
err
)
*
err
=
sdsnew
(
"Invalid engine in script shebang"
);
sdsfreesplitres
(
parts
,
numparts
);
sdsfreesplitres
(
parts
,
numparts
);
return
NULL
;
return
C_ERR
;
}
}
/* Verify lua interpreter was specified */
/* Verify lua interpreter was specified */
if
(
strcmp
(
parts
[
0
],
"#!lua"
))
{
if
(
strcmp
(
parts
[
0
],
"#!lua"
))
{
addReplyErrorFormat
(
c
,
"Unexpected engine in script shebang: %s"
,
parts
[
0
]);
if
(
err
)
*
err
=
sdscatfmt
(
sdsempty
(),
"Unexpected engine in script shebang: %s"
,
parts
[
0
]);
sdsfreesplitres
(
parts
,
numparts
);
sdsfreesplitres
(
parts
,
numparts
);
return
NULL
;
return
C_ERR
;
}
}
script_flags
&=
~
SCRIPT_FLAG_EVAL_COMPAT_MODE
;
script_flags
&=
~
SCRIPT_FLAG_EVAL_COMPAT_MODE
;
for
(
j
=
1
;
j
<
numparts
;
j
++
)
{
for
(
j
=
1
;
j
<
numparts
;
j
++
)
{
...
@@ -351,23 +353,93 @@ sds luaCreateFunction(client *c, robj *body) {
...
@@ -351,23 +353,93 @@ sds luaCreateFunction(client *c, robj *body) {
if
(
!
strcmp
(
flags
[
jj
],
sf
->
str
))
break
;
if
(
!
strcmp
(
flags
[
jj
],
sf
->
str
))
break
;
}
}
if
(
!
sf
->
flag
)
{
if
(
!
sf
->
flag
)
{
addReplyErrorFormat
(
c
,
"Unexpected flag in script shebang: %s"
,
flags
[
jj
]);
if
(
err
)
*
err
=
sdscatfmt
(
sdsempty
(),
"Unexpected flag in script shebang: %s"
,
flags
[
jj
]);
sdsfreesplitres
(
flags
,
numflags
);
sdsfreesplitres
(
flags
,
numflags
);
sdsfreesplitres
(
parts
,
numparts
);
sdsfreesplitres
(
parts
,
numparts
);
return
NULL
;
return
C_ERR
;
}
}
script_flags
|=
sf
->
flag
;
script_flags
|=
sf
->
flag
;
}
}
sdsfreesplitres
(
flags
,
numflags
);
sdsfreesplitres
(
flags
,
numflags
);
}
else
{
}
else
{
/* We only support function flags options for lua scripts */
/* We only support function flags options for lua scripts */
addReplyErrorFormat
(
c
,
"Unknown lua shebang option: %s"
,
parts
[
j
]);
if
(
err
)
*
err
=
sdscatfmt
(
sdsempty
(),
"Unknown lua shebang option: %s"
,
parts
[
j
]);
sdsfreesplitres
(
parts
,
numparts
);
sdsfreesplitres
(
parts
,
numparts
);
return
NULL
;
return
C_ERR
;
}
}
}
}
sdsfreesplitres
(
parts
,
numparts
);
sdsfreesplitres
(
parts
,
numparts
);
}
}
if
(
out_shebang_len
)
*
out_shebang_len
=
shebang_len
;
*
out_flags
=
script_flags
;
return
C_OK
;
}
/* Try to extract command flags if we can, returns the modified flags.
* Note that it does not guarantee the command arguments are right. */
uint64_t
evalGetCommandFlags
(
client
*
c
,
uint64_t
cmd_flags
)
{
char
funcname
[
43
];
int
evalsha
=
c
->
cmd
->
proc
==
evalShaCommand
||
c
->
cmd
->
proc
==
evalShaRoCommand
;
if
(
evalsha
&&
sdslen
(
c
->
argv
[
1
]
->
ptr
)
!=
40
)
return
cmd_flags
;
evalCalcFunctionName
(
evalsha
,
c
->
argv
[
1
]
->
ptr
,
funcname
);
char
*
lua_cur_script
=
funcname
+
2
;
dictEntry
*
de
=
dictFind
(
lctx
.
lua_scripts
,
lua_cur_script
);
uint64_t
script_flags
;
if
(
!
de
)
{
if
(
evalsha
)
return
cmd_flags
;
if
(
evalExtractShebangFlags
(
c
->
argv
[
1
]
->
ptr
,
&
script_flags
,
NULL
,
NULL
)
==
C_ERR
)
return
cmd_flags
;
}
else
{
luaScript
*
l
=
dictGetVal
(
de
);
script_flags
=
l
->
flags
;
}
if
(
script_flags
&
SCRIPT_FLAG_EVAL_COMPAT_MODE
)
return
cmd_flags
;
return
scriptFlagsToCmdFlags
(
cmd_flags
,
script_flags
);
}
/* Define a Lua function with the specified body.
* The function name will be generated in the following form:
*
* f_<hex sha1 sum>
*
* The function increments the reference count of the 'body' object as a
* side effect of a successful call.
*
* On success a pointer to an SDS string representing the function SHA1 of the
* just added function is returned (and will be valid until the next call
* to scriptingReset() function), otherwise NULL is returned.
*
* The function handles the fact of being called with a script that already
* exists, and in such a case, it behaves like in the success case.
*
* If 'c' is not NULL, on error the client is informed with an appropriate
* error describing the nature of the problem and the Lua interpreter error. */
sds
luaCreateFunction
(
client
*
c
,
robj
*
body
)
{
char
funcname
[
43
];
dictEntry
*
de
;
uint64_t
script_flags
;
funcname
[
0
]
=
'f'
;
funcname
[
1
]
=
'_'
;
sha1hex
(
funcname
+
2
,
body
->
ptr
,
sdslen
(
body
->
ptr
));
if
((
de
=
dictFind
(
lctx
.
lua_scripts
,
funcname
+
2
))
!=
NULL
)
{
return
dictGetKey
(
de
);
}
/* Handle shebang header in script code */
ssize_t
shebang_len
=
0
;
sds
err
=
NULL
;
if
(
evalExtractShebangFlags
(
body
->
ptr
,
&
script_flags
,
&
shebang_len
,
&
err
)
==
C_ERR
)
{
addReplyErrorSds
(
c
,
err
);
return
NULL
;
}
/* Note that in case of a shebang line we skip it but keep the line feed to conserve the user's line numbers */
/* Note that in case of a shebang line we skip it but keep the line feed to conserve the user's line numbers */
if
(
luaL_loadbuffer
(
lctx
.
lua
,(
char
*
)
body
->
ptr
+
shebang_len
,
sdslen
(
body
->
ptr
)
-
shebang_len
,
"@user_script"
))
{
if
(
luaL_loadbuffer
(
lctx
.
lua
,(
char
*
)
body
->
ptr
+
shebang_len
,
sdslen
(
body
->
ptr
)
-
shebang_len
,
"@user_script"
))
{
...
@@ -430,26 +502,7 @@ void evalGenericCommand(client *c, int evalsha) {
...
@@ -430,26 +502,7 @@ void evalGenericCommand(client *c, int evalsha) {
return
;
return
;
}
}
/* We obtain the script SHA1, then check if this function is already
evalCalcFunctionName
(
evalsha
,
c
->
argv
[
1
]
->
ptr
,
funcname
);
* defined into the Lua state */
funcname
[
0
]
=
'f'
;
funcname
[
1
]
=
'_'
;
if
(
!
evalsha
)
{
/* Hash the code if this is an EVAL call */
sha1hex
(
funcname
+
2
,
c
->
argv
[
1
]
->
ptr
,
sdslen
(
c
->
argv
[
1
]
->
ptr
));
}
else
{
/* We already have the SHA if it is an EVALSHA */
int
j
;
char
*
sha
=
c
->
argv
[
1
]
->
ptr
;
/* Convert to lowercase. We don't use tolower since the function
* managed to always show up in the profiler output consuming
* a non trivial amount of time. */
for
(
j
=
0
;
j
<
40
;
j
++
)
funcname
[
j
+
2
]
=
(
sha
[
j
]
>=
'A'
&&
sha
[
j
]
<=
'Z'
)
?
sha
[
j
]
+
(
'a'
-
'A'
)
:
sha
[
j
];
funcname
[
42
]
=
'\0'
;
}
/* Push the pcall error handler function on the stack. */
/* Push the pcall error handler function on the stack. */
lua_getglobal
(
lua
,
"__redis__err__handler"
);
lua_getglobal
(
lua
,
"__redis__err__handler"
);
...
...
src/evict.c
View file @
2667c412
...
@@ -481,7 +481,7 @@ void startEvictionTimeProc(void) {
...
@@ -481,7 +481,7 @@ void startEvictionTimeProc(void) {
static
int
isSafeToPerformEvictions
(
void
)
{
static
int
isSafeToPerformEvictions
(
void
)
{
/* - There must be no script in timeout condition.
/* - There must be no script in timeout condition.
* - Nor we are loading data right now. */
* - Nor we are loading data right now. */
if
(
scriptIsTimedout
()
||
server
.
loading
)
return
0
;
if
(
isInsideYieldingLongCommand
()
||
server
.
loading
)
return
0
;
/* By default replicas should ignore maxmemory
/* By default replicas should ignore maxmemory
* and just be masters exact copies. */
* and just be masters exact copies. */
...
...
src/expire.c
View file @
2667c412
...
@@ -662,22 +662,22 @@ void expireGenericCommand(client *c, long long basetime, int unit) {
...
@@ -662,22 +662,22 @@ void expireGenericCommand(client *c, long long basetime, int unit) {
}
}
}
}
/* EXPIRE key seconds */
/* EXPIRE key seconds
[ NX | XX | GT | LT]
*/
void
expireCommand
(
client
*
c
)
{
void
expireCommand
(
client
*
c
)
{
expireGenericCommand
(
c
,
mstime
(),
UNIT_SECONDS
);
expireGenericCommand
(
c
,
mstime
(),
UNIT_SECONDS
);
}
}
/* EXPIREAT key
time
*/
/* EXPIREAT key
unix-time-seconds [ NX | XX | GT | LT]
*/
void
expireatCommand
(
client
*
c
)
{
void
expireatCommand
(
client
*
c
)
{
expireGenericCommand
(
c
,
0
,
UNIT_SECONDS
);
expireGenericCommand
(
c
,
0
,
UNIT_SECONDS
);
}
}
/* PEXPIRE key milliseconds */
/* PEXPIRE key milliseconds
[ NX | XX | GT | LT]
*/
void
pexpireCommand
(
client
*
c
)
{
void
pexpireCommand
(
client
*
c
)
{
expireGenericCommand
(
c
,
mstime
(),
UNIT_MILLISECONDS
);
expireGenericCommand
(
c
,
mstime
(),
UNIT_MILLISECONDS
);
}
}
/* PEXPIREAT key
ms_time
*/
/* PEXPIREAT key
unix-time-milliseconds [ NX | XX | GT | LT]
*/
void
pexpireatCommand
(
client
*
c
)
{
void
pexpireatCommand
(
client
*
c
)
{
expireGenericCommand
(
c
,
0
,
UNIT_MILLISECONDS
);
expireGenericCommand
(
c
,
0
,
UNIT_MILLISECONDS
);
}
}
...
...
Prev
1
2
3
4
5
6
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