diff options
Diffstat (limited to 'src/server.c')
-rw-r--r-- | src/server.c | 97 |
1 files changed, 75 insertions, 22 deletions
diff --git a/src/server.c b/src/server.c index 96ceb0122..de32ff847 100644 --- a/src/server.c +++ b/src/server.c @@ -48,6 +48,7 @@ #include <arpa/inet.h> #include <sys/stat.h> #include <fcntl.h> +#include <sys/file.h> #include <sys/time.h> #include <sys/resource.h> #include <sys/uio.h> @@ -634,7 +635,7 @@ void resetChildState() { NULL); } -/* Return if child type is mutual exclusive with other fork children */ +/* Return if child type is mutually exclusive with other fork children */ int isMutuallyExclusiveChildType(int type) { return type == CHILD_TYPE_RDB || type == CHILD_TYPE_AOF || type == CHILD_TYPE_MODULE; } @@ -2793,8 +2794,23 @@ int populateArgsStructure(struct redisCommandArg *args) { return count; } -/* Recursively populate the command structure. */ -void populateCommandStructure(struct redisCommand *c) { +/* Recursively populate the command structure. + * + * On success, the function return C_OK. Otherwise C_ERR is returned and we won't + * add this command in the commands dict. */ +int populateCommandStructure(struct redisCommand *c) { + /* If the command marks with CMD_SENTINEL, it exists in sentinel. */ + if (!(c->flags & CMD_SENTINEL) && server.sentinel_mode) + return C_ERR; + + /* If the command marks with CMD_ONLY_SENTINEL, it only exists in sentinel. */ + if (c->flags & CMD_ONLY_SENTINEL && !server.sentinel_mode) + return C_ERR; + + /* Translate the command string flags description into an actual + * set of flags. */ + setImplicitACLCategories(c); + /* Redis commands don't need more args than STATIC_KEY_SPECS_NUM (Number of keys * specs can be greater than STATIC_KEY_SPECS_NUM only for module commands) */ c->key_specs = c->key_specs_static; @@ -2828,14 +2844,15 @@ void populateCommandStructure(struct redisCommand *c) { for (int j = 0; c->subcommands[j].declared_name; j++) { struct redisCommand *sub = c->subcommands+j; - /* Translate the command string flags description into an actual - * set of flags. */ - setImplicitACLCategories(sub); sub->fullname = catSubCommandFullname(c->declared_name, sub->declared_name); - populateCommandStructure(sub); + if (populateCommandStructure(sub) == C_ERR) + continue; + commandAddSubcommand(c, sub, sub->declared_name); } } + + return C_OK; } extern struct redisCommand redisCommandTable[]; @@ -2853,16 +2870,9 @@ void populateCommandTable(void) { int retval1, retval2; - setImplicitACLCategories(c); - - if (!(c->flags & CMD_SENTINEL) && server.sentinel_mode) - continue; - - if (c->flags & CMD_ONLY_SENTINEL && !server.sentinel_mode) - continue; - c->fullname = sdsnew(c->declared_name); - populateCommandStructure(c); + if (populateCommandStructure(c) == C_ERR) + continue; retval1 = dictAdd(server.commands, sdsdup(c->fullname), c); /* Populate an additional dictionary that will be unaffected @@ -3584,8 +3594,8 @@ int commandCheckArity(client *c, sds *err) { * if C_ERR is returned the client was destroyed (i.e. after QUIT). */ int processCommand(client *c) { if (!scriptIsTimedout()) { - /* Both EXEC and EVAL call call() directly so there should be - * no way in_exec or in_eval is 1. + /* Both EXEC and scripts call call() directly so there should be + * no way in_exec or scriptIsRunning() is 1. * That is unless lua_timedout, in which case client may run * some commands. */ serverAssert(!server.in_exec); @@ -4207,6 +4217,12 @@ int finishShutdown(void) { /* Close the listening sockets. Apparently this allows faster restarts. */ closeListeningSockets(1); + + /* Unlock the cluster config file before shutdown */ + if (server.cluster_enabled && server.cluster_config_file_lock_fd != -1) { + flock(server.cluster_config_file_lock_fd, LOCK_UN|LOCK_NB); + } + serverLog(LL_WARNING,"%s is now ready to exit, bye bye...", server.sentinel_mode ? "Sentinel" : "Redis"); return C_OK; @@ -5645,6 +5661,7 @@ sds genRedisInfoString(dict *section_dict, int all_sections, int everything) { "keyspace_misses:%lld\r\n" "pubsub_channels:%ld\r\n" "pubsub_patterns:%lu\r\n" + "pubsubshard_channels:%lu\r\n" "latest_fork_usec:%lld\r\n" "total_forks:%lld\r\n" "migrate_cached_sockets:%ld\r\n" @@ -5694,6 +5711,7 @@ sds genRedisInfoString(dict *section_dict, int all_sections, int everything) { server.stat_keyspace_misses, dictSize(server.pubsub_channels), dictSize(server.pubsub_patterns), + dictSize(server.pubsubshard_channels), server.stat_fork_time, server.stat_total_forks, dictSize(server.migrate_cached_sockets), @@ -6094,9 +6112,12 @@ void usage(void) { fprintf(stderr," ./redis-server - (read config from stdin)\n"); fprintf(stderr," ./redis-server -v or --version\n"); fprintf(stderr," ./redis-server -h or --help\n"); - fprintf(stderr," ./redis-server --test-memory <megabytes>\n\n"); + fprintf(stderr," ./redis-server --test-memory <megabytes>\n"); + fprintf(stderr," ./redis-server --check-system\n"); + fprintf(stderr,"\n"); fprintf(stderr,"Examples:\n"); fprintf(stderr," ./redis-server (run the server with default conf)\n"); + fprintf(stderr," echo 'maxmemory 128mb' | ./redis-server -\n"); fprintf(stderr," ./redis-server /etc/redis/6379.conf\n"); fprintf(stderr," ./redis-server --port 7777\n"); fprintf(stderr," ./redis-server --port 7777 --replicaof 127.0.0.1 8888\n"); @@ -6347,7 +6368,7 @@ int redisFork(int purpose) { server.stat_fork_rate = (double) zmalloc_used_memory() * 1000000 / server.stat_fork_time / (1024*1024*1024); /* GB per second. */ latencyAddSampleIfNeeded("fork",server.stat_fork_time/1000); - /* The child_pid and child_type are only for mutual exclusive children. + /* The child_pid and child_type are only for mutually exclusive children. * other child types should handle and store their pid's in dedicated variables. * * Today, we allows CHILD_TYPE_LDB to run in parallel with the other fork types: @@ -6433,7 +6454,7 @@ void dismissClientMemory(client *c) { /* In the child process, we don't need some buffers anymore, and these are * likely to change in the parent when there's heavy write traffic. - * We dismis them right away, to avoid CoW. + * We dismiss them right away, to avoid CoW. * see dismissMemeory(). */ void dismissMemoryInChild(void) { /* madvise(MADV_DONTNEED) may not work if Transparent Huge Pages is enabled. */ @@ -6880,6 +6901,8 @@ int main(int argc, char **argv) { server.exec_argv[1] = zstrdup(server.configfile); j = 2; // Skip this arg when parsing options } + sds *argv_tmp; + int argc_tmp; int handled_last_config_arg = 1; while(j < argc) { /* Either first or last argument - Should we read config from stdin? */ @@ -6897,7 +6920,37 @@ int main(int argc, char **argv) { /* argv[j]+2 for removing the preceding `--` */ options = sdscat(options,argv[j]+2); options = sdscat(options," "); - handled_last_config_arg = 0; + + argv_tmp = sdssplitargs(argv[j], &argc_tmp); + if (argc_tmp == 1) { + /* Means that we only have one option name, like --port or "--port " */ + handled_last_config_arg = 0; + + if ((j != argc-1) && argv[j+1][0] == '-' && argv[j+1][1] == '-' && + !strcasecmp(argv[j], "--save")) + { + /* Special case: handle some things like `--save --config value`. + * In this case, if next argument starts with `--`, we will reset + * handled_last_config_arg flag and append an empty "" config value + * to the options, so it will become `--save "" --config value`. + * We are doing it to be compatible with pre 7.0 behavior (which we + * break it in #10660, 7.0.1), since there might be users who generate + * a command line from an array and when it's empty that's what they produce. */ + options = sdscat(options, "\"\""); + handled_last_config_arg = 1; + } + else if ((j == argc-1) && !strcasecmp(argv[j], "--save")) { + /* Special case: when empty save is the last argument. + * In this case, we append an empty "" config value to the options, + * so it will become `--save ""` and will follow the same reset thing. */ + options = sdscat(options, "\"\""); + } + } else { + /* Means that we are passing both config name and it's value in the same arg, + * like "--port 6380", so we need to reset handled_last_config_arg flag. */ + handled_last_config_arg = 1; + } + sdsfreesplitres(argv_tmp, argc_tmp); } else { /* Option argument */ options = sdscatrepr(options,argv[j],strlen(argv[j])); |