From 1806ffda990d22393de7758460be0ab1d08ca40a Mon Sep 17 00:00:00 2001 From: "Timur A. Fatkhullin" Date: Thu, 12 Dec 2024 18:12:15 +0300 Subject: [PATCH] ... --- CMakeLists.txt | 41 +++++++--- raptor_eaglev_server.cpp | 157 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 188 insertions(+), 10 deletions(-) create mode 100644 raptor_eaglev_server.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index e8a2af4..dc218cb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,30 +8,51 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}") find_package(Threads REQUIRED) -find_package(spdlog REQUIRED) +# find_package(spdlog REQUIRED) +find_package(spdlog CONFIG) find_package(CFITSIO REQUIRED) find_package(XCLIB REQUIRED) +find_package(cxxopts CONFIG) set(RAPTOR_EAGLEV_LIB raptor_eaglev) -add_library(${RAPTOR_EAGLEV_LIB} SHARED + +option(STATIC_LIB "Create static '${RAPTOR_EAGLEV_LIB}' library" OFF) + +set(RAPTOR_EAGLEV_LIB_SRC raptor_eagle_ccd.h raptor_eagle_ccd.cpp raptor_eagle_cameralink.h raptor_eagle_exception.h raptor_eagle_acqproc.cpp) -# to activate spdlog-library support in ADC-library -target_compile_definitions(${RAPTOR_EAGLEV_LIB} PRIVATE USE_SPDLOG_LIBRARY) -# !!!!! TEMPORARY !!!!! -target_include_directories(${RAPTOR_EAGLEV_LIB} PRIVATE "../ADC/") -target_include_directories(${RAPTOR_EAGLEV_LIB} PRIVATE ${XCLIB_INCLUDE_DIR}) -target_link_libraries(${RAPTOR_EAGLEV_LIB} PUBLIC Threads::Threads spdlog::spdlog_header_only ${XCLIB_LIBRARIES}) +if (STATIC_LIB) + add_library(${RAPTOR_EAGLEV_LIB} STATIC ${RAPTOR_EAGLEV_LIB_SRC}) +else() + add_library(${RAPTOR_EAGLEV_LIB} SHARED ${RAPTOR_EAGLEV_LIB_SRC}) +# add_library(${RAPTOR_EAGLEV_LIB} SHARED +# raptor_eagle_ccd.h raptor_eagle_ccd.cpp +# raptor_eagle_cameralink.h +# raptor_eagle_exception.h +# raptor_eagle_acqproc.cpp) +endif() -add_executable(RaptorEagleV main.cpp) +# to activate spdlog-library support in ADC-library +# target_compile_definitions(${RAPTOR_EAGLEV_LIB} PRIVATE USE_ASIO_LIBRARY USE_SPDLOG_LIBRARY USE_OPENSSL_WITH_ASIO) +target_compile_definitions(${RAPTOR_EAGLEV_LIB} PUBLIC USE_ASIO_LIBRARY USE_SPDLOG_LIBRARY) + +# !!!!! TEMPORARY !!!!! +target_include_directories(${RAPTOR_EAGLEV_LIB} PUBLIC "../ADC/") +target_include_directories(${RAPTOR_EAGLEV_LIB} PUBLIC ${XCLIB_INCLUDE_DIR} ${CFITSIO_INCLUDE_DIR}) +target_link_libraries(${RAPTOR_EAGLEV_LIB} PUBLIC Threads::Threads spdlog::spdlog_header_only ${XCLIB_LIBRARIES} ${CFITSIO_LIBRARY}) + + +set(RAPTOR_EAGLEV_SERVER raptor_eaglev_server) +add_executable(${RAPTOR_EAGLEV_SERVER} raptor_eaglev_server.cpp) +target_link_libraries(${RAPTOR_EAGLEV_SERVER} PUBLIC ${RAPTOR_EAGLEV_LIB} cxxopts::cxxopts) include(GNUInstallDirs) -install(TARGETS RaptorEagleV +install(TARGETS ${RAPTOR_EAGLEV_LIB} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ) diff --git a/raptor_eaglev_server.cpp b/raptor_eaglev_server.cpp new file mode 100644 index 0000000..9e46f8c --- /dev/null +++ b/raptor_eaglev_server.cpp @@ -0,0 +1,157 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "raptor_eagle_ccd.h" + +typedef adc::impl::AdcDeviceNetServerASIO server_t; + +int main(int argc, char* argv[]) +{ + int exit_code = 0; + asio::io_context ctx; + std::vector threads; + std::size_t Nthreads = 2; + + /* COMMANDLINE OPTS */ + cxxopts::Options options(argv[0], "ADC-library test device network server (ASIO implementation)\n"); + + options.allow_unrecognised_options(); + + options.add_options()("h,help", "Print usage"); + options.add_options()("D", "Daemonize server", cxxopts::value()->default_value("false")); + + options.add_options()("l,log", "Log filename (use stdout and stderr for standard output and error stream)", + cxxopts::value()->default_value("")); + + options.add_options()("level", "Log level (see SPDLOG package description for valid values)", + cxxopts::value()->default_value("info")); + + options.add_options()("t,threads", "Number of threads used by the server", + cxxopts::value()->default_value(std::to_string(Nthreads))); + + + + options.add_options()( + "endpoints", + "endpoints server will be listening for. For 'local' endpoint the '@' symbol at the beginning of the path " + "means " + "abstract namespace socket.", + cxxopts::value>()->default_value("local://stream/@RAPTOR_EAGLEV_SERVER")); + + + options.positional_help("[endpoint0] [enpoint1] ... [endpointN]"); + options.parse_positional({"endpoints"}); + + try { + auto opt_result = options.parse(argc, argv); + + if (opt_result["help"].count()) { + std::cout << options.help(); + std::cout << "\n"; + std::cout << "[endpoint0] [enpoint1] ... [endpointN] - endpoints server will be listening for. For 'local' " + "endpoint the '@' symbol at the beginning of the path " + "means abstract namespace socket." + << "\n"; + return 0; + } + + + auto logname = opt_result["log"].as(); + + auto logger = [&logname]() { + if (logname == "stdout") { + return spdlog::stdout_color_mt("console"); + } else if (logname == "stderr") { + return spdlog::stderr_color_mt("stderr"); + } else if (logname == "") { + return spdlog::null_logger_mt("RAPTOR_EAGLEV_SERVER_NULL_LOGGER"); + } else { + return spdlog::basic_logger_mt(logname, logname); + } + }(); + + std::string level_str = opt_result["level"].as(); + + auto log_level = [&level_str]() { + if (level_str == "TRACE") { + return spdlog::level::trace; + } else if (level_str == "DEBUG") { + return spdlog::level::debug; + } else if (level_str == "INFO") { + return spdlog::level::info; + } else if (level_str == "WARN") { + return spdlog::level::warn; + } else if (level_str == "ERROR") { + return spdlog::level::err; + } else if (level_str == "CRITICAL") { + return spdlog::level::critical; + } else if (level_str == "OFF") { + return spdlog::level::off; + } + + return spdlog::level::info; + }(); + + logger->set_level(log_level); + + logger->flush_on(spdlog::level::trace); + + + asio::io_context io_ctx; + + asio::signal_set signals(io_ctx, SIGINT, SIGTERM); + signals.async_wait([&](std::error_code, int) { io_ctx.stop(); }); + + + RaptorEagleCCD ccd_device(logger); + + server_t server("RAPTOR EAGLE V CCD SERVER", io_ctx, logger); + server.setupSignals(); + + server.addDevice(&ccd_device); + + auto epnt = opt_result["endpoints"].as>(); + + for (auto& ep : epnt) { + adc::AdcEndpoint epn(ep); + if (epn.isValid()) { + if (epn.isLocalSeqpacket() || epn.isLocalStream()) { + if (epn.path()[0] == '@') { // replace '@' to '\0' (use of UNIX abstract namespace) + auto it = std::ranges::find(ep, '@'); + *it = '\0'; + epn = adc::AdcEndpoint(ep); + } + } + + server.start>(epn); + + } else { + std::cerr << "Unrecognized endpoint: '" << ep << "'! Ignore!\n"; + } + } + + if (opt_result["D"].as()) { + // server.daemonize(); + } + + io_ctx.run(); + + + + } catch (const cxxopts::exceptions::exception& ex) { + std::cerr << "\nAn error occured while parsing input options: " << ex.what() << "\n"; + return 127; + } catch (const std::system_error& ex) { + std::cerr << "\nAn error ocured: " << ex.what() << "\n"; + std::cerr << "Category: " << ex.code().category().name() << "; message: " << ex.code().message() << "\n"; + return 128; + } + + + return 0; +}