예제 #1
0
//TODO webserver_mode,              webserver_index_function,
//     webserver_whitelist_address, webserver_whitelist_netmask,
//     sqlslaveof
int DXDB_configSetCommand(cli *c, robj *o) {
    if        (!strcasecmp(c->argv[2]->ptr,"luacronfunc")) {
        if (server.alc.LuaCronFunc) zfree(server.alc.LuaCronFunc);
        server.alc.LuaCronFunc = zstrdup(o->ptr); return 0;
    } else if (!strcasecmp(c->argv[2]->ptr, "lua_output_start")) {
        if (server.alc.OutputLuaFunc_Start) {
            zfree(server.alc.OutputLuaFunc_Start);
        }
        server.alc.OutputLuaFunc_Start = zstrdup(o->ptr); return 0;
    } else if (!strcasecmp(c->argv[2]->ptr, "lua_output_cnames")) {
        if (server.alc.OutputLuaFunc_Cnames) {
            zfree(server.alc.OutputLuaFunc_Cnames);
        }
        server.alc.OutputLuaFunc_Cnames = zstrdup(o->ptr); return 0;
    } else if (!strcasecmp(c->argv[2]->ptr, "lua_output_row")) {
        if (server.alc.OutputLuaFunc_Row) zfree(server.alc.OutputLuaFunc_Row);
        server.alc.OutputLuaFunc_Row = zstrdup(o->ptr); return 0;
    } else if (!strcasecmp(c->argv[2]->ptr, "rest_api_mode")) {
        int yn = yesnotoi(o->ptr);
        if (yn == -1) goto badfmt;
        server.alc.RestAPIMode = yn ? 1 : -1; return 0;
    } else if (!strcasecmp(c->argv[2]->ptr, "outputmode")) {
        if        (!strcasecmp(o->ptr, "embedded")) {
            server.alc.OutputMode = OUTPUT_EMBEDDED;
        } else if (!strcasecmp(o->ptr, "pure_redis")) {
            server.alc.OutputMode = OUTPUT_PURE_REDIS;
        } else if (!strcasecmp(o->ptr, "normal")) {
            server.alc.OutputMode = OUTPUT_NORMAL;
        } else if (!strcasecmp(o->ptr, "lua")) {
            if (!server.alc.OutputLuaFunc_Start ||
                !server.alc.OutputLuaFunc_Cnames ||
                !server.alc.OutputLuaFunc_Row) {
                sds err = sdsnew("-ERR: OUTPUTMODE lua requires "         \
                                 "[lua_output_start, lua_output_cnames, " \
                                 "lua_output_row]\r\n");
                addReplySds(c, err); decrRefCount(o); return -1;
            }
            server.alc.OutputMode = OUTPUT_LUA;
        } else {
            addReplySds(c,sdscatprintf(sdsempty(),
               "-ERR OUTPUTMODE: [EMBEDDED|PURE_REDIS|LUA|NORMAL] not: %s\r\n",
                (char *)o->ptr));
            decrRefCount(o);
            return -1;
        }
        return 0;
    }
    return 1;

badfmt: /* Bad format errors */
    addReplyErrorFormat(c,"Invalid argument '%s' for CONFIG SET '%s'",
            (char*)o->ptr,
            (char*)c->argv[2]->ptr);
    return -1;

}
예제 #2
0
파일: config.c 프로젝트: zhouyuan/destor
void load_config_from_string(sds config) {
	char *err = NULL;
	int linenum = 0, totlines, i;
	sds *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");

		if (lines[i][0] == '#' || lines[i][0] == '\0')
			continue;

		argv = sdssplitargs(lines[i], &argc);
		if (argv == NULL) {
			err = "Unbalanced quotes in configuration line";
			goto loaderr;
		}

		if (argc == 0) {
			sdsfreesplitres(argv, argc);
			continue;
		}
		sdstolower(argv[0]);

		if (strcasecmp(argv[0], "working-directory") == 0 && argc == 2) {
			destor.working_directory = sdscpy(destor.working_directory,
					argv[1]);
		} else if (strcasecmp(argv[0], "simulation-level") == 0 && argc == 2) {
			if (strcasecmp(argv[1], "all") == 0) {
				destor.simulation_level = SIMULATION_ALL;
			} else if (strcasecmp(argv[1], "append") == 0) {
				destor.simulation_level = SIMULATION_APPEND;
			} else if (strcasecmp(argv[1], "restore") == 0) {
				destor.simulation_level = SIMULATION_RESTORE;
			} else if (strcasecmp(argv[1], "no") == 0) {
				destor.simulation_level = SIMULATION_NO;
			} else {
				err = "Invalid simulation level";
				goto loaderr;
			}
		} else if (strcasecmp(argv[0], "log-level") == 0 && argc == 2) {
			if (strcasecmp(argv[1], "debug") == 0) {
				destor.verbosity = DESTOR_DEBUG;
			} else if (strcasecmp(argv[1], "verbose") == 0) {
				destor.verbosity = DESTOR_VERBOSE;
			} else if (strcasecmp(argv[1], "notice") == 0) {
				destor.verbosity = DESTOR_NOTICE;
			} else if (strcasecmp(argv[1], "warning") == 0) {
				destor.verbosity = DESTOR_WARNING;
			} else {
				err = "Invalid log level";
				goto loaderr;
			}
		} else if (strcasecmp(argv[0], "chunk-algorithm") == 0 && argc == 2) {
			if (strcasecmp(argv[1], "fixed") == 0) {
				destor.chunk_algorithm = CHUNK_FIXED;
			} else if (strcasecmp(argv[1], "rabin") == 0) {
				destor.chunk_algorithm = CHUNK_RABIN;
			} else if (strcasecmp(argv[1], "normalized rabin") == 0) {
				destor.chunk_algorithm = CHUNK_NORMALIZED_RABIN;
			} else if (strcasecmp(argv[1], "file") == 0) {
				destor.chunk_algorithm = CHUNK_FILE;
			} else {
				err = "Invalid chunk algorithm";
				goto loaderr;
			}
		} else if (strcasecmp(argv[0], "chunk-avg-size") == 0 && argc == 2) {
			destor.chunk_avg_size = atoi(argv[1]);
		} else if (strcasecmp(argv[0], "chunk-max-size") == 0 && argc == 2) {
			destor.chunk_max_size = atoi(argv[1]);
		} else if (strcasecmp(argv[0], "chunk-min-size") == 0 && argc == 2) {
			destor.chunk_min_size = atoi(argv[1]);
		} else if (strcasecmp(argv[0], "fingerprint-index") == 0 && argc >= 3) {
			if (strcasecmp(argv[1], "exact") == 0) {
				destor.index_category[0] = INDEX_CATEGORY_EXACT;
			} else if (strcasecmp(argv[1], "near-exact") == 0) {
				destor.index_category[0] = INDEX_CATEGORY_NEAR_EXACT;
			} else {
				err = "Invalid index category";
				goto loaderr;
			}

			if (strcasecmp(argv[2], "physical") == 0) {
				destor.index_category[1] = INDEX_CATEGORY_PHYSICAL_LOCALITY;
			} else if (strcasecmp(argv[2], "logical") == 0) {
				destor.index_category[1] = INDEX_CATEGORY_LOGICAL_LOCALITY;
			} else {
				err = "Invalid index category";
				goto loaderr;
			}

			if (argc > 3) {
				if (strcasecmp(argv[3], "ddfs") == 0) {
					assert(destor.index_category[0] == INDEX_CATEGORY_EXACT 
                            && destor.index_category[1] == INDEX_CATEGORY_PHYSICAL_LOCALITY);
					destor.index_specific = INDEX_SPECIFIC_DDFS;
				} else if (strcasecmp(argv[3], "sampled index") == 0) {
					assert(destor.index_category[0] == INDEX_CATEGORY_NEAR_EXACT 
                            && destor.index_category[1] == INDEX_CATEGORY_PHYSICAL_LOCALITY);
					destor.index_specific = INDEX_SPECIFIC_SAMPLED;
				} else if (strcasecmp(argv[3], "block locality caching") == 0) {
					assert(destor.index_category[0] == INDEX_CATEGORY_EXACT 
                            && destor.index_category[1] == INDEX_CATEGORY_LOGICAL_LOCALITY);
					destor.index_specific =	INDEX_SPECIFIC_BLOCK_LOCALITY_CACHING;
				} else if (strcasecmp(argv[3], "extreme binning") == 0) {
					assert(destor.index_category[0] == INDEX_CATEGORY_NEAR_EXACT 
                            && destor.index_category[1] == INDEX_CATEGORY_LOGICAL_LOCALITY);
					destor.index_specific = INDEX_SPECIFIC_EXTREME_BINNING;
				} else if (strcasecmp(argv[3], "sparse index") == 0) {
					assert(destor.index_category[0] == INDEX_CATEGORY_NEAR_EXACT 
                            && destor.index_category[1] == INDEX_CATEGORY_LOGICAL_LOCALITY);
					destor.index_specific = INDEX_SPECIFIC_SPARSE;
				} else if (strcasecmp(argv[3], "silo") == 0) {
					assert(destor.index_category[0] == INDEX_CATEGORY_NEAR_EXACT 
                            && destor.index_category[1] == INDEX_CATEGORY_LOGICAL_LOCALITY);
					destor.index_specific = INDEX_SPECIFIC_SILO;
				} else {
					err = "Invalid index specific";
					goto loaderr;
				}
			}
		} else if (strcasecmp(argv[0], "fingerprint-index-cache-size")
				== 0 && argc == 2) {
			destor.index_cache_size = atoi(argv[1]);
		} else if (strcasecmp(argv[0], "fingerprint-index-key-value") == 0
				&& argc == 2) {
			if (strcasecmp(argv[1], "htable") == 0) {
				destor.index_key_value_store = INDEX_KEY_VALUE_HTABLE;
			} else {
				err = "Invalid key-value store";
				goto loaderr;
			}
		} else if (strcasecmp(argv[0], "fingerprint-index-key-size") == 0
				&& argc == 2) {
			destor.index_key_size = atoi(argv[1]);
		} else if (strcasecmp(argv[0], "fingerprint-index-value-length") == 0
				&& argc == 2) {
			destor.index_value_length = atoi(argv[1]);
		} else if (strcasecmp(argv[0], "fingerprint-index-bloom-filter") == 0
				&& argc == 2) {
			destor.index_bloom_filter_size = atoi(argv[1]);
		} else if (strcasecmp(argv[0], "fingerprint-index-sampling-method") == 0
				&& argc >= 2) {
			if (strcasecmp(argv[1], "optmin") == 0)
				destor.index_sampling_method[0] = INDEX_SAMPLING_OPTIMIZED_MIN;
			else if (strcasecmp(argv[1], "random") == 0)
				destor.index_sampling_method[0] = INDEX_SAMPLING_RANDOM;
			else if (strcasecmp(argv[1], "min") == 0)
				destor.index_sampling_method[0] = INDEX_SAMPLING_MIN;
			else if (strcasecmp(argv[1], "uniform") == 0)
				destor.index_sampling_method[0] = INDEX_SAMPLING_UNIFORM;
			else {
				err = "Invalid feature method!";
				goto loaderr;
			}

			if (argc > 2) {
				destor.index_sampling_method[1] = atoi(argv[2]);
			} else {
				destor.index_sampling_method[1] = 0;
			}
		} else if (strcasecmp(argv[0], "fingerprint-index-segment-algorithm")
				== 0 && argc >= 2) {
			if (strcasecmp(argv[1], "fixed") == 0)
				destor.index_segment_algorithm[0] = INDEX_SEGMENT_FIXED;
			else if (strcasecmp(argv[1], "file-defined") == 0)
				destor.index_segment_algorithm[0] = INDEX_SEGMENT_FILE_DEFINED;
			else if (strcasecmp(argv[1], "content-defined") == 0)
				destor.index_segment_algorithm[0] =	INDEX_SEGMENT_CONTENT_DEFINED;
			else {
				err = "Invalid segment algorithm";
				goto loaderr;
			}

			if (argc > 2) {
				assert(destor.index_segment_algorithm[0] != INDEX_SEGMENT_FILE_DEFINED);
				destor.index_segment_algorithm[1] = atoi(argv[2]);
			}
		} else if (strcasecmp(argv[0], "fingerprint-index-segment-boundary") == 0
				&& argc == 3) {
			destor.index_segment_min = atoi(argv[1]);
			destor.index_segment_max = atoi(argv[2]);
		} else if (strcasecmp(argv[0], "fingerprint-index-segment-selection")
				== 0 && argc >= 2) {
			destor.index_segment_selection_method[1] = 1;
			if (strcasecmp(argv[1], "base") == 0)
				destor.index_segment_selection_method[0] = INDEX_SEGMENT_SELECT_BASE;
			else if (strcasecmp(argv[1], "top") == 0) {
				destor.index_segment_selection_method[0] = INDEX_SEGMENT_SELECT_TOP;
				if (argc > 2)
					destor.index_segment_selection_method[1] = atoi(argv[2]);
			} else if (strcasecmp(argv[1], "mix") == 0)
				destor.index_segment_selection_method[0] = INDEX_SEGMENT_SELECT_MIX;
			else {
				err = "Invalid selection method!";
				goto loaderr;
			}
		} else if (strcasecmp(argv[0], "fingerprint-index-segment-prefetching")	== 0 && argc == 2) {
			destor.index_segment_prefech = atoi(argv[1]);
		} else if (strcasecmp(argv[0], "rewrite-algorithm") == 0 && argc >= 2) {
			if (strcasecmp(argv[1], "no") == 0)
				destor.rewrite_algorithm[0] = REWRITE_NO;
			else if (strcasecmp(argv[1], "cfl-based selective deduplication")
					== 0 || strcasecmp(argv[1], "cfl") == 0)
				destor.rewrite_algorithm[0] =
				REWRITE_CFL_SELECTIVE_DEDUPLICATION;
			else if (strcasecmp(argv[1], "context-based rewriting") == 0
					|| strcasecmp(argv[1], "cbr") == 0)
				destor.rewrite_algorithm[0] = REWRITE_CONTEXT_BASED;
			else if (strcasecmp(argv[1], "capping") == 0
					|| strcasecmp(argv[1], "cap") == 0)
				destor.rewrite_algorithm[0] = REWRITE_CAPPING;
			else {
				err = "Invalid rewriting algorithm";
				goto loaderr;
			}

			if (argc > 2) {
				assert(destor.rewrite_algorithm != REWRITE_NO);
				destor.rewrite_algorithm[1] = atoi(argv[2]);
			} else {
				destor.rewrite_algorithm[1] = 1024;
			}
		} else if (strcasecmp(argv[0], "rewrite-enable-cfl-switch") == 0
				&& argc == 2) {
			destor.rewrite_enable_cfl_switch = yesnotoi(argv[1]);
		} else if (strcasecmp(argv[0], "rewrite-cfl-require") == 0
				&& argc == 2) {
			destor.rewrite_cfl_require = atof(argv[1]);
		} else if (strcasecmp(argv[0], "rewrite-cfl-usage-threshold") == 0
				&& argc == 2) {
			destor.rewrite_cfl_usage_threshold = atof(argv[1]);
		} else if (strcasecmp(argv[0], "rewrite-cbr-limit") == 0 && argc == 2) {
			destor.rewrite_cbr_limit = atof(argv[1]);
		} else if (strcasecmp(argv[0], "rewrite-cbr-minimal-utility") == 0
				&& argc == 2) {
			destor.rewrite_cbr_minimal_utility = atof(argv[1]);
		} else if (strcasecmp(argv[0], "rewrite-capping-level") == 0
				&& argc == 2) {
			destor.rewrite_capping_level = atoi(argv[1]);
		} else if (strcasecmp(argv[0], "rewrite-enable-har") == 0
				&& argc == 2) {
			destor.rewrite_enable_har = yesnotoi(argv[1]);
		} else if (strcasecmp(argv[0], "rewrite-har-utilization-threshold") == 0
				&& argc == 2) {
			destor.rewrite_har_utilization_threshold = atof(argv[1]);
		} else if (strcasecmp(argv[0], "rewrite-har-rewrite-limit") == 0
				&& argc == 2) {
			destor.rewrite_har_rewrite_limit = atof(argv[1]);
		} else if (strcasecmp(argv[0], "rewrite-enable-cache-aware") == 0
				&& argc == 2) {
			destor.rewrite_enable_cache_aware = yesnotoi(argv[1]);
		} else if (strcasecmp(argv[0], "restore-cache") == 0 && argc == 3) {
			if (strcasecmp(argv[1], "lru") == 0)
				destor.restore_cache[0] = RESTORE_CACHE_LRU;
			else if (strcasecmp(argv[1], "optimal cache") == 0
					|| strcasecmp(argv[1], "opt") == 0)
				destor.restore_cache[0] = RESTORE_CACHE_OPT;
			else if (strcasecmp(argv[1], "forward assembly") == 0
					|| strcasecmp(argv[1], "asm") == 0)
				destor.restore_cache[0] = RESTORE_CACHE_ASM;
			else {
				err = "Invalid restore cache";
				goto loaderr;
			}

			destor.restore_cache[1] = atoi(argv[2]);
		} else if (strcasecmp(argv[0], "restore-opt-window-size") == 0
				&& argc == 2) {
			destor.restore_opt_window_size = atoi(argv[1]);
		} else if (strcasecmp(argv[0], "backup-retention-time") == 0
				&& argc == 2) {
			destor.backup_retention_time = atoi(argv[1]);
		} else {
			err = "Bad directive or wrong number of arguments";
			goto loaderr;
		}
		sdsfreesplitres(argv, argc);
	}
	sdsfreesplitres(lines, totlines);
	return;

	loaderr: fprintf(stderr, "\n*** FATAL CONFIG FILE ERROR in destor ***\n");
	fprintf(stderr, "Reading the configuration file, at line %d\n", linenum);
	fprintf(stderr, ">>> '%s'\n", lines[i]);
	fprintf(stderr, "%s\n", err);
	exit(1);
}
예제 #3
0
int DXDB_loadServerConfig(int argc, sds *argv) {
    //printf("DXDB_loadServerConfig: 0: %s\n", argv[0]);
    if (!strcasecmp(argv[0], "luacronfunc")   && argc == 2) {
        if (server.alc.LuaCronFunc) zfree(server.alc.LuaCronFunc);
        server.alc.LuaCronFunc = zstrdup(argv[1]);
        return 0;
    } else if (!strcasecmp(argv[0], "basedir")       && argc == 2) {
        if (server.alc.Basedir) zfree(server.alc.Basedir);
        server.alc.Basedir = zstrdup(argv[1]); return 0;
    } else if (!strcasecmp(argv[0], "lua_output_start") && argc == 2) {
        if (server.alc.OutputLuaFunc_Start) {
            zfree(server.alc.OutputLuaFunc_Start);
        }
        server.alc.OutputLuaFunc_Start = zstrdup(argv[1]); return 0;
    } else if (!strcasecmp(argv[0], "lua_output_cnames") && argc == 2) {
        if (server.alc.OutputLuaFunc_Cnames) {
            zfree(server.alc.OutputLuaFunc_Cnames);
        }
        server.alc.OutputLuaFunc_Cnames = zstrdup(argv[1]); return 0;
    } else if (!strcasecmp(argv[0], "lua_output_row") && argc == 2) {
        if (server.alc.OutputLuaFunc_Row) zfree(server.alc.OutputLuaFunc_Row);
        server.alc.OutputLuaFunc_Row = zstrdup(argv[1]); return 0;
    } else if (!strcasecmp(argv[0], "outputmode")    && argc >= 2) {
        if        (!strcasecmp(argv[1], "embedded")) {
            server.alc.OutputMode = OUTPUT_EMBEDDED;
        } else if (!strcasecmp(argv[1], "pure_redis")) {
            server.alc.OutputMode = OUTPUT_PURE_REDIS;
        } else if (!strcasecmp(argv[1], "normal")) {
            server.alc.OutputMode = OUTPUT_NORMAL;
        } else if (!strcasecmp(argv[1], "lua")) {
            if (!server.alc.OutputLuaFunc_Start ||
                !server.alc.OutputLuaFunc_Cnames ||
                !server.alc.OutputLuaFunc_Row) {
                char *err = "OUTPUTMODE lua requires [lua_output_start, "\
                            "lua_output_cnames, lua_output_row]";
                fprintf(stderr, "%s\n", err);
                return -1;
            }
            server.alc.OutputMode = OUTPUT_LUA;
        } else {
            char *err = "argument must be 'embedded', 'pure_redis' or 'normal'";
            fprintf(stderr, "%s\n", err);
            return -1;
        }
        return 0;
    } else if (!strcasecmp(argv[0], "webserver_mode") && argc == 2) {
        if ((server.alc.WebServerMode = yesnotoi(argv[1])) == -1) {
            char *err = "argument must be 'yes' or 'no'";
            fprintf(stderr, "%s\n", err);
            return -1;
        }
#if 0 //TODO webserver_mode & rest_api_mode can run in tandem??? right???
        if (server.alc.RestAPIMode != -1) {
            char *err = "CHOOSE: webserver_mode OR rest_api_mode ";
            fprintf(stderr, "%s\n", err);
            return -1;
        }
#endif
        return 0;
    } else if (!strcasecmp(argv[0], "webserver_index_function") && argc == 2) {
        if (server.alc.WebServerIndexFunc) zfree(server.alc.WebServerIndexFunc);
        server.alc.WebServerIndexFunc = zstrdup(argv[1]);
        return 0;
    } else if (!strcasecmp(argv[0], "webserver_whitelist_address") &&
                argc == 2) {
        if (!inet_aton(argv[1], &server.alc.WS_WL_Addr)) {
            fprintf(stderr, "ERR: webserver_whitelist_address: %s\n", argv[1]);
            return -1;
        }
        computeWS_WL_MinMax();
        return 0;
    } else if (!strcasecmp(argv[0], "webserver_whitelist_netmask") &&
                argc == 2) {
        if (!inet_aton(argv[1], &server.alc.WS_WL_Mask)) {
            fprintf(stderr, "ERR: webserver_whitelist_netmask: %s\n", argv[1]);
            return -1;
        }
        computeWS_WL_MinMax();
        return 0;
    } else if (!strcasecmp(argv[0], "rest_api_mode") && argc == 2) {
        int yn = yesnotoi(argv[1]);
        if (yn == -1) {
            char *err = "argument must be 'yes' or 'no'";
            fprintf(stderr, "%s\n", err);
            return -1;
        }
        server.alc.RestAPIMode = yn ? 1 : -1;
#if 0 //TODO webserver_mode & rest_api_mode can run in tandem??? right???
        if (server.alc.WebServerMode != -1) {
            char *err = "CHOOSE: webserver_mode OR rest_api_mode ";
            fprintf(stderr, "%s\n", err);
            return -1;
        }
#endif
        return 0;
    } else if (!strcasecmp(argv[0],"sqlappendonly") && argc == 2) {
        if        (!strcasecmp(argv[1], "no")) {
            server.appendonly = 0;
        } else if (!strcasecmp(argv[1], "yes")) {
            server.appendonly = 1;
        } else if (!strcasecmp(argv[1], "mysql")) {
            server.appendonly = 1;
            server.alc.SQL_AOF_MYSQL = 1;
        } else {
            fprintf(stderr, "argument must be 'yes', 'no' or 'mysql;\n");
            return -1;
        }
        server.alc.SQL_AOF = 1;
        return 0;
    }
    return 1;
}
예제 #4
0
파일: config.c 프로젝트: AllenDou/gsh
/* I agree, this is a very rudimental way to load a configuration...
   will improve later if the config gets more complex */
void loadServerConfig(char *filename) {
		FILE *fp;
		char buf[REDIS_CONFIGLINE_MAX+1], *err = NULL;
		int linenum = 0;
		sds line = NULL;

		if (filename[0] == '-' && filename[1] == '\0')
				fp = stdin;
		else {
				if ((fp = fopen(filename,"r")) == NULL) {
						redisLog(REDIS_WARNING, "Fatal error, can't open config file '%s'", filename);
						exit(1);
				}
		}

		while(fgets(buf,REDIS_CONFIGLINE_MAX+1,fp) != NULL) {
				sds *argv;
				int argc, j;

				linenum++;
				line = sdsnew(buf);
				line = sdstrim(line," \t\r\n");

				/* Skip comments and blank lines*/
				if (line[0] == '#' || line[0] == '\0') {
						sdsfree(line);
						continue;
				}

				/* Split into arguments */
				argv = sdssplitargs(line,&argc);
				sdstolower(argv[0]);

				/* Execute config directives */
				if (!strcasecmp(argv[0],"timeout") && argc == 2) {
						server.maxidletime = atoi(argv[1]);
						if (server.maxidletime < 0) {
								err = "Invalid timeout value"; goto loaderr;
						}
				} else if (!strcasecmp(argv[0],"port") && argc == 2) {
						server.port = atoi(argv[1]);
						if (server.port < 0 || server.port > 65535) {
								err = "Invalid port"; goto loaderr;
						}
				} else if (!strcasecmp(argv[0],"bind") && argc == 2) {
						server.bindaddr = zstrdup(argv[1]);
				} else if (!strcasecmp(argv[0],"formula") && argc == 2) {
						void *val = loadfm(argv[1]);
						if(!val) goto loaderr;
						int retval = dictAdd(server.fms, sdsnew(argv[1]), val);
						if(retval != DICT_OK) goto loaderr;
				} else if (!strcasecmp(argv[0],"dir") && argc == 2) {
						if (chdir(argv[1]) == -1) {
								redisLog(REDIS_WARNING,"Can't chdir to '%s': %s",
												argv[1], strerror(errno));
								exit(1);
						}
				} else if (!strcasecmp(argv[0],"loglevel") && argc == 2) {
						if (!strcasecmp(argv[1],"debug")) server.verbosity = REDIS_DEBUG;
						else if (!strcasecmp(argv[1],"verbose")) server.verbosity = REDIS_VERBOSE;
						else if (!strcasecmp(argv[1],"notice")) server.verbosity = REDIS_NOTICE;
						else if (!strcasecmp(argv[1],"warning")) server.verbosity = REDIS_WARNING;
						else {
								err = "Invalid log level. Must be one of debug, notice, warning";
								goto loaderr;
						}
				} else if (!strcasecmp(argv[0],"logfile") && argc == 2) {
						FILE *logfp;

						server.logfile = zstrdup(argv[1]);
						if (!strcasecmp(server.logfile,"stdout")) {
								zfree(server.logfile);
								server.logfile = NULL;
						}
						if (server.logfile) {
								/* 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],"databases") && argc == 2) {
						server.dbnum = atoi(argv[1]);
						if (server.dbnum < 1) {
								err = "Invalid number of databases"; goto loaderr;
						}
				} else if (!strcasecmp(argv[0],"maxclients") && argc == 2) {
						server.maxclients = atoi(argv[1]);
				} else if (!strcasecmp(argv[0],"daemonize") && argc == 2) {
						if ((server.daemonize = yesnotoi(argv[1])) == -1) {
								err = "argument must be 'yes' or 'no'"; goto loaderr;
						}
				} else if (!strcasecmp(argv[0],"pidfile") && argc == 2) {
						zfree(server.pidfile);
						server.pidfile = zstrdup(argv[1]);
				} else {
						err = "Bad directive or wrong number of arguments"; goto loaderr;
				}
				for (j = 0; j < argc; j++)
						sdsfree(argv[j]);
				zfree(argv);
				sdsfree(line);
		}
		if (fp != stdin) fclose(fp);
		return;

loaderr:
		fprintf(stderr, "\n*** FATAL CONFIG FILE ERROR ***\n");
		fprintf(stderr, "Reading the configuration file, at line %d\n", linenum);
		fprintf(stderr, ">>> '%s'\n", line);
		fprintf(stderr, "%s\n", err);
		exit(1);

}