这里主要是枚举和配置相关的:
- configEnum syslog_facility_enum[] = {
- {"user", LOG_USER},
- {"local0", LOG_LOCAL0},
- {"local1", LOG_LOCAL1},
- {"local2", LOG_LOCAL2},
- {"local3", LOG_LOCAL3},
- {"local4", LOG_LOCAL4},
- {"local5", LOG_LOCAL5},
- {"local6", LOG_LOCAL6},
- {"local7", LOG_LOCAL7},
- {NULL, 0}
- };
-
- configEnum loglevel_enum[] = {
- {"debug", LL_DEBUG},
- {"verbose", LL_VERBOSE},
- {"notice", LL_NOTICE},
- {"warning", LL_WARNING},
- {NULL,0}
- };
-
- configEnum supervised_mode_enum[] = {
- {"upstart", SUPERVISED_UPSTART},
- {"systemd", SUPERVISED_SYSTEMD},
- {"auto", SUPERVISED_AUTODETECT},
- {"no", SUPERVISED_NONE},
- {NULL, 0}
- };
-
- configEnum aof_fsync_enum[] = {
- {"everysec", AOF_FSYNC_EVERYSEC},
- {"always", AOF_FSYNC_ALWAYS},
- {"no", AOF_FSYNC_NO},
- {NULL, 0}
- };
-
- configEnum repl_diskless_load_enum[] = {
- {"disabled", REPL_DISKLESS_LOAD_DISABLED},
- {"on-empty-db", REPL_DISKLESS_LOAD_WHEN_DB_EMPTY},
- {"swapdb", REPL_DISKLESS_LOAD_SWAPDB},
- {NULL, 0}
- };
-
- configEnum tls_auth_clients_enum[] = {
- {"no", TLS_CLIENT_AUTH_NO},
- {"yes", TLS_CLIENT_AUTH_YES},
- {"optional", TLS_CLIENT_AUTH_OPTIONAL},
- {NULL, 0}
- };
-
- configEnum oom_score_adj_enum[] = {
- {"no", OOM_SCORE_ADJ_NO},
- {"yes", OOM_SCORE_RELATIVE},
- {"relative", OOM_SCORE_RELATIVE},
- {"absolute", OOM_SCORE_ADJ_ABSOLUTE},
- {NULL, 0}
- };
-
- configEnum acl_pubsub_default_enum[] = {
- {"allchannels", USER_FLAG_ALLCHANNELS},
- {"resetchannels", 0},
- {NULL, 0}
- };
-
- configEnum sanitize_dump_payload_enum[] = {
- {"no", SANITIZE_DUMP_NO},
- {"yes", SANITIZE_DUMP_YES},
- {"clients", SANITIZE_DUMP_CLIENTS},
- {NULL, 0}
- };
-
- /* Output buffer limits presets. */
- clientBufferLimitsConfig clientBufferLimitsDefaults[CLIENT_TYPE_OBUF_COUNT] = {
- {0, 0, 0}, /* normal */
- {1024*1024*256, 1024*1024*64, 60}, /* slave */
- {1024*1024*32, 1024*1024*8, 60} /* pubsub */
- };
-
- /* OOM Score defaults */
- int configOOMScoreAdjValuesDefaults[CONFIG_OOM_COUNT] = { 0, 200, 800 };
-
- /* Generic config infrastructure function pointers
- * int is_valid_fn(val, err)
- * Return 1 when val is valid, and 0 when invalid.
- * Optionally set err to a static error string.
- * int update_fn(val, prev, err)
- * This function is called only for CONFIG SET command (not at config file parsing)
- * It is called after the actual config is applied,
- * Return 1 for success, and 0 for failure.
- * Optionally set err to a static error string.
- * On failure the config change will be reverted.
- */
-
- /* Configuration values that require no special handling to set, get, load or
- * rewrite. */
- typedef struct boolConfigData {
- int *config; /* The pointer to the server config this value is stored in */
- const int default_value; /* The default value of the config on rewrite */
- int (*is_valid_fn)(int val, const char **err); /* Optional function to check validity of new value (generic doc above) */
- int (*update_fn)(int val, int prev, const char **err); /* Optional function to apply new value at runtime (generic doc above) */
- } boolConfigData;
-
- typedef struct stringConfigData {
- char **config; /* Pointer to the server config this value is stored in. */
- const char *default_value; /* Default value of the config on rewrite. */
- int (*is_valid_fn)(char* val, const char **err); /* Optional function to check validity of new value (generic doc above) */
- int (*update_fn)(char* val, char* prev, const char **err); /* Optional function to apply new value at runtime (generic doc above) */
- int convert_empty_to_null; /* Boolean indicating if empty strings should
- be stored as a NULL value. */
- } stringConfigData;
-
- typedef struct sdsConfigData {
- sds *config; /* Pointer to the server config this value is stored in. */
- const char *default_value; /* Default value of the config on rewrite. */
- int (*is_valid_fn)(sds val, const char **err); /* Optional function to check validity of new value (generic doc above) */
- int (*update_fn)(sds val, sds prev, const char **err); /* Optional function to apply new value at runtime (generic doc above) */
- int convert_empty_to_null; /* Boolean indicating if empty SDS strings should
- be stored as a NULL value. */
- } sdsConfigData;
-
- typedef struct enumConfigData {
- int *config; /* The pointer to the server config this value is stored in */
- configEnum *enum_value; /* The underlying enum type this data represents */
- const int default_value; /* The default value of the config on rewrite */
- int (*is_valid_fn)(int val, const char **err); /* Optional function to check validity of new value (generic doc above) */
- int (*update_fn)(int val, int prev, const char **err); /* Optional function to apply new value at runtime (generic doc above) */
- } enumConfigData;
-
- typedef enum numericType {
- NUMERIC_TYPE_INT,
- NUMERIC_TYPE_UINT,
- NUMERIC_TYPE_LONG,
- NUMERIC_TYPE_ULONG,
- NUMERIC_TYPE_LONG_LONG,
- NUMERIC_TYPE_ULONG_LONG,
- NUMERIC_TYPE_SIZE_T,
- NUMERIC_TYPE_SSIZE_T,
- NUMERIC_TYPE_OFF_T,
- NUMERIC_TYPE_TIME_T,
- } numericType;
-
- typedef struct numericConfigData {
- union {
- int *i;
- unsigned int *ui;
- long *l;
- unsigned long *ul;
- long long *ll;
- unsigned long long *ull;
- size_t *st;
- ssize_t *sst;
- off_t *ot;
- time_t *tt;
- } config; /* The pointer to the numeric config this value is stored in */
- int is_memory; /* Indicates if this value can be loaded as a memory value */
- numericType numeric_type; /* An enum indicating the type of this value */
- long long lower_bound; /* The lower bound of this numeric value */
- long long upper_bound; /* The upper bound of this numeric value */
- const long long default_value; /* The default value of the config on rewrite */
- int (*is_valid_fn)(long long val, const char **err); /* Optional function to check validity of new value (generic doc above) */
- int (*update_fn)(long long val, long long prev, const char **err); /* Optional function to apply new value at runtime (generic doc above) */
- } numericConfigData;
-
- typedef union typeData {
- boolConfigData yesno;
- stringConfigData string;
- sdsConfigData sds;
- enumConfigData enumd;
- numericConfigData numeric;
- } typeData;
-
- typedef struct typeInterface {
- /* Called on server start, to init the server with default value */
- void (*init)(typeData data);
- /* Called on server startup and CONFIG SET, returns 1 on success, 0 on error
- * and can set a verbose err string, update is true when called from CONFIG SET */
- int (*set)(typeData data, sds value, int update, const char **err);
- /* Called on CONFIG GET, required to add output to the client */
- void (*get)(client *c, typeData data);
- /* Called on CONFIG REWRITE, required to rewrite the config state */
- void (*rewrite)(typeData data, const char *name, struct rewriteConfigState *state);
- } typeInterface;
-
- typedef struct standardConfig {
- const char *name; /* The user visible name of this config */
- const char *alias; /* An alias that can also be used for this config */
- const unsigned int flags; /* Flags for this specific config */
- typeInterface interface; /* The function pointers that define the type interface */
- typeData data; /* The type specific data exposed used by the interface */
- } standardConfig;
-
- #define MODIFIABLE_CONFIG 0 /* This is the implied default for a standard
- * config, which is mutable. */
- #define IMMUTABLE_CONFIG (1ULL<<0) /* Can this value only be set at startup? */
- #define SENSITIVE_CONFIG (1ULL<<1) /* Does this value contain sensitive information */
-
- standardConfig configs[];
-
- /*-----------------------------------------------------------------------------
- * Enum access functions
- *----------------------------------------------------------------------------*/
-
- /* 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++;
- }
- return INT_MIN;
- }
-
- /* 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++;
- }
- 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";
- }
-
- /* Used for INFO generation. */
- const char *evictPolicyToString(void) {
- return configEnumGetNameOrUnknown(maxmemory_policy_enum,server.maxmemory_policy);
- }
-
- /*-----------------------------------------------------------------------------
- * Config file parsing
- *----------------------------------------------------------------------------*/
-
- int yesnotoi(char *s) {
- if (!strcasecmp(s,"yes")) return 1;
- else if (!strcasecmp(s,"no")) return 0;
- else return -1;
- }
-
- void appendServerSaveParams(time_t seconds, int changes) {
- server.saveparams = zrealloc(server.saveparams,sizeof(struct saveparam)*(server.saveparamslen+1));
- server.saveparams[server.saveparamslen].seconds = seconds;
- server.saveparams[server.saveparamslen].changes = changes;
- server.saveparamslen++;
- }
-
- void resetServerSaveParams(void) {
- zfree(server.saveparams);
- server.saveparams = NULL;
- server.saveparamslen = 0;
- }
-
- void queueLoadModule(sds path, sds *argv, int argc) {
- int i;
- struct moduleLoadQueueEntry *loadmod;
-
- loadmod = zmalloc(sizeof(struct moduleLoadQueueEntry));
- loadmod->argv = zmalloc(sizeof(robj*)*argc);
- loadmod->path = sdsnew(path);
- loadmod->argc = argc;
- for (i = 0; i < argc; i++) {
- loadmod->argv[i] = createRawStringObject(argv[i],sdslen(argv[i]));
- }
- listAddNodeTail(server.loadmodule_queue,loadmod);
- }
-
- /* Parse an array of CONFIG_OOM_COUNT sds strings, validate and populate
- * server.oom_score_adj_values if valid.
- */
-
- static int updateOOMScoreAdjValues(sds *args, const char **err, int apply) {
- int i;
- int values[CONFIG_OOM_COUNT];
-
- for (i = 0; i < CONFIG_OOM_COUNT; i++) {
- char *eptr;
- long long val = strtoll(args[i], &eptr, 10);
-
- if (*eptr != '\0' || val < -2000 || val > 2000) {
- if (err) *err = "Invalid oom-score-adj-values, elements must be between -2000 and 2000.";
- return C_ERR;
- }
-
- values[i] = val;
- }
-
- /* Verify that the values make sense. If they don't omit a warning but
- * keep the configuration, which may still be valid for privileged processes.
- */
-
- if (values[CONFIG_OOM_REPLICA] < values[CONFIG_OOM_MASTER] ||
- values[CONFIG_OOM_BGCHILD] < values[CONFIG_OOM_REPLICA]) {
- serverLog(LOG_WARNING,
- "The oom-score-adj-values configuration may not work for non-privileged processes! "
- "Please consult the documentation.");
- }
-
- /* Store values, retain previous config for rollback in case we fail. */
- int old_values[CONFIG_OOM_COUNT];
- for (i = 0; i < CONFIG_OOM_COUNT; i++) {
- old_values[i] = server.oom_score_adj_values[i];
- server.oom_score_adj_values[i] = values[i];
- }
-
- /* When parsing the config file, we want to apply only when all is done. */
- if (!apply)
- return C_OK;
-
- /* Update */
- if (setOOMScoreAdj(-1) == C_ERR) {
- /* Roll back */
- for (i = 0; i < CONFIG_OOM_COUNT; i++)
- server.oom_score_adj_values[i] = old_values[i];
-
- if (err)
- *err = "Failed to apply oom-score-adj-values configuration, check server logs.";
-
- return C_ERR;
- }
-
- return C_OK;
- }
-
- void initConfigValues() {
- for (standardConfig *config = configs; config->name != NULL; config++) {
- config->interface.init(config->data);
- }
- }
-
- void loadServerConfigFromString(char *config) {
- const char *err = NULL;
- int linenum = 0, totlines, i;
- int slaveof_linenum = 0;
- sds *lines;
- int save_loaded = 0;
-
- lines = sdssplitlen(config,strlen(config),"\n",1,&totlines);
-
- for (i = 0; i < totlines; i++) {
- sds *argv;
- int argc;
-
- linenum = i+1;
- lines[i] = sdstrim(lines[i]," \t\r\n");
-
- /* Skip comments and blank lines */
- if (lines[i][0] == '#' || lines[i][0] == '\0') continue;
-
- /* Split into arguments */
- argv = sdssplitargs(lines[i],&argc);
- if (argv == NULL) {
- err = "Unbalanced quotes in configuration line";
- goto loaderr;
- }
-
- /* Skip this line if the resulting command vector is empty. */
- if (argc == 0) {
- sdsfreesplitres(argv,argc);
- continue;
- }
- sdstolower(argv[0]);
-
- /* Iterate the configs that are standard */
- int match = 0;
- for (standardConfig *config = configs; config->name != NULL; config++) {
- if ((!strcasecmp(argv[0],config->name) ||
- (config->alias && !strcasecmp(argv[0],config->alias))))
- {
- if (argc != 2) {
- err = "wrong number of arguments";
- goto loaderr;
- }
- if (!config->interface.set(config->data, argv[1], 0, &err)) {
- goto loaderr;
- }
-
- match = 1;
- break;
- }
- }
-
- if (match) {
- sdsfreesplitres(argv,argc);
- continue;
- }
-
- /* Execute config directives */
- if (!strcasecmp(argv[0],"bind") && argc >= 2) {
- int j, addresses = argc-1;
-
- if (addresses > CONFIG_BINDADDR_MAX) {
- err = "Too many bind addresses specified"; goto loaderr;
- }
- /* Free old bind addresses */
- for (j = 0; j < server.bindaddr_count; j++) {
- zfree(server.bindaddr[j]);
- }
- for (j = 0; j < addresses; j++)
- server.bindaddr[j] = zstrdup(argv[j+1]);
- server.bindaddr_count = addresses;
- } else if (!strcasecmp(argv[0],"unixsocketperm") && argc == 2) {
- errno = 0;
- server.unixsocketperm = (mode_t)strtol(argv[1], NULL, 8);
- if (errno || server.unixsocketperm > 0777) {
- err = "Invalid socket file permissions"; goto loaderr;
- }
- } else if (!strcasecmp(argv[0],"save")) {
- /* We don't reset save params before loading, because if they're not part
- * of the file the defaults should be used.
- */
- if (!save_loaded) {
- save_loaded = 1;
- resetServerSaveParams();
- }
-
- if (argc == 3) {
- int seconds = atoi(argv[1]);
- int changes = atoi(argv[2]);
- if (seconds < 1 || changes < 0) {
- err = "Invalid save parameters"; goto loaderr;
- }
- appendServerSaveParams(seconds,changes);
- } else if (argc == 2 && !strcasecmp(argv[1],"")) {
- resetServerSaveParams();
- }
- } else if (!strcasecmp(argv[0],"dir") && argc == 2) {
- if (chdir(argv[1]) == -1) {
- serverLog(LL_WARNING,"Can't chdir to '%s': %s",
- argv[1], strerror(errno));
- exit(1);
- }
- } else if (!strcasecmp(argv[0],"logfile") && argc == 2) {
- FILE *logfp;
-
- zfree(server.logfile);
- server.logfile = zstrdup(argv[1]);
- if (server.logfile[0] != '\0') {
- /* Test if we are able to open the file. The server will not
- * be able to abort just for this problem later... */
- logfp = fopen(server.logfile,"a");
- if (logfp == NULL) {
- err = sdscatprintf(sdsempty(),
- "Can't open the log file: %s", strerror(errno));
- goto loaderr;
- }
- fclose(logfp);
- }
- } else if (!strcasecmp(argv[0],"include") && argc == 2) {
- loadServerConfig(argv[1], 0, NULL);
- } else if ((!strcasecmp(argv[0],"slaveof") ||
- !strcasecmp(argv[0],"replicaof")) && argc == 3) {
- slaveof_linenum = linenum;
- sdsfree(server.masterhost);
- if (!strcasecmp(argv[1], "no") && !strcasecmp(argv[2], "one")) {
- server.masterhost = NULL;
- continue;
- }
- server.masterhost = sdsnew(argv[1]);
- char *ptr;
- server.masterport = strtol(argv[2], &ptr, 10);
- if (server.masterport < 0 || server.masterport > 65535 || *ptr != '\0') {
- err = "Invalid master port"; goto loaderr;
- }
- server.repl_state = REPL_STATE_CONNECT;
- } else if (!strcasecmp(argv[0],"list-max-ziplist-entries") && argc == 2){
- /* DEAD OPTION */
- } else if (!strcasecmp(argv[0],"list-max-ziplist-value") && argc == 2) {
- /* DEAD OPTION */
- } else if (!strcasecmp(argv[0],"rename-command") && argc == 3) {
- struct redisCommand *cmd = lookupCommand(argv[1]);
- int retval;
-
- if (!cmd) {
- err = "No such command in rename-command";
- goto loaderr;
- }
-
- /* If the target command name is the empty string we just
- * remove it from the command table. */
- retval = dictDelete(server.commands, argv[1]);
- serverAssert(retval == DICT_OK);
-
- /* Otherwise we re-add the command under a different name. */
- if (sdslen(argv[2]) != 0) {
- sds copy = sdsdup(argv[2]);
-
- retval = dictAdd(server.commands, copy, cmd);
- if (retval != DICT_OK) {
- sdsfree(copy);
- err = "Target command name already exists"; goto loaderr;
- }
- }
- } else if (!strcasecmp(argv[0],"cluster-config-file") && argc == 2) {
- zfree(server.cluster_configfile);
- server.cluster_configfile = zstrdup(argv[1]);
- } else if (!strcasecmp(argv[0],"client-output-buffer-limit") &&
- argc == 5)
- {
- int class = getClientTypeByName(argv[1]);
- unsigned long long hard, soft;
- int soft_seconds;
-
- if (class == -1 || class == CLIENT_TYPE_MASTER) {
- err = "Unrecognized client limit class: the user specified "
- "an invalid one, or 'master' which has no buffer limits.";
- goto loaderr;
- }
- hard = memtoll(argv[2],NULL);
- soft = memtoll(argv[3],NULL);
- soft_seconds = atoi(argv[4]);
- if (soft_seconds < 0) {
- err = "Negative number of seconds in soft limit is invalid";
- goto loaderr;
- }
- server.client_obuf_limits[class].hard_limit_bytes = hard;
- server.client_obuf_limits[class].soft_limit_bytes = soft;
- server.client_obuf_limits[class].soft_limit_seconds = soft_seconds;
- } else if (!strcasecmp(argv[0],"oom-score-adj-values") && argc == 1 + CONFIG_OOM_COUNT) {
- if (updateOOMScoreAdjValues(&argv[1], &err, 0) == C_ERR) goto loaderr;
- } else if (!strcasecmp(argv[0],"notify-keyspace-events") && argc == 2) {
- int flags = keyspaceEventsStringToFlags(argv[1]);
-
- if (flags == -1) {
- err = "Invalid event class character. Use 'g$lshzxeA'.";
- goto loaderr;
- }
- server.notify_keyspace_events = flags;
- } else if (!strcasecmp(argv[0],"user") && argc >= 2) {
- int argc_err;
- if (ACLAppendUserForLoading(argv,argc,&argc_err) == C_ERR) {
- char buf[1024];
- const char *errmsg = ACLSetUserStringError();
- snprintf(buf,sizeof(buf),"Error in user declaration '%s': %s",
- argv[argc_err],errmsg);
- err = buf;
- goto loaderr;
- }
- } else if (!strcasecmp(argv[0],"loadmodule") && argc >= 2) {
- queueLoadModule(argv[1],&argv[2],argc-2);
- } else if (!strcasecmp(argv[0],"sentinel")) {
- /* argc == 1 is handled by main() as we need to enter the sentinel
- * mode ASAP. */
- if (argc != 1) {
- if (!server.sentinel_mode) {
- err = "sentinel directive while not in sentinel mode";
- goto loaderr;
- }
- queueSentinelConfig(argv+1,argc-1,linenum,lines[i]);
- }
- } else {
- err = "Bad directive or wrong number of arguments"; goto loaderr;
- }
- sdsfreesplitres(argv,argc);
- }
-
- /* Sanity checks. */
- if (server.cluster_enabled && server.masterhost) {
- linenum = slaveof_linenum;
- i = linenum-1;
- err = "replicaof directive not allowed in cluster mode";
- goto loaderr;
- }
-
- /* To ensure backward compatibility and work while hz is out of range */
- if (server.config_hz < CONFIG_MIN_HZ) server.config_hz = CONFIG_MIN_HZ;
- if (server.config_hz > CONFIG_MAX_HZ) server.config_hz = CONFIG_MAX_HZ;
-
- sdsfreesplitres(lines,totlines);
- return;
-
- loaderr:
- fprintf(stderr, "\n*** FATAL CONFIG FILE ERROR (Redis %s) ***\n",
- REDIS_VERSION);
- fprintf(stderr, "Reading the configuration file, at line %d\n", linenum);
- fprintf(stderr, ">>> '%s'\n", lines[i]);
- fprintf(stderr, "%s\n", err);
- exit(1);
- }
-
- /* Load the server configuration from the specified filename.
- * The function appends the additional configuration directives stored
- * in the 'options' string to the config file before loading.
- *
- * Both filename and options can be NULL, in such a case are considered
- * empty. This way loadServerConfig can be used to just load a file or
- * just load a string. */
- void loadServerConfig(char *filename, char config_from_stdin, char *options) {
- sds config = sdsempty();
- char buf[CONFIG_MAX_LINE+1];
- FILE *fp;
-
- /* Load the file content */
- if (filename) {
- if ((fp = fopen(filename,"r")) == NULL) {
- serverLog(LL_WARNING,
- "Fatal error, can't open config file '%s': %s",
- filename, strerror(errno));
- exit(1);
- }
- while(fgets(buf,CONFIG_MAX_LINE+1,fp) != NULL)
- config = sdscat(config,buf);
- fclose(fp);
- }
- /* Append content from stdin */
- if (config_from_stdin) {
- serverLog(LL_WARNING,"Reading config from stdin");
- fp = stdin;
- while(fgets(buf,CONFIG_MAX_LINE+1,fp) != NULL)
- config = sdscat(config,buf);
- }
-
- /* Append the additional options */
- if (options) {
- config = sdscat(config,"\n");
- config = sdscat(config,options);
- }
- loadServerConfigFromString(config);
- sdsfree(config);
- }