@@ -15804,6 +15804,122 @@ static bool sanitycheck(void)
1580415804 return true;
1580515805}
1580615806
15807+ typedef struct {
15808+ bool *daemonize;
15809+ bool *maxcore;
15810+ char **username;
15811+ bool *lock_memory;
15812+ char **pid_file;
15813+ char *protocol;
15814+ char **engine;
15815+ const char **engine_config;
15816+ bool *preallocate;
15817+ #ifdef ENABLE_ZK_INTEGRATION
15818+ int *arcus_zk_to;
15819+ #endif
15820+ #ifdef PROXY_SUPPORT
15821+ char **arcus_proxy_cfg;
15822+ #endif
15823+ } config_opt_t;
15824+
15825+ static int try_load_config_file(const char *path, config_opt_t *opt)
15826+ {
15827+ char *access_mask_str = NULL;
15828+ char *protocol_str = NULL;
15829+ char *extension_path[5] = {NULL,};
15830+
15831+ struct config_item main_config_items[] = {
15832+ { .key = "port", .datatype = DT_UINT32, .value.dt_uint32 = (uint32_t*)&settings.port },
15833+ { .key = "udpport", .datatype = DT_UINT32, .value.dt_uint32 = (uint32_t*)&settings.udpport },
15834+ { .key = "socketpath", .datatype = DT_STRING, .value.dt_string = &settings.socketpath },
15835+ { .key = "access", .datatype = DT_STRING, .value.dt_string = &access_mask_str },
15836+ { .key = "listen", .datatype = DT_STRING, .value.dt_string = &settings.inter },
15837+ { .key = "daemonize", .datatype = DT_BOOL, .value.dt_bool = opt->daemonize },
15838+ { .key = "maxcore", .datatype = DT_BOOL, .value.dt_bool = opt->maxcore },
15839+ { .key = "username", .datatype = DT_STRING, .value.dt_string = opt->username },
15840+ { .key = "maxconns", .datatype = DT_UINT32, .value.dt_uint32 = (uint32_t*)&settings.maxconns },
15841+ { .key = "lock_memory", .datatype = DT_BOOL, .value.dt_bool = opt->lock_memory },
15842+ { .key = "verbosity", .datatype = DT_SIZE, .value.dt_size = (size_t*)&settings.verbose },
15843+ { .key = "pid_file", .datatype = DT_STRING, .value.dt_string = opt->pid_file },
15844+ { .key = "threads", .datatype = DT_UINT32, .value.dt_uint32 = (uint32_t*)&settings.num_threads },
15845+ { .key = "reqs_per_event", .datatype = DT_UINT32, .value.dt_uint32 = (uint32_t*)&settings.reqs_per_event },
15846+ { .key = "backlog", .datatype = DT_UINT32, .value.dt_uint32 = (uint32_t*)&settings.backlog },
15847+ { .key = "protocol", .datatype = DT_STRING, .value.dt_string = &protocol_str },
15848+ { .key = "engine_path", .datatype = DT_STRING, .value.dt_string = opt->engine },
15849+
15850+ { .key = "memory_limit", .datatype = DT_SIZE, .value.dt_size = &settings.maxbytes },
15851+ { .key = "eviction", .datatype = DT_BOOL, .value.dt_bool = (bool*)&settings.evict_to_free },
15852+ { .key = "sticky_limit", .datatype = DT_SIZE, .value.dt_size = &settings.sticky_limit },
15853+ { .key = "factor", .datatype = DT_FLOAT, .value.dt_float = (float*)&settings.factor },
15854+ { .key = "chunk_size", .datatype = DT_SIZE, .value.dt_size = (size_t*)&settings.chunk_size },
15855+ { .key = "prefix_delimiter", .datatype = DT_CHAR, .value.dt_char = &settings.prefix_delimiter},
15856+ { .key = "use_cas", .datatype = DT_BOOL, .value.dt_bool = &settings.use_cas },
15857+ { .key = "item_size_max", .datatype = DT_SIZE, .value.dt_size = &settings.item_size_max },
15858+ { .key = "engine_config", .datatype = DT_STRING, .value.dt_string = (char**)opt->engine_config },
15859+ { .key = "preallocate", .datatype = DT_BOOL, .value.dt_bool = opt->preallocate },
15860+ { .key = "extension1", .datatype = DT_STRING, .value.dt_string = &extension_path[0] },
15861+ { .key = "extension2", .datatype = DT_STRING, .value.dt_string = &extension_path[1] },
15862+ { .key = "extension3", .datatype = DT_STRING, .value.dt_string = &extension_path[2] },
15863+ { .key = "extension4", .datatype = DT_STRING, .value.dt_string = &extension_path[3] },
15864+ { .key = "extension5", .datatype = DT_STRING, .value.dt_string = &extension_path[4] },
15865+ #ifdef ENABLE_ZK_INTEGRATION
15866+ { .key = "zookeeper", .datatype = DT_STRING, .value.dt_string = (char**)&arcus_zk_cfg },
15867+ { .key = "zk_timeout", .datatype = DT_UINT32, .value.dt_uint32 = (uint32_t*)opt->arcus_zk_to },
15868+ #ifdef PROXY_SUPPORT
15869+ { .key = "proxy_config", .datatype = DT_STRING, .value.dt_string = opt->arcus_proxy_cfg },
15870+ #endif
15871+ #endif
15872+
15873+ #ifdef SASL_ENABLED
15874+ { .key = "require_sasl", .datatype = DT_BOOL, .value.dt_bool = &settings.require_sasl },
15875+ #endif
15876+ { .key = NULL}
15877+ };
15878+
15879+ if (read_config_file(path, main_config_items, stderr) == -1) {
15880+ fprintf(stderr, "Error parsing config file. Aborting.\n");
15881+ return -1;
15882+ }
15883+
15884+ if (access_mask_str != NULL) {
15885+ settings.access = strtol(access_mask_str, NULL, 8);
15886+ free(access_mask_str);
15887+ }
15888+ if (protocol_str != NULL) {
15889+ if (strcmp(protocol_str, "auto") == 0) {
15890+ settings.binding_protocol = negotiating_prot;
15891+ } else if (strcmp(protocol_str, "binary") == 0) {
15892+ settings.binding_protocol = binary_prot;
15893+ } else if (strcmp(protocol_str, "ascii") == 0) {
15894+ settings.binding_protocol = ascii_prot;
15895+ } else {
15896+ fprintf(stderr, "Invalid value for binding protocol in config file: %s\n", protocol_str);
15897+ free(protocol_str);
15898+ return -1;
15899+ }
15900+ free(protocol_str);
15901+ }
15902+
15903+ for (int i = 0; i < 5; i++) {
15904+ if (extension_path[i] != NULL) {
15905+ char *ptr = strchr(extension_path[i], ',');
15906+ if (ptr != NULL) {
15907+ *ptr = '\0';
15908+ ptr++;
15909+ }
15910+ if (!load_extension(extension_path[i], ptr)) {
15911+ fprintf(stderr, "Failed to load extension: %s\n", extension_path[i]);
15912+ for (int j = 0; j < 5; j++)
15913+ if (extension_path[j]) free(extension_path[j]);
15914+ return -1;
15915+ }
15916+ free(extension_path[i]);
15917+ }
15918+ }
15919+
15920+ return 0;
15921+ }
15922+
1580715923static void settings_reload_engine_config(void)
1580815924{
1580915925 ENGINE_ERROR_CODE ret;
@@ -15898,6 +16014,34 @@ int main (int argc, char **argv)
1589816014 return EX_OSERR;
1589916015 }
1590016016
16017+ /* parse config file */
16018+ if (argc > 1 && argv[1][0] != '-') {
16019+ const char *config_file = argv[1];
16020+ config_opt_t opt = {
16021+ .daemonize = &do_daemonize,
16022+ .maxcore = (bool*)&maxcore,
16023+ .username = &username,
16024+ .lock_memory = &lock_memory,
16025+ .pid_file = &pid_file,
16026+ .engine = (char**)&engine,
16027+ .engine_config = &engine_config,
16028+ .preallocate = &preallocate,
16029+ #ifdef ENABLE_ZK_INTEGRATION
16030+ .arcus_zk_to = &arcus_zk_to,
16031+ #ifdef PROXY_SUPPORT
16032+ .arcus_proxy_cfg = &arcus_proxy_cfg,
16033+ #endif
16034+ #endif
16035+ };
16036+ if (try_load_config_file(config_file, &opt) != 0) {
16037+ fprintf(stderr, "Error parsing config file '%s'.", config_file);
16038+ exit(EXIT_FAILURE);
16039+ }
16040+ optind = 2;
16041+ } else {
16042+ optind = 1;
16043+ }
16044+
1590116045 /* process arguments */
1590216046 while (-1 != (c = getopt(argc, argv,
1590316047 "a:" /* access mask for unix socket */
@@ -16021,11 +16165,6 @@ int main (int argc, char **argv)
1602116165 break;
1602216166 case 'f':
1602316167 settings.factor = atof(optarg);
16024- if (settings.factor <= 1.0) {
16025- mc_logger->log(EXTENSION_LOG_WARNING, NULL,
16026- "Factor must be greater than 1\n");
16027- return 1;
16028- }
1602916168 break;
1603016169 case 'n':
1603116170 settings.chunk_size = atoi(optarg);
@@ -16097,26 +16236,6 @@ int main (int argc, char **argv)
1609716236 } else {
1609816237 settings.item_size_max = atoi(optarg);
1609916238 }
16100- /* small memory allocator needs the maximum item size larger than 20 KB */
16101- //if (settings.item_size_max < 1024) {
16102- if (settings.item_size_max < 1024 * 20) {
16103- mc_logger->log(EXTENSION_LOG_WARNING, NULL,
16104- "Item max size cannot be less than 20KB.\n");
16105- return 1;
16106- }
16107- if (settings.item_size_max > 1024 * 1024 * 128) {
16108- mc_logger->log(EXTENSION_LOG_WARNING, NULL,
16109- "Cannot set item size limit higher than 128 mb.\n");
16110- return 1;
16111- }
16112- if (settings.item_size_max > 1024 * 1024) {
16113- mc_logger->log(EXTENSION_LOG_WARNING, NULL,
16114- "WARNING: Setting item max size above 1MB is not"
16115- " recommended!\n"
16116- " Raising this limit increases the minimum memory requirements\n"
16117- " and will decrease your memory efficiency.\n"
16118- );
16119- }
1612016239 break;
1612116240 case 'E':
1612216241 engine = optarg;
@@ -16173,6 +16292,33 @@ int main (int argc, char **argv)
1617316292 return 1;
1617416293 }
1617516294 }
16295+
16296+ /* small memory allocator needs the maximum item size larger than 20 KB */
16297+ //if (settings.item_size_max < 1024) {
16298+ if (settings.item_size_max < 1024 * 20) {
16299+ mc_logger->log(EXTENSION_LOG_WARNING, NULL,
16300+ "Item max size cannot be less than 20KB.\n");
16301+ return 1;
16302+ }
16303+ if (settings.item_size_max > 1024 * 1024 * 128) {
16304+ mc_logger->log(EXTENSION_LOG_WARNING, NULL,
16305+ "Cannot set item size limit higher than 128 mb.\n");
16306+ return 1;
16307+ }
16308+ if (settings.item_size_max > 1024 * 1024) {
16309+ mc_logger->log(EXTENSION_LOG_WARNING, NULL,
16310+ "WARNING: Setting item max size above 1MB is not"
16311+ " recommended!\n"
16312+ " Raising this limit increases the minimum memory requirements\n"
16313+ " and will decrease your memory efficiency.\n"
16314+ );
16315+ }
16316+ if (settings.factor <= 1.0) {
16317+ mc_logger->log(EXTENSION_LOG_WARNING, NULL,
16318+ "Factor must be greater than 1\n");
16319+ return 1;
16320+ }
16321+
1617616322 old_opts += sprintf(old_opts, "num_threads=%lu;", (unsigned long)settings.num_threads);
1617716323 old_opts += sprintf(old_opts, "cache_size=%llu;", (unsigned long long)settings.maxbytes);
1617816324 if (settings.evict_to_free == 0) {
0 commit comments