Files
Jungfraujoch/receiver/jfjoch_receiver.cpp

161 lines
5.7 KiB
C++

// Copyright (2019-2022) Paul Scherrer Institute
// SPDX-License-Identifier: GPL-3.0-or-later
#include "nlohmann/json.hpp"
#include <fstream>
#include "../grpc/gRPCServer_Template.h"
#include "../common/ZMQImagePusher.h"
#include "host/PCIExpressDevice.h"
#include "host/MlxRawEthDevice.h"
#include "host/LinuxSocketDevice.h"
#include "JFJochReceiverService.h"
#include "host/HLSSimulatedDevice.h"
#include "../common/NetworkAddressConvert.h"
AcquisitionDevice *SetupAcquisitionDevice(const nlohmann::json &input, uint16_t data_stream) {
AcquisitionDevice *ret;
int16_t numa_node = -1;
if (input.contains("numa_node"))
numa_node = input["numa_node"];
int64_t frame_buffer_size = UINT16_MAX;
if (input.contains("frame_buffer_size"))
frame_buffer_size = input["frame_buffer_size"];
uint16_t pci_slot = data_stream;
if (input.contains("id"))
pci_slot = input["id"];
uint32_t ipv4_addr = IPv4AddressFromStr(input["ipv4_addr"].get<std::string>());
if (input.contains("type") && (input["type"] == "software"))
ret = new HLSSimulatedDevice(data_stream, frame_buffer_size, numa_node);
else if (input.contains("type") && (input["type"] == "software")) {
auto linux_dev = new LinuxSocketDevice(ipv4_addr,
input["udp_port"].get<uint16_t>(),
data_stream,
frame_buffer_size,
numa_node);
ret = linux_dev;
} else if (input.contains("type") && (input["type"] == "pcie")) {
auto pci_dev = new PCIExpressDevice(data_stream, pci_slot);
pci_dev->SetIPv4Address(ipv4_addr);
if (input.contains("mac_addr"))
pci_dev->SetMACAddress(MacAddressFromStr(input["mac_addr"].get<std::string>()));
else
pci_dev->SetDefaultMAC();
ret = pci_dev;
#ifdef JFJOCH_USE_IBVERBS
} else if (input.contains("type") && (input["type"] == "mlx_raw_eth")) {
auto mlx_dev = new MlxRawEthDevice(pci_slot, data_stream, frame_buffer_size, numa_node);
mlx_dev->SetIPv4Address(ipv4_addr);
mlx_dev->SetMACAddress(MacAddressFromStr(input["mac_addr"].get<std::string>()));
ret = mlx_dev;
}
#endif
else throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Unsupported device type");
if (input.contains("custom_test_frame")) {
std::vector<uint16_t> tmp(RAW_MODULE_SIZE);
auto filename = input["custom_test_frame"].get<std::string>();
std::fstream file(filename.c_str(), std::fstream::in | std::fstream::binary);
file.read((char *) tmp.data(),RAW_MODULE_SIZE * sizeof(uint16_t));
ret->SetCustomInternalGeneratorFrame(tmp);
}
return ret;
}
int main(int argc, char **argv) {
if ((argc < 2) || (argc > 3)) {
std::cout << "Usage ./jfjoch_receiver <JSON config> {<log file>}" << std::endl;
exit(EXIT_FAILURE);
}
std::string log_file;
if (argc >= 3)
log_file = argv[2];
Logger logger("jfjoch_receiver", log_file);
nlohmann::json input;
std::ifstream file(argv[1]);
try {
input = nlohmann::json::parse(file);
} catch (const nlohmann::json::exception &e) {
logger.Error("JSON Parsing exception: " + std::string(e.what()));
exit(EXIT_FAILURE);
}
std::string grpc_addr;
try {
grpc_addr = input["grpc_addr"];
} catch (...) {
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "grpc_addr is compulsory parameter");
}
bool verbose = false;
if (input.contains("verbose") && (input["verbose"]))
verbose = true;
int32_t zmq_threads = 4;
if (input.contains("zmq_threads"))
zmq_threads = input["zmq_threads"];
ZMQContext context;
context.NumThreads(zmq_threads);
logger.Verbose(verbose);
std::vector<std::unique_ptr<AcquisitionDevice>> aq_devices;
for (int i = 0; i < input["device"].size(); i++) {
auto ptr = SetupAcquisitionDevice(input["device"][i], i);
aq_devices.emplace_back(ptr);
}
std::vector<AcquisitionDevice *> aq_devices_ptr;
for (const auto &i: aq_devices) {
if (verbose)
i->EnableLogging(&logger);
aq_devices_ptr.push_back(i.get());
}
logger.Info("Enabled acquisition device count: " + std::to_string(aq_devices.size()));
int32_t send_buffer_size = -1;
if (input.contains("tcp_send_buffer_size"))
send_buffer_size = input["tcp_send_buffer_size"];
int32_t send_buffer_high_watermark = -1;
if (input.contains("zmq_send_high_watermark"))
send_buffer_high_watermark = input["zmq_send_high_watermark"];
std::vector<std::string> zmq_addr;
if (input.contains("image_zmq_addr") && input["image_zmq_addr"].is_array()) {
for (const auto &s: input["image_zmq_addr"])
zmq_addr.push_back(s);
}
ZMQImagePusher pusher(zmq_addr, send_buffer_high_watermark, send_buffer_size);
JFJochReceiverService service(aq_devices_ptr, logger, pusher);
std::unique_ptr<ZMQPreviewPublisher> preview;
if (input.contains("preview_zmq_addr")) {
preview = std::make_unique<ZMQPreviewPublisher>(context, input["preview_zmq_addr"]);
service.PreviewPublisher(preview.get());
logger.Info("Preview available on ZMQ addr " + input["preview_zmq_addr"].get<std::string>());
}
if (input.contains("compression_threads"))
service.NumThreads(input["compression_threads"]);
auto server = gRPCServer(grpc_addr, service);
logger.Info("gRPC configuration listening on address " + grpc_addr);
logger.Info("Started");
server->Wait();
}