#include "server.hpp" #include "config.hpp" #include #include #include #include #include #include #include namespace simple_object_storage { std::atomic g_running{true}; std::unique_ptr g_server; std::thread g_server_thread; std::filesystem::path get_config_path() { std::filesystem::path system_config_path = "/data/sos_config.json"; std::filesystem::path user_config_path = std::filesystem::path(std::getenv("HOME")) / ".config/simple_object_storage/config.json"; if (std::filesystem::exists(system_config_path)) return system_config_path; if (std::filesystem::exists(user_config_path)) return user_config_path; std::cout << "No config file found. Checked " << system_config_path << " and " << user_config_path << std::endl; return std::filesystem::path(); } bool initialize_server() { std::filesystem::path config_path = get_config_path(); if (config_path.empty()) { return false; } std::cout << "Config file: " << config_path << std::endl; ServerConfig config; if (!simple_object_storage::load_config(config_path, config)) { std::cout << "Config file at " << config_path << " is not valid." << std::endl; return false; } std::cout << "Starting server at " << config.host << ":" << config.port << std::endl; std::cout << "Object store path: " << config.object_store_path << std::endl; g_server = std::make_unique(config); // Start server in a separate thread g_server_thread = std::thread([&]() { if (!g_server->start()) { std::cerr << "Failed to start server" << std::endl; g_running = false; } }); return true; } void stop_server() { if (g_server) { std::cout << "Stopping server..." << std::endl; g_server->stop(); if (g_server_thread.joinable()) { g_server_thread.join(); } g_server.reset(); } } void signal_handler(int signal) { switch (signal) { case SIGHUP: std::cout << "Received SIGHUP signal - reloading configuration" << std::endl; stop_server(); if (!initialize_server()) { std::cerr << "Failed to restart server with new configuration" << std::endl; g_running = false; } break; case SIGTERM: case SIGINT: std::cout << "Received termination signal" << std::endl; g_running = false; break; } } int main(int argc, char* argv[]) { // Set up signal handlers struct sigaction sa; sa.sa_handler = signal_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; if (sigaction(SIGHUP, &sa, nullptr) == -1) { std::cerr << "Failed to set up SIGHUP handler" << std::endl; return 1; } if (sigaction(SIGTERM, &sa, nullptr) == -1) { std::cerr << "Failed to set up SIGTERM handler" << std::endl; return 1; } if (sigaction(SIGINT, &sa, nullptr) == -1) { std::cerr << "Failed to set up SIGINT handler" << std::endl; return 1; } // Initial server startup if (!initialize_server()) { return 1; } // Main loop - wait for signals while (g_running) { std::this_thread::sleep_for(std::chrono::milliseconds(100)); } // Graceful shutdown stop_server(); return 0; } } // namespace simple_object_storage int main(int argc, char* argv[]) { return simple_object_storage::main(argc, argv); }