blob: 8d51fbaddaca1683ace6a4d239c756ad42802ec8 [file] [log] [blame] [edit]
/**
* @brief GPU telemetry server executable
*
* SPDX-FileCopyrightText: Copyright (c) 2023-2024 NVIDIA CORPORATION & AFFILIATES.
* All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*/
#include "server/server.hpp"
#include "server/mock_device.hpp"
#include <stdexec/execution.hpp>
#include <iostream>
#include <csignal>
#include <cstdlib>
using namespace gpu::telemetry;
namespace {
volatile sig_atomic_t running = 1;
void signal_handler(int) {
running = 0;
}
void print_usage(const char* program) {
std::cerr << "Usage: " << program << " [options] <socket-path>\n"
<< "Options:\n"
<< " -m <clients> Maximum number of clients (default: 10)\n"
<< " -p <perms> Socket permissions in octal (default: 666)\n"
<< " -d <delay_ms> Mock device response delay (default: 0)\n"
<< " -t <min:max> Temperature range in Celsius (default: 30:80)\n"
<< " -h Show this help message\n";
}
}
int main(int argc, char* argv[]) {
// Parse command line options
ServerConfig serverConfig;
MockDeviceConfig deviceConfig;
int opt;
while ((opt = getopt(argc, argv, "m:p:d:t:h")) != -1) {
switch (opt) {
case 'm':
serverConfig.maxClients = std::atoi(optarg);
break;
case 'p':
serverConfig.socketPerms = std::stoul(optarg, nullptr, 8);
break;
case 'd':
deviceConfig.responseDelay =
std::chrono::milliseconds(std::atoi(optarg));
break;
case 't': {
char* colon = strchr(optarg, ':');
if (colon) {
*colon = '\0';
deviceConfig.temperature.min = std::atof(optarg);
deviceConfig.temperature.max = std::atof(colon + 1);
}
break;
}
case 'h':
print_usage(argv[0]);
return 0;
default:
print_usage(argv[0]);
return 1;
}
}
// Check for socket path argument
if (optind >= argc) {
std::cerr << "Error: Socket path required\n";
print_usage(argv[0]);
return 1;
}
serverConfig.socketPath = argv[optind];
try {
// Create mock device
auto device = std::make_unique<MockDevice>(deviceConfig);
// Create and start server
Server server(std::move(device), serverConfig);
// Set up signal handling
struct sigaction sa = {};
sa.sa_handler = signal_handler;
sigaction(SIGINT, &sa, nullptr);
sigaction(SIGTERM, &sa, nullptr);
// Start server
stdexec::sync_wait(server.start());
std::cout << "Server started on " << serverConfig.socketPath << std::endl;
// Run until signaled
while (running) {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
// Stop server
stdexec::sync_wait(server.stop());
std::cout << "\nServer stopped" << std::endl;
return 0;
}
catch (const std::exception& e) {
std::cerr << "Error: " << e.what() << std::endl;
return 1;
}
}