diff options
Diffstat (limited to 'src/config.c')
-rw-r--r-- | src/config.c | 100 |
1 files changed, 71 insertions, 29 deletions
diff --git a/src/config.c b/src/config.c index 61841cb62..805aececb 100644 --- a/src/config.c +++ b/src/config.c @@ -94,6 +94,15 @@ configEnum aof_fsync_enum[] = { {NULL, 0} }; +configEnum shutdown_on_sig_enum[] = { + {"default", 0}, + {"save", SHUTDOWN_SAVE}, + {"nosave", SHUTDOWN_NOSAVE}, + {"now", SHUTDOWN_NOW}, + {"force", SHUTDOWN_FORCE}, + {NULL, 0} +}; + configEnum repl_diskless_load_enum[] = { {"disabled", REPL_DISKLESS_LOAD_DISABLED}, {"on-empty-db", REPL_DISKLESS_LOAD_WHEN_DB_EMPTY}, @@ -283,33 +292,50 @@ static standardConfig *lookupConfig(sds name) { *----------------------------------------------------------------------------*/ /* Get enum value from name. If there is no match INT_MIN is returned. */ -int configEnumGetValue(configEnum *ce, char *name) { - while(ce->name != NULL) { - if (!strcasecmp(ce->name,name)) return ce->val; - ce++; +int configEnumGetValue(configEnum *ce, sds *argv, int argc, int bitflags) { + if (argc == 0 || (!bitflags && argc != 1)) return INT_MIN; + int values = 0; + for (int i = 0; i < argc; i++) { + int matched = 0; + for (configEnum *ceItem = ce; ceItem->name != NULL; ceItem++) { + if (!strcasecmp(argv[i],ceItem->name)) { + values |= ceItem->val; + matched = 1; + } + } + if (!matched) return INT_MIN; } - return INT_MIN; + return values; } -/* Get enum name from value. If no match is found NULL is returned. */ -const char *configEnumGetName(configEnum *ce, int val) { - while(ce->name != NULL) { - if (ce->val == val) return ce->name; - ce++; +/* Get enum name/s from value. If no matches are found "unknown" is returned. */ +static sds configEnumGetName(configEnum *ce, int values, int bitflags) { + sds names = NULL; + int matches = 0; + for( ; ce->name != NULL; ce++) { + if (values == ce->val) { /* Short path for perfect match */ + sdsfree(names); + return sdsnew(ce->name); + } + if (bitflags && (values & ce->val)) { + names = names ? sdscatfmt(names, " %s", ce->name) : sdsnew(ce->name); + matches |= ce->val; + } } - return NULL; -} - -/* Wrapper for configEnumGetName() returning "unknown" instead of NULL if - * there is no match. */ -const char *configEnumGetNameOrUnknown(configEnum *ce, int val) { - const char *name = configEnumGetName(ce,val); - return name ? name : "unknown"; + if (!names || values != matches) { + sdsfree(names); + return sdsnew("unknown"); + } + return names; } /* Used for INFO generation. */ const char *evictPolicyToString(void) { - return configEnumGetNameOrUnknown(maxmemory_policy_enum,server.maxmemory_policy); + for (configEnum *ce = maxmemory_policy_enum; ce->name != NULL; ce++) { + if (server.maxmemory_policy == ce->val) + return ce->name; + } + serverPanic("unknown eviction policy"); } /*----------------------------------------------------------------------------- @@ -1304,12 +1330,13 @@ void rewriteConfigOctalOption(struct rewriteConfigState *state, const char *opti /* Rewrite an enumeration option. It takes as usually state and option name, * and in addition the enumeration array and the default value for the * option. */ -void rewriteConfigEnumOption(struct rewriteConfigState *state, const char *option, int value, configEnum *ce, int defval) { - sds line; - const char *name = configEnumGetNameOrUnknown(ce,value); - int force = value != defval; +void rewriteConfigEnumOption(struct rewriteConfigState *state, const char *option, int value, standardConfig *config) { + int multiarg = config->flags & MULTI_ARG_CONFIG; + sds names = configEnumGetName(config->data.enumd.enum_value,value,multiarg); + sds line = sdscatfmt(sdsempty(),"%s %s",option,names); + sdsfree(names); + int force = value != config->data.enumd.default_value; - line = sdscatprintf(sdsempty(),"%s %s",option,name); rewriteConfigRewriteLine(state,option,line,force); } @@ -1898,10 +1925,12 @@ static void enumConfigInit(standardConfig *config) { } static int enumConfigSet(standardConfig *config, sds *argv, int argc, const char **err) { - UNUSED(argc); - int enumval = configEnumGetValue(config->data.enumd.enum_value, argv[0]); + int enumval; + int bitflags = !!(config->flags & MULTI_ARG_CONFIG); + enumval = configEnumGetValue(config->data.enumd.enum_value, argv, argc, bitflags); + if (enumval == INT_MIN) { - sds enumerr = sdsnew("argument must be one of the following: "); + sds enumerr = sdsnew("argument(s) must be one of the following: "); configEnum *enumNode = config->data.enumd.enum_value; while(enumNode->name != NULL) { enumerr = sdscatlen(enumerr, enumNode->name, @@ -1932,12 +1961,13 @@ static int enumConfigSet(standardConfig *config, sds *argv, int argc, const char static sds enumConfigGet(standardConfig *config) { int val = config->flags & MODULE_CONFIG ? getModuleEnumConfig(config->privdata) : *(config->data.enumd.config); - return sdsnew(configEnumGetNameOrUnknown(config->data.enumd.enum_value,val)); + int bitflags = !!(config->flags & MULTI_ARG_CONFIG); + return configEnumGetName(config->data.enumd.enum_value,val,bitflags); } static void enumConfigRewrite(standardConfig *config, const char *name, struct rewriteConfigState *state) { int val = config->flags & MODULE_CONFIG ? getModuleEnumConfig(config->privdata) : *(config->data.enumd.config); - rewriteConfigEnumOption(state, name, val, config->data.enumd.enum_value, config->data.enumd.default_value); + rewriteConfigEnumOption(state, name, val, config); } #define createEnumConfig(name, alias, flags, enum, config_addr, default, is_valid, apply) { \ @@ -2297,6 +2327,16 @@ static int isValidAOFdirname(char *val, const char **err) { return 1; } +static int isValidShutdownOnSigFlags(int val, const char **err) { + /* Individual arguments are validated by createEnumConfig logic. + * We just need to ensure valid combinations here. */ + if (val & SHUTDOWN_NOSAVE && val & SHUTDOWN_SAVE) { + *err = "shutdown options SAVE and NOSAVE can't be used simultaneously"; + return 0; + } + return 1; +} + static int isValidAnnouncedHostname(char *val, const char **err) { if (strlen(val) >= NET_HOST_STR_LEN) { *err = "Hostnames must be less than " @@ -2943,6 +2983,8 @@ standardConfig static_configs[] = { createEnumConfig("enable-module-command", NULL, IMMUTABLE_CONFIG, protected_action_enum, server.enable_module_cmd, PROTECTED_ACTION_ALLOWED_NO, NULL, NULL), createEnumConfig("cluster-preferred-endpoint-type", NULL, MODIFIABLE_CONFIG, cluster_preferred_endpoint_type_enum, server.cluster_preferred_endpoint_type, CLUSTER_ENDPOINT_TYPE_IP, NULL, NULL), createEnumConfig("propagation-error-behavior", NULL, MODIFIABLE_CONFIG, propagation_error_behavior_enum, server.propagation_error_behavior, PROPAGATION_ERR_BEHAVIOR_IGNORE, NULL, NULL), + createEnumConfig("shutdown-on-sigint", NULL, MODIFIABLE_CONFIG | MULTI_ARG_CONFIG, shutdown_on_sig_enum, server.shutdown_on_sigint, 0, isValidShutdownOnSigFlags, NULL), + createEnumConfig("shutdown-on-sigterm", NULL, MODIFIABLE_CONFIG | MULTI_ARG_CONFIG, shutdown_on_sig_enum, server.shutdown_on_sigterm, 0, isValidShutdownOnSigFlags, NULL), /* Integer configs */ createIntConfig("databases", NULL, IMMUTABLE_CONFIG, 1, INT_MAX, server.dbnum, 16, INTEGER_CONFIG, NULL, NULL), |