in src/common/utils/ConfigBase.cc [54:157]
Result<Void> IConfig::init(int *argc, char ***argv, bool follyInit /* = true */) {
constexpr std::string_view configPrefix = "--config.";
// 1. parse command line flags.
auto parseFlagsResult = parseFlags(configPrefix, *argc, *argv);
if (UNLIKELY(!parseFlagsResult)) {
XLOGF(ERR, "Parse config from command line flags failed: {}", parseFlagsResult.error());
return makeError(StatusCode::kConfigInvalidValue);
}
if (follyInit) {
folly::init(argc, argv);
}
if (FLAGS_dump_default_cfg) {
if (FLAGS_dump_path.empty()) {
std::cout << toString() << std::endl;
} else {
auto res = storeToFile(FLAGS_dump_path, toString());
if (res.hasError()) {
XLOGF(ERR, "Open file {} failed: {}", FLAGS_dump_path, res.error());
}
}
exit(0);
}
// 2. load config from toml files.
if (!FLAGS_cfg.empty()) {
toml::parse_result parseResult;
if (UNLIKELY(!boost::filesystem::exists(FLAGS_cfg))) {
auto msg = fmt::format("Config file {} not found", FLAGS_cfg);
XLOG(ERR, msg);
return makeError(StatusCode::kConfigInvalidValue, std::move(msg));
}
try {
parseResult = toml::parse_file(FLAGS_cfg);
} catch (const toml::parse_error &e) {
std::stringstream ss;
ss << e;
XLOGF(ERR, "Parse config file [{}] failed: {}", FLAGS_cfg, ss.str());
return makeError(StatusCode::kConfigParseError);
} catch (std::exception &e) {
XLOGF(ERR, "Parse config file [{}] failed: {}", FLAGS_cfg, e.what());
return makeError(StatusCode::kConfigInvalidValue);
}
auto updateResult = update(parseResult, /* isHotUpdate = */ false);
if (UNLIKELY(!updateResult)) {
XLOGF(ERR, "Load config file [{}] failed: {}", FLAGS_cfg, updateResult.error());
return makeError(StatusCode::kConfigInvalidValue);
}
}
// 3. load config from command line flags.
for (auto &[key, value] : parseFlagsResult.value()) {
auto findResult = find(key);
if (UNLIKELY(!findResult)) {
XLOGF(ERR, "Item {} is not found: {}", key, findResult.error());
return makeError(StatusCode::kConfigInvalidValue);
}
auto &item = *findResult.value();
auto toml = item.isParsedFromString() ? fmt::format(R"(v = """{}""")", value) : fmt::format("v = {}", value);
toml::parse_result parseResult;
try {
parseResult = toml::parse(toml);
} catch (const toml::parse_error &e) {
std::stringstream ss;
ss << e;
XLOGF(ERR, "Parse toml {} failed: {}", toml, ss.str());
return makeError(StatusCode::kConfigParseError);
} catch (std::exception &e) {
XLOGF(ERR, "Parse toml {} failed: {}", toml, e.what());
return makeError(StatusCode::kConfigInvalidValue);
}
auto updateResult = item.update(*parseResult["v"].node(), /* isHotUpdate = */ false, key);
if (UNLIKELY(!updateResult)) {
XLOGF(ERR, "Load config from toml {} failed: {}", toml, updateResult.error());
return makeError(StatusCode::kConfigInvalidValue);
}
}
// 4. validate config.
auto validateResult = validate();
if (UNLIKELY(!validateResult)) {
if (!FLAGS_dump_cfg) {
XLOGF(ERR, "Check default result failed: {}", validateResult.error());
return makeError(StatusCode::kConfigInvalidValue);
} else {
XLOGF(WARN, "Check default result failed: {}", validateResult.error());
}
}
if (FLAGS_dump_cfg) {
if (FLAGS_dump_path.empty()) {
std::cout << toString() << std::endl;
} else {
auto res = storeToFile(FLAGS_dump_path, toString());
if (res.hasError()) {
XLOGF(ERR, "Open file {} failed: {}", FLAGS_dump_path, res.error());
}
}
exit(0);
}
return Void{};
}