added first draft of matterhorn

This commit is contained in:
2026-02-13 18:14:59 +01:00
parent e106c64fd8
commit 5a8c31fec9
12 changed files with 453 additions and 11 deletions
+2 -2
View File
@@ -1,8 +1,6 @@
# SPDX-License-Identifier: LGPL-3.0-or-other
# Copyright (C) 2021 Contributors to the SLS Detector Package
# Install fake the library
install(TARGETS slsProjectCSettings
EXPORT "${TARGETS_EXPORT_NAME}"
@@ -17,3 +15,5 @@ add_subdirectory(jungfrauDetectorServer)
add_subdirectory(mythen3DetectorServer)
add_subdirectory(gotthard2DetectorServer)
add_subdirectory(moenchDetectorServer)
add_subdirectory(matterhonServer)
@@ -0,0 +1,36 @@
# TODO: should be different executable if not simulators on !!
add_executable(matterhornDetectorServer_virtual
${CMAKE_CURRENT_SOURCE_DIR}/src/MatterhornApp.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/MatterhornServer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/MatterhornClientInterface.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/CommandLineOptions.cpp
)
target_include_directories(matterhornDetectorServer_virtual
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_CURRENT_SOURCE_DIR}/../../slsSupportLib/include
${CMAKE_CURRENT_SOURCE_DIR}/../slsDetectorServer/include
)
target_compile_definitions(matterhornDetectorServer_virtual
PUBLIC VIRTUAL STOP_SERVER #what is this stop server should we really have a generic ServerAPP and pass compile options to create server e.g. MatterHorn?
)
target_link_libraries(matterhornDetectorServer_virtual
PUBLIC
slsProjectCSettings
slsSupportStatic
slsDetectorStatic
slsServerStatic
fmt::fmt
)
set_target_properties(matterhornDetectorServer_virtual PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
)
install(TARGETS matterhornDetectorServer_virtual
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
@@ -0,0 +1,49 @@
#include "MatterhornServer.h"
#include "sls/sls_detector_defs.h"
#include <array>
#include <cstdint>
#include <getopt.h>
#include <string>
namespace sls {
struct DetectorServerOptions {
uint16_t port{DEFAULT_TCP_CNTRL_PORTNO};
bool isControlServer{true};
bool debugflag{false};
bool updateFlag{false};
bool checkModuleFlag{true};
bool versionRequested{false};
bool helpRequested{false};
};
// TODO should be a general server specific class or even shared with
// CommandLIneOptions in Receiver
class CommandLineOptions {
public:
CommandLineOptions() = default;
~CommandLineOptions() = default;
DetectorServerOptions parse(int argc, char *argv[]);
std::string getHelpMessage(const std::string &executable) const;
std::string getVersion() const;
uint16_t parsePort(const char *optarg) const;
private:
static constexpr std::array<option, 6> options{
{{"help", no_argument, nullptr, 'h'},
{"version", no_argument, nullptr, 'v'},
{"port", required_argument, nullptr, 'p'},
{"devel", no_argument, nullptr, 'd'},
{"update", no_argument, nullptr, 'u'},
{nullptr, 0, nullptr, 0}}};
inline static const std::string optstring{"hvp:du"};
};
} // namespace sls
@@ -0,0 +1,19 @@
#include "ClientInterface.h"
namespace sls {
class MatterhornClientInterface : public ClientInterface {
public:
MatterhornClientInterface(
const uint16_t portNumber = DEFAULT_TCP_CNTRL_PORTNO);
~MatterhornClientInterface() = default;
private:
ReturnCode get_version(ServerInterface &socket);
static std::string getMatterhornServerVersion();
};
} // namespace sls
@@ -0,0 +1,37 @@
#pragma once
#include "MatterhornClientInterface.h"
#include "sls/sls_detector_defs.h"
#include <memory>
namespace sls {
/// @brief struct saving udp details (one UDP port per module)
struct UDPInfo {
uint16_t srcport;
uint16_t dstport;
uint64_t srcmac;
uint64_t dstmac;
uint32_t srcip;
uint32_t dstip;
};
class MatterhornServer {
public:
/**
* Constructor
* Starts up a Matterhorn server.
* Assembles a Matterhorn server using TCP and UDP detector interfaces
* throws an exception in case of failure
* @param port TCP/IP port number
*/
explicit MatterhornServer(uint16_t port = DEFAULT_TCP_CNTRL_PORTNO);
~MatterhornServer() = default;
private:
std::unique_ptr<MatterhornClientInterface> tcpipInterface;
UDPInfo udpDetails{}; // TODO: for now only one receiver per module
};
} // namespace sls
@@ -0,0 +1,9 @@
#include <cstdint>
// TODO: should this inherit from MatterhornServer?
class StopServer {
public:
StopServer(uint16_t port);
~StopServer();
};
@@ -0,0 +1,95 @@
#include "CommandLineOptions.h"
#include "sls/ToString.h"
#include "sls/sls_detector_exceptions.h"
#include "sls/versionAPI.h"
#include <cstdint>
#include <fmt/format.h>
#include <getopt.h>
#include <iostream>
namespace sls {
std::string CommandLineOptions::getVersion() const {
return fmt::format(
"MatterhornServer Version: {}",
APIMATTERHORN); // TODO check that it is updated correctly !!!
}
uint16_t CommandLineOptions::parsePort(const char *optarg) const {
uint16_t val = 0; // TODO: in c code its unsigned int
try {
val = sls::StringTo<uint16_t>(optarg);
} catch (...) {
throw("Could not parse port number " + std::string(optarg));
}
if (val == std::numeric_limits<uint16_t>::max()) {
throw sls::RuntimeError("Cannot parse stop server port number. "
"Value must be in range 0 - 65535.");
}
if (val < 1024) {
throw sls::RuntimeError(
"Invalid/ privileged port number parsed. Min: 1024.");
}
return val;
}
std::string
CommandLineOptions::getHelpMessage(const std::string &executable) const {
// TODO: update if we keep it Matterhonr specific - refactor a bit better -
// e.g. if compiled with detector macro
std::string helpmessage = fmt::format(
"Usage: {}"
" [arguments]\n"
"Possible arguments are:\n"
"\t-v, --version : Software version\n"
"\t-p, --port <port> : TCP communication port with client. "
"\n"
"\t-d, --devel : Developer mode. Skips firmware "
"checks. \n"
"\t-u, --update : Update mode. Skips firmware checks "
"and "
"initial detector setup. \n",
executable);
return helpmessage;
}
DetectorServerOptions CommandLineOptions::parse(int argc, char *argv[]) {
int opt, option_index = 0;
DetectorServerOptions serverOptionsValues{};
while ((opt = getopt_long(argc, argv, optstring.c_str(), options.data(),
&option_index)) != -1) {
switch (opt) {
case 'h':
std::cout << getHelpMessage(argv[0]) << std::endl;
serverOptionsValues.helpRequested = true; // to exit in main
break;
case 'v':
serverOptionsValues.versionRequested = true; // to exit in main
std::cout << getVersion() << std::endl;
break;
case 'p':
serverOptionsValues.port = parsePort(optarg);
break;
case 'd':
serverOptionsValues.debugflag = true;
break;
case 'u':
serverOptionsValues.updateFlag = true;
break;
default:
std::cout << getHelpMessage(argv[0]) << std::endl;
throw std::runtime_error("Wrong command line arguments.");
}
}
return serverOptionsValues;
}
} // namespace sls
@@ -0,0 +1,116 @@
#include "CommandLineOptions.h"
#include "MatterhornServer.h"
#include "StopServer.h"
#include "sls/logger.h"
#include "sls/sls_detector_exceptions.h"
#include <semaphore.h>
#include <csignal>
#include <signal.h>
#include <sys/wait.h>
#include <unistd.h>
// gettid added in glibc 2.30
#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 30
#include <sys/syscall.h>
#define gettid() syscall(SYS_gettid)
#endif
using namespace sls;
sem_t semaphore;
pid_t child_pid = -1;
/**
* Control+C Interrupt Handler
* to let all the other process know to exit properly
*/
void sigInterruptHandler(int signal) {
(void)signal; // suppress unused warning if needed
if (child_pid > 0) {
kill(child_pid, SIGTERM); // tell child to exit
}
sem_post(&semaphore);
}
void childSigTermHandler(int signal) {
(void)signal; // suppress unused warning if needed
sem_post(&semaphore);
}
// TODO: should be a generic ServerApp for all detectors
int main(int argc, char *argv[]) {
CommandLineOptions cli;
DetectorServerOptions opts{};
try {
opts = cli.parse(argc, argv);
} catch (sls::RuntimeError &e) {
return EXIT_FAILURE;
}
if (opts.versionRequested || opts.helpRequested) {
return EXIT_SUCCESS;
}
// LOG(sls::logINFOBLUE) << "Current Process [ Tid: " << gettid() << " ]";
// handle locally on socket crash
// sls::setupSignalHandler(SIGPIPE, SIG_IGN); / what is this?
sem_init(&semaphore, 1, 0);
child_pid = fork(); // fork process for control and stop server
if (child_pid == 0) {
// Stop server Process
std::signal(SIGTERM, childSigTermHandler);
LOG(TLogLevel::logINFOBLUE) << "Stop Server [" << opts.port + 1 << "]";
try {
// StopServer stopServer(opts.port + 1); TODO: forget the stop
// server for now
sem_wait(&semaphore); // wait until parent signals to exit
sem_destroy(&semaphore);
} catch (...) {
sem_destroy(&semaphore);
LOG(TLogLevel::logINFOBLUE)
<< "Exiting Stop Server [ Tid: " << gettid() << " ]";
// TODO: maybe also terminate the control server !!!!
std::exit(EXIT_FAILURE);
}
LOG(TLogLevel::logINFOBLUE)
<< "Exiting Stop Server [ Tid: " << gettid() << " ]";
LOG(sls::logINFO) << "Exiting Stop Server";
exit(EXIT_SUCCESS);
} else if (child_pid > 0) {
// Control Server Process
LOG(TLogLevel::logINFOBLUE) << "Control Server [" << opts.port << "]\n";
if (opts.updateFlag == 0) {
// update flag if update file exists (command line arg overwrites)
}
try {
sls::MatterhornServer server(opts.port);
LOG(sls::logINFO) << "[ Press \'Ctrl+c\' to exit ]";
// exit upon ctr + c
sem_wait(&semaphore);
sem_destroy(&semaphore);
} catch (...) {
sem_destroy(&semaphore);
kill(child_pid, SIGTERM); // tell child to exit
LOG(sls::logINFOBLUE) << "Exiting [ Tid: " << gettid() << " ]";
std::exit(EXIT_FAILURE);
}
waitpid(child_pid, nullptr, 0); // wait for child to exit
LOG(sls::logINFOBLUE) << "Exiting [ Tid: " << gettid() << " ]";
LOG(sls::logINFO) << "Exiting Detector Server";
exit(EXIT_SUCCESS);
} else {
LOG(sls::logERROR)
<< "Failed to fork process for control and stop server";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
@@ -0,0 +1,33 @@
#include "MatterhornClientInterface.h"
#include "sls/logger.h"
#include "sls/sls_detector_funcs.h"
#include "sls/versionAPI.h"
namespace sls {
MatterhornClientInterface::MatterhornClientInterface(const uint16_t portNumber)
: ClientInterface(portNumber) {
// TODO: maybe define the function list in another .hpp file as inline
// unorderer map also this F_GET_SERVER_VERSION should be a global enum
// shared by client and server
functionTable = {
{detFuncs::F_GET_SERVER_VERSION,
[this](ServerInterface &si) { return this->get_version(si); }}};
}
ReturnCode MatterhornClientInterface::get_version(ServerInterface &socket) {
auto version = getMatterhornServerVersion();
version.resize(MAX_STR_LENGTH);
LOG(TLogLevel::logDEBUG1) << "Matterhorn Server Version: " << version;
return static_cast<ReturnCode>(socket.sendResult(
version)); // TODO: check what would be possible return codes!!!
}
std::string MatterhornClientInterface::getMatterhornServerVersion() {
return APIMATTERHORN;
}
} // namespace sls
@@ -0,0 +1,35 @@
#include "MatterhornServer.h"
#include "sls/network_utils.h"
#include "sls/sls_detector_defs.h"
// #include "sharedMemory.h"
#include "communication_funcs.h"
namespace sls {
MatterhornServer::MatterhornServer(uint16_t port) {
validatePortNumber(port);
/*
// TODO: keep the c code for now
if (sharedMemory_create(port) == slsDetectorDefs::FAIL) {
throw sls::RuntimeError("Failed to create shared memory");
}
*/
// mmh do I want a virtual server inheriting from parent Server class? and
// parent Matterhorn class - probably better
#ifdef VIRTUAL
udpDetails.srcip = LOCALHOSTIP_INT;
#endif
udpDetails.srcport = DEFAULT_UDP_SRC_PORTNO;
udpDetails.dstport = DEFAULT_UDP_DST_PORTNO;
// TODO: when do i set the udp mac and ip ?
tcpipInterface = std::make_unique<MatterhornClientInterface>(
port); // TODO: need a tcp and udp interface
// need a function to setup detector - e.g. set all registers etc.
}
} // namespace sls
@@ -0,0 +1,12 @@
#include "StopServer.h"
#include "sls/network_utils.h"
#include "sls/sls_detector_defs.h"
StopServer::StopServer(uint16_t port) {
validatePortNumber(port);
// open shared memory segment of control server map to virtual memory space
if (sharedMemory_open(port - 1) == slsDetectorDefs::FAIL) {
throw sls::RuntimeError("Failed to open shared memory");
}
}
+10 -9
View File
@@ -1,12 +1,13 @@
// SPDX-License-Identifier: LGPL-3.0-or-other
// Copyright (C) 2021 Contributors to the SLS Detector Package
/** API versions */
#define APILIB "0.0.0 0x250909"
#define APIRECEIVER "0.0.0 0x250822"
#define APICTB "0.0.0 0x250922"
#define APIGOTTHARD2 "0.0.0 0x250909"
#define APIMOENCH "0.0.0 0x250909"
#define APIEIGER "0.0.0 0x250909"
#define APIXILINXCTB "0.0.0 0x260128"
#define APIJUNGFRAU "0.0.0 0x250909"
#define APIMYTHEN3 "0.0.0 0x250922"
#define APILIB "0.0.0 0x250909"
#define APIRECEIVER "0.0.0 0x250822"
#define APICTB "0.0.0 0x250922"
#define APIGOTTHARD2 "0.0.0 0x250909"
#define APIMOENCH "0.0.0 0x250909"
#define APIEIGER "0.0.0 0x250909"
#define APIXILINXCTB "0.0.0 0x260128"
#define APIJUNGFRAU "0.0.0 0x250909"
#define APIMYTHEN3 "0.0.0 0x250922"
#define APIMATTERHORN "0.0.0 0x260212"