mirror of
https://github.com/slsdetectorgroup/slsDetectorPackage.git
synced 2026-05-30 10:28:27 +02:00
added first draft of matterhorn
This commit is contained in:
@@ -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");
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user