int main()

in src/oomd/Main.cpp [232:489]


int main(int argc, char** argv) {
  std::string flag_conf_file = kConfigFilePath;
  std::string cgroup_fs = kCgroupFsRoot;
  std::string drop_in_dir;
  std::string runtime_dir = std::string(kRuntimeDir);
  std::string stats_socket_path = runtime_dir + "/" + kStatsSocket;
  std::string dev_id;
  std::string kmsg_path = kKmsgPath;
  int interval = 5;
  bool should_check_config = false;

  int option_index = 0;
  int c = 0;
  bool should_dump_stats = false;
  bool should_reset_stats = false;
  Oomd::SystemMaybe<std::unordered_map<std::string, Oomd::DeviceType>> io_devs;
  struct Oomd::IOCostCoeffs hdd_coeffs = default_hdd_coeffs;
  struct Oomd::IOCostCoeffs ssd_coeffs = default_ssd_coeffs;

  const char* const short_options = "hvC:w:i:f:c:lD:dr";
  option long_options[] = {
      option{"help", no_argument, nullptr, 'h'},
      option{"version", no_argument, nullptr, 'v'},
      option{"config", required_argument, nullptr, 'C'},
      option{"interval", required_argument, nullptr, 'i'},
      option{"cgroup-fs", required_argument, nullptr, 'f'},
      option{"check-config", required_argument, nullptr, 'c'},
      option{"list-plugins", no_argument, nullptr, 'l'},
      option{"drop-in-dir", required_argument, nullptr, 'w'},
      option{"runtime-dir", required_argument, nullptr, 'D'},
      option{"dump-stats", no_argument, nullptr, 'd'},
      option{"reset-stats", no_argument, nullptr, 'r'},
      option{"device", required_argument, nullptr, OPT_DEVICE},
      option{"ssd-coeffs", required_argument, nullptr, OPT_SSD_COEFFS},
      option{"hdd-coeffs", required_argument, nullptr, OPT_HDD_COEFFS},
      option{"kmsg-override", required_argument, nullptr, 'k'},
      option{nullptr, 0, nullptr, 0}};

  while ((c = getopt_long(
              argc, argv, short_options, long_options, &option_index)) != -1) {
    size_t parsed_len;
    bool parse_error = false;

    switch (c) {
      case 'h':
        printUsage();
        return 0;
      case 'v':
        std::cout << GIT_VERSION << std::endl;
        return 0;
      case 'C':
        flag_conf_file = std::string(optarg);
        break;
      case 'c':
        should_check_config = true;
        flag_conf_file = std::string(optarg);
        break;
      case 'w':
        drop_in_dir = std::string(optarg);
        break;
      case 'l':
        std::cerr << "List of plugins oomd was compiled with:\n";
        for (const auto& plugin_name :
             Oomd::getPluginRegistry().getRegistered()) {
          std::cerr << " " << plugin_name << "\n";
        }
        return 0;
      case 'i':
        try {
          interval = std::stoi(optarg, &parsed_len);
        } catch (const std::invalid_argument& e) {
          parse_error = true;
        }
        if (parse_error || interval < 1 || parsed_len != strlen(optarg)) {
          std::cerr << "Interval not a >0 integer: " << optarg << std::endl;
          return 1;
        }

        break;
      case 'f':
        cgroup_fs = std::string(optarg);
        break;
      case 'D':
        runtime_dir = std::string(optarg);
        stats_socket_path = runtime_dir + "/" + kStatsSocket;
        break;
      case 'd':
        should_dump_stats = true;
        break;
      case 'r':
        should_reset_stats = true;
        break;
      case OPT_DEVICE:
        io_devs = parseDevices(optarg);
        if (!io_devs) {
          std::cerr << "Invalid devices: " << io_devs.error().what() << '\n';
          return 1;
        }
        break;
      case OPT_SSD_COEFFS:
        try {
          ssd_coeffs = parseCoeffs(optarg);
        } catch (const std::invalid_argument& e) {
          std::cerr << "Invalid SSD coefficients: " << e.what() << '\n';
          return 1;
        }
        break;
      case OPT_HDD_COEFFS:
        try {
          hdd_coeffs = parseCoeffs(optarg);
        } catch (const std::invalid_argument& e) {
          std::cerr << "Invalid HDD coefficients: " << e.what() << '\n';
          return 1;
        }
        break;
      case 'k':
        kmsg_path = std::string(optarg);
        break;
      case 0:
        break;
      case '?':
        std::cerr << "Unknown option or missing argument\n";
        printUsage();
        return 1;
      default:
        return 1;
    }
  }

  if (optind < argc) {
    std::cerr << "Non-option argument is not supported: ";
    while (optind < argc) {
      std::cerr << "\"" << argv[optind++] << "\" ";
    }
    std::cerr << std::endl;
    printUsage();
    return 1;
  }

  if (should_dump_stats) {
    try {
      Oomd::StatsClient client(stats_socket_path);
      auto map = client.getStats();
      if (!map) {
        std::cerr << "Failed to retrieve stats" << std::endl;
        return 1;
      }
      Json::Value root(Json::objectValue);
      for (const auto& pair : *map) {
        root[pair.first] = pair.second;
      }
      std::cout << root.toStyledString() << std::endl;
    } catch (const std::runtime_error& e) {
      std::cerr << e.what() << std::endl;
      return 1;
    }
    if (!should_reset_stats) {
      return 0;
    }
  }

  if (should_reset_stats) {
    try {
      Oomd::StatsClient client(stats_socket_path);
      int res = client.resetStats();
      if (res != 0) {
        std::cerr << "Reset stats error: received error code= " << res
                  << std::endl;
        return 1;
      }
    } catch (const std::runtime_error& e) {
      std::cerr << e.what() << std::endl;
      return 1;
    }
    return 0;
  }

  // Init oomd logging code
  //
  // NB: do not use OLOG before initializing logging. Doing so will disable
  // kmsg logging (due to some weird setup code required to get unit testing
  // correct). Be careful not to make any oomd library calls before initing
  // logging.
  if (!Oomd::Log::init(kmsg_path)) {
    std::cerr << "Logging failed to initialize. Try running with sudo\n";
    return 1;
  }

  if (should_check_config) {
    auto ir = parseConfig(flag_conf_file);
    if (!ir) {
      return 1;
    }

    Oomd::PluginConstructionContext compile_context(cgroup_fs);

    auto engine = Oomd::Config2::compile(*ir, compile_context);
    if (!engine) {
      OLOG << "Config is not valid";
      return 1;
    }

    return 0;
  }

  //
  // Daemon code below here
  //

  if (!initRuntimeDir(runtime_dir)) {
    return 1;
  }

  // NB: do not start stats module unless we are going to daemonize
  if (!Oomd::Stats::init(stats_socket_path)) {
    OLOG << "Stats module failed to initialize";
    return 1;
  }

  initializeCoreStats();

  if (!system_reqs_met()) {
    std::cerr << "System requirements not met\n";
    return EXIT_CANT_RECOVER;
  }

  if (!cgroup_fs_valid(cgroup_fs)) {
    std::cerr << cgroup_fs << " is not a valid cgroup2 filesystem" << std::endl;
    return EXIT_CANT_RECOVER;
  }

  std::cerr << "oomd running with conf_file=" << flag_conf_file
            << " interval=" << interval << std::endl;

  auto ir = parseConfig(flag_conf_file);
  if (!ir) {
    return EXIT_CANT_RECOVER;
  }

  Oomd::PluginConstructionContext compile_context(cgroup_fs);

  auto engine = Oomd::Config2::compile(*ir, compile_context);
  if (!engine) {
    OLOG << "Config failed to compile";
    return EXIT_CANT_RECOVER;
  }

  Oomd::Oomd oomd(
      std::move(ir),
      std::move(engine),
      interval,
      cgroup_fs,
      drop_in_dir,
      *io_devs,
      hdd_coeffs,
      ssd_coeffs);
  return oomd.run();
}