mirror of
https://github.com/slsdetectorgroup/slsDetectorPackage.git
synced 2025-06-12 04:47:14 +02:00
merge from 7.0.0
This commit is contained in:
@ -31,6 +31,11 @@ namespace sls {
|
||||
// #define ZMQ_DETAIL
|
||||
#define ROIVERBOSITY
|
||||
|
||||
// high water mark for gui
|
||||
#define DEFFAULT_LOW_ZMQ_HWM (25)
|
||||
#define DEFAULT_LOW_ZMQ_HWM_BUFFERSIZE (1024 * 1024) // 1MB
|
||||
#define DEFAULT_ZMQ_BUFFERSIZE (-1) // os default
|
||||
|
||||
/** zmq header structure */
|
||||
struct zmqHeader {
|
||||
/** true if incoming data, false if end of acquisition */
|
||||
@ -108,15 +113,29 @@ class ZmqSocket {
|
||||
/** Returns high water mark for outbound messages */
|
||||
int GetSendHighWaterMark();
|
||||
|
||||
/** Sets high water mark for outbound messages. Default 1000 (zmqlib) */
|
||||
/** Sets high water mark for outbound messages. Default 1000 (zmqlib). Also
|
||||
* changes send buffer size depending on hwm. Must rebind. */
|
||||
void SetSendHighWaterMark(int limit);
|
||||
|
||||
/** Returns high water mark for inbound messages */
|
||||
int GetReceiveHighWaterMark();
|
||||
|
||||
/** Sets high water mark for inbound messages. Default 1000 (zmqlib) */
|
||||
/** Sets high water mark for inbound messages. Default 1000 (zmqlib). Also
|
||||
* changes receiver buffer size depending on hwm. Must reconnect */
|
||||
void SetReceiveHighWaterMark(int limit);
|
||||
|
||||
/** Gets kernel buffer for outbound messages. Default 0 (os) */
|
||||
int GetSendBuffer();
|
||||
|
||||
/** Sets kernel buffer for outbound messages. Default 0 (os) */
|
||||
void SetSendBuffer(int limit);
|
||||
|
||||
/** Gets kernel buffer for inbound messages. Default 0 (os) */
|
||||
int GetReceiveBuffer();
|
||||
|
||||
/** Sets kernel buffer for inbound messages. Default 0 (os) */
|
||||
void SetReceiveBuffer(int limit);
|
||||
|
||||
/**
|
||||
* Returns Port Number
|
||||
* @returns Port Number
|
||||
@ -129,6 +148,9 @@ class ZmqSocket {
|
||||
*/
|
||||
std::string GetZmqServerAddress() { return sockfd.serverAddress; }
|
||||
|
||||
/** unbinds and rebind, to apply changes of HWM */
|
||||
void Rebind();
|
||||
|
||||
/**
|
||||
* Connect client socket to server socket
|
||||
* @returns 1 for fail, 0 for success
|
||||
|
@ -148,6 +148,18 @@ Squash(const Container &c, typename Container::value_type default_value = {}) {
|
||||
return default_value;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename std::enable_if<is_container<T>::value, bool>::type
|
||||
removeDuplicates(T &c) {
|
||||
auto containerSize = c.size();
|
||||
std::sort(c.begin(), c.end());
|
||||
c.erase(std::unique(c.begin(), c.end()), c.end());
|
||||
if (c.size() != containerSize) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace sls
|
||||
|
||||
#endif // CONTAINER_UTILS_H
|
||||
|
@ -50,6 +50,8 @@ ssize_t getFileSize(FILE *fd, const std::string &prependErrorString);
|
||||
|
||||
std::string getFileNameFromFilePath(const std::string &fpath);
|
||||
|
||||
std::vector<int> getChannelsFromStringList(const std::vector<std::string> list);
|
||||
|
||||
/** File can have # for comments.
|
||||
* Channels can be separated by spaces, commas
|
||||
* and ranges provided using ':', eg. 23:29
|
||||
|
@ -10,6 +10,8 @@
|
||||
*@short functions indices to call on server (detector/receiver)
|
||||
*/
|
||||
|
||||
#define UNRECOGNIZED_FNUM_ENUM "Unrecognized Function enum"
|
||||
|
||||
enum detFuncs {
|
||||
F_EXEC_COMMAND = 0,
|
||||
F_GET_DETECTOR_TYPE,
|
||||
|
@ -1,6 +1,7 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
/** API versions */
|
||||
<<<<<<< HEAD
|
||||
#define RELEASE "developer"
|
||||
#define APILIB "developer 0x221213"
|
||||
#define APIRECEIVER "developer 0x221213"
|
||||
@ -11,3 +12,15 @@
|
||||
#define APIMOENCH "developer 0x221215"
|
||||
#define APIGOTTHARD "developer 0x230117"
|
||||
#define APIMYTHEN3 "developer 0x230117"
|
||||
=======
|
||||
#define RELEASE "7.0.0"
|
||||
#define APICTB "7.0.0 0x230222"
|
||||
#define APIGOTTHARD "7.0.0 0x230222"
|
||||
#define APIGOTTHARD2 "7.0.0 0x230222"
|
||||
#define APIJUNGFRAU "7.0.0 0x230222"
|
||||
#define APIMYTHEN3 "7.0.0 0x230222"
|
||||
#define APIMOENCH "7.0.0 0x230222"
|
||||
#define APIEIGER "7.0.0 0x230222"
|
||||
#define APILIB "7.0.0 0x230223"
|
||||
#define APIRECEIVER "7.0.0 0x230222"
|
||||
>>>>>>> 7.0.0.rc
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include "sls/logger.h"
|
||||
#include "sls/sls_detector_defs.h"
|
||||
#include "sls/sls_detector_exceptions.h"
|
||||
#include "sls/sls_detector_funcs.h"
|
||||
#include <arpa/inet.h>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
@ -76,9 +77,7 @@ void ClientSocket::readReply(int &ret, void *retval, size_t retval_size) {
|
||||
try {
|
||||
Receive(&ret, sizeof(ret));
|
||||
if (ret == slsDetectorDefs::FAIL) {
|
||||
char mess[MAX_STR_LENGTH]{};
|
||||
// get error message
|
||||
Receive(mess, sizeof(mess));
|
||||
std::string mess = readErrorMessage();
|
||||
// Do we need to know hostname here?
|
||||
// In that case save it???
|
||||
if (socketType == "Receiver") {
|
||||
@ -107,6 +106,9 @@ void ClientSocket::readReply(int &ret, void *retval, size_t retval_size) {
|
||||
std::string ClientSocket::readErrorMessage() {
|
||||
std::string error_msg(MAX_STR_LENGTH, '\0');
|
||||
Receive(&error_msg[0], error_msg.size());
|
||||
if (error_msg.find(UNRECOGNIZED_FNUM_ENUM) != std::string::npos) {
|
||||
error_msg.insert(0, "Software version mismatch. ");
|
||||
}
|
||||
return error_msg;
|
||||
}
|
||||
|
||||
|
@ -27,15 +27,18 @@ UdpRxSocket::UdpRxSocket(int port, ssize_t packet_size, const char *hostname,
|
||||
const std::string portname = std::to_string(port);
|
||||
if (getaddrinfo(hostname, portname.c_str(), &hints, &res)) {
|
||||
throw RuntimeError("Failed at getaddrinfo with " +
|
||||
std::string(hostname));
|
||||
std::string(hostname) + " [" +
|
||||
std::string(strerror(errno)) + ']');
|
||||
}
|
||||
sockfd_ = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
|
||||
if (sockfd_ == -1) {
|
||||
throw RuntimeError("Failed to create UDP RX socket");
|
||||
throw RuntimeError("Failed to create UDP RX socket [" +
|
||||
std::string(strerror(errno)) + ']');
|
||||
}
|
||||
if (bind(sockfd_, res->ai_addr, res->ai_addrlen) == -1) {
|
||||
close(sockfd_);
|
||||
throw RuntimeError("Failed to bind UDP RX socket");
|
||||
throw RuntimeError("Failed to bind UDP RX socket [" +
|
||||
std::string(strerror(errno)) + ']');
|
||||
}
|
||||
freeaddrinfo(res);
|
||||
|
||||
@ -74,13 +77,15 @@ int UdpRxSocket::getBufferSize() const {
|
||||
int ret = 0;
|
||||
socklen_t optlen = sizeof(ret);
|
||||
if (getsockopt(sockfd_, SOL_SOCKET, SO_RCVBUF, &ret, &optlen) == -1)
|
||||
throw RuntimeError("Could not get socket buffer size");
|
||||
throw RuntimeError("Could not get socket buffer size [" +
|
||||
std::string(strerror(errno)) + ']');
|
||||
return ret;
|
||||
}
|
||||
|
||||
void UdpRxSocket::setBufferSize(int size) {
|
||||
if (setsockopt(sockfd_, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)))
|
||||
throw RuntimeError("Could not set socket buffer size");
|
||||
throw RuntimeError("Could not set socket buffer size [" +
|
||||
std::string(strerror(errno)) + ']');
|
||||
}
|
||||
|
||||
void UdpRxSocket::Shutdown() {
|
||||
|
@ -102,6 +102,16 @@ void ZmqSocket::SetSendHighWaterMark(int limit) {
|
||||
PrintError();
|
||||
throw ZmqSocketError("Could not set ZMQ_SNDHWM");
|
||||
}
|
||||
if (GetSendHighWaterMark() != limit) {
|
||||
throw ZmqSocketError("Could not set ZMQ_SNDHWM to " +
|
||||
std::to_string(limit));
|
||||
}
|
||||
|
||||
int bufsize = DEFAULT_ZMQ_BUFFERSIZE;
|
||||
if (limit < DEFFAULT_LOW_ZMQ_HWM) {
|
||||
bufsize = DEFAULT_LOW_ZMQ_HWM_BUFFERSIZE;
|
||||
}
|
||||
SetSendBuffer(bufsize);
|
||||
}
|
||||
|
||||
int ZmqSocket::GetReceiveHighWaterMark() {
|
||||
@ -110,7 +120,7 @@ int ZmqSocket::GetReceiveHighWaterMark() {
|
||||
if (zmq_getsockopt(sockfd.socketDescriptor, ZMQ_RCVHWM, &value,
|
||||
&value_size)) {
|
||||
PrintError();
|
||||
throw ZmqSocketError("Could not get ZMQ_SNDHWM");
|
||||
throw ZmqSocketError("Could not get ZMQ_RCVHWM");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
@ -119,7 +129,77 @@ void ZmqSocket::SetReceiveHighWaterMark(int limit) {
|
||||
if (zmq_setsockopt(sockfd.socketDescriptor, ZMQ_RCVHWM, &limit,
|
||||
sizeof(limit))) {
|
||||
PrintError();
|
||||
throw ZmqSocketError("Could not set ZMQ_SNDHWM");
|
||||
throw ZmqSocketError("Could not set ZMQ_RCVHWM");
|
||||
}
|
||||
if (GetReceiveHighWaterMark() != limit) {
|
||||
throw ZmqSocketError("Could not set ZMQ_RCVHWM to " +
|
||||
std::to_string(limit));
|
||||
}
|
||||
int bufsize = DEFAULT_ZMQ_BUFFERSIZE;
|
||||
if (limit < DEFFAULT_LOW_ZMQ_HWM) {
|
||||
bufsize = DEFAULT_LOW_ZMQ_HWM_BUFFERSIZE;
|
||||
}
|
||||
SetReceiveBuffer(bufsize);
|
||||
}
|
||||
|
||||
int ZmqSocket::GetSendBuffer() {
|
||||
int value = 0;
|
||||
size_t value_size = sizeof(value);
|
||||
if (zmq_getsockopt(sockfd.socketDescriptor, ZMQ_SNDBUF, &value,
|
||||
&value_size)) {
|
||||
PrintError();
|
||||
throw ZmqSocketError("Could not get ZMQ_SNDBUF");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
void ZmqSocket::SetSendBuffer(int limit) {
|
||||
if (zmq_setsockopt(sockfd.socketDescriptor, ZMQ_SNDBUF, &limit,
|
||||
sizeof(limit))) {
|
||||
PrintError();
|
||||
throw ZmqSocketError("Could not set ZMQ_SNDBUF");
|
||||
}
|
||||
if (GetSendBuffer() != limit) {
|
||||
throw ZmqSocketError("Could not set ZMQ_SNDBUF to " +
|
||||
std::to_string(limit));
|
||||
}
|
||||
}
|
||||
|
||||
int ZmqSocket::GetReceiveBuffer() {
|
||||
int value = 0;
|
||||
size_t value_size = sizeof(value);
|
||||
if (zmq_getsockopt(sockfd.socketDescriptor, ZMQ_RCVBUF, &value,
|
||||
&value_size)) {
|
||||
PrintError();
|
||||
throw ZmqSocketError("Could not get ZMQ_RCVBUF");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
void ZmqSocket::SetReceiveBuffer(int limit) {
|
||||
if (zmq_setsockopt(sockfd.socketDescriptor, ZMQ_RCVBUF, &limit,
|
||||
sizeof(limit))) {
|
||||
PrintError();
|
||||
throw ZmqSocketError("Could not set ZMQ_RCVBUF");
|
||||
}
|
||||
if (GetReceiveBuffer() != limit) {
|
||||
throw ZmqSocketError("Could not set ZMQ_RCVBUF to " +
|
||||
std::to_string(limit));
|
||||
}
|
||||
}
|
||||
|
||||
void ZmqSocket::Rebind() { // the purpose is to apply HWL changes, which are
|
||||
// frozen at bind, which is in the constructor.
|
||||
|
||||
// unbbind
|
||||
if (zmq_unbind(sockfd.socketDescriptor, sockfd.serverAddress.c_str())) {
|
||||
PrintError();
|
||||
throw ZmqSocketError("Could not unbind socket");
|
||||
}
|
||||
// bind address
|
||||
if (zmq_bind(sockfd.socketDescriptor, sockfd.serverAddress.c_str())) {
|
||||
PrintError();
|
||||
throw ZmqSocketError("Could not bind socket");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
#include "sls/file_utils.h"
|
||||
#include "sls/ToString.h"
|
||||
#include "sls/container_utils.h"
|
||||
#include "sls/logger.h"
|
||||
#include "sls/sls_detector_exceptions.h"
|
||||
|
||||
@ -165,6 +166,63 @@ ssize_t getFileSize(FILE *fd, const std::string &prependErrorString) {
|
||||
return fileSize;
|
||||
}
|
||||
|
||||
std::vector<int>
|
||||
getChannelsFromStringList(const std::vector<std::string> list) {
|
||||
std::vector<int> channels;
|
||||
for (auto line : list) {
|
||||
|
||||
// replace comma with space
|
||||
std::replace_if(
|
||||
begin(line), end(line), [](char c) { return (c == ','); }, ' ');
|
||||
|
||||
// split line (delim space)
|
||||
std::vector<std::string> vec = split(line, ' ');
|
||||
|
||||
// for every channel separated by space
|
||||
for (auto it : vec) {
|
||||
// find range and replace with sequence of x to y
|
||||
auto result = it.find(':');
|
||||
if (result != std::string::npos) {
|
||||
try {
|
||||
int istart = StringTo<int>(it.substr(0, result));
|
||||
int istop = StringTo<int>(
|
||||
it.substr(result + 1, it.length() - result - 1));
|
||||
LOG(logDEBUG1) << "istart:" << istart << " istop:" << istop;
|
||||
std::vector<int> range(istop - istart);
|
||||
std::generate(range.begin(), range.end(),
|
||||
[n = istart]() mutable { return n++; });
|
||||
for (auto range_it : range) {
|
||||
channels.push_back(range_it);
|
||||
}
|
||||
} catch (std::exception &e) {
|
||||
throw RuntimeError(
|
||||
"Could not load channels. Invalid channel range: " +
|
||||
it);
|
||||
}
|
||||
}
|
||||
|
||||
// else convert to int
|
||||
else {
|
||||
int ival = 0;
|
||||
try {
|
||||
ival = StringTo<int>(it);
|
||||
} catch (std::exception &e) {
|
||||
throw RuntimeError(
|
||||
"Could not load channels. Invalid channel number: " +
|
||||
it);
|
||||
}
|
||||
channels.push_back(ival);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (removeDuplicates(channels)) {
|
||||
LOG(logWARNING) << "Removed duplicates from channel file";
|
||||
}
|
||||
LOG(logDEBUG1) << "list:" << ToString(channels);
|
||||
return channels;
|
||||
}
|
||||
|
||||
std::vector<int> getChannelsFromFile(const std::string &fname) {
|
||||
// read bad channels file
|
||||
std::ifstream input_file(fname);
|
||||
@ -172,73 +230,19 @@ std::vector<int> getChannelsFromFile(const std::string &fname) {
|
||||
throw RuntimeError("Could not open bad channels file " + fname +
|
||||
" for reading");
|
||||
}
|
||||
std::vector<int> list;
|
||||
std::vector<std::string> lines;
|
||||
for (std::string line; std::getline(input_file, line);) {
|
||||
// ignore comments
|
||||
if (line.find('#') != std::string::npos) {
|
||||
line.erase(line.find('#'));
|
||||
}
|
||||
|
||||
// replace comma with space
|
||||
std::replace_if(
|
||||
begin(line), end(line), [](char c) { return (c == ','); }, ' ');
|
||||
|
||||
// replace x:y with a sequence of x to y
|
||||
auto result = line.find(':');
|
||||
while (result != std::string::npos) {
|
||||
auto start = line.rfind(' ', result);
|
||||
if (start == std::string::npos) {
|
||||
start = 0;
|
||||
} else
|
||||
++start;
|
||||
int istart = StringTo<int>(line.substr(start, result - start));
|
||||
|
||||
auto stop = line.find(' ', result);
|
||||
if (stop == std::string::npos) {
|
||||
stop = line.length();
|
||||
}
|
||||
int istop =
|
||||
StringTo<int>(line.substr(result + 1, stop - result - 1));
|
||||
|
||||
std::vector<int> v(istop - istart);
|
||||
std::generate(v.begin(), v.end(),
|
||||
[n = istart]() mutable { return n++; });
|
||||
line.replace(start, stop - start, ToString(v));
|
||||
|
||||
LOG(logDEBUG1) << line;
|
||||
result = line.find(':');
|
||||
}
|
||||
|
||||
// remove punctuations including [ and ]
|
||||
line.erase(std::remove_if(begin(line), end(line), ispunct), end(line));
|
||||
|
||||
LOG(logDEBUG) << "\nline: [" << line << ']';
|
||||
|
||||
// split line (delim space) and push to list
|
||||
std::vector<std::string> vec = split(line, ' ');
|
||||
for (auto it : vec) {
|
||||
int ival = 0;
|
||||
try {
|
||||
ival = StringTo<int>(it);
|
||||
} catch (std::exception &e) {
|
||||
throw RuntimeError("Could not load channels from file. Invalid "
|
||||
"channel number: " +
|
||||
it);
|
||||
}
|
||||
list.push_back(ival);
|
||||
// ignore empty lines
|
||||
if (line.empty()) {
|
||||
continue;
|
||||
}
|
||||
lines.push_back(line);
|
||||
}
|
||||
|
||||
// remove duplicates from list
|
||||
auto listSize = list.size();
|
||||
std::sort(list.begin(), list.end());
|
||||
list.erase(unique(list.begin(), list.end()), list.end());
|
||||
if (list.size() != listSize) {
|
||||
LOG(logWARNING) << "Removed duplicates from channel file";
|
||||
}
|
||||
|
||||
LOG(logDEBUG1) << "list:" << ToString(list);
|
||||
return list;
|
||||
return getChannelsFromStringList(lines);
|
||||
}
|
||||
|
||||
std::string getAbsolutePathFromCurrentProcess(const std::string &fname) {
|
||||
|
@ -136,4 +136,18 @@ TEST_CASE("compare a vector of arrays", "[support]") {
|
||||
CHECK(minusOneIfDifferent(vec1) == arr);
|
||||
}
|
||||
|
||||
TEST_CASE("remove duplicates from vector") {
|
||||
std::vector<int> v{5, 6, 5, 3};
|
||||
auto r = removeDuplicates(v);
|
||||
CHECK(r == true); // did indeed remove elements
|
||||
CHECK(v == std::vector<int>{3, 5, 6});
|
||||
}
|
||||
|
||||
TEST_CASE("remove duplicated empty vector") {
|
||||
std::vector<int> v;
|
||||
auto r = removeDuplicates(v);
|
||||
CHECK(r == false); // no elements to remove
|
||||
CHECK(v == std::vector<int>{});
|
||||
}
|
||||
|
||||
} // namespace sls
|
||||
|
Reference in New Issue
Block a user