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();
}