in mcrouter/StandaloneUtils.cpp [215:385]
CmdLineOptions parseCmdLineOptions(int argc, char** argv, std::string pkgName) {
CmdLineOptions res;
CHECK(argc >= 1) << "invalid argc value";
if (pkgName.empty()) {
res.packageName = argv[0];
} else {
res.packageName = std::move(pkgName);
}
res.commandArgs = constructArgString(argc, argv);
std::vector<option> longOptions = {
{"verbosity", 1, nullptr, 'v'},
{"help", 0, nullptr, 'h'},
{"version", 0, nullptr, 'V'},
{"validate-config", 2, nullptr, 0},
{"proxy-threads", 1, nullptr, 0},
{"service-name", 1, nullptr, 0},
// Deprecated or not supported
{"gets", 0, nullptr, 0},
{"skip-sanity-checks", 0, nullptr, 0},
{"retry-timeout", 1, nullptr, 0},
};
std::string optstring = "dD:v:hV";
// Append auto-generated options to longOptions and optstring
auto optionData = McrouterOptions::getOptionData();
auto standaloneData = McrouterStandaloneOptions::getOptionData();
auto combinedOptionData = optionData;
combinedOptionData.insert(
combinedOptionData.end(), standaloneData.begin(), standaloneData.end());
for (auto& opt : combinedOptionData) {
if (!opt.long_option.empty()) {
// Toggle options can have optional argument
int extraArgs = (opt.type == McrouterOptionData::Type::toggle ? 2 : 1);
longOptions.push_back(
{opt.long_option.c_str(), extraArgs, nullptr, opt.short_option});
if (opt.short_option) {
optstring.push_back(opt.short_option);
if (extraArgs == 1) {
optstring += ":";
} else if (extraArgs == 2) {
optstring += "::";
}
}
}
}
longOptions.push_back({0, 0, 0, 0});
int longIndex = -1;
int c;
while ((c = getopt_long(
argc, argv, optstring.c_str(), longOptions.data(), &longIndex)) !=
-1) {
switch (c) {
case 'v':
FLAGS_v = folly::to<int>(optarg);
break;
case 'h':
printUsageAndDie(argv[0], /* errorCode */ 0, pkgName);
case 'V':
printf("%s\n", MCROUTER_PACKAGE_STRING);
exit(0);
case 0:
default:
if (longIndex != -1 &&
strcmp("constantly-reload-configs", longOptions[longIndex].name) ==
0) {
LOG(ERROR)
<< "CRITICAL: You have enabled constantly-reload-configs. "
"This undocumented feature is incredibly dangerous. "
"It will result in massively increased CPU consumption. "
"It will trigger lots of edge cases, surely causing hard failures. "
"If you're using this for *anything* other than testing, "
"please resign.";
}
// If the current short/long option is found in optData,
// set it in the optDict and return true. False otherwise.
auto find_and_set =
[&](const std::vector<McrouterOptionData>& optData,
std::unordered_map<std::string, std::string>& optDict) {
for (auto& opt : optData) {
if (!opt.long_option.empty()) {
if ((opt.short_option && opt.short_option == c) ||
(!opt.long_option.empty() && longIndex != -1 &&
opt.long_option == longOptions[longIndex].name)) {
if (opt.type == McrouterOptionData::Type::toggle) {
optDict[opt.name] =
(optarg != nullptr
? optarg
: (opt.default_value == "false" ? "1" : "0"));
;
} else {
optDict[opt.name] = optarg;
}
return true;
}
}
}
return false;
};
if (find_and_set(optionData, res.libmcrouterOptionsOverrides)) {
break;
}
if (find_and_set(standaloneData, res.standaloneOptionsOverrides)) {
break;
}
if (longIndex == -1) {
res.unrecognizedOptions.insert(argv[optind - 1]);
} else if (strcmp("proxy-threads", longOptions[longIndex].name) == 0) {
if (strcmp(optarg, "auto") == 0) {
int nprocs = sysconf(_SC_NPROCESSORS_ONLN);
if (nprocs > 0) {
res.libmcrouterOptionsOverrides["num_proxies"] =
std::to_string(nprocs);
} else {
LOG(INFO) << "Couldn't determine how many cores are available. "
"Defaulting to "
<< DEFAULT_NUM_PROXIES << " proxy thread(s)";
}
} else {
res.libmcrouterOptionsOverrides["num_proxies"] = optarg;
}
} else if (
strcmp("validate-config", longOptions[longIndex].name) == 0) {
if (!optarg || strcmp(optarg, "exit") == 0) {
res.validateConfigMode = ValidateConfigMode::Exit;
} else if (strcmp(optarg, "run") == 0) {
res.validateConfigMode = ValidateConfigMode::Run;
} else {
LOG(ERROR) << "Invalid argument for --validate-config: '" << optarg
<< "'. Ignoring the option.";
}
} else if (strcmp("retry-timeout", longOptions[longIndex].name) == 0) {
LOG(WARNING) << "--retry-timeout is deprecated, use"
" --probe-timeout-initial";
res.libmcrouterOptionsOverrides["probe_delay_initial_ms"] = optarg;
} else if (strcmp("service-name", longOptions[longIndex].name) == 0) {
// setup service name for standalone mcrouter
res.serviceName = optarg;
} else {
res.unrecognizedOptions.insert(argv[optind - 1]);
}
}
longIndex = -1;
}
// getopt permutes argv so that all non-options are at the end.
// For now we only expect one non-option argument, so look at the last one.
if (optind < argc && argv[optind]) {
res.flavor = std::string(argv[optind]);
}
if (optind + 1 < argc) {
LOG(ERROR) << "Expected only one non-option argument";
}
return res;
}