Allow most CONFIG SET during loading, block some commands in async-loading (#9878)
## background Till now CONFIG SET was blocked during loading. (In the not so distant past, GET was disallowed too) We recently (not released yet) added an async-loading mode, see #9323, and during that time it'll serve CONFIG SET and any other command. And now we realized (#9770) that some configs, and commands are dangerous during async-loading. ## changes * Allow most CONFIG SET during loading (both on async-loading and normal loading) * Allow CONFIG REWRITE and CONFIG RESETSTAT during loading * Block a few config during loading (`appendonly`, `repl-diskless-load`, and `dir`) * Block a few commands during loading (list below) ## the blocked commands: * SAVE - obviously we don't wanna start a foregreound save during loading 8-) * BGSAVE - we don't mind to schedule one, but we don't wanna fork now * BGREWRITEAOF - we don't mind to schedule one, but we don't wanna fork now * MODULE - we obviously don't wanna unload a module during replication / rdb loading (MODULE HELP and MODULE LIST are not blocked) * SYNC / PSYNC - we're in the middle of RDB loading from master, must not allow sync requests now. * REPLICAOF / SLAVEOF - we're in the middle of replicating, maybe it makes sense to let the user abort it, but he couldn't do that so far, i don't wanna take any risk of bugs due to odd state. * CLUSTER - only allow [HELP, SLOTS, NODES, INFO, MYID, LINKS, KEYSLOT, COUNTKEYSINSLOT, GETKEYSINSLOT, RESET, REPLICAS, COUNT_FAILURE_REPORTS], for others, preserve the status quo ## other fixes * processEventsWhileBlocked had an issue when being nested, this could happen with a busy script during async loading (new), but also in a busy script during AOF loading (old). this lead to a crash in the scenario described in #6988
This commit is contained in:
parent
ad55fbaabb
commit
41e6e05dee
@ -546,30 +546,30 @@ commandHistory CLUSTER_SLOTS_History[] = {
|
||||
|
||||
/* CLUSTER command table */
|
||||
struct redisCommand CLUSTER_Subcommands[] = {
|
||||
{"addslots","Assign new hash slots to receiving node","O(N) where N is the total number of hash slot arguments","3.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_CLUSTER,CLUSTER_ADDSLOTS_History,CLUSTER_ADDSLOTS_Hints,clusterCommand,-3,CMD_ADMIN|CMD_RANDOM|CMD_STALE,0,.args=CLUSTER_ADDSLOTS_Args},
|
||||
{"addslotsrange","Assign new hash slots to receiving node","O(N) where N is the total number of the slots between the start slot and end slot arguments.","7.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_CLUSTER,CLUSTER_ADDSLOTSRANGE_History,CLUSTER_ADDSLOTSRANGE_Hints,clusterCommand,-4,CMD_ADMIN|CMD_RANDOM|CMD_STALE,0,.args=CLUSTER_ADDSLOTSRANGE_Args},
|
||||
{"bumpepoch","Advance the cluster config epoch","O(1)","3.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_CLUSTER,CLUSTER_BUMPEPOCH_History,CLUSTER_BUMPEPOCH_Hints,clusterCommand,2,CMD_ADMIN|CMD_RANDOM|CMD_STALE,0},
|
||||
{"addslots","Assign new hash slots to receiving node","O(N) where N is the total number of hash slot arguments","3.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_CLUSTER,CLUSTER_ADDSLOTS_History,CLUSTER_ADDSLOTS_Hints,clusterCommand,-3,CMD_NO_ASYNC_LOADING|CMD_ADMIN|CMD_RANDOM|CMD_STALE,0,.args=CLUSTER_ADDSLOTS_Args},
|
||||
{"addslotsrange","Assign new hash slots to receiving node","O(N) where N is the total number of the slots between the start slot and end slot arguments.","7.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_CLUSTER,CLUSTER_ADDSLOTSRANGE_History,CLUSTER_ADDSLOTSRANGE_Hints,clusterCommand,-4,CMD_NO_ASYNC_LOADING|CMD_ADMIN|CMD_RANDOM|CMD_STALE,0,.args=CLUSTER_ADDSLOTSRANGE_Args},
|
||||
{"bumpepoch","Advance the cluster config epoch","O(1)","3.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_CLUSTER,CLUSTER_BUMPEPOCH_History,CLUSTER_BUMPEPOCH_Hints,clusterCommand,2,CMD_NO_ASYNC_LOADING|CMD_ADMIN|CMD_RANDOM|CMD_STALE,0},
|
||||
{"count-failure-reports","Return the number of failure reports active for a given node","O(N) where N is the number of failure reports","3.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_CLUSTER,CLUSTER_COUNT_FAILURE_REPORTS_History,CLUSTER_COUNT_FAILURE_REPORTS_Hints,clusterCommand,3,CMD_ADMIN|CMD_RANDOM|CMD_STALE,0,.args=CLUSTER_COUNT_FAILURE_REPORTS_Args},
|
||||
{"countkeysinslot","Return the number of local keys in the specified hash slot","O(1)","3.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_CLUSTER,CLUSTER_COUNTKEYSINSLOT_History,CLUSTER_COUNTKEYSINSLOT_Hints,clusterCommand,3,CMD_RANDOM|CMD_STALE,0,.args=CLUSTER_COUNTKEYSINSLOT_Args},
|
||||
{"delslots","Set hash slots as unbound in receiving node","O(N) where N is the total number of hash slot arguments","3.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_CLUSTER,CLUSTER_DELSLOTS_History,CLUSTER_DELSLOTS_Hints,clusterCommand,-3,CMD_ADMIN|CMD_RANDOM|CMD_STALE,0,.args=CLUSTER_DELSLOTS_Args},
|
||||
{"delslotsrange","Set hash slots as unbound in receiving node","O(N) where N is the total number of the slots between the start slot and end slot arguments.","7.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_CLUSTER,CLUSTER_DELSLOTSRANGE_History,CLUSTER_DELSLOTSRANGE_Hints,clusterCommand,-4,CMD_ADMIN|CMD_RANDOM|CMD_STALE,0,.args=CLUSTER_DELSLOTSRANGE_Args},
|
||||
{"failover","Forces a replica to perform a manual failover of its master.","O(1)","3.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_CLUSTER,CLUSTER_FAILOVER_History,CLUSTER_FAILOVER_Hints,clusterCommand,-2,CMD_ADMIN|CMD_RANDOM|CMD_STALE,0,.args=CLUSTER_FAILOVER_Args},
|
||||
{"flushslots","Delete a node's own slots information","O(1)","3.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_CLUSTER,CLUSTER_FLUSHSLOTS_History,CLUSTER_FLUSHSLOTS_Hints,clusterCommand,2,CMD_ADMIN|CMD_RANDOM|CMD_STALE,0},
|
||||
{"forget","Remove a node from the nodes table","O(1)","3.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_CLUSTER,CLUSTER_FORGET_History,CLUSTER_FORGET_Hints,clusterCommand,3,CMD_ADMIN|CMD_RANDOM|CMD_STALE,0,.args=CLUSTER_FORGET_Args},
|
||||
{"delslots","Set hash slots as unbound in receiving node","O(N) where N is the total number of hash slot arguments","3.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_CLUSTER,CLUSTER_DELSLOTS_History,CLUSTER_DELSLOTS_Hints,clusterCommand,-3,CMD_NO_ASYNC_LOADING|CMD_ADMIN|CMD_RANDOM|CMD_STALE,0,.args=CLUSTER_DELSLOTS_Args},
|
||||
{"delslotsrange","Set hash slots as unbound in receiving node","O(N) where N is the total number of the slots between the start slot and end slot arguments.","7.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_CLUSTER,CLUSTER_DELSLOTSRANGE_History,CLUSTER_DELSLOTSRANGE_Hints,clusterCommand,-4,CMD_NO_ASYNC_LOADING|CMD_ADMIN|CMD_RANDOM|CMD_STALE,0,.args=CLUSTER_DELSLOTSRANGE_Args},
|
||||
{"failover","Forces a replica to perform a manual failover of its master.","O(1)","3.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_CLUSTER,CLUSTER_FAILOVER_History,CLUSTER_FAILOVER_Hints,clusterCommand,-2,CMD_NO_ASYNC_LOADING|CMD_ADMIN|CMD_RANDOM|CMD_STALE,0,.args=CLUSTER_FAILOVER_Args},
|
||||
{"flushslots","Delete a node's own slots information","O(1)","3.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_CLUSTER,CLUSTER_FLUSHSLOTS_History,CLUSTER_FLUSHSLOTS_Hints,clusterCommand,2,CMD_NO_ASYNC_LOADING|CMD_ADMIN|CMD_RANDOM|CMD_STALE,0},
|
||||
{"forget","Remove a node from the nodes table","O(1)","3.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_CLUSTER,CLUSTER_FORGET_History,CLUSTER_FORGET_Hints,clusterCommand,3,CMD_NO_ASYNC_LOADING|CMD_ADMIN|CMD_RANDOM|CMD_STALE,0,.args=CLUSTER_FORGET_Args},
|
||||
{"getkeysinslot","Return local key names in the specified hash slot","O(log(N)) where N is the number of requested keys","3.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_CLUSTER,CLUSTER_GETKEYSINSLOT_History,CLUSTER_GETKEYSINSLOT_Hints,clusterCommand,4,CMD_RANDOM|CMD_STALE,0,.args=CLUSTER_GETKEYSINSLOT_Args},
|
||||
{"help","Show helpful text about the different subcommands","O(1)","5.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_CLUSTER,CLUSTER_HELP_History,CLUSTER_HELP_Hints,clusterCommand,2,CMD_LOADING|CMD_STALE,0},
|
||||
{"info","Provides info about Redis Cluster node state","O(1)","3.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_CLUSTER,CLUSTER_INFO_History,CLUSTER_INFO_Hints,clusterCommand,2,CMD_RANDOM|CMD_STALE,0},
|
||||
{"keyslot","Returns the hash slot of the specified key","O(N) where N is the number of bytes in the key","3.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_CLUSTER,CLUSTER_KEYSLOT_History,CLUSTER_KEYSLOT_Hints,clusterCommand,3,CMD_RANDOM|CMD_STALE,0,.args=CLUSTER_KEYSLOT_Args},
|
||||
{"links","Returns a list of all TCP links to and from peer nodes in cluster","O(N) where N is the total number of Cluster nodes","7.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_CLUSTER,CLUSTER_LINKS_History,CLUSTER_LINKS_Hints,clusterCommand,2,CMD_RANDOM|CMD_STALE,0},
|
||||
{"meet","Force a node cluster to handshake with another node","O(1)","3.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_CLUSTER,CLUSTER_MEET_History,CLUSTER_MEET_Hints,clusterCommand,-4,CMD_ADMIN|CMD_RANDOM|CMD_STALE,0,.args=CLUSTER_MEET_Args},
|
||||
{"meet","Force a node cluster to handshake with another node","O(1)","3.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_CLUSTER,CLUSTER_MEET_History,CLUSTER_MEET_Hints,clusterCommand,-4,CMD_NO_ASYNC_LOADING|CMD_ADMIN|CMD_RANDOM|CMD_STALE,0,.args=CLUSTER_MEET_Args},
|
||||
{"myid","Return the node id","O(1)","3.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_CLUSTER,CLUSTER_MYID_History,CLUSTER_MYID_Hints,clusterCommand,2,CMD_RANDOM|CMD_STALE,0},
|
||||
{"nodes","Get Cluster config for the node","O(N) where N is the total number of Cluster nodes","3.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_CLUSTER,CLUSTER_NODES_History,CLUSTER_NODES_Hints,clusterCommand,2,CMD_RANDOM|CMD_STALE,0},
|
||||
{"replicas","List replica nodes of the specified master node","O(1)","5.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_CLUSTER,CLUSTER_REPLICAS_History,CLUSTER_REPLICAS_Hints,clusterCommand,3,CMD_ADMIN|CMD_RANDOM|CMD_STALE,0,.args=CLUSTER_REPLICAS_Args},
|
||||
{"replicate","Reconfigure a node as a replica of the specified master node","O(1)","3.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_CLUSTER,CLUSTER_REPLICATE_History,CLUSTER_REPLICATE_Hints,clusterCommand,3,CMD_ADMIN|CMD_RANDOM|CMD_STALE,0,.args=CLUSTER_REPLICATE_Args},
|
||||
{"replicate","Reconfigure a node as a replica of the specified master node","O(1)","3.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_CLUSTER,CLUSTER_REPLICATE_History,CLUSTER_REPLICATE_Hints,clusterCommand,3,CMD_NO_ASYNC_LOADING|CMD_ADMIN|CMD_RANDOM|CMD_STALE,0,.args=CLUSTER_REPLICATE_Args},
|
||||
{"reset","Reset a Redis Cluster node","O(N) where N is the number of known nodes. The command may execute a FLUSHALL as a side effect.","3.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_CLUSTER,CLUSTER_RESET_History,CLUSTER_RESET_Hints,clusterCommand,3,CMD_ADMIN|CMD_RANDOM|CMD_STALE|CMD_NOSCRIPT,0,.args=CLUSTER_RESET_Args},
|
||||
{"saveconfig","Forces the node to save cluster state on disk","O(1)","3.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_CLUSTER,CLUSTER_SAVECONFIG_History,CLUSTER_SAVECONFIG_Hints,clusterCommand,2,CMD_ADMIN|CMD_RANDOM|CMD_STALE,0},
|
||||
{"set-config-epoch","Set the configuration epoch in a new node","O(1)","3.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_CLUSTER,CLUSTER_SET_CONFIG_EPOCH_History,CLUSTER_SET_CONFIG_EPOCH_Hints,clusterCommand,3,CMD_ADMIN|CMD_RANDOM|CMD_STALE,0,.args=CLUSTER_SET_CONFIG_EPOCH_Args},
|
||||
{"setslot","Bind a hash slot to a specific node","O(1)","3.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_CLUSTER,CLUSTER_SETSLOT_History,CLUSTER_SETSLOT_Hints,clusterCommand,-4,CMD_ADMIN|CMD_RANDOM|CMD_STALE,0,.args=CLUSTER_SETSLOT_Args},
|
||||
{"saveconfig","Forces the node to save cluster state on disk","O(1)","3.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_CLUSTER,CLUSTER_SAVECONFIG_History,CLUSTER_SAVECONFIG_Hints,clusterCommand,2,CMD_NO_ASYNC_LOADING|CMD_ADMIN|CMD_RANDOM|CMD_STALE,0},
|
||||
{"set-config-epoch","Set the configuration epoch in a new node","O(1)","3.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_CLUSTER,CLUSTER_SET_CONFIG_EPOCH_History,CLUSTER_SET_CONFIG_EPOCH_Hints,clusterCommand,3,CMD_NO_ASYNC_LOADING|CMD_ADMIN|CMD_RANDOM|CMD_STALE,0,.args=CLUSTER_SET_CONFIG_EPOCH_Args},
|
||||
{"setslot","Bind a hash slot to a specific node","O(1)","3.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_CLUSTER,CLUSTER_SETSLOT_History,CLUSTER_SETSLOT_Hints,clusterCommand,-4,CMD_NO_ASYNC_LOADING|CMD_ADMIN|CMD_RANDOM|CMD_STALE,0,.args=CLUSTER_SETSLOT_Args},
|
||||
{"slots","Get array of Cluster slot to node mappings","O(N) where N is the total number of Cluster nodes","3.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_CLUSTER,CLUSTER_SLOTS_History,CLUSTER_SLOTS_Hints,clusterCommand,2,CMD_RANDOM|CMD_STALE,0},
|
||||
{0}
|
||||
};
|
||||
@ -3804,9 +3804,9 @@ struct redisCommandArg CONFIG_SET_Args[] = {
|
||||
struct redisCommand CONFIG_Subcommands[] = {
|
||||
{"get","Get the values of configuration parameters","O(N) when N is the number of configuration parameters provided","2.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SERVER,CONFIG_GET_History,CONFIG_GET_Hints,configGetCommand,-3,CMD_ADMIN|CMD_NOSCRIPT|CMD_LOADING|CMD_STALE,0,.args=CONFIG_GET_Args},
|
||||
{"help","Show helpful text about the different subcommands","O(1)","5.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SERVER,CONFIG_HELP_History,CONFIG_HELP_Hints,configHelpCommand,2,CMD_LOADING|CMD_STALE,0},
|
||||
{"resetstat","Reset the stats returned by INFO","O(1)","2.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SERVER,CONFIG_RESETSTAT_History,CONFIG_RESETSTAT_Hints,configResetStatCommand,2,CMD_ADMIN|CMD_NOSCRIPT|CMD_STALE,0},
|
||||
{"rewrite","Rewrite the configuration file with the in memory configuration","O(1)","2.8.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SERVER,CONFIG_REWRITE_History,CONFIG_REWRITE_Hints,configRewriteCommand,2,CMD_ADMIN|CMD_NOSCRIPT|CMD_STALE,0},
|
||||
{"set","Set configuration parameters to the given values","O(N) when N is the number of configuration parameters provided","2.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SERVER,CONFIG_SET_History,CONFIG_SET_Hints,configSetCommand,-4,CMD_ADMIN|CMD_NOSCRIPT|CMD_STALE,0,.args=CONFIG_SET_Args},
|
||||
{"resetstat","Reset the stats returned by INFO","O(1)","2.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SERVER,CONFIG_RESETSTAT_History,CONFIG_RESETSTAT_Hints,configResetStatCommand,2,CMD_ADMIN|CMD_NOSCRIPT|CMD_LOADING|CMD_STALE,0},
|
||||
{"rewrite","Rewrite the configuration file with the in memory configuration","O(1)","2.8.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SERVER,CONFIG_REWRITE_History,CONFIG_REWRITE_Hints,configRewriteCommand,2,CMD_ADMIN|CMD_NOSCRIPT|CMD_LOADING|CMD_STALE,0},
|
||||
{"set","Set configuration parameters to the given values","O(N) when N is the number of configuration parameters provided","2.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SERVER,CONFIG_SET_History,CONFIG_SET_Hints,configSetCommand,-4,CMD_ADMIN|CMD_NOSCRIPT|CMD_LOADING|CMD_STALE,0,.args=CONFIG_SET_Args},
|
||||
{0}
|
||||
};
|
||||
|
||||
@ -4148,8 +4148,8 @@ struct redisCommandArg MODULE_UNLOAD_Args[] = {
|
||||
struct redisCommand MODULE_Subcommands[] = {
|
||||
{"help","Show helpful text about the different subcommands","O(1)","5.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SERVER,MODULE_HELP_History,MODULE_HELP_Hints,moduleCommand,2,CMD_LOADING|CMD_STALE,0},
|
||||
{"list","List all modules loaded by the server","O(N) where N is the number of loaded modules.","4.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SERVER,MODULE_LIST_History,MODULE_LIST_Hints,moduleCommand,2,CMD_ADMIN|CMD_NOSCRIPT,0},
|
||||
{"load","Load a module","O(1)","4.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SERVER,MODULE_LOAD_History,MODULE_LOAD_Hints,moduleCommand,-3,CMD_ADMIN|CMD_NOSCRIPT|CMD_PROTECTED,0,.args=MODULE_LOAD_Args},
|
||||
{"unload","Unload a module","O(1)","4.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SERVER,MODULE_UNLOAD_History,MODULE_UNLOAD_Hints,moduleCommand,3,CMD_ADMIN|CMD_NOSCRIPT|CMD_PROTECTED,0,.args=MODULE_UNLOAD_Args},
|
||||
{"load","Load a module","O(1)","4.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SERVER,MODULE_LOAD_History,MODULE_LOAD_Hints,moduleCommand,-3,CMD_NO_ASYNC_LOADING|CMD_ADMIN|CMD_NOSCRIPT|CMD_PROTECTED,0,.args=MODULE_LOAD_Args},
|
||||
{"unload","Unload a module","O(1)","4.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SERVER,MODULE_UNLOAD_History,MODULE_UNLOAD_Hints,moduleCommand,3,CMD_NO_ASYNC_LOADING|CMD_ADMIN|CMD_NOSCRIPT|CMD_PROTECTED,0,.args=MODULE_UNLOAD_Args},
|
||||
{0}
|
||||
};
|
||||
|
||||
@ -6426,8 +6426,8 @@ struct redisCommand redisCommandTable[] = {
|
||||
{"sentinel","A container for Sentinel commands","Depends on subcommand.","2.8.4",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SENTINEL,SENTINEL_History,SENTINEL_Hints,NULL,-2,CMD_ADMIN|CMD_SENTINEL|CMD_ONLY_SENTINEL,0,.subcommands=SENTINEL_Subcommands},
|
||||
/* server */
|
||||
{"acl","A container for Access List Control commands ","Depends on subcommand.","6.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SERVER,ACL_History,ACL_Hints,NULL,-2,CMD_SENTINEL,0,.subcommands=ACL_Subcommands},
|
||||
{"bgrewriteaof","Asynchronously rewrite the append-only file","O(1)","1.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SERVER,BGREWRITEAOF_History,BGREWRITEAOF_Hints,bgrewriteaofCommand,1,CMD_ADMIN|CMD_NOSCRIPT,0},
|
||||
{"bgsave","Asynchronously save the dataset to disk","O(1)","1.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SERVER,BGSAVE_History,BGSAVE_Hints,bgsaveCommand,-1,CMD_ADMIN|CMD_NOSCRIPT,0,.args=BGSAVE_Args},
|
||||
{"bgrewriteaof","Asynchronously rewrite the append-only file","O(1)","1.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SERVER,BGREWRITEAOF_History,BGREWRITEAOF_Hints,bgrewriteaofCommand,1,CMD_NO_ASYNC_LOADING|CMD_ADMIN|CMD_NOSCRIPT,0},
|
||||
{"bgsave","Asynchronously save the dataset to disk","O(1)","1.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SERVER,BGSAVE_History,BGSAVE_Hints,bgsaveCommand,-1,CMD_NO_ASYNC_LOADING|CMD_ADMIN|CMD_NOSCRIPT,0,.args=BGSAVE_Args},
|
||||
{"command","Get array of Redis command details","O(N) where N is the total number of Redis commands","2.8.13",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SERVER,COMMAND_History,COMMAND_Hints,commandCommand,-1,CMD_RANDOM|CMD_LOADING|CMD_STALE|CMD_SENTINEL,ACL_CATEGORY_CONNECTION,.subcommands=COMMAND_Subcommands},
|
||||
{"config","A container for server configuration commands","Depends on subcommand.","2.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SERVER,CONFIG_History,CONFIG_Hints,NULL,-2,0,0,.subcommands=CONFIG_Subcommands},
|
||||
{"dbsize","Return the number of keys in the selected database","O(1)","1.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SERVER,DBSIZE_History,DBSIZE_Hints,dbsizeCommand,1,CMD_READONLY|CMD_FAST,ACL_CATEGORY_KEYSPACE},
|
||||
@ -6442,17 +6442,17 @@ struct redisCommand redisCommandTable[] = {
|
||||
{"memory","A container for memory diagnostics commands","Depends on subcommand.","4.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SERVER,MEMORY_History,MEMORY_Hints,NULL,-2,0,0,.subcommands=MEMORY_Subcommands},
|
||||
{"module","A container for module commands","Depends on subcommand.","4.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SERVER,MODULE_History,MODULE_Hints,NULL,-2,0,0,.subcommands=MODULE_Subcommands},
|
||||
{"monitor","Listen for all requests received by the server in real time",NULL,"1.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SERVER,MONITOR_History,MONITOR_Hints,monitorCommand,1,CMD_ADMIN|CMD_NOSCRIPT|CMD_LOADING|CMD_STALE,0},
|
||||
{"psync","Internal command used for replication",NULL,"2.8.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SERVER,PSYNC_History,PSYNC_Hints,syncCommand,-3,CMD_ADMIN|CMD_NOSCRIPT,0,.args=PSYNC_Args},
|
||||
{"psync","Internal command used for replication",NULL,"2.8.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SERVER,PSYNC_History,PSYNC_Hints,syncCommand,-3,CMD_NO_ASYNC_LOADING|CMD_ADMIN|CMD_NOSCRIPT,0,.args=PSYNC_Args},
|
||||
{"replconf","An internal command for configuring the replication stream","O(1)","3.0.0",CMD_DOC_SYSCMD,NULL,NULL,COMMAND_GROUP_SERVER,REPLCONF_History,REPLCONF_Hints,replconfCommand,-1,CMD_ADMIN|CMD_NOSCRIPT|CMD_LOADING|CMD_STALE,0},
|
||||
{"replicaof","Make the server a replica of another instance, or promote it as master.","O(1)","5.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SERVER,REPLICAOF_History,REPLICAOF_Hints,replicaofCommand,3,CMD_ADMIN|CMD_NOSCRIPT|CMD_STALE,0,.args=REPLICAOF_Args},
|
||||
{"replicaof","Make the server a replica of another instance, or promote it as master.","O(1)","5.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SERVER,REPLICAOF_History,REPLICAOF_Hints,replicaofCommand,3,CMD_NO_ASYNC_LOADING|CMD_ADMIN|CMD_NOSCRIPT|CMD_STALE,0,.args=REPLICAOF_Args},
|
||||
{"restore-asking","An internal command for migrating keys in a cluster","O(1) to create the new key and additional O(N*M) to reconstruct the serialized value, where N is the number of Redis objects composing the value and M their average size. For small string values the time complexity is thus O(1)+O(1*M) where M is small, so simply O(1). However for sorted set values the complexity is O(N*M*log(N)) because inserting values into sorted sets is O(log(N)).","3.0.0",CMD_DOC_SYSCMD,NULL,NULL,COMMAND_GROUP_SERVER,RESTORE_ASKING_History,RESTORE_ASKING_Hints,restoreCommand,-4,CMD_WRITE|CMD_DENYOOM|CMD_ASKING,ACL_CATEGORY_KEYSPACE|ACL_CATEGORY_DANGEROUS,{{CMD_KEY_WRITE,KSPEC_BS_INDEX,.bs.index={1},KSPEC_FK_RANGE,.fk.range={0,1,0}}}},
|
||||
{"role","Return the role of the instance in the context of replication","O(1)","2.8.12",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SERVER,ROLE_History,ROLE_Hints,roleCommand,1,CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_FAST|CMD_SENTINEL,ACL_CATEGORY_ADMIN|ACL_CATEGORY_DANGEROUS},
|
||||
{"save","Synchronously save the dataset to disk","O(N) where N is the total number of keys in all databases","1.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SERVER,SAVE_History,SAVE_Hints,saveCommand,1,CMD_ADMIN|CMD_NOSCRIPT,0},
|
||||
{"save","Synchronously save the dataset to disk","O(N) where N is the total number of keys in all databases","1.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SERVER,SAVE_History,SAVE_Hints,saveCommand,1,CMD_NO_ASYNC_LOADING|CMD_ADMIN|CMD_NOSCRIPT,0},
|
||||
{"shutdown","Synchronously save the dataset to disk and then shut down the server",NULL,"1.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SERVER,SHUTDOWN_History,SHUTDOWN_Hints,shutdownCommand,-1,CMD_ADMIN|CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL,0,.args=SHUTDOWN_Args},
|
||||
{"slaveof","Make the server a replica of another instance, or promote it as master. Deprecated starting with Redis 5. Use REPLICAOF instead.","O(1)","1.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SERVER,SLAVEOF_History,SLAVEOF_Hints,replicaofCommand,3,CMD_ADMIN|CMD_NOSCRIPT|CMD_STALE,0,.args=SLAVEOF_Args},
|
||||
{"slaveof","Make the server a replica of another instance, or promote it as master. Deprecated starting with Redis 5. Use REPLICAOF instead.","O(1)","1.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SERVER,SLAVEOF_History,SLAVEOF_Hints,replicaofCommand,3,CMD_NO_ASYNC_LOADING|CMD_ADMIN|CMD_NOSCRIPT|CMD_STALE,0,.args=SLAVEOF_Args},
|
||||
{"slowlog","A container for slow log commands","Depends on subcommand.","2.2.12",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SERVER,SLOWLOG_History,SLOWLOG_Hints,NULL,-2,0,0,.subcommands=SLOWLOG_Subcommands},
|
||||
{"swapdb","Swaps two Redis databases","O(N) where N is the count of clients watching or blocking on keys from both databases.","4.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SERVER,SWAPDB_History,SWAPDB_Hints,swapdbCommand,3,CMD_WRITE|CMD_FAST,ACL_CATEGORY_KEYSPACE|ACL_CATEGORY_DANGEROUS,.args=SWAPDB_Args},
|
||||
{"sync","Internal command used for replication",NULL,"1.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SERVER,SYNC_History,SYNC_Hints,syncCommand,1,CMD_ADMIN|CMD_NOSCRIPT,0},
|
||||
{"sync","Internal command used for replication",NULL,"1.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SERVER,SYNC_History,SYNC_Hints,syncCommand,1,CMD_NO_ASYNC_LOADING|CMD_ADMIN|CMD_NOSCRIPT,0},
|
||||
{"time","Return the current server time","O(1)","2.6.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SERVER,TIME_History,TIME_Hints,timeCommand,1,CMD_RANDOM|CMD_LOADING|CMD_STALE|CMD_FAST,0},
|
||||
/* set */
|
||||
{"sadd","Add one or more members to a set","O(1) for each element added, so O(N) to add N elements when the command is called with multiple arguments.","1.0.0",CMD_DOC_NONE,NULL,NULL,COMMAND_GROUP_SET,SADD_History,SADD_Hints,saddCommand,-3,CMD_WRITE|CMD_DENYOOM|CMD_FAST,ACL_CATEGORY_SET,{{CMD_KEY_WRITE,KSPEC_BS_INDEX,.bs.index={1},KSPEC_FK_RANGE,.fk.range={0,1,0}}},.args=SADD_Args},
|
||||
|
@ -7,6 +7,7 @@
|
||||
"arity": 1,
|
||||
"function": "bgrewriteaofCommand",
|
||||
"command_flags": [
|
||||
"NO_ASYNC_LOADING",
|
||||
"ADMIN",
|
||||
"NOSCRIPT"
|
||||
]
|
||||
|
@ -13,6 +13,7 @@
|
||||
]
|
||||
],
|
||||
"command_flags": [
|
||||
"NO_ASYNC_LOADING",
|
||||
"ADMIN",
|
||||
"NOSCRIPT"
|
||||
],
|
||||
|
@ -8,6 +8,7 @@
|
||||
"container": "CLUSTER",
|
||||
"function": "clusterCommand",
|
||||
"command_flags": [
|
||||
"NO_ASYNC_LOADING",
|
||||
"ADMIN",
|
||||
"RANDOM",
|
||||
"STALE"
|
||||
|
@ -8,6 +8,7 @@
|
||||
"container": "CLUSTER",
|
||||
"function": "clusterCommand",
|
||||
"command_flags": [
|
||||
"NO_ASYNC_LOADING",
|
||||
"ADMIN",
|
||||
"RANDOM",
|
||||
"STALE"
|
||||
|
@ -8,6 +8,7 @@
|
||||
"container": "CLUSTER",
|
||||
"function": "clusterCommand",
|
||||
"command_flags": [
|
||||
"NO_ASYNC_LOADING",
|
||||
"ADMIN",
|
||||
"RANDOM",
|
||||
"STALE"
|
||||
|
@ -8,6 +8,7 @@
|
||||
"container": "CLUSTER",
|
||||
"function": "clusterCommand",
|
||||
"command_flags": [
|
||||
"NO_ASYNC_LOADING",
|
||||
"ADMIN",
|
||||
"RANDOM",
|
||||
"STALE"
|
||||
|
@ -8,6 +8,7 @@
|
||||
"container": "CLUSTER",
|
||||
"function": "clusterCommand",
|
||||
"command_flags": [
|
||||
"NO_ASYNC_LOADING",
|
||||
"ADMIN",
|
||||
"RANDOM",
|
||||
"STALE"
|
||||
|
@ -8,6 +8,7 @@
|
||||
"container": "CLUSTER",
|
||||
"function": "clusterCommand",
|
||||
"command_flags": [
|
||||
"NO_ASYNC_LOADING",
|
||||
"ADMIN",
|
||||
"RANDOM",
|
||||
"STALE"
|
||||
|
@ -8,6 +8,7 @@
|
||||
"container": "CLUSTER",
|
||||
"function": "clusterCommand",
|
||||
"command_flags": [
|
||||
"NO_ASYNC_LOADING",
|
||||
"ADMIN",
|
||||
"RANDOM",
|
||||
"STALE"
|
||||
|
@ -8,6 +8,7 @@
|
||||
"container": "CLUSTER",
|
||||
"function": "clusterCommand",
|
||||
"command_flags": [
|
||||
"NO_ASYNC_LOADING",
|
||||
"ADMIN",
|
||||
"RANDOM",
|
||||
"STALE"
|
||||
|
@ -8,6 +8,7 @@
|
||||
"container": "CLUSTER",
|
||||
"function": "clusterCommand",
|
||||
"command_flags": [
|
||||
"NO_ASYNC_LOADING",
|
||||
"ADMIN",
|
||||
"RANDOM",
|
||||
"STALE"
|
||||
|
@ -8,6 +8,7 @@
|
||||
"container": "CLUSTER",
|
||||
"function": "clusterCommand",
|
||||
"command_flags": [
|
||||
"NO_ASYNC_LOADING",
|
||||
"ADMIN",
|
||||
"RANDOM",
|
||||
"STALE"
|
||||
|
@ -8,6 +8,7 @@
|
||||
"container": "CLUSTER",
|
||||
"function": "clusterCommand",
|
||||
"command_flags": [
|
||||
"NO_ASYNC_LOADING",
|
||||
"ADMIN",
|
||||
"RANDOM",
|
||||
"STALE"
|
||||
|
@ -8,6 +8,7 @@
|
||||
"container": "CLUSTER",
|
||||
"function": "clusterCommand",
|
||||
"command_flags": [
|
||||
"NO_ASYNC_LOADING",
|
||||
"ADMIN",
|
||||
"RANDOM",
|
||||
"STALE"
|
||||
|
@ -8,6 +8,7 @@
|
||||
"container": "CLUSTER",
|
||||
"function": "clusterCommand",
|
||||
"command_flags": [
|
||||
"NO_ASYNC_LOADING",
|
||||
"ADMIN",
|
||||
"RANDOM",
|
||||
"STALE"
|
||||
|
@ -10,6 +10,7 @@
|
||||
"command_flags": [
|
||||
"ADMIN",
|
||||
"NOSCRIPT",
|
||||
"LOADING",
|
||||
"STALE"
|
||||
]
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
"command_flags": [
|
||||
"ADMIN",
|
||||
"NOSCRIPT",
|
||||
"LOADING",
|
||||
"STALE"
|
||||
]
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
"command_flags": [
|
||||
"ADMIN",
|
||||
"NOSCRIPT",
|
||||
"LOADING",
|
||||
"STALE"
|
||||
],
|
||||
"arguments": [
|
||||
|
@ -8,6 +8,7 @@
|
||||
"container": "MODULE",
|
||||
"function": "moduleCommand",
|
||||
"command_flags": [
|
||||
"NO_ASYNC_LOADING",
|
||||
"ADMIN",
|
||||
"NOSCRIPT",
|
||||
"PROTECTED"
|
||||
|
@ -8,6 +8,7 @@
|
||||
"container": "MODULE",
|
||||
"function": "moduleCommand",
|
||||
"command_flags": [
|
||||
"NO_ASYNC_LOADING",
|
||||
"ADMIN",
|
||||
"NOSCRIPT",
|
||||
"PROTECTED"
|
||||
|
@ -6,6 +6,7 @@
|
||||
"arity": -3,
|
||||
"function": "syncCommand",
|
||||
"command_flags": [
|
||||
"NO_ASYNC_LOADING",
|
||||
"ADMIN",
|
||||
"NOSCRIPT"
|
||||
],
|
||||
|
@ -7,6 +7,7 @@
|
||||
"arity": 3,
|
||||
"function": "replicaofCommand",
|
||||
"command_flags": [
|
||||
"NO_ASYNC_LOADING",
|
||||
"ADMIN",
|
||||
"NOSCRIPT",
|
||||
"STALE"
|
||||
|
@ -7,6 +7,7 @@
|
||||
"arity": 1,
|
||||
"function": "saveCommand",
|
||||
"command_flags": [
|
||||
"NO_ASYNC_LOADING",
|
||||
"ADMIN",
|
||||
"NOSCRIPT"
|
||||
]
|
||||
|
@ -7,6 +7,7 @@
|
||||
"arity": 3,
|
||||
"function": "replicaofCommand",
|
||||
"command_flags": [
|
||||
"NO_ASYNC_LOADING",
|
||||
"ADMIN",
|
||||
"NOSCRIPT",
|
||||
"STALE"
|
||||
|
@ -6,6 +6,7 @@
|
||||
"arity": 1,
|
||||
"function": "syncCommand",
|
||||
"command_flags": [
|
||||
"NO_ASYNC_LOADING",
|
||||
"ADMIN",
|
||||
"NOSCRIPT"
|
||||
]
|
||||
|
20
src/config.c
20
src/config.c
@ -269,6 +269,7 @@ typedef struct standardConfig {
|
||||
#define MULTI_ARG_CONFIG (1ULL<<3) /* This config receives multiple arguments. */
|
||||
#define HIDDEN_CONFIG (1ULL<<4) /* This config is hidden in `config get <pattern>` (used for tests/debugging) */
|
||||
#define PROTECTED_CONFIG (1ULL<<5) /* Becomes immutable if enable-protected-configs is enabled. */
|
||||
#define DENY_LOADING_CONFIG (1ULL<<6) /* This config is forbidden during loading. */
|
||||
|
||||
standardConfig configs[];
|
||||
|
||||
@ -710,7 +711,7 @@ void configSetCommand(client *c) {
|
||||
sds *old_values = NULL;
|
||||
apply_fn *apply_fns; /* TODO: make this a set for better performance */
|
||||
int config_count, i, j;
|
||||
int invalid_args = 0;
|
||||
int invalid_args = 0, deny_loading_error = 0;
|
||||
int *config_map_fns;
|
||||
|
||||
/* Make sure we have an even number of arguments: conf-val pairs */
|
||||
@ -749,6 +750,12 @@ void configSetCommand(client *c) {
|
||||
invalid_args = 1;
|
||||
}
|
||||
|
||||
if (server.loading && config->flags & DENY_LOADING_CONFIG) {
|
||||
/* Note: we don't abort the loop since we still want to handle redacting sensitive configs (above) */
|
||||
deny_loading_error = 1;
|
||||
invalid_args = 1;
|
||||
}
|
||||
|
||||
/* If this config appears twice then fail */
|
||||
for (j = 0; j < i; j++) {
|
||||
if (set_configs[j] == config) {
|
||||
@ -819,7 +826,10 @@ void configSetCommand(client *c) {
|
||||
goto end;
|
||||
|
||||
err:
|
||||
if (invalid_arg_name) {
|
||||
if (deny_loading_error) {
|
||||
/* We give the loading error precedence because it may be handled by clients differently, unlike a plain -ERR. */
|
||||
addReplyErrorObject(c,shared.loadingerr);
|
||||
} else if (invalid_arg_name) {
|
||||
addReplyErrorFormat(c,"Unknown option or number of arguments for CONFIG SET - '%s'", invalid_arg_name);
|
||||
} else if (errstr) {
|
||||
addReplyErrorFormat(c,"CONFIG SET failed (possibly related to argument '%s') - %s", err_arg_name, errstr);
|
||||
@ -2624,7 +2634,7 @@ standardConfig configs[] = {
|
||||
createBoolConfig("activedefrag", NULL, DEBUG_CONFIG | MODIFIABLE_CONFIG, server.active_defrag_enabled, 0, isValidActiveDefrag, NULL),
|
||||
createBoolConfig("syslog-enabled", NULL, IMMUTABLE_CONFIG, server.syslog_enabled, 0, NULL, NULL),
|
||||
createBoolConfig("cluster-enabled", NULL, IMMUTABLE_CONFIG, server.cluster_enabled, 0, NULL, NULL),
|
||||
createBoolConfig("appendonly", NULL, MODIFIABLE_CONFIG, server.aof_enabled, 0, NULL, updateAppendonly),
|
||||
createBoolConfig("appendonly", NULL, MODIFIABLE_CONFIG | DENY_LOADING_CONFIG, server.aof_enabled, 0, NULL, updateAppendonly),
|
||||
createBoolConfig("cluster-allow-reads-when-down", NULL, MODIFIABLE_CONFIG, server.cluster_allow_reads_when_down, 0, NULL, NULL),
|
||||
createBoolConfig("crash-log-enabled", NULL, MODIFIABLE_CONFIG, server.crashlog_enabled, 1, NULL, updateSighandlerEnabled),
|
||||
createBoolConfig("crash-memcheck-enabled", NULL, MODIFIABLE_CONFIG, server.memcheck_enabled, 1, NULL, NULL),
|
||||
@ -2660,7 +2670,7 @@ standardConfig configs[] = {
|
||||
/* Enum Configs */
|
||||
createEnumConfig("supervised", NULL, IMMUTABLE_CONFIG, supervised_mode_enum, server.supervised_mode, SUPERVISED_NONE, NULL, NULL),
|
||||
createEnumConfig("syslog-facility", NULL, IMMUTABLE_CONFIG, syslog_facility_enum, server.syslog_facility, LOG_LOCAL0, NULL, NULL),
|
||||
createEnumConfig("repl-diskless-load", NULL, DEBUG_CONFIG | MODIFIABLE_CONFIG, repl_diskless_load_enum, server.repl_diskless_load, REPL_DISKLESS_LOAD_DISABLED, NULL, NULL),
|
||||
createEnumConfig("repl-diskless-load", NULL, DEBUG_CONFIG | MODIFIABLE_CONFIG | DENY_LOADING_CONFIG, repl_diskless_load_enum, server.repl_diskless_load, REPL_DISKLESS_LOAD_DISABLED, NULL, NULL),
|
||||
createEnumConfig("loglevel", NULL, MODIFIABLE_CONFIG, loglevel_enum, server.verbosity, LL_NOTICE, NULL, NULL),
|
||||
createEnumConfig("maxmemory-policy", NULL, MODIFIABLE_CONFIG, maxmemory_policy_enum, server.maxmemory_policy, MAXMEMORY_NO_EVICTION, NULL, NULL),
|
||||
createEnumConfig("appendfsync", NULL, MODIFIABLE_CONFIG, aof_fsync_enum, server.aof_fsync, AOF_FSYNC_EVERYSEC, NULL, NULL),
|
||||
@ -2772,7 +2782,7 @@ standardConfig configs[] = {
|
||||
#endif
|
||||
|
||||
/* Special configs */
|
||||
createSpecialConfig("dir", NULL, MODIFIABLE_CONFIG | PROTECTED_CONFIG, setConfigDirOption, getConfigDirOption, rewriteConfigDirOption, NULL),
|
||||
createSpecialConfig("dir", NULL, MODIFIABLE_CONFIG | PROTECTED_CONFIG | DENY_LOADING_CONFIG, setConfigDirOption, getConfigDirOption, rewriteConfigDirOption, NULL),
|
||||
createSpecialConfig("save", NULL, MODIFIABLE_CONFIG | MULTI_ARG_CONFIG, setConfigSaveOption, getConfigSaveOption, rewriteConfigSaveOption, NULL),
|
||||
createSpecialConfig("client-output-buffer-limit", NULL, MODIFIABLE_CONFIG | MULTI_ARG_CONFIG, setConfigClientOutputBufferLimitOption, getConfigClientOutputBufferLimitOption, rewriteConfigClientOutputBufferLimitOption, NULL),
|
||||
createSpecialConfig("oom-score-adj-values", NULL, MODIFIABLE_CONFIG | MULTI_ARG_CONFIG, setConfigOOMScoreAdjValuesOption, getConfigOOMScoreAdjValuesOption, rewriteConfigOOMScoreAdjValuesOption, updateOOMScoreAdj),
|
||||
|
@ -3625,8 +3625,11 @@ void processEventsWhileBlocked(void) {
|
||||
/* Note: when we are processing events while blocked (for instance during
|
||||
* busy Lua scripts), we set a global flag. When such flag is set, we
|
||||
* avoid handling the read part of clients using threaded I/O.
|
||||
* See https://github.com/redis/redis/issues/6988 for more info. */
|
||||
ProcessingEventsWhileBlocked = 1;
|
||||
* See https://github.com/redis/redis/issues/6988 for more info.
|
||||
* Note that there could be cases of nested calls to this function,
|
||||
* specifically on a busy script during async_loading rdb, and scripts
|
||||
* that came from AOF. */
|
||||
ProcessingEventsWhileBlocked++;
|
||||
while (iterations--) {
|
||||
long long startval = server.events_processed_while_blocked;
|
||||
long long ae_events = aeProcessEvents(server.el,
|
||||
@ -3641,7 +3644,8 @@ void processEventsWhileBlocked(void) {
|
||||
|
||||
whileBlockedCron();
|
||||
|
||||
ProcessingEventsWhileBlocked = 0;
|
||||
ProcessingEventsWhileBlocked--;
|
||||
serverAssert(ProcessingEventsWhileBlocked >= 0);
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
|
@ -3236,6 +3236,8 @@ int processCommand(client *c) {
|
||||
(c->cmd->proc == execCommand && (c->mstate.cmd_inv_flags & CMD_LOADING));
|
||||
int is_may_replicate_command = (c->cmd->flags & (CMD_WRITE | CMD_MAY_REPLICATE)) ||
|
||||
(c->cmd->proc == execCommand && (c->mstate.cmd_flags & (CMD_WRITE | CMD_MAY_REPLICATE)));
|
||||
int is_deny_async_loading_command = (c->cmd->flags & CMD_NO_ASYNC_LOADING) ||
|
||||
(c->cmd->proc == execCommand && (c->mstate.cmd_flags & CMD_NO_ASYNC_LOADING));
|
||||
|
||||
if (authRequired(c)) {
|
||||
/* AUTH and HELLO and no auth commands are valid even in
|
||||
@ -3434,6 +3436,12 @@ int processCommand(client *c) {
|
||||
return C_OK;
|
||||
}
|
||||
|
||||
/* During async-loading, block certain commands. */
|
||||
if (server.async_loading && is_deny_async_loading_command) {
|
||||
rejectCommand(c,shared.loadingerr);
|
||||
return C_OK;
|
||||
}
|
||||
|
||||
/* Lua script too slow? Only allow a limited number of commands.
|
||||
* Note that we need to allow the transactions commands, otherwise clients
|
||||
* sending a transaction with pipelining without error checking, may have
|
||||
|
@ -204,9 +204,9 @@ extern int configOOMScoreAdjValuesDefaults[CONFIG_OOM_COUNT];
|
||||
#define CMD_ONLY_SENTINEL (1ULL<<18)
|
||||
#define CMD_NO_MANDATORY_KEYS (1ULL<<19)
|
||||
#define CMD_PROTECTED (1ULL<<20)
|
||||
/* Command flags used by the module system. */
|
||||
#define CMD_MODULE_GETKEYS (1ULL<<21) /* Use the modules getkeys interface. */
|
||||
#define CMD_MODULE_NO_CLUSTER (1ULL<<22) /* Deny on Redis Cluster. */
|
||||
#define CMD_NO_ASYNC_LOADING (1ULL<<23)
|
||||
|
||||
/* Command flags that describe ACLs categories. */
|
||||
#define ACL_CATEGORY_KEYSPACE (1ULL<<0)
|
||||
@ -2008,6 +2008,9 @@ typedef int redisGetKeysProc(struct redisCommand *cmd, robj **argv, int argc, ge
|
||||
*
|
||||
* CMD_LOADING: Allow the command while loading the database.
|
||||
*
|
||||
* CMD_NO_ASYNC_LOADING: Deny during async loading (when a replica uses diskless
|
||||
sync swapdb, and allows access to the old dataset)
|
||||
*
|
||||
* CMD_STALE: Allow the command while a slave has stale data but is not
|
||||
* allowed to serve this data. Normally no command is accepted
|
||||
* in this condition but just a few.
|
||||
|
@ -568,6 +568,23 @@ foreach testType {Successful Aborted} {
|
||||
assert_equal [$replica dbsize] 2001
|
||||
}
|
||||
|
||||
test {Busy script during async loading} {
|
||||
set rd_replica [redis_deferring_client -1]
|
||||
$replica config set lua-time-limit 10
|
||||
$rd_replica eval {while true do end} 0
|
||||
after 200
|
||||
assert_error {BUSY*} {$replica ping}
|
||||
$replica script kill
|
||||
after 200 ; # Give some time to Lua to call the hook again...
|
||||
assert_equal [$replica ping] "PONG"
|
||||
$rd_replica close
|
||||
}
|
||||
|
||||
test {Blocked commands and configs during async-loading} {
|
||||
assert_error {LOADING*} {$replica config set appendonly no}
|
||||
assert_error {LOADING*} {$replica REPLICAOF no one}
|
||||
}
|
||||
|
||||
# Make sure that next sync will not start immediately so that we can catch the replica in between syncs
|
||||
$master config set repl-diskless-sync-delay 5
|
||||
|
||||
|
@ -460,4 +460,31 @@ start_server {config "minimal.conf" tags {"introspection external:skip"} overrid
|
||||
assert_error "ERR*DEBUG command not allowed*" {$r2 DEBUG HELP}
|
||||
}
|
||||
} {} {needs:debug}
|
||||
}
|
||||
}
|
||||
|
||||
test {config during loading} {
|
||||
start_server [list overrides [list key-load-delay 50 rdbcompression no]] {
|
||||
# create a big rdb that will take long to load. it is important
|
||||
# for keys to be big since the server processes events only once in 2mb.
|
||||
# 100mb of rdb, 100k keys will load in more than 5 seconds
|
||||
r debug populate 100000 key 1000
|
||||
|
||||
restart_server 0 false false
|
||||
|
||||
# make sure it's still loading
|
||||
assert_equal [s loading] 1
|
||||
|
||||
# verify some configs are allowed during loading
|
||||
r config set loglevel debug
|
||||
assert_equal [lindex [r config get loglevel] 1] debug
|
||||
|
||||
# verify some configs are forbidden during loading
|
||||
assert_error {LOADING*} {r config set dir asdf}
|
||||
|
||||
# make sure it's still loading
|
||||
assert_equal [s loading] 1
|
||||
|
||||
# no need to keep waiting for loading to complete
|
||||
exec kill [srv 0 pid]
|
||||
}
|
||||
} {} {external:skip}
|
||||
|
Loading…
x
Reference in New Issue
Block a user