diff --git a/src/commands.c b/src/commands.c index aae902edc..0a07fb25f 100644 --- a/src/commands.c +++ b/src/commands.c @@ -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}, diff --git a/src/commands/bgrewriteaof.json b/src/commands/bgrewriteaof.json index cd38080d2..27d64dd93 100644 --- a/src/commands/bgrewriteaof.json +++ b/src/commands/bgrewriteaof.json @@ -7,6 +7,7 @@ "arity": 1, "function": "bgrewriteaofCommand", "command_flags": [ + "NO_ASYNC_LOADING", "ADMIN", "NOSCRIPT" ] diff --git a/src/commands/bgsave.json b/src/commands/bgsave.json index a9596b856..0c2c96ff9 100644 --- a/src/commands/bgsave.json +++ b/src/commands/bgsave.json @@ -13,6 +13,7 @@ ] ], "command_flags": [ + "NO_ASYNC_LOADING", "ADMIN", "NOSCRIPT" ], diff --git a/src/commands/cluster-addslots.json b/src/commands/cluster-addslots.json index 9a8c10fa5..962dde82c 100644 --- a/src/commands/cluster-addslots.json +++ b/src/commands/cluster-addslots.json @@ -8,6 +8,7 @@ "container": "CLUSTER", "function": "clusterCommand", "command_flags": [ + "NO_ASYNC_LOADING", "ADMIN", "RANDOM", "STALE" diff --git a/src/commands/cluster-addslotsrange.json b/src/commands/cluster-addslotsrange.json index e2c0445d4..810609ad1 100644 --- a/src/commands/cluster-addslotsrange.json +++ b/src/commands/cluster-addslotsrange.json @@ -8,6 +8,7 @@ "container": "CLUSTER", "function": "clusterCommand", "command_flags": [ + "NO_ASYNC_LOADING", "ADMIN", "RANDOM", "STALE" diff --git a/src/commands/cluster-bumpepoch.json b/src/commands/cluster-bumpepoch.json index 4d1bd7c9c..98eaa0721 100644 --- a/src/commands/cluster-bumpepoch.json +++ b/src/commands/cluster-bumpepoch.json @@ -8,6 +8,7 @@ "container": "CLUSTER", "function": "clusterCommand", "command_flags": [ + "NO_ASYNC_LOADING", "ADMIN", "RANDOM", "STALE" diff --git a/src/commands/cluster-delslots.json b/src/commands/cluster-delslots.json index ff188eaa5..99f1ea9ff 100644 --- a/src/commands/cluster-delslots.json +++ b/src/commands/cluster-delslots.json @@ -8,6 +8,7 @@ "container": "CLUSTER", "function": "clusterCommand", "command_flags": [ + "NO_ASYNC_LOADING", "ADMIN", "RANDOM", "STALE" diff --git a/src/commands/cluster-delslotsrange.json b/src/commands/cluster-delslotsrange.json index e635be6ba..d2e826d36 100644 --- a/src/commands/cluster-delslotsrange.json +++ b/src/commands/cluster-delslotsrange.json @@ -8,6 +8,7 @@ "container": "CLUSTER", "function": "clusterCommand", "command_flags": [ + "NO_ASYNC_LOADING", "ADMIN", "RANDOM", "STALE" diff --git a/src/commands/cluster-failover.json b/src/commands/cluster-failover.json index 366fc2f21..6dcb381ae 100644 --- a/src/commands/cluster-failover.json +++ b/src/commands/cluster-failover.json @@ -8,6 +8,7 @@ "container": "CLUSTER", "function": "clusterCommand", "command_flags": [ + "NO_ASYNC_LOADING", "ADMIN", "RANDOM", "STALE" diff --git a/src/commands/cluster-flushslots.json b/src/commands/cluster-flushslots.json index bea405c23..af362b447 100644 --- a/src/commands/cluster-flushslots.json +++ b/src/commands/cluster-flushslots.json @@ -8,6 +8,7 @@ "container": "CLUSTER", "function": "clusterCommand", "command_flags": [ + "NO_ASYNC_LOADING", "ADMIN", "RANDOM", "STALE" diff --git a/src/commands/cluster-forget.json b/src/commands/cluster-forget.json index 86b17dc7f..3d1432a2a 100644 --- a/src/commands/cluster-forget.json +++ b/src/commands/cluster-forget.json @@ -8,6 +8,7 @@ "container": "CLUSTER", "function": "clusterCommand", "command_flags": [ + "NO_ASYNC_LOADING", "ADMIN", "RANDOM", "STALE" diff --git a/src/commands/cluster-meet.json b/src/commands/cluster-meet.json index f8dfc8c03..e7e4b537e 100644 --- a/src/commands/cluster-meet.json +++ b/src/commands/cluster-meet.json @@ -8,6 +8,7 @@ "container": "CLUSTER", "function": "clusterCommand", "command_flags": [ + "NO_ASYNC_LOADING", "ADMIN", "RANDOM", "STALE" diff --git a/src/commands/cluster-replicate.json b/src/commands/cluster-replicate.json index 8494660b3..9faf34661 100644 --- a/src/commands/cluster-replicate.json +++ b/src/commands/cluster-replicate.json @@ -8,6 +8,7 @@ "container": "CLUSTER", "function": "clusterCommand", "command_flags": [ + "NO_ASYNC_LOADING", "ADMIN", "RANDOM", "STALE" diff --git a/src/commands/cluster-saveconfig.json b/src/commands/cluster-saveconfig.json index 12887229f..db744bbe0 100644 --- a/src/commands/cluster-saveconfig.json +++ b/src/commands/cluster-saveconfig.json @@ -8,6 +8,7 @@ "container": "CLUSTER", "function": "clusterCommand", "command_flags": [ + "NO_ASYNC_LOADING", "ADMIN", "RANDOM", "STALE" diff --git a/src/commands/cluster-set-config-epoch.json b/src/commands/cluster-set-config-epoch.json index 5f1dc7c41..cd91e66c3 100644 --- a/src/commands/cluster-set-config-epoch.json +++ b/src/commands/cluster-set-config-epoch.json @@ -8,6 +8,7 @@ "container": "CLUSTER", "function": "clusterCommand", "command_flags": [ + "NO_ASYNC_LOADING", "ADMIN", "RANDOM", "STALE" diff --git a/src/commands/cluster-setslot.json b/src/commands/cluster-setslot.json index 6831fdd23..9e3b924a5 100644 --- a/src/commands/cluster-setslot.json +++ b/src/commands/cluster-setslot.json @@ -8,6 +8,7 @@ "container": "CLUSTER", "function": "clusterCommand", "command_flags": [ + "NO_ASYNC_LOADING", "ADMIN", "RANDOM", "STALE" diff --git a/src/commands/config-resetstat.json b/src/commands/config-resetstat.json index 74cdba130..0180402ab 100644 --- a/src/commands/config-resetstat.json +++ b/src/commands/config-resetstat.json @@ -10,6 +10,7 @@ "command_flags": [ "ADMIN", "NOSCRIPT", + "LOADING", "STALE" ] } diff --git a/src/commands/config-rewrite.json b/src/commands/config-rewrite.json index d2f04993d..4e31dd82d 100644 --- a/src/commands/config-rewrite.json +++ b/src/commands/config-rewrite.json @@ -10,6 +10,7 @@ "command_flags": [ "ADMIN", "NOSCRIPT", + "LOADING", "STALE" ] } diff --git a/src/commands/config-set.json b/src/commands/config-set.json index 731713d4b..f4a2c07b5 100644 --- a/src/commands/config-set.json +++ b/src/commands/config-set.json @@ -16,6 +16,7 @@ "command_flags": [ "ADMIN", "NOSCRIPT", + "LOADING", "STALE" ], "arguments": [ diff --git a/src/commands/module-load.json b/src/commands/module-load.json index 836f5261b..84e6d3596 100644 --- a/src/commands/module-load.json +++ b/src/commands/module-load.json @@ -8,6 +8,7 @@ "container": "MODULE", "function": "moduleCommand", "command_flags": [ + "NO_ASYNC_LOADING", "ADMIN", "NOSCRIPT", "PROTECTED" diff --git a/src/commands/module-unload.json b/src/commands/module-unload.json index 38cba4e43..8820ba3aa 100644 --- a/src/commands/module-unload.json +++ b/src/commands/module-unload.json @@ -8,6 +8,7 @@ "container": "MODULE", "function": "moduleCommand", "command_flags": [ + "NO_ASYNC_LOADING", "ADMIN", "NOSCRIPT", "PROTECTED" diff --git a/src/commands/psync.json b/src/commands/psync.json index 46b037c37..e0ed9eb42 100644 --- a/src/commands/psync.json +++ b/src/commands/psync.json @@ -6,6 +6,7 @@ "arity": -3, "function": "syncCommand", "command_flags": [ + "NO_ASYNC_LOADING", "ADMIN", "NOSCRIPT" ], diff --git a/src/commands/replicaof.json b/src/commands/replicaof.json index 82e36d354..805b81e4c 100644 --- a/src/commands/replicaof.json +++ b/src/commands/replicaof.json @@ -7,6 +7,7 @@ "arity": 3, "function": "replicaofCommand", "command_flags": [ + "NO_ASYNC_LOADING", "ADMIN", "NOSCRIPT", "STALE" diff --git a/src/commands/save.json b/src/commands/save.json index 6edc76fad..ca6272d15 100644 --- a/src/commands/save.json +++ b/src/commands/save.json @@ -7,6 +7,7 @@ "arity": 1, "function": "saveCommand", "command_flags": [ + "NO_ASYNC_LOADING", "ADMIN", "NOSCRIPT" ] diff --git a/src/commands/slaveof.json b/src/commands/slaveof.json index fb534d416..f9db6afbb 100644 --- a/src/commands/slaveof.json +++ b/src/commands/slaveof.json @@ -7,6 +7,7 @@ "arity": 3, "function": "replicaofCommand", "command_flags": [ + "NO_ASYNC_LOADING", "ADMIN", "NOSCRIPT", "STALE" diff --git a/src/commands/sync.json b/src/commands/sync.json index 958c6b447..6f3ccac2f 100644 --- a/src/commands/sync.json +++ b/src/commands/sync.json @@ -6,6 +6,7 @@ "arity": 1, "function": "syncCommand", "command_flags": [ + "NO_ASYNC_LOADING", "ADMIN", "NOSCRIPT" ] diff --git a/src/config.c b/src/config.c index 4304fb03a..407cf7249 100644 --- a/src/config.c +++ b/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 ` (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), diff --git a/src/networking.c b/src/networking.c index 2c12b39f9..7e5779b02 100644 --- a/src/networking.c +++ b/src/networking.c @@ -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); } /* ========================================================================== diff --git a/src/server.c b/src/server.c index b9bce8ad1..bfc58e0ed 100644 --- a/src/server.c +++ b/src/server.c @@ -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 diff --git a/src/server.h b/src/server.h index f620f5e1e..31506a773 100644 --- a/src/server.h +++ b/src/server.h @@ -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. diff --git a/tests/integration/replication.tcl b/tests/integration/replication.tcl index 1332c8380..40e1f996f 100644 --- a/tests/integration/replication.tcl +++ b/tests/integration/replication.tcl @@ -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 diff --git a/tests/unit/introspection.tcl b/tests/unit/introspection.tcl index eeab7ee06..22a91ea4f 100644 --- a/tests/unit/introspection.tcl +++ b/tests/unit/introspection.tcl @@ -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} -} \ No newline at end of file +} + +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}