Program Listing for File config.cpp
↰ Return to documentation for file (config/config.cpp)
#include "config.hpp"
#include "felixtag.h"
#include "felix/FelixClientUtility.hpp"
#include "felix/felix_fid.h"
#include "felix/felix_ports.h"
#include <cstdint>
#include <format>
#include <format>
std::string Config::options() {
return
R"(
General Options:
--bus-dir=DIRECTORY Write felix-bus information to this directory. [default: ./bus]
--bus-groupname=NAME Use this groupname for the bus. [default: FELIX]
--cid=<cid>... CID (Connector Ids) to set in FID (Felix ID). Can be used multiple times. [default: device]
--did=<did> DID (Detector Id) to set in FID (Felix ID). [default: 0]
-d, --device=<device>... Use FLX device DEVICE. [default: 0]
--error-out=<fifo> Write error information to a UNIX FIFO
--free-cmem Free previously booked cmem segment by name-<device>-<dma>
--iface=<iface> Send data to the interface. [calculated: use --ip value]
-i, --ip=<ip> Publish data on the ip address IP. [default: libfabric:127.0.0.1]
-b, --netio-pagesize=<size> NetIO page size in Byte. [default: 65536]
-B, --netio-pages=<size> Number of NetIO pages. [default: 256]
--is-monitoring Sends monitoring data to "is"
--prometheus-port=<port> Sets Prometheus port and sends monitoring data to Prometheus
--stats-out=<fifo> Write periodic statistics data to a UNIX FIFO
--stats-period=<ms> Period in milliseconds for statistics dumps. [default: 1000]
-?, --help Give this help list
-v, --verbose Produce verbose output
--verbose-bus Produce verbose output for bus
-V, --version Print program version
--netio-type=<type> Event loop type to use. [default: netio3] {netio3|netio-next}
--daq-network-mode=<mode> Network mode to use for DAQ. [default: RDMA] {RDMA|TCP}
--dcs-network-mode=<mode> Network mode to use for DCS. [default: TCP] {RDMA|TCP}
--vid=N VID (Version Id) to set in FID (Felix ID) [default: 1]
)";
}
Config::Config() {}
Config::~Config() {}
void Config::parse(int argc, char **argv) {
appname = argv[0];
std::map<std::string, docopt::value> args
= docopt::docopt(usage() + options() + bugs(),
{ argv + 1, argv + argc },
true, // show help if requested
(std::string(argv[0]) + " " + FELIX_TAG).c_str()); // version string
handle_cmd_line(args);
}
std::ostream& Config::format(std::ostream& os) const {
os << "Config" << std::endl;
os << "bus_dir: " << network.bus_dir << std::endl;
os << "bus_groupname: " << network.bus_groupname << std::endl;
os << "cid: ";
std::copy(resource.cid.begin(), resource.cid.end(), std::ostream_iterator<int>(os << std::hex << std::showbase, " "));
os << std::endl;
os << "did: 0x" << std::hex << resource.did << std::dec << std::endl;
os << "device: ";
std::copy(resource.device.begin(), resource.device.end(), std::ostream_iterator<int>(os, " "));
os << std::endl;
os << "free_previous_cmem: " << resource.free_previous_cmem << std::endl;
os << "ip: " << network.ip << std::endl;
os << "netio_pagesize: " << network.netio_pagesize << std::endl;
os << "netio_pages: " << network.netio_pages << std::endl;
os << "statistics_fifo: " << stats.monitoring_fifo << std::endl;
os << "statistics_period: " << stats.monitoring_period_ms << std::endl;
os << "statistics_port: " << stats.prometheus_port << std::endl;
os << "monitoring_type: ";
if (not stats.local_monitoring_types.empty()) {
for (const auto & t : stats.local_monitoring_types) {
os << MonitoringConfig::printType(t) << " ";
}
} else {
os << "N/A";
}
os << std::endl;
os << "verbose: " << verbose << std::endl;
os << "verbose_bus: " << network.verbose_bus << std::endl;
os << "daq_network_mode: " << network_mode_to_str(network.daq_network_mode) << std::endl;
os << "dcs_network_mode: " << network_mode_to_str(network.dcs_network_mode) << std::endl;
os << "vid: 0x" << std::hex << static_cast<uint32_t>(resource.vid) << std::dec << std::endl;
os << std::endl;
return os;
}
std::ostream& operator<<(std::ostream& os, const Config& c) {
return c.format(os);
}
void Config::handle_cmd_line(std::map<std::string, docopt::value> args) {
auto devices = args["--device"].asStringList();
for(const auto& i : devices){
resource.device.push_back(stoi(i));
}
resource.vid = args["--vid"].asLong();
resource.did = args["--did"].asLong();
auto cids = args["--cid"].asStringList();
if (cids.empty()) { // No cids, impossible, there should be the default
ers::error(felix_log::config_issue("No cid provided, aborting."));
throw std::runtime_error("No cid provided, aborting.");
}
else if (cids.size() == 1) {
if ( cids.at(0) == "device" ) {
resource.cid = resource.device;
}
else {
int base_cid = stoi(cids.at(0), 0, 16);
for(unsigned int i = 0; i < resource.device.size(); ++i) {
resource.cid.push_back(base_cid + i);
}
}
}
else if (cids.size() == devices.size()){
for(unsigned int i = 0; i < cids.size(); ++i) {
uint16_t cid = static_cast<uint16_t>(stoi(cids.at(i), 0, 16));
resource.cid.push_back(cid);
}
}
else {
ers::error(felix_log::config_issue("The number of provided CIDs is not one nor equal to the number of devices."));
throw std::runtime_error("No cid provided, aborting.");
}
resource.free_previous_cmem = args["--free-cmem"].asBool();
network.bus_dir = args["--bus-dir"].asString();
network.bus_groupname = args["--bus-groupname"].asString();
network.netio_pagesize = args["--netio-pagesize"].asLong();
network.netio_pages = args["--netio-pages"].asLong();
network.verbose_bus = args["--verbose-bus"].asBool();
network.daq_network_mode = network_mode_from_str(args["--daq-network-mode"].asString());
network.dcs_network_mode = network_mode_from_str(args["--dcs-network-mode"].asString());
stats.monitoring_fifo = args["--stats-out"] ? args["--stats-out"].asString() : "";
stats.prometheus_port = args["--prometheus-port"] ? args["--prometheus-port"].asLong() : -1;
if(args["--stats-out"]) { stats.local_monitoring_types.push_back(MonitoringType::FIFO); }
if(args["--prometheus-port"]) { stats.local_monitoring_types.push_back(MonitoringType::Prometheus); }
if(args["--is-monitoring"].asBool()) { stats.local_monitoring_types.push_back(MonitoringType::WebIS); }
stats.monitoring_period_ms = args["--stats-period"].asLong();
verbose = args["--verbose"].asBool();
// derive ip
if (args["--iface"]) {
network.ip = utility::get_value_from_getifaddrs(args["--iface"].asString());
} else {
network.ip = args["--ip"].asString();
}
}
std::string Config::bugs() {
return
R"(
Report bugs to <https://its.cern.ch/jira/projects/FLXUSERS>.
)";
}
int Config::get_number_devices()
{
return resource.device.size();
};
uint16_t Config::get_device_cid(unsigned int dev_no)
{
auto it = std::find(resource.device.begin(), resource.device.end(), dev_no);
if ( it == resource.device.end() ){
throw std::invalid_argument("Cannot find cid for the requested device.");
} else {
int idx = it - resource.device.begin();
return resource.cid.at(idx);
}
}
int Config::get_unique_dmaid(int dmaid, uint16_t device)
{
return (dmaid + 10*device);
}
int Config::udmaid_to_dmaid(int udmaid)
{
return (udmaid % 10);
}
int Config::udmaid_to_deviceid(int udmaid)
{
return ( (udmaid - udmaid_to_dmaid(udmaid)) / 10 );
}
std::string Config::network_mode_to_str(NetworkMode type)
{
switch (type) {
case NetworkMode::rdma:
return "RDMA";
case NetworkMode::tcp:
return "TCP";
default:
throw std::logic_error("Invalid NetworkMode");
}
}
NetworkMode Config::network_mode_from_str(std::string_view type)
{
if (type == "RDMA") {
return NetworkMode::rdma;
} else if (type == "TCP") {
return NetworkMode::tcp;
} else {
throw std::logic_error("Invalid NetworkMode");
}
}