Result IConfig::init()

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{};
}