// SPDX-FileCopyrightText: 2024 Filip Leonarski, Paul Scherrer Institute // SPDX-License-Identifier: GPL-3.0-only // Using OpenAPI licensed with Apache License 2.0 #include #include #include #include #include #include "../common/Logger.h" #include "../common/print_license.h" #include "../detector_control/DectrisSimplonClient.h" #include "../writer/HDF5Objects.h" #include "JFJochBrokerHttp.h" #include "JFJochBrokerParser.h" static httplib::Server *httpServer = nullptr; static void sigHandler [[noreturn]] (int sig) { switch (sig) { case SIGINT: case SIGQUIT: case SIGTERM: case SIGHUP: default: if (httpServer) httpServer->stop(); break; } std::exit(0); } static void setUpUnixSignals(std::vector quitSignals) { sigset_t blocking_mask; sigemptyset(&blocking_mask); for (auto sig : quitSignals) sigaddset(&blocking_mask, sig); struct sigaction sa; sa.sa_handler = sigHandler; sa.sa_mask = blocking_mask; sa.sa_flags = 0; for (auto sig : quitSignals) sigaction(sig, &sa, nullptr); } int main(int argc, char **argv) { RegisterHDF5Filter(); print_license("jfjoch_broker"); if ((argc == 1) || (argc > 3)) { std::cout << "Usage ./jfjoch_broker {}" << std::endl; return EXIT_FAILURE; } uint16_t http_port = 5232; if (argc >= 3) http_port = static_cast(std::atoi(argv[2])); Logger logger("jfjoch_broker"); org::openapitools::server::model::Jfjoch_settings settings; std::ifstream file(argv[1]); try { nlohmann::json input = nlohmann::json::parse(file); settings = input; settings.validate(); logger.Info("JSON configuration file read properly"); } catch (const std::exception &e) { logger.Error("Error reading JSON configuration file: " + std::string(e.what())); return EXIT_FAILURE; } if (settings.numaPolicyIsSet()) logger.Warning("NUMA policy is deprecated and ignored - processed are split over all the CPUs/GPUs in the system"); if (settings.verboseIsSet() && settings.isVerbose()) logger.Verbose(true); else logger.Verbose(false); std::unique_ptr image_pusher = ParseImagePusher(settings); if (image_pusher) logger.Info(image_pusher->PrintSetup()); std::vector det_setup; for (const auto &d: settings.getDetector()) det_setup.push_back(ParseDetectorSetup(d)); if (det_setup.empty()) { logger.Error("At least one detector need to be defined in the config file"); return EXIT_FAILURE; } DiffractionExperiment experiment(det_setup[0]); ParseFacilityConfiguration(settings, experiment); SpotFindingSettings spot_finding_settings = ParseSpotFindingSettings(settings); AcquisitionDeviceGroup aq_devices; ParseAcquisitionDeviceGroup(settings, aq_devices); experiment.DataStreams(aq_devices.size()); int32_t send_buffer_size_MiB = settings.getImageBufferMiB(); std::unique_ptr receiver = std::make_unique(aq_devices, logger, *image_pusher, send_buffer_size_MiB); ParseReceiverSettings(settings, *receiver); JFJochBrokerHttp broker(experiment, spot_finding_settings); broker.FrontendDirectory(settings.getFrontendDirectory()); for (const auto &d: det_setup) broker.AddDetectorSetup(d); if (receiver) broker.Services().Receiver(receiver.get()); httplib::Server server; httpServer = &server; server.Get("/", [](const httplib::Request &req, httplib::Response &res) { res.status = 302; // Found (temporary redirect) res.set_header("Location", "/frontend"); }); server.set_mount_point("/frontend", settings.getFrontendDirectory()); signal(SIGPIPE, SIG_IGN); std::vector sigs{SIGQUIT, SIGINT, SIGTERM, SIGHUP}; setUpUnixSignals(sigs); broker.attach(server); if (!server.listen("0.0.0.0", http_port)) { logger.Error("Failed to start HTTP server"); return EXIT_FAILURE; } return EXIT_SUCCESS; }