Compare commits

...

55 Commits

Author SHA1 Message Date
92be88ee19 zmq fixed WIP 2020-04-27 18:43:41 +02:00
56bc9c4e08 fix for segfault WIP 2020-04-27 14:00:00 +02:00
edbd70e91a free fix WIP 2020-04-27 13:53:13 +02:00
4f712fcd70 WIP 2020-04-24 15:28:41 +02:00
bb32b2f653 rxr done WIP 2020-04-24 15:13:37 +02:00
085cbbf0d6 WIP, separated rxr from module 2020-04-23 16:09:40 +02:00
45a770cf38 WIP 2020-04-23 15:16:14 +02:00
990008c9d9 WIP 2020-04-23 12:20:04 +02:00
5339e16101 port sequences and client zmq implementation needs revisit, WIP 2020-04-22 17:55:02 +02:00
c976c63fb5 WIP udp 2020-04-22 14:05:20 +02:00
9ee2d389fb WIP 2020-04-22 13:43:10 +02:00
8d0146949c WIP 2020-04-22 12:54:55 +02:00
6de68eacc2 WIP 2020-04-21 18:48:04 +02:00
94103a05b1 parallel3 fix, software version check 2020-04-21 18:27:52 +02:00
1185f1ea17 WIP, a in shm name 2020-04-21 18:02:27 +02:00
d3f420ffd4 WIP, indexstring 2020-04-21 17:14:09 +02:00
6b5511c9e5 WIP, moved bool primaryinterface to an int interface_id 2020-04-21 14:34:48 +02:00
d8aa1ab08e json para and header added 2020-04-21 14:10:07 +02:00
b4c31327d6 WIP, temp fix 2020-04-21 12:35:08 +02:00
c408f9807a Merge branch 'developer' into separateRxr 2020-04-21 11:30:23 +02:00
c1ae67ac46 Small refactor on ThreadObject and listener (#93)
* removed pointer, slight cleaning of loop

* removed semaphore, use getters

* removed redundant log msg

* removed comment

* added const

* removed comment

* changed header
2020-04-21 09:45:29 +02:00
9df128fced WIP, cant compile squash for rxParameters 2020-04-20 18:35:30 +02:00
e39ec65d19 Merge branch 'developer' into separateRxr 2020-04-20 18:33:37 +02:00
601be462af WIP, rxhostname 2020-04-20 18:33:14 +02:00
68f76e5356 more like UdpRxSocket 2020-04-20 17:24:53 +02:00
8afa11ed33 removed pointer to server socket 2020-04-20 17:20:33 +02:00
bc389f4825 moved data members to top 2020-04-20 14:51:48 +02:00
095ced153c removed need for pointer 2020-04-20 14:31:10 +02:00
1d31695cc1 WIP 2020-04-17 12:15:16 +02:00
df63a6dffe rx_statusL unknown, but others good WIP 2020-04-17 12:09:23 +02:00
cfa9049ed3 WIP: none to remove receivers 2020-04-17 10:34:10 +02:00
a1a5a20845 from thread sanitizer 2020-04-17 09:35:38 +02:00
9a208caca8 WIP: first connect to rxr 2020-04-16 18:20:04 +02:00
78fb8080ce WIP: some bug fixes and reducing redundant code 2020-04-16 18:07:11 +02:00
cd45f9d45b WIP, parallel 2020-04-16 16:18:50 +02:00
c725a05ef8 fix RH7 2020-04-16 15:51:28 +02:00
d536ad2b5b WIP, rxr constr done 2020-04-16 13:58:59 +02:00
815b6a37aa moved flag to base class 2020-04-16 13:22:51 +02:00
655a410d43 cleaned up UdpRxSocket 2020-04-16 09:45:44 +02:00
97ba81d923 fixed test 2020-04-14 16:58:37 +02:00
3d00eed0f0 Change SetTrimbits() and SaveAllTrimbits() to rely on top/bottom signal instead of TopAddressIsValid() for further cleanup. 2020-04-14 16:13:26 +02:00
2921cbfac8 WIP 2020-04-14 12:44:43 +02:00
a7f5300455 Merge pull request #92 from slsdetectorgroup/setrxhostname
Setrxhostname
2020-04-09 11:52:46 +02:00
2f33a1a479 updated binaries 2020-04-09 09:35:46 +02:00
39fa5e0185 client recieve rx parameters as a struct 2020-04-09 09:34:20 +02:00
ba4985ed4d Merge branch 'developer' of github.com:slsdetectorgroup/slsDetectorPackage into developer 2020-04-09 09:32:09 +02:00
f811c065d1 corrected a delete [] in multiThreadedAnalogDetector 2020-04-09 09:31:43 +02:00
3a1d87728c updated client api 2020-04-09 08:38:37 +02:00
0652ff6b5a updated binaries 2020-04-09 08:37:27 +02:00
373e177274 WIP 2020-04-09 08:35:30 +02:00
6dd6685e7d minor 2020-04-09 08:24:16 +02:00
38c31fdada WIP 2020-04-08 20:27:10 +02:00
b3fe0e79bc WIP 2020-04-08 16:43:28 +02:00
215e4a56fd Merge branch 'developer' into setrxhostname 2020-04-08 12:00:21 +02:00
55f8497eac WIP 2020-04-08 11:05:06 +02:00
55 changed files with 4258 additions and 3650 deletions

View File

@ -320,7 +320,7 @@ public:
// int nnx, nny, ns;
int nn=dets[0]->getImageSize(nnx, nny,ns, nsy);
if (image) {
delete image;
delete [] image;
image=NULL;
}
image=new int[nn];

View File

@ -429,7 +429,7 @@ int *getClusters(char *data, int *ph=NULL) {
max=*v;
}
}
}
}

View File

@ -898,7 +898,7 @@ int Feb_Control_SendDACValue(unsigned int dst_num, unsigned int ch, unsigned int
int Feb_Control_SetTrimbits(unsigned int module_num, unsigned int *trimbits) {
int Feb_Control_SetTrimbits(unsigned int module_num, unsigned int *trimbits, int top) {
LOG(logINFO, ("Setting Trimbits\n"));
//for (int iy=10000;iy<20020;++iy)//263681
@ -963,7 +963,7 @@ int Feb_Control_SetTrimbits(unsigned int module_num, unsigned int *trimbits) {
int i;
for(i=0;i<8;i++) { // column loop i
if (Module_TopAddressIsValid(&modules[1])) {
if (top==1) {
trimbits_to_load_l[offset+chip_sc] |= ( 0x7 & trimbits[row_set*16480+super_column_start_position_l+i])<<((7-i)*4);//low
trimbits_to_load_l[offset+chip_sc+32] |= ((0x38 & trimbits[row_set*16480+super_column_start_position_l+i])>>3)<<((7-i)*4);//upper
trimbits_to_load_r[offset+chip_sc] |= ( 0x7 & trimbits[row_set*16480+super_column_start_position_r+i])<<((7-i)*4);//low
@ -1572,12 +1572,12 @@ int Feb_Control_StopAcquisition() {
int Feb_Control_SaveAllTrimbitsTo(int value) {
int Feb_Control_SaveAllTrimbitsTo(int value, int top) {
unsigned int chanregs[Feb_Control_trimbit_size];
int i;
for(i=0;i<Feb_Control_trimbit_size;i++)
chanregs[i] = value;
return Feb_Control_SetTrimbits(0,chanregs);
return Feb_Control_SetTrimbits(0,chanregs, top);
}

View File

@ -93,9 +93,9 @@ int Feb_Control_SetDAC(char* s, int value, int is_a_voltage_mv);
int Feb_Control_GetDAC(char* s, int* ret_value, int voltage_mv);
int Feb_Control_GetDACName(unsigned int dac_num,char* s);
int Feb_Control_SetTrimbits(unsigned int module_num, unsigned int* trimbits);
int Feb_Control_SetTrimbits(unsigned int module_num, unsigned int* trimbits, int top);
unsigned int* Feb_Control_GetTrimbits();
int Feb_Control_SaveAllTrimbitsTo(int value);
int Feb_Control_SaveAllTrimbitsTo(int value, int top);
int Feb_Control_Reset();
int Feb_Control_PrepareForAcquisition();

View File

@ -759,7 +759,7 @@ int64_t getSubExpTime() {
#endif
}
int setDeadTime(int64_t val) {
int setSubDeadTime(int64_t val) {
LOG(logINFO, ("Setting subdeadtime %lld ns\n", (long long int)val));
#ifndef VIRTUAL
// get subexptime
@ -781,7 +781,7 @@ int setDeadTime(int64_t val) {
return OK;
}
int64_t getDeadTime() {
int64_t getSubDeadTime() {
#ifndef VIRTUAL
// get subexptime
int64_t subexptime = Feb_Control_GetSubFrameExposureTime();
@ -890,7 +890,7 @@ int setModule(sls_detector_module myMod, char* mess) {
}
//set trimbits
if (!Feb_Control_SetTrimbits(Feb_Control_GetModuleNumber(), tt)) {
if (!Feb_Control_SetTrimbits(Feb_Control_GetModuleNumber(), tt,top)) {
sprintf(mess, "Could not set module. Could not set trimbits\n");
LOG(logERROR, (mess));
setSettings(UNDEFINED);
@ -1671,7 +1671,7 @@ void setExternalGating(int enable[]) {
int setAllTrimbits(int val) {
#ifndef VIRTUAL
if (!Feb_Control_SaveAllTrimbitsTo(val)) {
if (!Feb_Control_SaveAllTrimbitsTo(val,top)) {
LOG(logERROR, ("Could not set all trimbits\n"));
return FAIL;
}

View File

@ -52,12 +52,11 @@ int Server_VerifyLock();
* Server sends result to client (also set ret to force_update if different clients)
* @param fileDes file descriptor for the socket
* @param itype 32 or 64 or others to determine to swap data from big endian to little endian
* @param update 1 if one must update if different clients, else 0
* @param retval pointer to result
* @param retvalSize size of result
* @returns result of operation
*/
int Server_SendResult(int fileDes, intType itype, int update, void* retval, int retvalSize);
int Server_SendResult(int fileDes, intType itype, void* retval, int retvalSize);
/**
* Convert mac address from integer to char array

View File

@ -206,8 +206,8 @@ int64_t getBurstPeriod();
#ifdef EIGERD
int setSubExpTime(int64_t val);
int64_t getSubExpTime();
int setDeadTime(int64_t val);
int64_t getDeadTime();
int setSubDeadTime(int64_t val);
int64_t getSubDeadTime();
int64_t getMeasuredPeriod();
int64_t getMeasuredSubPeriod();
#endif

View File

@ -216,4 +216,5 @@ int get_timing_source(int);
int set_timing_source(int);
int get_num_channels(int);
int update_rate_correction(int);
int get_receiver_parameters(int);

View File

@ -577,7 +577,7 @@ int Server_VerifyLock() {
}
int Server_SendResult(int fileDes, intType itype, int update, void* retval, int retvalSize) {
int Server_SendResult(int fileDes, intType itype, void* retval, int retvalSize) {
// send success of operation
int ret1 = ret;

View File

@ -3,6 +3,7 @@ set(SOURCES
src/slsDetectorUsers.cpp
src/Module.cpp
src/Detector.cpp
src/Receiver.cpp
src/CmdProxy.cpp
src/CmdParser.cpp
)

View File

@ -19,7 +19,7 @@ class IpAddr;
//Free function to avoid dependence on class
//and avoid the option to free another objects
//shm by mistake
void freeSharedMemory(int multiId, int detPos = -1);
void freeSharedMemory(int detectorId, int moduleId = -1);
/**
@ -57,6 +57,8 @@ class Detector {
/* Frees shared memory, adds detectors to the list
* and updates local detector cache */
void setHostname(const std::vector<std::string> &hostname);
void setHostname(const std::vector<std::string> &hostname,
const std::vector<int> &port);
/** connects to n servers at local host starting at specific control port */
void setVirtualDetectorServers(int numServers, int startingPort);
@ -344,11 +346,15 @@ class Detector {
Result<defs::runStatus> getDetectorStatus(Positions pos = {}) const;
Result<defs::runStatus> getReceiverStatus(Positions pos = {}) const;
Result<defs::runStatus> getReceiverStatus() const;
/** interface is by 1 (primary udp interface),
* 2 for second udp interface [Eiger][Jungfrau] */
Result<defs::runStatus> getReceiverStatus(const int udpInterface,
Positions pos = {}) const;
Result<int64_t> getFramesCaught(Positions pos = {}) const;
Result<uint64_t> getFramesCaught(Positions pos = {}) const;
Result<std::vector<uint64_t>> getNumMissingPackets(Positions pos = {}) const;
Result<uint64_t> getNumMissingPackets(Positions pos = {}) const;
/** [Eiger][Jungfrau] */
Result<uint64_t> getStartingFrameNumber(Positions pos = {}) const;
@ -503,28 +509,40 @@ class Detector {
* *
* ************************************************/
/** interface is by 1 (primary udp interface),
* 2 for second udp interface [Eiger][Jungfrau] */
void removeReceivers(const int udpInterface);
/** true when slsReceiver is used */
Result<bool> getUseReceiverFlag(Positions pos = {}) const;
Result<std::string> getRxHostname(Positions pos = {}) const;
/** interface is by 1 (primary udp interface),
* 2 for second udp interface [Eiger][Jungfrau]
*/
Result<std::string> getRxHostname(const int udpInterface, Positions pos = {}) const;
/**
* Validates and sets the receiver.
* Updates local receiver cache parameters
* Configures the detector to the receiver as UDP destination
* @param receiver receiver hostname or IP address, can include tcp port eg. hostname:port
* interface is by 1 (primary udp interface),
* 2 for second udp interface [Eiger][Jungfrau]
*/
void setRxHostname(const std::string &receiver, Positions pos = {});
void setRxHostname(const int udpInterface, const std::string &hostname,
Positions pos = {});
/** cannot be for multiple detectors as port is unique */
void setRxHostname(const int udpInterface, const std::string &hostname,
const int port, int module_id);
/** multiple rx hostnames (same as setRxHostname) */
void setRxHostname(const std::vector<std::string> &name);
Result<int> getRxPort(Positions pos = {}) const;
/** interface is by 1 (primary udp interface),
* 2 for second udp interface [Eiger][Jungfrau] */
Result<int> getRxPort(const int udpInterface, Positions pos = {}) const;
/** Receiver TCP port (for client communication with Receiver)
* module_id is -1 for all detectors, ports for each module is calculated
* (increments) */
void setRxPort(int port, int module_id = -1);
* (increments)
* interface is by 1 (primary udp interface),
* 2 for second udp interface [Eiger][Jungfrau] */
void setRxPort(const int udpInterface, const int port, int module_id = -1);
Result<int> getRxFifoDepth(Positions pos = {}) const;
@ -656,6 +674,9 @@ class Detector {
void setRxZmqIP(const IpAddr ip, Positions pos = {});
Result<bool> getClientZmq(Positions pos = {}) const;
void setClientZmq(const bool enable, Positions pos = {});
Result<int> getClientZmqPort(Positions pos = {}) const;
/**
@ -1352,8 +1373,6 @@ class Detector {
Result<uint64_t> getRxCurrentFrameIndex(Positions pos = {}) const;
private:
std::vector<int> getPortNumbers(int start_port);
};
} // namespace sls

View File

@ -115,13 +115,29 @@ std::string CmdProxy::ListCommands(int action) {
}
/* configuration */
std::pair<std::string, int>
CmdProxy::parseHostnameAndPort(std::string name) {
std::string host = name;
std::string hostname;
int port = 0;
auto res = sls::split(host, ':');
if (res.size() > 1) {
hostname = res[0];
port = StringTo<int>(res[1]);
} else {
hostname = host;
}
return std::make_pair(hostname, port);
}
std::string CmdProxy::Hostname(int action) {
std::ostringstream os;
os << cmd << ' ';
if (action == defs::HELP_ACTION) {
os << "\n\tFrees shared memory and sets hostname (or IP address) of "
"all modules concatenated by +."
"all modules concatenated by +.\n\t"
"[hostname or ip address]:[tcp port] Use this for virtual servers\n\t"
<< '\n';
} else if (action == defs::GET_ACTION) {
if (!args.empty()) {
@ -136,17 +152,35 @@ std::string CmdProxy::Hostname(int action) {
if (det_id != -1) {
throw sls::RuntimeError("Cannot execute this at module level");
}
std::vector<std::string> arguments;
// only args[0], but many hostames concatenated with +
if (args[0].find('+') != std::string::npos) {
auto t = sls::split(args[0], '+');
det->setHostname(t);
os << ToString(t) << '\n';
if (args.size() > 1) {
throw sls::RuntimeError("Cannot have concatenated hostnames and"
"multiple arguments");
}
arguments = sls::split(args[0], '+');
}
// either hostnames separated by space, or single hostname
else {
det->setHostname(args);
os << ToString(args) << '\n';
arguments.assign(args.begin(), args.end());
}
// separate hostname and port
std::vector<std::string> hostnames;
std::vector<int> ports;
for (size_t i = 0; i < arguments.size(); ++i) {
std::pair<std::string, int> res = parseHostnameAndPort(arguments[i]);
hostnames.push_back(res.first);
if (res.second == 0) {
ports.push_back(DEFAULT_PORTNO);
} else {
ports.push_back(res.second);
}
}
det->setHostname(hostnames, ports);
auto t = det->getHostname({det_id});
os << OutString(t) << '\n';
} else {
throw sls::RuntimeError("Unknown action");
}
@ -787,16 +821,29 @@ std::vector<std::string> CmdProxy::DacCommands() {
/* acquisition */
std::string CmdProxy::ReceiverStatus(int action) {
int udpInterface = 1;
if (cmd == "rx_status") {
udpInterface = 1;
} else if (cmd == "rx_status2") {
udpInterface = 2;
} else {
throw sls::RuntimeError("Unknown command, use list to list all commands");
}
std::ostringstream os;
os << cmd << ' ';
if (action == defs::HELP_ACTION) {
os << "running, idle]\n\tReceiver listener status."
if (cmd == "rx_status") {
os << "running, idle]\n\tReceiver listener status."
<< '\n';
} else {
os << "running, idle]\n\tReceiver listener status for second udp port."
<< '\n';
}
} else if (action == defs::GET_ACTION) {
if (args.size() != 0) {
WrongNumberOfParameters(0);
}
auto t = det->getReceiverStatus({det_id});
auto t = det->getReceiverStatus(udpInterface, {det_id});
os << OutString(t) << '\n';
} else if (action == defs::PUT_ACTION) {
throw sls::RuntimeError("Cannot put. Did you mean to use command 'rx_start' or 'rx_stop'?");
@ -905,61 +952,76 @@ std::string CmdProxy::UDPDestinationIP2(int action) {
}
/* Receiver Config */
std::string CmdProxy::ReceiveHostname(int action) {
std::string CmdProxy::ReceiverHostname(int action) {
int udpInterface = 1;
if (cmd == "rx_hostname") {
udpInterface = 1;
} else if (cmd == "rx_hostname2") {
udpInterface = 2;
} else {
throw sls::RuntimeError("Unknown command, use list to list all commands");
}
std::ostringstream os;
os << cmd << ' ';
if (action == defs::HELP_ACTION) {
os << "[hostname or ip address]\n\t"
"[hostname or ip address]:[tcp port]\n\t"
"[hostname1]:[tcp_port1]+[hostname2]:[tcp_port2]+\n\t"
"Receiver hostname or IP. If port included, then the receiver tcp port.\n\t"
"Used for TCP control communication between client and receiver "
"to configure receiver. Also updates receiver with detector parameters."
<< '\n';
if (cmd == "rx_hostname") {
os << "[hostname or ip address]\n\t"
"[hostname or ip address]:[tcp port]\n\t"
"Receiver hostname or IP. Port is the receiver tcp port (optional).\n\t"
"Use 'none' to remove receivers\n\t"
"Used for TCP control communication between client and receiver "
"to configure receiver. Also updates receiver with detector parameters.\n\t"
"TCP port must be unique, if included.\n\t"
"If port not included and not set earlier, then it takes default port 1954"
" and calculates from there. \n\t"
"[Eiger][Jungfrau] For the 2nd udp interface, use rx_hostname2."
<< '\n';
} else {
os << "[hostname or ip address]\n\t"
"[hostname or ip address]:[tcp port]\n\t"
"[Eiger][Jungfrau] Receiver hostname or IP for the second udp port. "
"Port is the receiver tcp port (optional).\n\t"
"Use 'none' to remove receivers\n\t"
"Refer rx_hostname help for details"
<< '\n';
}
} else if (action == defs::GET_ACTION) {
if (!args.empty()) {
WrongNumberOfParameters(0);
}
auto t = det->getRxHostname({det_id});
auto t = det->getRxHostname(udpInterface, {det_id});
os << OutString(t) << '\n';
} else if (action == defs::PUT_ACTION) {
if (args.size() < 1) {
if (args.size() != 1) {
WrongNumberOfParameters(1);
}
// multiple arguments
if (args.size() > 1) {
// multiple in mulitple
if (args[0].find('+') != std::string::npos) {
throw sls::RuntimeError("Cannot add multiple receivers at module level");
}
if (det_id != -1) {
throw sls::RuntimeError("Cannot add multiple receivers at module level");
}
det->setRxHostname(args);
os << ToString(args) << '\n';
if (args[0].find('+') != std::string::npos) {
throw sls::RuntimeError("Cannot concatenate receiver hostnames");
}
std::pair<std::string, int> res = parseHostnameAndPort(args[0]);
// removing receivers
if (res.first == "none") {
det->removeReceivers(udpInterface);
os << "removed" << '\n';
}
// single argument
// adding receivers
else {
// multiple receivers concatenated with +
if (args[0].find('+') != std::string::npos) {
if (det_id != -1) {
throw sls::RuntimeError("Cannot add multiple receivers at module level");
}
auto t = sls::split(args[0], '+');
det->setRxHostname(t);
os << ToString(t) << '\n';
}
// single receiver
else {
det->setRxHostname(args[0], {det_id});
os << ToString(args) << '\n';
std::string hostname = res.first;
int port = res.second;
if (port == 0) {
det->setRxHostname(udpInterface, hostname, {det_id});
} else {
det->setRxHostname(udpInterface, hostname, port, det_id);
}
auto t = det->getRxHostname(udpInterface, {det_id});
os << OutString(t) << '\n';
}
} else {
throw sls::RuntimeError("Unknown action");
}
return os.str();
}
/* File */
/* ZMQ Streaming Parameters (Receiver<->Client) */
/* Eiger Specific */

View File

@ -719,8 +719,10 @@ class CmdProxy {
{"txndelay_right", &CmdProxy::txndelay_right},
/* Receiver Config */
{"rx_hostname", &CmdProxy::ReceiveHostname},
{"rx_hostname", &CmdProxy::ReceiverHostname},
{"rx_hostname2", &CmdProxy::ReceiverHostname},
{"rx_tcpport", &CmdProxy::rx_tcpport},
{"rx_tcpport2", &CmdProxy::rx_tcpport2},
{"rx_fifodepth", &CmdProxy::rx_fifodepth},
{"rx_silent", &CmdProxy::rx_silent},
{"rx_discardpolicy", &CmdProxy::rx_discardpolicy},
@ -911,6 +913,7 @@ class CmdProxy {
/* configuration */
std::string free(int action);
// std::string config2(int action);
std::pair<std::string, int> parseHostnameAndPort(std::string name);
std::string Hostname(int action);
std::string VirtualServer(int action);
std::string FirmwareVersion(int action);
@ -940,7 +943,7 @@ class CmdProxy {
std::string UDPDestinationIP(int action);
std::string UDPDestinationIP2(int action);
/* Receiver Config */
std::string ReceiveHostname(int action);
std::string ReceiverHostname(int action);
/* File */
/* ZMQ Streaming Parameters (Receiver<->Client) */
/* Eiger Specific */
@ -1431,8 +1434,11 @@ class CmdProxy {
/* Receiver Config */
INTEGER_COMMAND(rx_tcpport, getRxPort, setRxPort, StringTo<int>,
INTEGER_IND_COMMAND(rx_tcpport, getRxPort, setRxPort, StringTo<int>, 1,
"[port]\n\tTCP port for client-receiver communication. Default is 1954. Must be different if multiple receivers on same pc. Must be first command to set a receiver parameter. Multi command will automatically increment for individual modules.");
INTEGER_IND_COMMAND(rx_tcpport2, getRxPort, setRxPort, StringTo<int>, 2,
"[port]\n\t[Eiger][Jungfrau] TCP port for client-receiver communication for 2nd udp port. For details, refer rx_tcpport.");
INTEGER_COMMAND(rx_fifodepth, getRxFifoDepth, setRxFifoDepth, StringTo<int>,
"[n_frames]\n\tSet the number of frames in the receiver fifo (buffer between listener and writer threads).");

File diff suppressed because it is too large Load Diff

View File

@ -5,6 +5,7 @@
#include "file_utils.h"
#include "logger.h"
#include "Module.h"
#include "Receiver.h"
#include "sls_detector_exceptions.h"
#include "versionAPI.h"
@ -28,14 +29,14 @@
namespace sls{
DetectorImpl::DetectorImpl(int multi_id, bool verify, bool update)
: multiId(multi_id), multi_shm(multi_id, -1) {
setupMultiDetector(verify, update);
DetectorImpl::DetectorImpl(int detector_id, bool verify, bool update)
: detectorId(detector_id), detector_shm(detector_id, -1) {
setupDetector(verify, update);
}
DetectorImpl::~DetectorImpl() = default;
void DetectorImpl::setupMultiDetector(bool verify, bool update) {
void DetectorImpl::setupDetector(bool verify, bool update) {
initSharedMemory(verify);
initializeMembers(verify);
if (update) {
@ -44,47 +45,94 @@ void DetectorImpl::setupMultiDetector(bool verify, bool update) {
}
void DetectorImpl::setAcquiringFlag(bool flag) {
multi_shm()->acquiringFlag = flag;
detector_shm()->acquiringFlag = flag;
}
int DetectorImpl::getMultiId() const { return multiId; }
int DetectorImpl::getDetectorId() const { return detectorId; }
void DetectorImpl::freeSharedMemory(int multiId, int detPos) {
void DetectorImpl::freeSharedMemory(int detectorId, int moduleId) {
// single
if (detPos >= 0) {
SharedMemory<sharedSlsDetector> temp_shm(multiId, detPos);
if (temp_shm.IsExisting()) {
temp_shm.RemoveSharedMemory();
if (moduleId >= 0) {
SharedMemory<sharedModule> moduleShm(detectorId, moduleId);
if (moduleShm.IsExisting()) {
moduleShm.OpenSharedMemory();
int numReceivers = 0, numReceivers2 = 0;
if (Module::hasSharedMemoryReceiverList(moduleShm()->shmversion)) {
numReceivers = moduleShm()->numberOfReceivers;
numReceivers2 = moduleShm()->numberOfReceivers2;
}
moduleShm.RemoveSharedMemory();
for (int iReceiver = 0; iReceiver < numReceivers; ++iReceiver) {
SharedMemory<sharedModule> receiverShm(detectorId, moduleId, 0, iReceiver);
if (receiverShm.IsExisting()) {
receiverShm.RemoveSharedMemory();
}
}
for (int iReceiver = 0; iReceiver < numReceivers2; ++iReceiver) {
SharedMemory<sharedModule> receiverShm(detectorId, moduleId, 1, iReceiver);
if (receiverShm.IsExisting()) {
receiverShm.RemoveSharedMemory();
}
}
}
return;
}
// multi - get number of detectors from shm
SharedMemory<sharedMultiSlsDetector> multiShm(multiId, -1);
SharedMemory<sharedDetector> detectorShm(detectorId, -1);
int numDetectors = 0;
if (multiShm.IsExisting()) {
multiShm.OpenSharedMemory();
numDetectors = multiShm()->numberOfDetectors;
multiShm.RemoveSharedMemory();
if (detectorShm.IsExisting()) {
detectorShm.OpenSharedMemory();
numDetectors = detectorShm()->numberOfModules;
detectorShm.RemoveSharedMemory();
}
for (int i = 0; i < numDetectors; ++i) {
SharedMemory<sharedSlsDetector> shm(multiId, i);
shm.RemoveSharedMemory();
for (int iModule = 0; iModule < numDetectors; ++iModule) {
SharedMemory<sharedModule> moduleShm(detectorId, iModule);
if (moduleShm.IsExisting()) {
moduleShm.OpenSharedMemory();
int numReceivers = 0, numReceivers2 = 0;
if (Module::hasSharedMemoryReceiverList(moduleShm()->shmversion)) {
numReceivers = moduleShm()->numberOfReceivers;
numReceivers2 = moduleShm()->numberOfReceivers2;
}
moduleShm.RemoveSharedMemory();
for (int iReceiver = 0; iReceiver < numReceivers; ++iReceiver) {
SharedMemory<sharedModule> receiverShm(detectorId, iModule, 0, iReceiver);
if (receiverShm.IsExisting()) {
receiverShm.RemoveSharedMemory();
}
}
for (int iReceiver = 0; iReceiver < numReceivers2; ++iReceiver) {
SharedMemory<sharedModule> receiverShm(detectorId, iModule, 1, iReceiver);
if (receiverShm.IsExisting()) {
receiverShm.RemoveSharedMemory();
}
}
}
}
}
void DetectorImpl::freeSharedMemory() {
zmqSocket.clear();
for (auto &d : detectors) {
d->freeSharedMemory();
}
detectors.clear();
for (auto &dr : receivers) {
for (auto &r : dr) {
r->freeSharedMemory();
}
}
receivers.clear();
for (auto &dr : receivers2) {
for (auto &r : dr) {
r->freeSharedMemory();
}
}
receivers2.clear();
// clear multi detector shm
multi_shm.RemoveSharedMemory();
client_downstream = false;
detector_shm.RemoveSharedMemory();
}
std::string DetectorImpl::getUserDetails() {
@ -101,8 +149,8 @@ std::string DetectorImpl::getUserDetails() {
}
sstream << "\nType: ";
// get type from multi shm
if (multi_shm()->shmversion >= MULTI_SHMAPIVERSION) {
sstream << ToString(multi_shm()->multiDetectorType);
if (detector_shm()->shmversion >= DETECTOR_SHMAPIVERSION) {
sstream << ToString(detector_shm()->multiDetectorType);
}
// get type from slsdet shm
else {
@ -114,33 +162,33 @@ std::string DetectorImpl::getUserDetails() {
}
}
sstream << "\nPID: " << multi_shm()->lastPID
<< "\nUser: " << multi_shm()->lastUser
<< "\nDate: " << multi_shm()->lastDate << std::endl;
sstream << "\nPID: " << detector_shm()->lastPID
<< "\nUser: " << detector_shm()->lastUser
<< "\nDate: " << detector_shm()->lastDate << std::endl;
return sstream.str();
}
bool DetectorImpl::getInitialChecks() const {
return multi_shm()->initialChecks;
return detector_shm()->initialChecks;
}
void DetectorImpl::setInitialChecks(const bool value) {
multi_shm()->initialChecks = value;
detector_shm()->initialChecks = value;
}
void DetectorImpl::initSharedMemory(bool verify) {
if (!multi_shm.IsExisting()) {
multi_shm.CreateSharedMemory();
if (!detector_shm.IsExisting()) {
detector_shm.CreateSharedMemory();
initializeDetectorStructure();
} else {
multi_shm.OpenSharedMemory();
if (verify && multi_shm()->shmversion != MULTI_SHMVERSION) {
LOG(logERROR) << "Multi shared memory (" << multiId
detector_shm.OpenSharedMemory();
if (verify && detector_shm()->shmversion != DETECTOR_SHMVERSION) {
LOG(logERROR) << "Detector shared memory (" << detectorId
<< ") version mismatch "
"(expected 0x"
<< std::hex << MULTI_SHMVERSION << " but got 0x"
<< multi_shm()->shmversion << std::dec
<< std::hex << DETECTOR_SHMVERSION << " but got 0x"
<< detector_shm()->shmversion << std::dec
<< ". Clear Shared memory to continue.";
throw SharedMemoryError("Shared memory version mismatch!");
}
@ -148,56 +196,76 @@ void DetectorImpl::initSharedMemory(bool verify) {
}
void DetectorImpl::initializeDetectorStructure() {
multi_shm()->shmversion = MULTI_SHMVERSION;
multi_shm()->numberOfDetectors = 0;
multi_shm()->multiDetectorType = GENERIC;
multi_shm()->numberOfDetector.x = 0;
multi_shm()->numberOfDetector.y = 0;
multi_shm()->numberOfChannels.x = 0;
multi_shm()->numberOfChannels.y = 0;
multi_shm()->acquiringFlag = false;
multi_shm()->initialChecks = true;
multi_shm()->gapPixels = false;
detector_shm()->shmversion = DETECTOR_SHMVERSION;
detector_shm()->numberOfModules = 0;
detector_shm()->multiDetectorType = GENERIC;
detector_shm()->numberOfDetector.x = 0;
detector_shm()->numberOfDetector.y = 0;
detector_shm()->numberOfChannels.x = 0;
detector_shm()->numberOfChannels.y = 0;
detector_shm()->acquiringFlag = false;
detector_shm()->initialChecks = true;
detector_shm()->gapPixels = false;
}
void DetectorImpl::initializeMembers(bool verify) {
// DetectorImpl
zmqSocket.clear();
int numModules = detector_shm()->numberOfModules;
// get objects from single det shared memory (open)
for (int i = 0; i < multi_shm()->numberOfDetectors; i++) {
try {
try {
for (int iModule = 0; iModule < numModules; ++iModule) {
detectors.push_back(
sls::make_unique<Module>(multiId, i, verify));
} catch (...) {
detectors.clear();
throw;
sls::make_unique<Module>(detectorId, iModule, verify));
int numReceivers = detectors[iModule]->getNumberOfReceivers();
if (numReceivers != 0) {
receivers.resize(numModules);
for (int iReceiver = 0; iReceiver < numReceivers; ++iReceiver) {
receivers[iModule].push_back(
sls::make_unique<Receiver>(detectorId, iModule, 0,
iReceiver, verify));
}
}
int numReceivers2 = detectors[iModule]->getNumberOfReceivers2();
if (numReceivers2 != 0) {
receivers2.resize(numModules);
for (int iReceiver = 0; iReceiver < numReceivers2; ++iReceiver) {
receivers2[iModule].push_back(
sls::make_unique<Receiver>(detectorId, iModule, 1,
iReceiver, verify));
}
}
}
} catch (...) {
detectors.clear();
receivers.clear();
receivers2.clear();
throw;
}
}
void DetectorImpl::updateUserdetails() {
multi_shm()->lastPID = getpid();
memset(multi_shm()->lastUser, 0, sizeof(multi_shm()->lastUser));
memset(multi_shm()->lastDate, 0, sizeof(multi_shm()->lastDate));
detector_shm()->lastPID = getpid();
memset(detector_shm()->lastUser, 0, sizeof(detector_shm()->lastUser));
memset(detector_shm()->lastDate, 0, sizeof(detector_shm()->lastDate));
try {
sls::strcpy_safe(multi_shm()->lastUser, exec("whoami").c_str());
sls::strcpy_safe(multi_shm()->lastDate, exec("date").c_str());
sls::strcpy_safe(detector_shm()->lastUser, exec("whoami").c_str());
sls::strcpy_safe(detector_shm()->lastDate, exec("date").c_str());
} catch (...) {
sls::strcpy_safe(multi_shm()->lastUser, "errorreading");
sls::strcpy_safe(multi_shm()->lastDate, "errorreading");
sls::strcpy_safe(detector_shm()->lastUser, "errorreading");
sls::strcpy_safe(detector_shm()->lastDate, "errorreading");
}
}
bool DetectorImpl::isAcquireReady() {
if (multi_shm()->acquiringFlag) {
if (detector_shm()->acquiringFlag) {
LOG(logWARNING)
<< "Acquire has already started. "
"If previous acquisition terminated unexpectedly, "
"reset busy flag to restart.(sls_detector_put clearbusy)";
return false;
}
multi_shm()->acquiringFlag = true;
detector_shm()->acquiringFlag = true;
return true;
}
@ -222,48 +290,63 @@ std::string DetectorImpl::exec(const char *cmd) {
void DetectorImpl::setVirtualDetectorServers(const int numdet, const int port) {
std::vector<std::string> hostnames;
std::vector<int> ports;
for (int i = 0; i < numdet; ++i) {
hostnames.push_back(std::string("localhost"));
// * 2 is for control and stop port
hostnames.push_back(std::string("localhost:") +
std::to_string(port + i * 2));
ports.push_back(port + i * 2);
}
setHostname(hostnames);
setHostname(hostnames, ports);
}
void DetectorImpl::setHostname(const std::vector<std::string> &name) {
// this check is there only to allow the previous detsizechan command
if (multi_shm()->numberOfDetectors != 0) {
if (detector_shm()->numberOfModules != 0) {
LOG(logWARNING)
<< "There are already detector(s) in shared memory."
"Freeing Shared memory now.";
bool initialChecks = multi_shm()->initialChecks;
bool initialChecks = detector_shm()->initialChecks;
freeSharedMemory();
setupMultiDetector();
multi_shm()->initialChecks = initialChecks;
setupDetector();
detector_shm()->initialChecks = initialChecks;
}
for (const auto &hostname : name) {
addSlsDetector(hostname);
addModule(hostname, DEFAULT_PORTNO);
}
updateDetectorSize();
}
void DetectorImpl::addSlsDetector(const std::string &hostname) {
LOG(logINFO) << "Adding detector " << hostname;
int port = DEFAULT_PORTNO;
std::string host = hostname;
auto res = sls::split(hostname, ':');
if (res.size() > 1) {
host = res[0];
port = StringTo<int>(res[1]);
void DetectorImpl::setHostname(const std::vector<std::string> &name,
const std::vector<int> &port) {
if (name.size() != port.size()) {
throw RuntimeError("hostname vector size and port vector size do not match");
}
// this check is there only to allow the previous detsizechan command
if (detector_shm()->numberOfModules != 0) {
LOG(logWARNING)
<< "There are already detector(s) in shared memory."
"Freeing Shared memory now.";
bool initialChecks = detector_shm()->initialChecks;
freeSharedMemory();
setupDetector();
detector_shm()->initialChecks = initialChecks;
}
for (size_t i = 0; i < name.size(); ++i) {
addModule(name[i], port[i]);
}
updateDetectorSize();
}
if (host != "localhost") {
void DetectorImpl::addModule(const std::string &hostname,
const int port) {
LOG(logINFO) << "Adding detector " << hostname << " on port " << port;
if (hostname != "localhost") {
for (auto &d : detectors) {
if (d->getHostname() == host) {
if (d->getHostname() == hostname) {
LOG(logWARNING)
<< "Detector " << host
<< "already part of the multiDetector!" << std::endl
<< "Detector " << hostname
<< "already part of the Detector!" << std::endl
<< "Remove it before adding it back in a new position!";
return;
}
@ -271,28 +354,176 @@ void DetectorImpl::addSlsDetector(const std::string &hostname) {
}
// get type by connecting
detectorType type = Module::getTypeFromDetector(host, port);
detectorType type = Module::getTypeFromDetector(hostname, port);
auto pos = detectors.size();
detectors.emplace_back(
sls::make_unique<Module>(type, multiId, pos, false));
multi_shm()->numberOfDetectors = detectors.size();
sls::make_unique<Module>(type, detectorId, pos, false));
detector_shm()->numberOfModules = detectors.size();
detectors[pos]->setControlPort(port);
detectors[pos]->setStopPort(port + 1);
detectors[pos]->setHostname(host, multi_shm()->initialChecks);
detectors[pos]->setHostname(hostname, detector_shm()->initialChecks);
// detector type updated by now
multi_shm()->multiDetectorType =
detector_shm()->multiDetectorType =
Parallel(&Module::getDetectorType, {})
.tsquash("Inconsistent detector types.");
// for moench and ctb
detectors[pos]->updateNumberOfChannels();
}
int DetectorImpl::getNumberofReceiversPerModule() const {
int retval = receivers.size();
if (receivers2.size()) {
retval *= 2;
}
// for round robin
if (retval) {
retval *= receivers[0].size();
}
return retval;
}
void DetectorImpl::initReceiver(const int udpInterface) {
if (udpInterface == 1) {
if (receivers.size() != 0) {
throw RuntimeError("receiver vector already initialized");
}
int tcpPort = DEFAULT_RX_PORTNO;
int zmqPort = DEFAULT_ZMQ_CL_PORTNO;
try {
for (int iModule = 0; iModule < size(); ++iModule) {
receivers.resize(detectors.size());
receivers[iModule].push_back(
sls::make_unique<Receiver>(detectorId, iModule, 0,
0, tcpPort++, "", zmqPort++));
detectors[iModule]->setNumberOfReceivers(1);
}
} catch (...) {
receivers.clear();
throw;
}
} else if (udpInterface == 2) {
if (receivers2.size() != 0) {
throw RuntimeError("receiver2 vector already initialized");
}
int tcpPort = DEFAULT_RX_PORTNO + size();
int zmqPort = DEFAULT_ZMQ_CL_PORTNO + size();
try {
for (int iModule = 0; iModule < size(); ++iModule) {
receivers2.resize(detectors.size());
receivers2[iModule].push_back(
sls::make_unique<Receiver>(detectorId, iModule, 1,
0, tcpPort++, "", zmqPort++));
detectors[iModule]->setNumberOfReceivers2(1);
}
} catch (...) {
receivers2.clear();
throw;
}
} else {
throw RuntimeError("Invalid udp interface number " +
std::to_string(udpInterface));
}
}
bool DetectorImpl::isReceiverInitialized(const int udpInterface) {
switch (udpInterface) {
case 1:
return (receivers.size() > 0);
case 2:
return (receivers2.size() > 0);
default:
throw RuntimeError("Invalid udp interface number " +
std::to_string(udpInterface));
}
}
void DetectorImpl::removeReceivers(const int udpInterface) {
if (udpInterface == 1) {
for (auto & dr: receivers) {
for (auto & r : dr) {
r->freeSharedMemory();
}
}
receivers.clear();
} else if (udpInterface == 2) {
for (auto & dr: receivers2) {
for (auto & r : dr) {
r->freeSharedMemory();
}
}
receivers2.clear();
} else {
throw RuntimeError("Invalid udp interface number " +
std::to_string(udpInterface));
}
}
void DetectorImpl::configureReceiver(const int udpInterface, Positions pos,
const std::string &hostname) {
if (Parallel(&Module::getRunStatus, pos).squash(defs::ERROR) == defs::RUNNING) {
LOG(logWARNING) << "Acquisition already running, Stopping it.";
Parallel(&Module::stopAcquisition, {});
}
if (!isReceiverInitialized(udpInterface)) {
initReceiver(udpInterface);
}
auto t = Parallel(&Module::getReceiverParameters, pos);
if (udpInterface == 1) {
Parallel1(&Receiver::setHostname, pos, {}, hostname);
for (int iMod = 0; iMod < size(); ++iMod) {
auto m = receivers[iMod][0]->configure(t[iMod]);
if (m != 0) {
detectors[iMod]->setDestinationUDPMAC(m);
}
}
} else {
Parallel2(&Receiver::setHostname, pos, {}, hostname);
for (int iMod = 0; iMod < size(); ++iMod) {
auto m = receivers2[iMod][0]->configure(t[iMod]);
if (m != 0) {
detectors[iMod]->setDestinationUDPMAC2(m);
}
}
}
}
void DetectorImpl::configureReceiver(const int udpInterface, int module_id,
const std::string &hostname, const int port) {
if (Parallel(&Module::getRunStatus, {}).squash(defs::ERROR) == defs::RUNNING) {
LOG(logWARNING) << "Acquisition already running, Stopping it.";
Parallel(&Module::stopAcquisition, {});
}
if (!isReceiverInitialized(udpInterface)) {
initReceiver(udpInterface);
}
std::cout << "module_id:"<<module_id << std::endl;
auto t = detectors[module_id]->getReceiverParameters();
if (udpInterface == 1) {
receivers[module_id][0]->setTCPPort(port);
receivers[module_id][0]->setHostname(hostname);
auto m = receivers[module_id][0]->configure(t);
if (m != 0) {
detectors[module_id]->setDestinationUDPMAC(m);
}
} else {
receivers2[module_id][0]->setTCPPort(port);
receivers2[module_id][0]->setHostname(hostname);
auto m = receivers2[module_id][0]->configure(t);
if (m != 0) {
detectors[module_id]->setDestinationUDPMAC2(m);
}
}
}
void DetectorImpl::updateDetectorSize() {
LOG(logDEBUG) << "Updating Multi-Detector Size: " << size();
LOG(logDEBUG) << "Updating Detector Size: " << size();
const slsDetectorDefs::xy det_size = detectors[0]->getNumberOfChannels();
int maxy = multi_shm()->numberOfChannels.y;
int maxy = detector_shm()->numberOfChannels.y;
if (maxy == 0) {
maxy = det_size.y * size();
}
@ -303,33 +534,33 @@ void DetectorImpl::updateDetectorSize() {
++ndetx;
}
multi_shm()->numberOfDetector.x = ndetx;
multi_shm()->numberOfDetector.y = ndety;
multi_shm()->numberOfChannels.x = det_size.x * ndetx;
multi_shm()->numberOfChannels.y = det_size.y * ndety;
detector_shm()->numberOfDetector.x = ndetx;
detector_shm()->numberOfDetector.y = ndety;
detector_shm()->numberOfChannels.x = det_size.x * ndetx;
detector_shm()->numberOfChannels.y = det_size.y * ndety;
LOG(logDEBUG) << "\n\tNumber of Detectors in X direction:"
<< multi_shm()->numberOfDetector.x
<< detector_shm()->numberOfDetector.x
<< "\n\tNumber of Detectors in Y direction:"
<< multi_shm()->numberOfDetector.y
<< detector_shm()->numberOfDetector.y
<< "\n\tNumber of Channels in X direction:"
<< multi_shm()->numberOfChannels.x
<< detector_shm()->numberOfChannels.x
<< "\n\tNumber of Channels in Y direction:"
<< multi_shm()->numberOfChannels.y;
<< detector_shm()->numberOfChannels.y;
for (auto &d : detectors) {
d->updateMultiSize(multi_shm()->numberOfDetector);
d->updateDetectorSize(detector_shm()->numberOfDetector);
}
}
int DetectorImpl::size() const { return detectors.size(); }
slsDetectorDefs::xy DetectorImpl::getNumberOfDetectors() const {
return multi_shm()->numberOfDetector;
return detector_shm()->numberOfDetector;
}
slsDetectorDefs::xy DetectorImpl::getNumberOfChannels() const {
return multi_shm()->numberOfChannels;
return detector_shm()->numberOfChannels;
}
void DetectorImpl::setNumberOfChannels(const slsDetectorDefs::xy c) {
@ -337,90 +568,38 @@ void DetectorImpl::setNumberOfChannels(const slsDetectorDefs::xy c) {
throw RuntimeError(
"Set the number of channels before setting hostname.");
}
multi_shm()->numberOfChannels = c;
detector_shm()->numberOfChannels = c;
}
bool DetectorImpl::getGapPixelsinCallback() const {
return multi_shm()->gapPixels;
return detector_shm()->gapPixels;
}
void DetectorImpl::setGapPixelsinCallback(const bool enable) {
if (enable) {
switch (multi_shm()->multiDetectorType) {
switch (detector_shm()->multiDetectorType) {
case JUNGFRAU:
break;
case EIGER:
if (size() && detectors[0]->getQuad()) {
break;
}
if (multi_shm()->numberOfDetector.y % 2 != 0) {
if (detector_shm()->numberOfDetector.y % 2 != 0) {
throw RuntimeError("Gap pixels can only be used "
"for full modules.");
}
break;
default:
throw RuntimeError("Gap Pixels is not implemented for "
+ multi_shm()->multiDetectorType);
+ detector_shm()->multiDetectorType);
}
}
multi_shm()->gapPixels = enable;
}
int DetectorImpl::createReceivingDataSockets(const bool destroy) {
if (destroy) {
LOG(logINFO) << "Going to destroy data sockets";
// close socket
zmqSocket.clear();
client_downstream = false;
LOG(logINFO) << "Destroyed Receiving Data Socket(s)";
return OK;
}
if (client_downstream) {
return OK;
}
LOG(logINFO) << "Going to create data sockets";
size_t numSockets = detectors.size();
size_t numSocketsPerDetector = 1;
if (multi_shm()->multiDetectorType == EIGER) {
numSocketsPerDetector = 2;
}
if (Parallel(&Module::getNumberofUDPInterfacesFromShm, {}).squash() ==
2) {
numSocketsPerDetector = 2;
}
numSockets *= numSocketsPerDetector;
for (size_t iSocket = 0; iSocket < numSockets; ++iSocket) {
uint32_t portnum = (detectors[iSocket / numSocketsPerDetector]
->getClientStreamingPort());
portnum += (iSocket % numSocketsPerDetector);
try {
zmqSocket.push_back(sls::make_unique<ZmqSocket>(
detectors[iSocket / numSocketsPerDetector]
->getClientStreamingIP()
.str()
.c_str(),
portnum));
LOG(logINFO) << "Zmq Client[" << iSocket << "] at "
<< zmqSocket.back()->GetZmqServerAddress();
} catch (...) {
LOG(logERROR)
<< "Could not create Zmq socket on port " << portnum;
createReceivingDataSockets(true);
return FAIL;
}
}
client_downstream = true;
LOG(logINFO) << "Receiving Data Socket(s) created";
return OK;
detector_shm()->gapPixels = enable;
}
void DetectorImpl::readFrameFromReceiver() {
bool gapPixels = multi_shm()->gapPixels;
bool gapPixels = detector_shm()->gapPixels;
LOG(logDEBUG) << "Gap pixels: " << gapPixels;
int nX = 0;
@ -429,23 +608,32 @@ void DetectorImpl::readFrameFromReceiver() {
int nDetPixelsY = 0;
bool quadEnable = false;
bool eiger = false;
bool numInterfaces =
int numInterfaces =
Parallel(&Module::getNumberofUDPInterfacesFromShm, {})
.squash(); // cannot pick up from zmq
bool runningList[zmqSocket.size()], connectList[zmqSocket.size()];
size_t nZmq = receivers.size() + receivers2.size();
std::vector<ZmqSocket*> zmqSockets;
for (size_t i = 0; i < receivers.size(); ++i) {
zmqSockets.push_back(receivers[i][0]->getZmqSocket());
if (receivers2.size()) {
zmqSockets.push_back(receivers2[i][0]->getZmqSocket());
}
}
bool runningList[nZmq], connectList[nZmq];
int numRunning = 0;
for (size_t i = 0; i < zmqSocket.size(); ++i) {
if (zmqSocket[i]->Connect() == 0) {
for (size_t i = 0; i < nZmq; ++i) {
if (zmqSockets[i]->Connect() == 0) {
connectList[i] = true;
runningList[i] = true;
++numRunning;
} else {
// to remember the list it connected to, to disconnect later
connectList[i] = false;
LOG(logERROR) << "Could not connect to socket "
<< zmqSocket[i]->GetZmqServerAddress();
runningList[i] = false;
LOG(logERROR) << "Could not connect to socket "
<< zmqSockets[i]->GetZmqServerAddress();
}
}
int numConnected = numRunning;
@ -482,7 +670,7 @@ void DetectorImpl::readFrameFromReceiver() {
completeImage = true;
// get each frame
for (unsigned int isocket = 0; isocket < zmqSocket.size(); ++isocket) {
for (unsigned int isocket = 0; isocket < nZmq; ++isocket) {
// if running
if (runningList[isocket]) {
@ -490,7 +678,7 @@ void DetectorImpl::readFrameFromReceiver() {
// HEADER
{
zmqHeader zHeader;
if (zmqSocket[isocket]->ReceiveHeader(
if (zmqSockets[isocket]->ReceiveHeader(
isocket, zHeader, SLS_DETECTOR_JSON_HEADER_VERSION) ==
0) {
// parse error, version error or end of acquisition for
@ -504,7 +692,7 @@ void DetectorImpl::readFrameFromReceiver() {
if (image == nullptr) {
// allocate
size = zHeader.imageSize;
multisize = size * zmqSocket.size();
multisize = size * nZmq;
image = new char[size];
multiframe = new char[multisize];
memset(multiframe, 0xFF, multisize);
@ -515,8 +703,8 @@ void DetectorImpl::readFrameFromReceiver() {
nPixelsX = zHeader.npixelsx;
nPixelsY = zHeader.npixelsy;
// detector shape
nX = zHeader.ndetx;
nY = zHeader.ndety;
nX = zHeader.nSocketX;
nY = zHeader.nSocketY;
nY *= numInterfaces;
nDetPixelsX = nX * nPixelsX;
nDetPixelsY = nY * nPixelsY;
@ -569,7 +757,7 @@ void DetectorImpl::readFrameFromReceiver() {
// DATA
data = true;
zmqSocket[isocket]->ReceiveData(isocket, image, size);
zmqSockets[isocket]->ReceiveData(isocket, image, size);
// creating multi image
{
@ -577,7 +765,7 @@ void DetectorImpl::readFrameFromReceiver() {
uint32_t yoffset = coordY * nPixelsY;
uint32_t singledetrowoffset = nPixelsX * bytesPerPixel;
uint32_t rowoffset = nX * singledetrowoffset;
if (multi_shm()->multiDetectorType == CHIPTESTBOARD) {
if (detector_shm()->multiDetectorType == CHIPTESTBOARD) {
singledetrowoffset = size;
}
LOG(logDEBUG1)
@ -656,7 +844,7 @@ void DetectorImpl::readFrameFromReceiver() {
running = false;
} else {
// starting a new scan/measurement (got dummy data)
for (size_t i = 0; i < zmqSocket.size(); ++i) {
for (size_t i = 0; i < zmqSockets.size(); ++i) {
runningList[i] = connectList[i];
}
numRunning = numConnected;
@ -665,9 +853,9 @@ void DetectorImpl::readFrameFromReceiver() {
}
// Disconnect resources
for (size_t i = 0; i < zmqSocket.size(); ++i) {
for (size_t i = 0; i < zmqSockets.size(); ++i) {
if (connectList[i]) {
zmqSocket[i]->Disconnect();
zmqSockets[i]->Disconnect();
}
}
@ -755,7 +943,7 @@ int DetectorImpl::InsertGapPixels(char *image, char *&gpImage,
// eiger requires inter chip gap pixels are halved
// jungfrau prefers same inter chip gap pixels as the boundary pixels
int divisionValue = 2;
slsDetectorDefs::detectorType detType = multi_shm()->multiDetectorType;
slsDetectorDefs::detectorType detType = detector_shm()->multiDetectorType;
if (detType == JUNGFRAU) {
divisionValue = 1;
}
@ -973,23 +1161,6 @@ int DetectorImpl::InsertGapPixels(char *image, char *&gpImage,
return imagesize;
}
bool DetectorImpl::enableDataStreamingToClient(int enable) {
if (enable >= 0) {
// destroy data threads
if (enable == 0) {
createReceivingDataSockets(true);
// create data threads
} else {
if (createReceivingDataSockets() == FAIL) {
throw RuntimeError("Could not create data threads in client.");
}
}
}
return client_downstream;
}
void DetectorImpl::registerAcquisitionFinishedCallback(void (*func)(double, int,
void *),
void *pArg) {
@ -1003,7 +1174,6 @@ void DetectorImpl::registerDataCallback(void (*userCallback)(detectorData *,
void *pArg) {
dataReady = userCallback;
pCallbackArg = pArg;
enableDataStreamingToClient(dataReady == nullptr ? 0 : 1);
}
int DetectorImpl::acquire() {
@ -1024,16 +1194,16 @@ int DetectorImpl::acquire() {
// receiver/ext process)
sem_init(&sem_endRTAcquisition, 1, 0);
bool receiver =
Parallel(&Module::getUseReceiverFlag, {}).squash(false);
bool receiver1 = isReceiverInitialized(1);
bool receiver2 = isReceiverInitialized(2);
bool receiver = receiver1 || receiver2;
setJoinThreadFlag(false);
// verify receiver is idle
if (receiver) {
if (Parallel(&Module::getReceiverStatus, {}).squash(ERROR) !=
IDLE) {
Parallel(&Module::stopReceiver, {});
if (Parallel3(&Receiver::getStatus).squash(ERROR) != IDLE) {
Parallel3(&Receiver::stop);
}
}
@ -1041,32 +1211,32 @@ int DetectorImpl::acquire() {
// start receiver
if (receiver) {
Parallel(&Module::startReceiver, {});
Parallel3(&Receiver::start);
// let processing thread listen to these packets
sem_post(&sem_newRTAcquisition);
}
// start and read all
try {
if (multi_shm()->multiDetectorType == EIGER) {
if (detector_shm()->multiDetectorType == EIGER) {
Parallel(&Module::prepareAcquisition, {});
}
Parallel(&Module::startAndReadAll, {});
} catch (...) {
Parallel(&Module::stopReceiver, {});
Parallel3(&Receiver::stop);
throw;
}
// stop receiver
if (receiver) {
Parallel(&Module::stopReceiver, {});
Parallel3(&Receiver::stop);
if (dataReady != nullptr) {
sem_wait(&sem_endRTAcquisition); // waits for receiver's
}
// external process to be
// done sending data to gui
Parallel(&Module::incrementFileIndex, {});
Parallel3(&Receiver::incrementFileIndex);
}
// waiting for the data processing thread to finish!
@ -1076,7 +1246,7 @@ int DetectorImpl::acquire() {
if (acquisition_finished != nullptr) {
int status = Parallel(&Module::getRunStatus, {}).squash(ERROR);
auto a = Parallel(&Module::getReceiverProgress, {});
auto a = Parallel3(&Receiver::getProgress);
int progress = (*std::min_element (a.begin(), a.end()));
acquisition_finished((double)progress, status, acqFinished_p);
}
@ -1109,7 +1279,7 @@ void DetectorImpl::startProcessingThread() {
}
void DetectorImpl::processData() {
if (Parallel(&Module::getUseReceiverFlag, {}).squash(false)) {
if (isReceiverInitialized(1) || isReceiverInitialized(2)) {
if (dataReady != nullptr) {
readFrameFromReceiver();
}
@ -1128,7 +1298,7 @@ void DetectorImpl::processData() {
}
}
// get and print progress
double temp = (double)Parallel(&Module::getReceiverProgress, {0}).squash();
double temp = (double)Parallel1(&Receiver::getProgress, {0}, {0}).squash();
if (temp != progress) {
printProgress(progress);
progress = temp;
@ -1137,7 +1307,7 @@ void DetectorImpl::processData() {
// exiting loop
if (getJoinThreadFlag()) {
// print progress one final time before exiting
progress = (double)Parallel(&Module::getReceiverProgress, {0}).squash();
progress = (double)Parallel1(&Receiver::getProgress, {0}, {0}).squash();
printProgress(progress);
break;
}
@ -1172,7 +1342,7 @@ int DetectorImpl::kbhit() {
std::vector<char> DetectorImpl::readProgrammingFile(const std::string &fname) {
// validate type of file
bool isPof = false;
switch (multi_shm()->multiDetectorType) {
switch (detector_shm()->multiDetectorType) {
case JUNGFRAU:
case CHIPTESTBOARD:
case MOENCH:

View File

@ -5,7 +5,6 @@
#include "logger.h"
#include "sls_detector_defs.h"
class ZmqSocket;
class detectorData;
#include <memory>
@ -15,8 +14,8 @@ class detectorData;
#include <thread>
#include <vector>
#define MULTI_SHMAPIVERSION 0x190809
#define MULTI_SHMVERSION 0x200319
#define DETECTOR_SHMAPIVERSION 0x190809
#define DETECTOR_SHMVERSION 0x200319
#define SHORT_STRING_LENGTH 50
#include <future>
@ -25,12 +24,13 @@ class detectorData;
namespace sls{
class Module;
class Receiver;
/**
* @short structure allocated in shared memory to store detector settings
* for IPC and cache
*/
struct sharedMultiSlsDetector {
struct sharedDetector {
/* FIXED PATTERN FOR STATIC FUNCTIONS. DO NOT CHANGE, ONLY APPEND
* ------*/
@ -47,7 +47,7 @@ struct sharedMultiSlsDetector {
/** last time stamp when accessing the shared memory */
char lastDate[SHORT_STRING_LENGTH];
int numberOfDetectors;
int numberOfModules;
slsDetectorDefs::detectorType multiDetectorType;
/** END OF FIXED PATTERN
@ -68,12 +68,12 @@ class DetectorImpl : public virtual slsDetectorDefs {
public:
/**
* Constructor
* @param id multi detector id
* @param detector_id multi detector id
* @param verify true to verify if shared memory version matches existing
* one
* @param update true to update last user pid, date etc
*/
explicit DetectorImpl(int multi_id = 0, bool verify = true,
explicit DetectorImpl(int detector_id = 0, bool verify = true,
bool update = true);
/**
@ -189,14 +189,460 @@ class DetectorImpl : public virtual slsDetectorDefs {
}
template <typename RT, typename... CT>
sls::Result<RT> Parallel1(RT (sls::Receiver::*somefunc)(CT...),
std::vector<int> dPositions,
std::vector<int> rxPositions,
typename NonDeduced<CT>::type... Args) {
if (receivers.size() == 0)
throw sls::RuntimeError("No receivers added");
if (dPositions.empty() ||
(dPositions.size() == 1 && dPositions[0] == -1)) {
dPositions.resize(receivers.size());
std::iota(begin(dPositions), end(dPositions), 0);
}
if (rxPositions.empty() ||
(rxPositions.size() == 1 && rxPositions[0] == -1)) {
rxPositions.resize(receivers[0].size());
std::iota(begin(rxPositions), end(rxPositions), 0);
}
std::vector<std::future<RT>> futures;
futures.reserve(dPositions.size() * rxPositions.size());
for (size_t i : dPositions) {
if (i >= receivers.size())
throw sls::RuntimeError("Detector out of range");
// each entry
for (size_t j : rxPositions) {
futures.push_back(std::async(std::launch::async, somefunc,
receivers[i][j].get(), Args...));
}
}
sls::Result<RT> result;
result.reserve(dPositions.size() * rxPositions.size());
for (auto &i : futures) {
result.push_back(i.get());
}
return result;
}
template <typename RT, typename... CT>
sls::Result<RT> Parallel1(RT (sls::Receiver::*somefunc)(CT...) const,
std::vector<int> dPositions,
std::vector<int> rxPositions,
typename NonDeduced<CT>::type... Args) const {
if (receivers.size() == 0)
throw sls::RuntimeError("No receivers added");
if (dPositions.empty() ||
(dPositions.size() == 1 && dPositions[0] == -1)) {
dPositions.resize(receivers.size());
std::iota(begin(dPositions), end(dPositions), 0);
}
if (rxPositions.empty() ||
(rxPositions.size() == 1 && rxPositions[0] == -1)) {
rxPositions.resize(receivers[0].size());
std::iota(begin(rxPositions), end(rxPositions), 0);
}
std::vector<std::future<RT>> futures;
futures.reserve(dPositions.size() * rxPositions.size());
for (size_t i : dPositions) {
if (i >= receivers.size())
throw sls::RuntimeError("Detector out of range");
// each entry
for (size_t j : rxPositions) {
futures.push_back(std::async(std::launch::async, somefunc,
receivers[i][j].get(), Args...));
}
}
sls::Result<RT> result;
result.reserve(dPositions.size() * rxPositions.size());
for (auto &i : futures) {
result.push_back(i.get());
}
return result;
}
template <typename... CT>
void Parallel1(void (sls::Receiver::*somefunc)(CT...),
std::vector<int> dPositions,
std::vector<int> rxPositions,
typename NonDeduced<CT>::type... Args) {
if (receivers.size() == 0)
throw sls::RuntimeError("No receivers added");
if (dPositions.empty() ||
(dPositions.size() == 1 && dPositions[0] == -1)) {
dPositions.resize(receivers.size());
std::iota(begin(dPositions), end(dPositions), 0);
}
if (rxPositions.empty() ||
(rxPositions.size() == 1 && rxPositions[0] == -1)) {
rxPositions.resize(receivers[0].size());
std::iota(begin(rxPositions), end(rxPositions), 0);
}
std::vector<std::future<void>> futures;
futures.reserve(dPositions.size() * rxPositions.size());
for (size_t i : dPositions) {
if (i >= receivers.size())
throw sls::RuntimeError("Detector out of range");
// each entry
for (size_t j : rxPositions) {
futures.push_back(std::async(std::launch::async, somefunc,
receivers[i][j].get(), Args...));
}
}
for (auto &i : futures) {
i.get();
}
}
template <typename... CT>
void Parallel1(void (sls::Receiver::*somefunc)(CT...) const,
std::vector<int> dPositions,
std::vector<int> rxPositions,
typename NonDeduced<CT>::type... Args) const {
if (receivers.size() == 0)
throw sls::RuntimeError("No receivers added");
if (dPositions.empty() ||
(dPositions.size() == 1 && dPositions[0] == -1)) {
dPositions.resize(receivers.size());
std::iota(begin(dPositions), end(dPositions), 0);
}
if (rxPositions.empty() ||
(rxPositions.size() == 1 && rxPositions[0] == -1)) {
rxPositions.resize(receivers[0].size());
std::iota(begin(rxPositions), end(rxPositions), 0);
}
std::vector<std::future<void>> futures;
futures.reserve(dPositions.size() * rxPositions.size());
for (size_t i : dPositions) {
if (i >= receivers.size())
throw sls::RuntimeError("Detector out of range");
// each entry
for (size_t j : rxPositions) {
futures.push_back(std::async(std::launch::async, somefunc,
receivers[i][j].get(), Args...));
}
}
for (auto &i : futures) {
i.get();
}
}
template <typename RT, typename... CT>
sls::Result<RT> Parallel2(RT (sls::Receiver::*somefunc)(CT...),
std::vector<int> dPositions,
std::vector<int> rxPositions,
typename NonDeduced<CT>::type... Args) {
if (receivers2.size() == 0)
throw sls::RuntimeError("No receivers2 added");
if (dPositions.empty() ||
(dPositions.size() == 1 && dPositions[0] == -1)) {
dPositions.resize(receivers2.size());
std::iota(begin(dPositions), end(dPositions), 0);
}
if (rxPositions.empty() ||
(rxPositions.size() == 1 && rxPositions[0] == -1)) {
rxPositions.resize(receivers2[0].size());
std::iota(begin(rxPositions), end(rxPositions), 0);
}
std::vector<std::future<RT>> futures;
futures.reserve(dPositions.size() * rxPositions.size());
for (size_t i : dPositions) {
if (i >= receivers2.size())
throw sls::RuntimeError("Detector out of range");
// each entry
for (size_t j : rxPositions) {
futures.push_back(std::async(std::launch::async, somefunc,
receivers2[i][j].get(), Args...));
}
}
sls::Result<RT> result;
result.reserve(dPositions.size() * rxPositions.size());
for (auto &i : futures) {
result.push_back(i.get());
}
return result;
}
template <typename RT, typename... CT>
sls::Result<RT> Parallel2(RT (sls::Receiver::*somefunc)(CT...) const,
std::vector<int> dPositions,
std::vector<int> rxPositions,
typename NonDeduced<CT>::type... Args) const {
if (receivers2.size() == 0)
throw sls::RuntimeError("No receivers2 added");
if (dPositions.empty() ||
(dPositions.size() == 1 && dPositions[0] == -1)) {
dPositions.resize(receivers2.size());
std::iota(begin(dPositions), end(dPositions), 0);
}
if (rxPositions.empty() ||
(rxPositions.size() == 1 && rxPositions[0] == -1)) {
rxPositions.resize(receivers2[0].size());
std::iota(begin(rxPositions), end(rxPositions), 0);
}
std::vector<std::future<RT>> futures;
futures.reserve(dPositions.size() * rxPositions.size());
for (size_t i : dPositions) {
if (i >= receivers2.size())
throw sls::RuntimeError("Detector out of range");
// each entry
for (size_t j : rxPositions) {
futures.push_back(std::async(std::launch::async, somefunc,
receivers2[i][j].get(), Args...));
}
}
sls::Result<RT> result;
result.reserve(dPositions.size() * rxPositions.size());
for (auto &i : futures) {
result.push_back(i.get());
}
return result;
}
template <typename... CT>
void Parallel2(void (sls::Receiver::*somefunc)(CT...),
std::vector<int> dPositions,
std::vector<int> rxPositions,
typename NonDeduced<CT>::type... Args) {
if (receivers2.size() == 0)
throw sls::RuntimeError("No receivers2 added");
if (dPositions.empty() ||
(dPositions.size() == 1 && dPositions[0] == -1)) {
dPositions.resize(receivers2.size());
std::iota(begin(dPositions), end(dPositions), 0);
}
if (rxPositions.empty() ||
(rxPositions.size() == 1 && rxPositions[0] == -1)) {
rxPositions.resize(receivers2[0].size());
std::iota(begin(rxPositions), end(rxPositions), 0);
}
std::vector<std::future<void>> futures;
futures.reserve(dPositions.size() * rxPositions.size());
for (size_t i : dPositions) {
if (i >= receivers2.size())
throw sls::RuntimeError("Detector out of range");
// each entry
for (size_t j : rxPositions) {
futures.push_back(std::async(std::launch::async, somefunc,
receivers2[i][j].get(), Args...));
}
}
for (auto &i : futures) {
i.get();
}
}
template <typename... CT>
void Parallel2(void (sls::Receiver::*somefunc)(CT...) const,
std::vector<int> dPositions,
std::vector<int> rxPositions,
typename NonDeduced<CT>::type... Args) const {
if (receivers2.size() == 0)
throw sls::RuntimeError("No receivers2 added");
if (dPositions.empty() ||
(dPositions.size() == 1 && dPositions[0] == -1)) {
dPositions.resize(receivers2.size());
std::iota(begin(dPositions), end(dPositions), 0);
}
if (rxPositions.empty() ||
(rxPositions.size() == 1 && rxPositions[0] == -1)) {
rxPositions.resize(receivers2[0].size());
std::iota(begin(rxPositions), end(rxPositions), 0);
}
std::vector<std::future<void>> futures;
futures.reserve(dPositions.size() * rxPositions.size());
for (size_t i : dPositions) {
if (i >= receivers2.size())
throw sls::RuntimeError("Detector out of range");
// each entry
for (size_t j : rxPositions) {
futures.push_back(std::async(std::launch::async, somefunc,
receivers2[i][j].get(), Args...));
}
}
for (auto &i : futures) {
i.get();
}
}
// for all , but dont complain if receiver2 doesnt exist
template <typename RT, typename... CT>
sls::Result<RT> Parallel3(RT (sls::Receiver::*somefunc)(CT...),
typename NonDeduced<CT>::type... Args) {
if (receivers.size() == 0)
throw sls::RuntimeError("No receivers added");
std::vector<int> dPositions;
dPositions.resize(receivers.size());
std::iota(begin(dPositions), end(dPositions), 0);
std::vector<int> rxPositions;
rxPositions.resize(receivers[0].size());
std::iota(begin(rxPositions), end(rxPositions), 0);
// multiply by 2 if receivers2 exists
size_t futureSize = dPositions.size() * rxPositions.size() *
(receivers2.size() > 0 ? 2 : 1);
std::vector<std::future<RT>> futures;
futures.reserve(futureSize);
for (size_t i : dPositions) {
// each entry
for (size_t j : rxPositions) {
futures.push_back(std::async(std::launch::async, somefunc,
receivers[i][j].get(), Args...));
if (receivers2.size()) {
futures.push_back(std::async(std::launch::async, somefunc,
receivers2[i][j].get(), Args...));
}
}
}
sls::Result<RT> result;
result.reserve(futureSize);
for (auto &i : futures) {
result.push_back(i.get());
}
return result;
}
template <typename RT, typename... CT>
sls::Result<RT> Parallel3(RT (sls::Receiver::*somefunc)(CT...) const,
typename NonDeduced<CT>::type... Args) const {
if (receivers.size() == 0)
throw sls::RuntimeError("No receivers added");
std::vector<int> dPositions;
dPositions.resize(receivers.size());
std::iota(begin(dPositions), end(dPositions), 0);
std::vector<int> rxPositions;
rxPositions.resize(receivers[0].size());
std::iota(begin(rxPositions), end(rxPositions), 0);
// multiply by 2 if receivers2 exists
size_t futureSize = dPositions.size() * rxPositions.size() *
(receivers2.size() > 0 ? 2 : 1);
std::vector<std::future<RT>> futures;
futures.reserve(futureSize);
for (size_t i : dPositions) {
// each entry
for (size_t j : rxPositions) {
futures.push_back(std::async(std::launch::async, somefunc,
receivers[i][j].get(), Args...));
if (receivers2.size()) {
futures.push_back(std::async(std::launch::async, somefunc,
receivers2[i][j].get(), Args...));
}
}
}
sls::Result<RT> result;
result.reserve(futureSize);
for (auto &i : futures) {
result.push_back(i.get());
}
return result;
}
template <typename... CT>
void Parallel3(void (sls::Receiver::*somefunc)(CT...),
typename NonDeduced<CT>::type... Args) {
if (receivers.size() == 0)
throw sls::RuntimeError("No receivers added");
std::vector<int> dPositions;
dPositions.resize(receivers.size());
std::iota(begin(dPositions), end(dPositions), 0);
std::vector<int> rxPositions;
rxPositions.resize(receivers[0].size());
std::iota(begin(rxPositions), end(rxPositions), 0);
// multiply by 2 if receivers2 exists
size_t futureSize = dPositions.size() * rxPositions.size() *
(receivers2.size() > 0 ? 2 : 1);
std::vector<std::future<void>> futures;
futures.reserve(futureSize);
for (size_t i : dPositions) {
// each entry
for (size_t j : rxPositions) {
futures.push_back(std::async(std::launch::async, somefunc,
receivers[i][j].get(), Args...));
if (receivers2.size()) {
futures.push_back(std::async(std::launch::async, somefunc,
receivers2[i][j].get(), Args...));
}
}
}
for (auto &i : futures) {
i.get();
}
}
template <typename... CT>
void Parallel3(void (sls::Receiver::*somefunc)(CT...) const,
typename NonDeduced<CT>::type... Args) const {
if (receivers.size() == 0)
throw sls::RuntimeError("No receivers added");
std::vector<int> dPositions;
dPositions.resize(receivers.size());
std::iota(begin(dPositions), end(dPositions), 0);
std::vector<int> rxPositions;
rxPositions.resize(receivers[0].size());
std::iota(begin(rxPositions), end(rxPositions), 0);
// multiply by 2 if receivers2 exists
size_t futureSize = dPositions.size() * rxPositions.size() *
(receivers2.size() > 0 ? 2 : 1);
std::vector<std::future<void>> futures;
futures.reserve(futureSize);
for (size_t i : dPositions) {
// each entry
for (size_t j : rxPositions) {
futures.push_back(std::async(std::launch::async, somefunc,
receivers[i][j].get(), Args...));
if (receivers2.size()) {
futures.push_back(std::async(std::launch::async, somefunc,
receivers2[i][j].get(), Args...));
}
}
}
for (auto &i : futures) {
i.get();
}
}
/** set acquiring flag in shared memory */
void setAcquiringFlag(bool flag);
/** return multi detector shared memory ID */
int getMultiId() const;
/** return detector shared memory ID */
int getDetectorId() const;
/** Free specific shared memory from the command line without creating object */
static void freeSharedMemory(int multiId, int detPos = -1);
static void freeSharedMemory(int detectorId, int moduleId = -1);
/** Free all modules from current multi Id shared memory and delete members */
void freeSharedMemory();
@ -217,8 +663,18 @@ class DetectorImpl : public virtual slsDetectorDefs {
*/
void setVirtualDetectorServers(const int numdet, const int port);
/** Sets the hostname of all sls detectors in shared memory and updates local cache */
void setHostname(const std::vector<std::string> &name);
void setHostname(const std::vector<std::string> &name,
const std::vector<int> &port);
int getNumberofReceiversPerModule() const;
void initReceiver(const int udpInterface);
bool isReceiverInitialized(const int udpInterface);
void removeReceivers(const int udpInterface);
void configureReceiver(const int udpInterface, Positions pos,
const std::string &hostname);
void configureReceiver(const int udpInterface, int module_id,
const std::string &hostname, const int port);
/** Gets the total number of detectors */
int size() const;
@ -236,13 +692,6 @@ class DetectorImpl : public virtual slsDetectorDefs {
/** [Eiger][Jungfrau] */
void setGapPixelsinCallback(const bool enable);
/**
* Enable data streaming to client
* @param enable 0 to disable, 1 to enable, -1 to get the value
* @returns data streaming to client enable
*/
bool enableDataStreamingToClient(int enable = -1);
/**
* register callback for accessing acquisition final data
* @param func function to be called at the end of the acquisition.
@ -298,7 +747,7 @@ class DetectorImpl : public virtual slsDetectorDefs {
* one
* @param update true to update last user pid, date etc
*/
void setupMultiDetector(bool verify = true, bool update = true);
void setupDetector(bool verify = true, bool update = true);
/**
* Creates shm and initializes shm structure OR
@ -324,17 +773,10 @@ class DetectorImpl : public virtual slsDetectorDefs {
/** Execute command in terminal and return result */
std::string exec(const char *cmd);
void addSlsDetector(const std::string &hostname);
void addModule(const std::string &hostname, const int port);
void updateDetectorSize();
/**
* Create Receiving Data Sockets
* @param destroy is true to destroy all the sockets
* @returns OK or FAIL
*/
int createReceivingDataSockets(const bool destroy = false);
/**
* Reads frames from receiver through a constant socket
* Called during acquire() when call back registered or when using gui
@ -377,19 +819,18 @@ class DetectorImpl : public virtual slsDetectorDefs {
int kbhit();
/** Multi detector Id */
const int multiId{0};
const int detectorId{0};
/** Shared Memory object */
sls::SharedMemory<sharedMultiSlsDetector> multi_shm{0, -1};
sls::SharedMemory<sharedDetector> detector_shm{0, -1};
/** pointers to the Module structures */
std::vector<std::unique_ptr<sls::Module>> detectors;
/** data streaming (down stream) enabled in client (zmq sckets created) */
bool client_downstream{false};
/** ZMQ Socket - Receiver to Client */
std::vector<std::unique_ptr<ZmqSocket>> zmqSocket;
/** pointers to the Receiver structures, each row for a module */
std::vector<std::vector<std::unique_ptr<sls::Receiver>>> receivers;
/** for the second udp port [Eiger][Jungfrau] */
std::vector<std::vector<std::unique_ptr<sls::Receiver>>> receivers2;
/** semaphore to let postprocessing thread continue for next
* scan/measurement */

File diff suppressed because it is too large Load Diff

View File

@ -13,8 +13,9 @@
class ServerInterface;
#define SLS_SHMAPIVERSION 0x190726
#define SLS_SHMVERSION 0x200402
#define MODULE_SHMRXVERSION 0x200415
#define MODULE_SHMAPIVERSION 0x190726
#define MODULE_SHMVERSION 0x200423
namespace sls{
@ -22,7 +23,7 @@ namespace sls{
* @short structure allocated in shared memory to store detector settings for
* IPC and cache
*/
struct sharedSlsDetector {
struct sharedModule {
/* FIXED PATTERN FOR STATIC FUNCTIONS. DO NOT CHANGE, ONLY APPEND ------*/
@ -36,10 +37,13 @@ struct sharedSlsDetector {
/** detector type \ see :: detectorType*/
slsDetectorDefs::detectorType myDetectorType;
int numberOfReceivers;
int numberOfReceivers2;
/** END OF FIXED PATTERN -----------------------------------------------*/
/** Number of detectors in multi list in x dir and y dir */
slsDetectorDefs::xy multiSize;
slsDetectorDefs::xy detectorSize;
/** is the port used for control functions */
int controlPort;
@ -62,27 +66,8 @@ struct sharedSlsDetector {
/** number of dacs per module*/
int nDacs;
/** ip address/hostname of the receiver for client control via TCP */
char rxHostname[MAX_STR_LENGTH];
/** is the TCP port used to communicate between client and the receiver */
int rxTCPPort;
/** is set if the receiver hostname given and is connected,
* unset if socket connection is not possible */
bool useReceiverFlag;
/** tcp port from gui/different process to receiver (only data) */
int zmqport;
/** zmq tcp src ip address in client (only data) **/
sls::IpAddr zmqip;
/** num udp interfaces */
int numUDPInterfaces;
/** stopped flag to inform rxr */
bool stoppedFlag;
};
class Module : public virtual slsDetectorDefs {
@ -90,22 +75,22 @@ class Module : public virtual slsDetectorDefs {
/**
* Constructor called when creating new shared memory
* @param type detector type
* @param multi_id multi detector shared memory id
* @param id sls detector id (position in detectors list)
* @param detector_id multi detector shared memory id
* @param module_id module id (position in detectors list)
* @param verify true to verify if shared memory version matches existing
* one
*/
explicit Module(detectorType type, int multi_id = 0, int det_id = 0,
explicit Module(detectorType type, int detector_id = 0, int module_id = 0,
bool verify = true);
/**
* Constructor called when opening existing shared memory
* @param multi_id multi detector shared memory id
* @param id sls detector id (position in detectors list)
* @param detector_id multi detector shared memory id
* @param module_id module id (position in detectors list)
* @param verify true to verify if shared memory version matches existing
* one
*/
explicit Module(int multi_id = 0, int det_id = 0, bool verify = true);
explicit Module(int detector_id = 0, int module_id = 0, bool verify = true);
/**
* Destructor
@ -118,11 +103,13 @@ class Module : public virtual slsDetectorDefs {
*/
bool isFixedPatternSharedMemoryCompatible();
/**
* Check version compatibility with receiver software
*/
void checkReceiverVersionCompatibility();
static bool hasSharedMemoryReceiverList(int version);
int getNumberOfReceivers() const;
void setNumberOfReceivers(const int num);
int getNumberOfReceivers2() const;
void setNumberOfReceivers2(const int num);
/**
* Check version compatibility with detector software
*/
@ -134,14 +121,9 @@ class Module : public virtual slsDetectorDefs {
int64_t getSerialNumber();
/**
* Get Receiver Software version
*/
int64_t getReceiverSoftwareVersion() const;
/**
* Free shared memory and delete shared memory structure
* occupied by the sharedSlsDetector structure
* occupied by the sharedModule structure
* Is only safe to call if one deletes the Module object afterward
* and frees multi shared memory/updates
* thisMultiDetector->numberOfDetectors
@ -176,13 +158,6 @@ class Module : public virtual slsDetectorDefs {
*/
detectorType getDetectorType() const;
/**
* Gets detector type from detector and set it in receiver
* @param type the detector type
* @returns detector type in receiver
*/
int setDetectorType(detectorType type = GET_DETECTOR_TYPE);
/**
* Update total number of channels (chiptestboard or moench)
* from the detector server
@ -220,12 +195,12 @@ class Module : public virtual slsDetectorDefs {
* Set Detector offset in shared memory in dimension d
* @param det detector size
*/
void updateMultiSize(slsDetectorDefs::xy det);
void updateDetectorSize(slsDetectorDefs::xy det);
int setControlPort(int port_number);
/**
* Returns the detector TCP control port \sa sharedSlsDetector
* Returns the detector TCP control port
* @returns the detector TCP control port
*/
int getControlPort() const;
@ -233,19 +208,11 @@ class Module : public virtual slsDetectorDefs {
int setStopPort(int port_number);
/**
* Returns the detector TCP stop port \sa sharedSlsDetector
* Returns the detector TCP stop port
* @returns the detector TCP stop port
*/
int getStopPort() const;
int setReceiverPort(int port_number);
/**
* Returns the receiver TCP port \sa sharedSlsDetector
* @returns the receiver TCP port
*/
int getReceiverPort() const;
/**
* Lock server for this client IP
* @param p 0 to unlock, 1 to lock (-1 gets)
@ -313,13 +280,13 @@ class Module : public virtual slsDetectorDefs {
int tb = 1);
/**
* Returns the detector trimbit/settings directory \sa sharedSlsDetector
* Returns the detector trimbit/settings directory
* @returns the trimbit/settings directory
*/
std::string getSettingsDir();
/**
* Sets the detector trimbit/settings directory \sa sharedSlsDetector
* Sets the detector trimbit/settings directory
* @param s trimbits/settings directory
* @returns the trimbit/settings directory
*/
@ -641,22 +608,9 @@ class Module : public virtual slsDetectorDefs {
*/
uint32_t clearBit(uint32_t addr, int n);
/**
* Validates and sets the receiver.
* Also updates the receiver with all the shared memory parameters
* significant for the receiver Also configures the detector to the receiver
* as UDP destination
* @param receiver receiver hostname or IP address
* @returns the receiver IP address from shared memory
*/
std::string setReceiverHostname(const std::string &receiver);
/**
* Returns the receiver IP address\sa sharedSlsDetector
* @returns the receiver IP address
*/
std::string getReceiverHostname() const;
/** gets receiver parameters from detector and shared memory */
rxParameters getReceiverParameters();
/**
* Validates the format of the detector MAC address and sets it
* @param mac detector MAC address
@ -721,13 +675,6 @@ class Module : public virtual slsDetectorDefs {
*/
sls::IpAddr getDestinationUDPIP();
/**
* Gets destination udp ip from detector,
* if 0, it converts rx_hostname to ip and
* updates both detector and receiver
*/
void updateRxDestinationUDPIP();
/**
* Validates the format of the receiver UDP IP address (bottom half) and
* sets it(Jungfrau only)
@ -743,13 +690,6 @@ class Module : public virtual slsDetectorDefs {
*/
sls::IpAddr getDestinationUDPIP2();
/**
* Gets destination udp ip2 from detector,
* if 0, it converts rx_hostname to ip and
* updates both detector and receiver
*/
void updateRxDestinationUDPIP2();
/**
* Validates the format of the receiver UDP MAC address and sets it
* @param mac receiver UDP MAC address
@ -776,26 +716,26 @@ class Module : public virtual slsDetectorDefs {
sls::MacAddr getDestinationUDPMAC2();
/**
* Sets the receiver UDP port\sa sharedSlsDetector
* Sets the receiver UDP port
* @param udpport receiver UDP port
*/
void setDestinationUDPPort(int udpport);
/**
* Returns the receiver UDP port\sa sharedSlsDetector
* Returns the receiver UDP port
* @returns the receiver UDP port
*/
int getDestinationUDPPort();
/**
* Sets the receiver UDP port 2\sa sharedSlsDetector (Eiger and Jungfrau
* Sets the receiver UDP port 2 (Eiger and Jungfrau
* only)
* @param udpport receiver UDP port 2
*/
void setDestinationUDPPort2(int udpport);
/**
* Returns the receiver UDP port 2 of same interface\sa sharedSlsDetector
* Returns the receiver UDP port 2 of same interface
* (Eiger and Jungfrau only)
* @returns the receiver UDP port 2 of same interface
*/
@ -834,53 +774,7 @@ class Module : public virtual slsDetectorDefs {
*/
int getSelectedUDPInterface();
/**
* Sets the client zmq port\sa sharedSlsDetector
* @param port client zmq port
*/
void setClientStreamingPort(int port);
/**
* Returns the client zmq port \sa sharedSlsDetector
* @returns the client zmq port
*/
int getClientStreamingPort();
/**
* Sets the receiver zmq port\sa sharedSlsDetector
* @param port receiver zmq port
*/
void setReceiverStreamingPort(int port);
/**
* Returns the receiver zmq port \sa sharedSlsDetector
* @returns the receiver zmq port
*/
int getReceiverStreamingPort();
/**
* Sets the client zmq ip\sa sharedSlsDetector
* @param ip client zmq ip
*/
void setClientStreamingIP(const sls::IpAddr ip);
/**
* Returns the client zmq ip \sa sharedSlsDetector
* @returns the client zmq ip
*/
sls::IpAddr getClientStreamingIP();
/**
* Sets the receiver zmq ip\sa sharedSlsDetector
* @param ip receiver zmq ip
*/
void setReceiverStreamingIP(const sls::IpAddr ip);
/**
* Returns the receiver zmq ip \sa sharedSlsDetector
* @returns the receiver zmq ip
*/
sls::IpAddr getReceiverStreamingIP();
std::string printUDPConfiguration();
/** update receiver stremaing ip from shm to receiver
* if empty, use rx_hostname ip
@ -924,35 +818,6 @@ class Module : public virtual slsDetectorDefs {
*/
void setTransmissionDelayRight(int value);
/** empty vector deletes entire additional json header */
void setAdditionalJsonHeader(const std::map<std::string, std::string> &jsonHeader);
std::map<std::string, std::string> getAdditionalJsonHeader();
/**
* Sets the value for the additional json header parameter key if found, else
* append it. If value empty, then deletes parameter */
void setAdditionalJsonParameter(const std::string &key, const std::string &value);
std::string getAdditionalJsonParameter(const std::string &key);
/**
* Sets the receiver UDP socket buffer size
* @param udpsockbufsize additional json header
* @returns receiver udp socket buffer size
*/
int64_t setReceiverUDPSocketBufferSize(int64_t udpsockbufsize = -1);
/**
* Returns the receiver UDP socket buffer size\sa sharedSlsDetector
* @returns the receiver UDP socket buffer size
*/
int64_t getReceiverUDPSocketBufferSize();
/**
* Returns the receiver real UDP socket buffer size\sa sharedSlsDetector
* @returns the receiver real UDP socket buffer size
*/
int64_t getReceiverRealUDPSocketBufferSize() const;
/** [Gotthard][Jungfrau][CTB][Moench] */
void executeFirmwareTest();
@ -1030,28 +895,10 @@ class Module : public virtual slsDetectorDefs {
*/
slsDetectorDefs::ROI getROI();
/**
* Set ADC Enable Mask (CTB, Moench)
* @param mask ADC Enable mask
*/
void setADCEnableMask(uint32_t mask);
/**
* Get ADC Enable Mask (CTB, Moench)
* @returns ADC Enable mask
*/
uint32_t getADCEnableMask();
/**
* Set 10Gb ADC Enable Mask (CTB, Moench)
* @param mask ADC Enable mask
*/
void setTenGigaADCEnableMask(uint32_t mask);
/**
* Get 10Gb ADC Enable Mask (CTB, Moench)
* @returns ADC Enable mask
*/
uint32_t getTenGigaADCEnableMask();
/**
@ -1098,14 +945,6 @@ class Module : public virtual slsDetectorDefs {
*/
int getExternalSampling();
/** digital data bits enable (CTB only) */
void setReceiverDbitList(const std::vector<int>& list);
std::vector<int> getReceiverDbitList() const;
/** Set digital data offset in bytes (CTB only) */
void setReceiverDbitOffset(int value);
int getReceiverDbitOffset();
/**
* Write to ADC register (Gotthard, Jungfrau, ChipTestBoard). For expert
* users
@ -1114,32 +953,10 @@ class Module : public virtual slsDetectorDefs {
*/
void writeAdcRegister(uint32_t addr, uint32_t val);
/**
* Activates/Deactivates the detector (Eiger only)
* @param enable active (1) or inactive (0), -1 gets
* @returns 0 (inactive) or 1 (active)for activate mode
*/
int activate(int const enable = -1);
bool getDeactivatedRxrPaddingMode();
/**
* Set deactivated Receiver padding mode (Eiger only)
*/
void setDeactivatedRxrPaddingMode(bool padding);
/**
* Returns the enable if data will be flipped across x axis (Eiger)
* @returns if flipped across x axis
*/
bool getFlippedDataX();
/**
* Sets the enable which determines if
* data will be flipped across x axis (Eiger)
* @param value 0 or 1 to reset/set
*/
void setFlippedDataX(bool value);
/** [Eiger] */
bool getActivate();
/** [Eiger] */
void setActivate(const bool enable);
/**
* Sets all the trimbits to a particular value (Eiger)
@ -1150,7 +967,6 @@ class Module : public virtual slsDetectorDefs {
/**
* Sets the number of trim energies and their value (Eiger)
* \sa sharedSlsDetector
* @param nen number of energies
* @param vector os trimmed energies
* @returns number of trim energies
@ -1159,7 +975,6 @@ class Module : public virtual slsDetectorDefs {
/**
* Returns a vector with the trimmed energies (Eiger)
* \sa sharedSlsDetector
* @returns vector with the trimmed energies
*/
std::vector<int> getTrimEn();
@ -1308,169 +1123,8 @@ class Module : public virtual slsDetectorDefs {
*/
void updateRateCorrection();
/**
* Prints receiver configuration
* @returns receiver configuration
*/
std::string printReceiverConfiguration();
/**
* Gets the use receiver flag from shared memory
*/
bool getUseReceiverFlag() const;
/**
* Locks/Unlocks the connection to the receiver
* @param lock sets (1), usets (0), gets (-1) the lock
* @returns lock status of the receiver
*/
int lockReceiver(int lock = -1);
/**
* Returns the IP of the last client connecting to the receiver
* @returns the IP of the last client connecting to the receiver
*/
sls::IpAddr getReceiverLastClientIP() const;
/**
* Exits the receiver TCP server
*/
void exitReceiver();
/**
* Executes a system command on the receiver server
* e.g. mount an nfs disk, reboot and returns answer etc.
* @param cmd command to be executed
*/
void execReceiverCommand(const std::string &cmd);
/**
* Send the multi detector size to the detector
* @param detx number of detectors in x dir
* @param dety number of detectors in y dir
*/
void sendMultiDetectorSize();
/**
* Send the detector pos id to the receiver
* for various file naming conventions for multi detectors in receiver
*/
void setDetectorId();
/**
* Send the detector host name to the receiver
* for various handshaking required with the detector
*/
void setDetectorHostname();
std::string getFilePath();
void setFilePath(const std::string &path);
std::string getFileName();
void setFileName(const std::string &fname);
int64_t getFileIndex();
void setFileIndex(int64_t file_index);
void incrementFileIndex();
fileFormat getFileFormat() ;
void setFileFormat(fileFormat f);
int getFramesPerFile();
/** 0 will set frames per file to unlimited */
void setFramesPerFile(int n_frames);
frameDiscardPolicy getReceiverFramesDiscardPolicy();
void setReceiverFramesDiscardPolicy(frameDiscardPolicy f);
bool getPartialFramesPadding();
void setPartialFramesPadding(bool padding);
/**
* Receiver starts listening to packets
*/
void startReceiver();
/**
* Stops the listening mode of receiver
*/
void stopReceiver();
/**
* Gets the status of the listening mode of receiver
* @returns status
*/
runStatus getReceiverStatus() const;
/**
* Gets the number of frames caught by receiver
* @returns number of frames caught by receiver
*/
int64_t getFramesCaughtByReceiver() const;
/** Gets number of missing packets */
std::vector<uint64_t> getNumMissingPackets() const;
/**
* Gets the current frame index of receiver
* @returns current frame index of receiver
*/
uint64_t getReceiverCurrentFrameIndex() const;
int getReceiverProgress() const;
void setFileWrite(bool value);
bool getFileWrite();
void setMasterFileWrite(bool value);
bool getMasterFileWrite();
void setFileOverWrite(bool value);
bool getFileOverWrite();
int getReceiverStreamingFrequency();
/**
* (previously setReadReceiverFrequency)
* Sets the receiver streaming frequency
* @param freq nth frame streamed out, if 0, streamed out at a timer of 200
* ms
* @param detPos -1 for all detectors in list or specific detector position
*/
void setReceiverStreamingFrequency(int freq);
/**
* (previously setReceiverReadTimer)
* Sets the receiver streaming timer
* If receiver streaming frequency is 0, then this timer between each
* data stream is set. Default is 200 ms.
* @param time_in_ms timer between frames
* @returns receiver streaming timer in ms
*/
int setReceiverStreamingTimer(int time_in_ms = 200);
bool getReceiverStreaming();
void setReceiverStreaming(bool enable);
/**
* Enable/disable or 10Gbe
* @param i is -1 to get, 0 to disable and 1 to enable
* @returns if 10Gbe is enabled
*/
bool enableTenGigabitEthernet(int value = -1);
/**
* Set/get receiver fifo depth
* @param i is -1 to get, any other value to set the fifo deph
* @returns the receiver fifo depth
*/
int setReceiverFifoDepth(int n_frames = -1);
bool getReceiverSilentMode();
void setReceiverSilentMode(bool enable);
/**
* If data streaming in receiver is enabled,
* restream the stop dummy packet from receiver
* Used usually for Moench,
* in case it is lost in network due to high data rate
*/
void restreamStopFromReceiver();
bool getTenGiga();
void setTenGiga(bool value);
/**
* Opens pattern file and sends pattern to CTB
@ -1606,9 +1260,6 @@ class Module : public virtual slsDetectorDefs {
/** [Mythen3] */
void setCounterMask(uint32_t countermask);
/** [Mythen3] */
void sendNumberofCounterstoReceiver(uint32_t countermask);
/** [Mythen3] */
uint32_t getCounterMask();
@ -1674,67 +1325,23 @@ class Module : public virtual slsDetectorDefs {
void sendToDetectorStop(int fnum) const;
/**
* Send function parameters to receiver
* @param fnum function enum
* @param args argument pointer
* @param args_size size of argument
* @param retval return pointers
* @param retval_size size of return value
*/
void sendToReceiver(int fnum, const void *args, size_t args_size,
void *retval, size_t retval_size);
void sendToReceiver(int fnum, const void *args, size_t args_size,
void *retval, size_t retval_size) const;
template <typename Arg, typename Ret>
void sendToReceiver(int fnum, const Arg &args, Ret &retval);
template <typename Arg, typename Ret>
void sendToReceiver(int fnum, const Arg &args, Ret &retval) const;
template <typename Arg>
void sendToReceiver(int fnum, const Arg &args, std::nullptr_t);
template <typename Arg>
void sendToReceiver(int fnum, const Arg &args, std::nullptr_t) const;
template <typename Ret>
void sendToReceiver(int fnum, std::nullptr_t, Ret &retval);
template <typename Ret>
void sendToReceiver(int fnum, std::nullptr_t, Ret &retval) const;
template <typename Ret>
Ret sendToReceiver(int fnum);
template <typename Ret>
Ret sendToReceiver(int fnum) const;
template <typename Ret, typename Arg>
Ret sendToReceiver(int fnum, const Arg &args);
template <typename Ret, typename Arg>
Ret sendToReceiver(int fnum, const Arg &args) const;
/**
* Get Detector Type from Shared Memory (opening shm without verifying size)
* @param multi_id multi detector Id
* @param detector_id multi detector Id
* @param verify true to verify if shm size matches existing one
* @returns detector type
*/
detectorType getDetectorTypeFromShm(int multi_id, bool verify = true);
detectorType getDetectorTypeFromShm(int detector_id, bool verify = true);
/**
* Initialize shared memory
* @param created true if shared memory must be created, else false to open
* @param type type of detector
* @param multi_id multi detector Id
* @param detector_id multi detector Id
* @param verify true to verify if shm size matches existing one
* @returns true if the shared memory was created now
*/
void initSharedMemory(detectorType type, int multi_id, bool verify = true);
void initSharedMemory(detectorType type, int detector_id, bool verify = true);
/**
* Initialize detector structure to defaults
@ -1817,10 +1424,10 @@ class Module : public virtual slsDetectorDefs {
std::vector<std::string> getSettingsFileDacNames();
/** Module Id or position in the detectors list */
const int detId;
const int moduleId;
/** Shared Memory object */
mutable sls::SharedMemory<sharedSlsDetector> shm{0, 0};
mutable sls::SharedMemory<sharedModule> shm{0, 0};
};
}// sls

View File

@ -0,0 +1,918 @@
#include "Receiver.h"
#include "ClientSocket.h"
#include "ZmqSocket.h"
#include "FixedCapacityContainer.h"
#include "string_utils.h"
#include "versionAPI.h"
#include "ToString.h"
#include "container_utils.h"
namespace sls {
// create shm
Receiver::Receiver(int detector_id, int module_id, int interface_id,
int receiver_id, int tcp_port, std::string hostname,
int zmq_port) :
receiverId(receiver_id), interfaceId(interface_id), moduleId(module_id),
shm(detector_id, module_id, interface_id, receiver_id) {
createIndexString();
// ensure shared memory was not created before
if (shm.IsExisting()) {
LOG(logWARNING) << "This shared memory should have been deleted "
"before! " << shm.GetName() << ". Freeing it again";
shm.RemoveSharedMemory();
}
shm = SharedMemory<sharedReceiver>(detector_id, module_id, interface_id,
receiver_id);
shm.CreateSharedMemory();
// initalize receiver structure
shm()->shmversion = RECEIVER_SHMVERSION;
memset(shm()->hostname, 0, MAX_STR_LENGTH);
shm()->tcpPort = DEFAULT_RX_PORTNO + receiver_id;
shm()-> stoppedFlag = false;
shm()->zmqPort = DEFAULT_ZMQ_RX_PORTNO + receiver_id;
shm()->zmqIp = IpAddr{};
// copy port, hostname if given
if (tcp_port != 0) {
setTCPPort(tcp_port);
}
if (zmq_port != 0) {
shm()->zmqPort = zmq_port;
}
if (!hostname.empty()) {
setHostname(hostname);
}
}
// open shm
Receiver::Receiver(int detector_id, int module_id, int interface_id,
int receiver_id, bool verify) :
receiverId(receiver_id), interfaceId(interface_id), moduleId(module_id),
shm(detector_id, module_id, interface_id, receiver_id) {
createIndexString();
shm.OpenSharedMemory();
if (verify && shm()->shmversion != RECEIVER_SHMVERSION) {
std::ostringstream ss;
ss << "Receiver shared memory (" << detector_id << "-" << indexString
<< ":" << receiverId << ") version mismatch (expected 0x" << std::hex
<< RECEIVER_SHMVERSION << " but got 0x" << shm()->shmversion << ")"
<< std::dec << ". Clear Shared memory to continue.";
throw SharedMemoryError(ss.str());
}
}
Receiver::~Receiver() = default;
void Receiver::createIndexString() {
std::ostringstream oss;
oss << '(' << moduleId << (char)(interfaceId + 97) << "." << receiverId << ')';
indexString = oss.str();
}
/** Configuration */
void Receiver::freeSharedMemory() {
if (shm.IsExisting()) {
shm.RemoveSharedMemory();
}
}
std::string Receiver::getHostname() const {
return shm()->hostname;
}
void Receiver::setHostname(const std::string &hostname) {
if (hostname.empty()) {
throw RuntimeError("Invalid receiver hostname. Cannot be empty.");
}
sls::strcpy_safe(shm()->hostname, hostname.c_str());
checkVersionCompatibility();
}
int Receiver::getTCPPort() const {
return shm()->tcpPort;
}
void Receiver::setTCPPort(const int port) {
LOG(logDEBUG1) << "Setting reciever port to " << port;
if (port >= 0 && port != shm()->tcpPort) {
if (strlen(shm()->hostname) != 0) {
int retval = -1;
sendToReceiver(F_SET_RECEIVER_PORT, port, retval);
shm()->tcpPort = retval;
LOG(logDEBUG1) << "Receiver port: " << retval;
} else {
shm()->tcpPort = port;
}
}
}
void Receiver::checkVersionCompatibility() {
int64_t arg = APIRECEIVER;
LOG(logDEBUG1)
<< "Checking version compatibility with receiver with value "
<< std::hex << arg << std::dec;
sendToReceiver(F_RECEIVER_CHECK_VERSION, arg, nullptr);
}
sls::MacAddr Receiver::configure(slsDetectorDefs::rxParameters arg) {
// hostname
memset(arg.hostname, 0, sizeof(arg.hostname));
strcpy_safe(arg.hostname, shm()->hostname);
// interface id
arg.interfaceId = interfaceId;
// zmqip
{
sls::IpAddr ip;
// Hostname could be ip try to decode otherwise look up the hostname
ip = sls::IpAddr{shm()->hostname};
if (ip == 0) {
ip = HostnameToIp(shm()->hostname);
}
LOG(logINFO) << "Setting default receiver " << indexString
<< " streaming zmq ip to " << ip;
// if client zmqip is empty, update it
if (shm()->zmqIp == 0) {
shm()->zmqIp = ip;
}
memcpy(&arg.zmq_ip, &ip, sizeof(ip));
}
if (arg.detType == EIGER) {
arg.udpInterfaces = 2;
}
LOG(logDEBUG)
<< "detType:" << arg.detType << std::endl
<< "detectorSize.x:" << arg.detectorSize.x << std::endl
<< "detectorSize.y:" << arg.detectorSize.y << std::endl
<< "moduleId:" << arg.moduleId << std::endl
<< "hostname:" << arg.hostname << std::endl
<< "interfaceId: " << arg.interfaceId << std::endl
<< "zmq ip:" << arg.zmq_ip << std::endl
<< "udpInterfaces:" << arg.udpInterfaces << std::endl
<< "udp_dstport:" << arg.udp_dstport << std::endl
<< "udp_dstip:" << sls::IpAddr(arg.udp_dstip) << std::endl
<< "udp_dstmac:" << sls::MacAddr(arg.udp_dstmac) << std::endl
<< "udp_dstport2:" << arg.udp_dstport2 << std::endl
<< "udp_dstip2:" << sls::IpAddr(arg.udp_dstip2) << std::endl
<< "udp_dstmac2:" << sls::MacAddr(arg.udp_dstmac2) << std::endl
<< "frames:" << arg.frames << std::endl
<< "triggers:" << arg.triggers << std::endl
<< "bursts:" << arg.bursts << std::endl
<< "analogSamples:" << arg.analogSamples << std::endl
<< "digitalSamples:" << arg.digitalSamples << std::endl
<< "expTimeNs:" << arg.expTimeNs << std::endl
<< "periodNs:" << arg.periodNs << std::endl
<< "subExpTimeNs:" << arg.subExpTimeNs << std::endl
<< "subDeadTimeNs:" << arg.subDeadTimeNs << std::endl
<< "activate:" << arg.activate << std::endl
<< "quad:" << arg.quad << std::endl
<< "dynamicRange:" << arg.dynamicRange << std::endl
<< "timMode:" << arg.timMode << std::endl
<< "tenGiga:" << arg.tenGiga << std::endl
<< "roMode:" << arg.roMode << std::endl
<< "adcMask:" << arg.adcMask << std::endl
<< "adc10gMask:" << arg.adc10gMask << std::endl
<< "roi.xmin:" << arg.roi.xmin << std::endl
<< "roi.xmax:" << arg.roi.xmax << std::endl
<< "countermask:" << arg.countermask << std::endl
<< "burstType:" << arg.burstType << std::endl;
sls::MacAddr mac;
{
sls::MacAddr retval;
sendToReceiver(F_SETUP_RECEIVER, arg, retval);
// detector does not have customized udp mac
if (arg.udp_dstmac == 0) {
mac = retval;
}
}
if (arg.detType == MOENCH) {
setAdditionalJsonParameter("adcmask_1g", std::to_string(arg.adcMask));
setAdditionalJsonParameter("adcmask_10g", std::to_string(arg.adc10gMask));
}
LOG(logINFOBLUE) << "reciever " << indexString << " configured!";
return mac;
}
std::string Receiver::printConfiguration() {
std::ostringstream oss;
oss << std::endl << std::endl
<< "Receiver " << indexString << std::endl
<< "Hostname : " << shm()->hostname << std::endl
<< "Tcp port : " << shm()->tcpPort << std::endl;
/*
os << "\nReceiver UDP IP:\t"
<< getDestinationUDPIP() << "\nReceiver UDP MAC:\t" << getDestinationUDPMAC();
if (shm()->myDetectorType == JUNGFRAU) {
os << "\nDetector UDP IP2:\t" << getSourceUDPIP2()
<< "\nDetector UDP MAC2:\t" << getSourceUDPMAC2()
<< "\nReceiver UDP IP2:\t" << getDestinationUDPIP2()
<< "\nReceiver UDP MAC2:\t" << getDestinationUDPMAC2();
}
os << "\nReceiver UDP Port:\t" << getDestinationUDPPort();
if (shm()->myDetectorType == JUNGFRAU || shm()->myDetectorType == EIGER) {
os << "\nReceiver UDP Port2:\t" << getDestinationUDPPort2();
}
*/
oss << "\n";
return oss.str();
}
int64_t Receiver::getSoftwareVersion() const {
LOG(logDEBUG1) << "Getting receiver software version";
return sendToReceiver<int64_t>(F_GET_RECEIVER_VERSION);
}
/** Acquisition */
void Receiver::start() {
LOG(logDEBUG1) << "Starting Receiver";
shm()->stoppedFlag = false;
sendToReceiver(F_START_RECEIVER, nullptr, nullptr);
}
void Receiver::stop() {
LOG(logDEBUG1) << "Stopping Receiver";
int arg = static_cast<int>(shm()->stoppedFlag);
sendToReceiver(F_STOP_RECEIVER, arg, nullptr);
}
slsDetectorDefs::runStatus Receiver::getStatus() const {
runStatus retval = ERROR;
LOG(logDEBUG1) << "Getting Receiver Status";
sendToReceiver(F_GET_RECEIVER_STATUS, nullptr, retval);
LOG(logDEBUG1) << "Receiver Status: " << ToString(retval);
return retval;
}
int Receiver::getProgress() const {
int retval = -1;
sendToReceiver(F_GET_RECEIVER_PROGRESS, nullptr, retval);
LOG(logDEBUG1) << "Current Progress of Receiver: " << retval;
return retval;
}
void Receiver::setStoppedFlag() {
shm()->stoppedFlag = true;
}
void Receiver::restreamStop() {
LOG(logDEBUG1) << "Restream stop dummy from Receiver via zmq";
sendToReceiver(F_RESTREAM_STOP_FROM_RECEIVER, nullptr, nullptr);
}
uint64_t Receiver::getFramesCaught() const {
return sendToReceiver<uint64_t>(F_GET_RECEIVER_FRAMES_CAUGHT);
}
uint64_t Receiver::getNumMissingPackets() const {
return sendToReceiver<uint64_t>(F_GET_NUM_MISSING_PACKETS);
}
uint64_t Receiver::getCurrentFrameIndex() const {
return sendToReceiver<uint64_t>(F_GET_RECEIVER_FRAME_INDEX);
}
/** Network Configuration (Detector<->Receiver) */
sls::MacAddr Receiver::setUDPIP(const IpAddr ip) {
LOG(logDEBUG1) << "Setting udp ip to receier: " << ip;
if (ip == 0) {
throw RuntimeError("Invalid destination udp ip address");
}
sls::MacAddr retval(0LU);
sendToReceiver(F_SET_RECEIVER_UDP_IP, ip, retval);
return retval;
}
void Receiver::setUDPPort(const int port) {
LOG(logDEBUG1) << "Setting udp port to receiver: " << port;
sendToReceiver(F_SET_RECEIVER_UDP_PORT, port, nullptr);
}
int64_t Receiver::getUDPSocketBufferSize() const {
return sendToReceiver<int64_t>(F_GET_RECEIVER_UDP_SOCK_BUF_SIZE);
}
void Receiver::setUDPSocketBufferSize(int64_t value) {
LOG(logDEBUG1) << "Sending UDP Socket Buffer size to receiver: "
<< value;
sendToReceiver(F_SET_RECEIVER_UDP_SOCK_BUF_SIZE, value, nullptr);
}
int64_t Receiver::getRealUDPSocketBufferSize() const {
return sendToReceiver<int64_t>(F_GET_RECEIVER_REAL_UDP_SOCK_BUF_SIZE);
}
/** ZMQ Streaming Parameters (Receiver<->Client) */
bool Receiver::getZmq() const {
return sendToReceiver<int>(F_GET_RECEIVER_STREAMING);
}
void Receiver::setZmq(const bool enable) {
int arg = static_cast<int>(enable);
sendToReceiver(F_SET_RECEIVER_STREAMING, arg, nullptr);
}
int Receiver::getZmqFrequency() const {
return sendToReceiver<int>(F_GET_RECEIVER_STREAMING_FREQUENCY);
}
void Receiver::setZmqFrequency(const int freq) {
if (freq < 0) {
throw RuntimeError("Invalid streaming frequency " + std::to_string(freq));
}
sendToReceiver(F_SET_RECEIVER_STREAMING_FREQUENCY, freq, nullptr);
}
int Receiver::getZmqTimer() const {
return sendToReceiver<int>(F_GET_RECEIVER_STREAMING_TIMER);
}
void Receiver::setZmqTimer(const int time_in_ms) {
sendToReceiver(F_SET_RECEIVER_STREAMING_TIMER, time_in_ms, nullptr);
}
int Receiver::getZmqPort() const {
return sendToReceiver<int>(F_GET_RECEIVER_STREAMING_PORT);
}
void Receiver::setZmqPort(int port) {
sendToReceiver(F_SET_RECEIVER_STREAMING_PORT, port, nullptr);
}
sls::IpAddr Receiver::getZmqIP() const {
return sendToReceiver<sls::IpAddr>(F_GET_RECEIVER_STREAMING_SRC_IP);
}
void Receiver::setZmqIP(const sls::IpAddr ip) {
if (ip == 0) {
throw RuntimeError("Invalid receiver zmq ip address");
}
// if client zmqip is empty, update it
if (shm()->zmqIp == 0) {
shm()->zmqIp = ip;
}
sendToReceiver(F_SET_RECEIVER_STREAMING_SRC_IP, ip, nullptr);
}
int Receiver::getClientZmqPort() const {
return shm()->zmqPort;
}
void Receiver::setClientZmqPort(const int port) {
shm()->zmqPort = port;
}
sls::IpAddr Receiver::getClientZmqIP() const {
return shm()->zmqIp;
}
void Receiver::setClientZmqIP(const sls::IpAddr ip) {
LOG(logDEBUG1) << "Setting client zmq ip to " << ip;
if (ip == 0) {
throw RuntimeError("Invalid client zmq ip address");
}
shm()->zmqIp = ip;
}
bool Receiver::getClientZmq() const {
return (zmqSocket != nullptr);
}
void Receiver::setClientZmq(const bool enable) {
// destroy
if (!enable) {
if (zmqSocket != nullptr) {
zmqSocket.reset();
}
}
// create
else {
if (zmqSocket == nullptr) {
try {
zmqSocket = sls::make_unique<ZmqSocket>(
shm()->zmqIp.str().c_str(), shm()->zmqPort);
LOG(logINFO) << "Zmq Client[" << indexString << "] at "
<< zmqSocket->GetZmqServerAddress();
} catch(...) {
throw RuntimeError(
"Could not create Zmq socket [" + indexString
+ " on port " + std::to_string(shm()->zmqPort));
}
}
}
}
ZmqSocket* Receiver::getZmqSocket() {
return zmqSocket.get();
}
/** Receiver Parameters */
bool Receiver::getLock() const {
return sendToReceiver<int>(F_GET_LOCK_RECEIVER);
}
void Receiver::setLock(const bool lock) {
LOG(logDEBUG1) << "Setting receiver server lock to " << lock;
sendToReceiver(F_SET_LOCK_RECEIVER, lock, nullptr);
}
sls::IpAddr Receiver::getLastClientIP() const {
return sendToReceiver<sls::IpAddr>(F_GET_LAST_RECEIVER_CLIENT_IP);
}
void Receiver::exitServer() {
LOG(logDEBUG1) << "Sending exit command to receiver server";
sendToReceiver(F_EXIT_RECEIVER, nullptr, nullptr);
}
bool Receiver::getDeactivatedPaddingMode() const {
return sendToReceiver<int>(F_GET_RECEIVER_DEACTIVATED_PADDING);
}
void Receiver::setDeactivatedPaddingMode(const bool padding) {
int arg = static_cast<int>(padding);
sendToReceiver(F_SET_RECEIVER_DEACTIVATED_PADDING, arg, nullptr);
}
bool Receiver::getFlippedDataX() const {
int arg = -1;
return sendToReceiver<int>(F_GET_FLIPPED_DATA_RECEIVER, arg);
}
void Receiver::setFlippedDataX(const bool value) {
int arg = static_cast<int>(value);
LOG(logDEBUG1) << "Setting flipped data across x axis with value: "
<< value;
sendToReceiver(F_SET_FLIPPED_DATA_RECEIVER, arg, nullptr);
}
slsDetectorDefs::frameDiscardPolicy Receiver::getFramesDiscardPolicy() const {
return static_cast<frameDiscardPolicy>(
sendToReceiver<int>(F_GET_RECEIVER_DISCARD_POLICY));
}
void Receiver::setFramesDiscardPolicy(const frameDiscardPolicy f) {
int arg = static_cast<int>(f);
sendToReceiver(F_SET_RECEIVER_DISCARD_POLICY, arg, nullptr);
}
bool Receiver::getPartialFramesPadding() const {
return sendToReceiver<int>(F_GET_RECEIVER_PADDING);
}
void Receiver::setPartialFramesPadding(const bool padding) {
int arg = static_cast<int>(padding);
sendToReceiver(F_SET_RECEIVER_PADDING, arg, nullptr);
}
int Receiver::getFifoDepth() const {
return sendToReceiver<int>(F_GET_RECEIVER_FIFO_DEPTH);
}
void Receiver::setFifoDepth(const int value) {
sendToReceiver(F_SET_RECEIVER_FIFO_DEPTH, value, nullptr);
}
bool Receiver::getSilentMode() const {
return sendToReceiver<int>(F_GET_RECEIVER_SILENT_MODE);
}
void Receiver::setSilentMode(const bool enable) {
int arg = static_cast<int>(enable);
sendToReceiver(F_SET_RECEIVER_SILENT_MODE, arg, nullptr);
}
/** File */
std::string Receiver::getFilePath() const {
char retvals[MAX_STR_LENGTH]{};
sendToReceiver(F_GET_RECEIVER_FILE_PATH, nullptr, retvals);
return std::string(retvals);
}
void Receiver::setFilePath(const std::string &path) {
if (path.empty()) {
throw RuntimeError("Cannot set empty file path");
}
char args[MAX_STR_LENGTH]{};
sls::strcpy_safe(args, path.c_str());
sendToReceiver(F_SET_RECEIVER_FILE_PATH, args, nullptr);
}
std::string Receiver::getFileName() const {
char retvals[MAX_STR_LENGTH]{};
sendToReceiver(F_GET_RECEIVER_FILE_NAME, nullptr, retvals);
return std::string(retvals);
}
void Receiver::setFileName(const std::string &fname) {
if (fname.empty()) {
throw RuntimeError("Cannot set empty file name prefix");
}
char args[MAX_STR_LENGTH]{};
sls::strcpy_safe(args, fname.c_str());
sendToReceiver(F_SET_RECEIVER_FILE_NAME, args, nullptr);
}
int64_t Receiver::getFileIndex() const {
return sendToReceiver<int64_t>(F_GET_RECEIVER_FILE_INDEX);
}
void Receiver::setFileIndex(const int64_t file_index) {
sendToReceiver(F_SET_RECEIVER_FILE_INDEX, file_index, nullptr);
}
void Receiver::incrementFileIndex() {
sendToReceiver(F_INCREMENT_FILE_INDEX, nullptr, nullptr);
}
slsDetectorDefs::fileFormat Receiver::getFileFormat() const {
return static_cast<fileFormat>(
sendToReceiver<int>(F_GET_RECEIVER_FILE_FORMAT));
}
void Receiver::setFileFormat(const fileFormat f) {
int arg = static_cast<int>(f);
sendToReceiver(F_SET_RECEIVER_FILE_FORMAT, arg, nullptr);
}
int Receiver::getFramesPerFile() const {
return sendToReceiver<int>(F_GET_RECEIVER_FRAMES_PER_FILE);
}
void Receiver::setFramesPerFile(const int n_frames) {
sendToReceiver(F_SET_RECEIVER_FRAMES_PER_FILE, n_frames, nullptr);
}
bool Receiver::getFileWrite() const {
return sendToReceiver<int>(F_GET_RECEIVER_FILE_WRITE);
}
void Receiver::setFileWrite(const bool value) {
int arg = static_cast<int>(value);
sendToReceiver(F_SET_RECEIVER_FILE_WRITE, arg, nullptr);
}
bool Receiver::getMasterFileWrite() const {
return sendToReceiver<int>(F_GET_RECEIVER_MASTER_FILE_WRITE);
}
void Receiver::setMasterFileWrite(const bool value) {
int arg = static_cast<int>(value);
sendToReceiver(F_SET_RECEIVER_MASTER_FILE_WRITE, arg, nullptr);
}
bool Receiver::getFileOverWrite() const {
return sendToReceiver<int>(F_GET_RECEIVER_OVERWRITE);
}
void Receiver::setFileOverWrite(const bool value) {
int arg = static_cast<int>(value);
sendToReceiver(F_SET_RECEIVER_OVERWRITE, arg, nullptr);
}
/** Detector Parameters */
void Receiver::setNumberOfFrames(const int64_t value) {
LOG(logDEBUG1) << "Sending number of frames to Receiver: " << value;
sendToReceiver(F_RECEIVER_SET_NUM_FRAMES, value, nullptr);
}
void Receiver::setNumberOfTriggers(const int64_t value) {
LOG(logDEBUG1) << "Sending number of triggers to Receiver: " << value;
sendToReceiver(F_SET_RECEIVER_NUM_TRIGGERS, value, nullptr);
}
void Receiver::setNumberOfBursts(const int64_t value) {
LOG(logDEBUG1) << "Sending number of bursts to Receiver: " << value;
sendToReceiver(F_SET_RECEIVER_NUM_BURSTS, value, nullptr);
}
void Receiver::setNumberOfAnalogSamples(const int value) {
LOG(logDEBUG1) << "Sending number of analog samples to Receiver: " << value;
sendToReceiver(F_RECEIVER_SET_NUM_ANALOG_SAMPLES, value, nullptr);
}
void Receiver::setNumberOfDigitalSamples(const int value) {
LOG(logDEBUG1) << "Sending number of digital samples to Receiver: " << value;
sendToReceiver(F_RECEIVER_SET_NUM_DIGITAL_SAMPLES, value, nullptr);
}
void Receiver::setExptime(const int64_t value) {
LOG(logDEBUG1) << "Sending exptime to Receiver: " << value;
sendToReceiver(F_RECEIVER_SET_EXPTIME, value, nullptr);
}
void Receiver::setPeriod(const int64_t value) {
LOG(logDEBUG1) << "Sending period to Receiver: " << value;
sendToReceiver(F_RECEIVER_SET_PERIOD, value, nullptr);
}
void Receiver::setSubExptime(const int64_t value) {
LOG(logDEBUG1) << "Sending sub exptime to Receiver: " << value;
sendToReceiver(F_RECEIVER_SET_SUB_EXPTIME, value, nullptr);
}
void Receiver::setSubDeadTime(const int64_t value) {
LOG(logDEBUG1) << "Sending sub deadtime to Receiver: " << value;
sendToReceiver(F_RECEIVER_SET_SUB_DEADTIME, value, nullptr);
}
void Receiver::setTimingMode(const timingMode value) {
LOG(logDEBUG1) << "Sending timing mode to Receiver: " << value;
sendToReceiver(F_SET_RECEIVER_TIMING_MODE, value, nullptr);
}
void Receiver::setDynamicRange(const int n) {
int retval = -1;
LOG(logDEBUG1) << "Sending dynamic range to receiver: " << n;
sendToReceiver(F_SET_RECEIVER_DYNAMIC_RANGE, n, retval);
}
void Receiver::setReadoutMode(const slsDetectorDefs::readoutMode mode) {
sendToReceiver(F_RECEIVER_SET_READOUT_MODE, mode, nullptr);
}
void Receiver::setQuad(const bool enable) {
int value = enable ? 1 : 0;
LOG(logDEBUG1) << "Setting Quad type to " << value << " in Receiver";
sendToReceiver(F_SET_RECEIVER_QUAD, value, nullptr);
}
void Receiver::setReadNLines(const int value) {
LOG(logDEBUG1) << "Setting read n lines to " << value
<< " in Receiver";
sendToReceiver(F_SET_RECEIVER_READ_N_LINES, value, nullptr);
}
void Receiver::setADCEnableMask(const uint32_t mask) {
sendToReceiver(F_RECEIVER_SET_ADC_MASK, mask, nullptr);
}
void Receiver::setTenGigaADCEnableMask(const uint32_t mask) {
sendToReceiver(F_RECEIVER_SET_ADC_MASK_10G, mask, nullptr);
}
void Receiver::setBurstMode(const slsDetectorDefs::burstMode value) {
LOG(logDEBUG1) << "Sending burst mode to Receiver: " << value;
sendToReceiver(F_SET_RECEIVER_BURST_MODE, value, nullptr);
}
void Receiver::setROI(const slsDetectorDefs::ROI arg) {
std::array<int, 2> args{arg.xmin, arg.xmax};
LOG(logDEBUG1) << "Sending ROI to receiver";
sendToReceiver(F_RECEIVER_SET_ROI, args, nullptr);
}
void Receiver::clearROI() {
LOG(logDEBUG1) << "Clearing ROI";
slsDetectorDefs::ROI arg;
arg.xmin = -1;
arg.xmax = -1;
setROI(arg);
}
std::vector<int> Receiver::getDbitList() const {
sls::FixedCapacityContainer<int, MAX_RX_DBIT> retval;
sendToReceiver(F_GET_RECEIVER_DBIT_LIST, nullptr, retval);
return retval;
}
void Receiver::setDbitList(const std::vector<int>& list) {
LOG(logDEBUG1) << "Setting Receiver Dbit List";
if (list.size() > 64) {
throw sls::RuntimeError("Dbit list size cannot be greater than 64\n");
}
for (auto &it : list) {
if (it < 0 || it > 63) {
throw sls::RuntimeError(
"Dbit list value must be between 0 and 63\n");
}
}
sls::FixedCapacityContainer<int, MAX_RX_DBIT> arg = list;
sendToReceiver(F_SET_RECEIVER_DBIT_LIST, arg, nullptr);
}
int Receiver::getDbitOffset() const {
return sendToReceiver<int>(F_GET_RECEIVER_DBIT_OFFSET);
}
void Receiver::setDbitOffset(const int value) {
sendToReceiver(F_SET_RECEIVER_DBIT_OFFSET, value, nullptr);
}
void Receiver::setActivate(const bool enable) {
int arg = static_cast<int>(enable);
sendToReceiver(F_RECEIVER_ACTIVATE, arg, nullptr);
}
void Receiver::setTenGiga(const bool enable) {
int arg = static_cast<int>(enable);
sendToReceiver(F_ENABLE_RECEIVER_TEN_GIGA, arg, nullptr);
}
void Receiver::setCounterMask(const uint32_t mask) {
int ncounters = __builtin_popcount(mask);
LOG(logDEBUG1) << "Sending Reciver #counters: " << ncounters;
sendToReceiver(F_RECEIVER_SET_NUM_COUNTERS, ncounters, nullptr);
}
/** Json */
std::map<std::string, std::string> Receiver::getAdditionalJsonHeader() const {
int fnum = F_GET_ADDITIONAL_JSON_HEADER;
int ret = FAIL;
int size = 0;
auto client = ReceiverSocket(shm()->hostname, shm()->tcpPort);
client.Send(&fnum, sizeof(fnum));
client.Receive(&ret, sizeof(ret));
if (ret == FAIL) {
char mess[MAX_STR_LENGTH]{};
client.Receive(mess, MAX_STR_LENGTH);
throw RuntimeError("Receiver " + std::to_string(moduleId) +
" returned error: " + std::string(mess));
} else {
client.Receive(&size, sizeof(size));
std::map<std::string, std::string> retval;
if (size > 0) {
char retvals[size * 2][SHORT_STR_LENGTH];
memset(retvals, 0, sizeof(retvals));
client.Receive(retvals, sizeof(retvals));
for (int i = 0; i < size; ++i) {
retval[retvals[2 * i]] = retvals[2 * i + 1];
}
}
LOG(logDEBUG) << "Getting additional json header " << ToString(retval);
return retval;
}
}
void Receiver::setAdditionalJsonHeader(const std::map<std::string, std::string> &jsonHeader) {
for (auto &it : jsonHeader) {
if (it.first.empty() || it.first.length() > SHORT_STR_LENGTH ||
it.second.length() > SHORT_STR_LENGTH ) {
throw RuntimeError(it.first + " or " + it.second + " pair has invalid size. "
"Key cannot be empty. Both can have max 20 characters");
}
}
const int size = jsonHeader.size();
int fnum = F_SET_ADDITIONAL_JSON_HEADER;
int ret = FAIL;
LOG(logDEBUG) << "Sending to receiver additional json header " << ToString(jsonHeader);
auto client = ReceiverSocket(shm()->hostname, shm()->tcpPort);
client.Send(&fnum, sizeof(fnum));
client.Send(&size, sizeof(size));
if (size > 0) {
char args[size * 2][SHORT_STR_LENGTH];
memset(args, 0, sizeof(args));
int iarg = 0;
for (auto &it : jsonHeader) {
sls::strcpy_safe(args[iarg], it.first.c_str());
sls::strcpy_safe(args[iarg + 1], it.second.c_str());
iarg += 2;
}
client.Send(args, sizeof(args));
}
client.Receive(&ret, sizeof(ret));
if (ret == FAIL) {
char mess[MAX_STR_LENGTH]{};
client.Receive(mess, MAX_STR_LENGTH);
throw RuntimeError("Receiver " + std::to_string(moduleId) +
" returned error: " + std::string(mess));
}
}
std::string Receiver::getAdditionalJsonParameter(const std::string &key) const {
char arg[SHORT_STR_LENGTH]{};
sls::strcpy_safe(arg, key.c_str());
char retval[SHORT_STR_LENGTH]{};
sendToReceiver(F_GET_ADDITIONAL_JSON_PARAMETER, arg, retval);
return retval;
}
void Receiver::setAdditionalJsonParameter(const std::string &key, const std::string &value) {
if (key.empty() || key.length() > SHORT_STR_LENGTH ||
value.length() > SHORT_STR_LENGTH ) {
throw RuntimeError(key + " or " + value + " pair has invalid size. "
"Key cannot be empty. Both can have max 2 characters");
}
char args[2][SHORT_STR_LENGTH]{};
sls::strcpy_safe(args[0], key.c_str());
sls::strcpy_safe(args[1], value.c_str());
sendToReceiver(F_SET_ADDITIONAL_JSON_PARAMETER, args, nullptr);
}
void Receiver::sendToReceiver(int fnum, const void *args, size_t args_size,
void *retval, size_t retval_size) {
static_cast<const Receiver &>(*this).sendToReceiver(
fnum, args, args_size, retval, retval_size);
}
void Receiver::sendToReceiver(int fnum, const void *args, size_t args_size,
void *retval, size_t retval_size) const {
if (strlen(shm()->hostname) == 0) {
throw RuntimeError("Reciver not added");
}
auto receiver = ReceiverSocket(shm()->hostname, shm()->tcpPort);
receiver.sendCommandThenRead(fnum, args, args_size, retval, retval_size);
receiver.close();
}
template <typename Arg, typename Ret>
void Receiver::sendToReceiver(int fnum, const Arg &args, Ret &retval) {
sendToReceiver(fnum, &args, sizeof(args), &retval, sizeof(retval));
}
template <typename Arg, typename Ret>
void Receiver::sendToReceiver(int fnum, const Arg &args, Ret &retval) const {
sendToReceiver(fnum, &args, sizeof(args), &retval, sizeof(retval));
}
template <typename Arg>
void Receiver::sendToReceiver(int fnum, const Arg &args, std::nullptr_t) {
sendToReceiver(fnum, &args, sizeof(args), nullptr, 0);
}
template <typename Arg>
void Receiver::sendToReceiver(int fnum, const Arg &args,
std::nullptr_t) const {
sendToReceiver(fnum, &args, sizeof(args), nullptr, 0);
}
template <typename Ret>
void Receiver::sendToReceiver(int fnum, std::nullptr_t, Ret &retval) {
sendToReceiver(fnum, nullptr, 0, &retval, sizeof(retval));
}
template <typename Ret>
void Receiver::sendToReceiver(int fnum, std::nullptr_t, Ret &retval) const {
sendToReceiver(fnum, nullptr, 0, &retval, sizeof(retval));
}
template <typename Ret>
Ret Receiver::sendToReceiver(int fnum){
LOG(logDEBUG1) << "Sending: ["
<< getFunctionNameFromEnum(static_cast<slsDetectorDefs::detFuncs>(fnum))
<< ", nullptr, 0, " << typeid(Ret).name() << ", " << sizeof(Ret) << "]";
Ret retval{};
sendToReceiver(fnum, nullptr, 0, &retval, sizeof(retval));
LOG(logDEBUG1) << "Got back: " << retval;
return retval;
}
template <typename Ret>
Ret Receiver::sendToReceiver(int fnum) const{
LOG(logDEBUG1) << "Sending: ["
<< getFunctionNameFromEnum(static_cast<slsDetectorDefs::detFuncs>(fnum))
<< ", nullptr, 0, " << typeid(Ret).name() << ", " << sizeof(Ret) << "]";
Ret retval{};
sendToReceiver(fnum, nullptr, 0, &retval, sizeof(retval));
LOG(logDEBUG1) << "Got back: " << retval;
return retval;
}
template <typename Ret, typename Arg>
Ret Receiver::sendToReceiver(int fnum, const Arg &args){
LOG(logDEBUG1) << "Sending: ["
<< getFunctionNameFromEnum(static_cast<slsDetectorDefs::detFuncs>(fnum))
<< ", " << args << ", " << sizeof(args) << ", " << typeid(Ret).name()
<< ", " << sizeof(Ret) << "]";
Ret retval{};
sendToReceiver(fnum, &args, sizeof(args), &retval, sizeof(retval));
LOG(logDEBUG1) << "Got back: " << retval;
return retval;
}
template <typename Ret, typename Arg>
Ret Receiver::sendToReceiver(int fnum, const Arg &args) const{
LOG(logDEBUG1) << "Sending: ["
<< getFunctionNameFromEnum(static_cast<slsDetectorDefs::detFuncs>(fnum))
<< ", " << args << ", " << sizeof(args) << ", " << typeid(Ret).name()
<< ", " << sizeof(Ret) << "]";
Ret retval{};
sendToReceiver(fnum, &args, sizeof(args), &retval, sizeof(retval));
LOG(logDEBUG1) << "Got back: " << retval;
return retval;
}
} // namespace sls

View File

@ -0,0 +1,258 @@
#pragma once
#include "SharedMemory.h"
#include "logger.h"
#include "sls_detector_defs.h"
#include "network_utils.h"
#include <map>
#include <memory>
#define RECEIVER_SHMVERSION 0x200421
class ZmqSocket;
namespace sls {
struct sharedReceiver {
/* FIXED PATTERN FOR STATIC FUNCTIONS. DO NOT CHANGE, ONLY APPEND ------*/
int shmversion;
char hostname[MAX_STR_LENGTH];
int tcpPort;
/** END OF FIXED PATTERN -----------------------------------------------*/
int stoppedFlag;
int zmqPort;
sls::IpAddr zmqIp;
};
class Receiver : public virtual slsDetectorDefs {
public:
static size_t getNumReceivers();
// create shm
explicit Receiver(int detector_id, int module_id, int interface_id,
int receiver_id, int tcp_port = 0, std::string hostname = "",
int zmq_port = 0);
// open shm
explicit Receiver(int detector_id, int module_id, int interface_id,
int receiver_id, bool verify);
virtual ~Receiver();
void createIndexString();
/**************************************************
* *
* Configuration *
* *
* ************************************************/
/**
* Free shared memory and delete shared memory structure
* occupied by the sharedReceiver structure
* Is only safe to call if one deletes the Receiver object afterward
* and frees multi shared memory/updates
* thisMultiDetector->numberOfReceivers
*/
void freeSharedMemory();
std::string getHostname() const;
void setHostname(const std::string &hostname);
sls::MacAddr configure(slsDetectorDefs::rxParameters arg);
int getTCPPort() const;
void setTCPPort(const int port);
std::string printConfiguration();
int64_t getSoftwareVersion() const;
/**************************************************
* *
* Acquisition *
* *
* ************************************************/
void start();
void stop();
slsDetectorDefs::runStatus getStatus() const;
int getProgress() const;
void setStoppedFlag();
void restreamStop();
uint64_t getFramesCaught() const;
uint64_t getNumMissingPackets() const;
uint64_t getCurrentFrameIndex() const;
/**************************************************
* *
* Network Configuration (Detector<->Receiver) *
* *
* ************************************************/
sls::MacAddr setUDPIP(const sls::IpAddr ip);
void setUDPPort(const int udpport);
int64_t getUDPSocketBufferSize() const;
void setUDPSocketBufferSize(int64_t value);
int64_t getRealUDPSocketBufferSize() const;
/**************************************************
* *
* ZMQ Streaming Parameters (Receiver<->Client)*
* *
* ************************************************/
bool getZmq() const;
void setZmq(const bool enable);
int getZmqFrequency() const;
/** Freq = 0 for a timer, else frequency */
void setZmqFrequency(const int freq);
int getZmqTimer() const;
void setZmqTimer(const int time_in_ms = 200);
int getZmqPort() const;
void setZmqPort(int port);
sls::IpAddr getZmqIP() const;
void setZmqIP(const sls::IpAddr ip);
int getClientZmqPort() const;
void setClientZmqPort(const int port);
sls::IpAddr getClientZmqIP() const;
void setClientZmqIP(const sls::IpAddr ip);
bool getClientZmq() const;
void setClientZmq(const bool enable);
ZmqSocket* getZmqSocket();
/**************************************************
* *
* Receiver Parameters *
* *
* ************************************************/
bool getLock() const;
void setLock(const bool lock);
sls::IpAddr getLastClientIP() const;
void exitServer();
bool getDeactivatedPaddingMode() const;
void setDeactivatedPaddingMode(const bool padding);
bool getFlippedDataX() const;
void setFlippedDataX(const bool value);
frameDiscardPolicy getFramesDiscardPolicy() const;
void setFramesDiscardPolicy(const frameDiscardPolicy f);
bool getPartialFramesPadding() const;
void setPartialFramesPadding(const bool padding);
int getFifoDepth() const;
void setFifoDepth(const int value);
bool getSilentMode() const;
void setSilentMode(const bool value);
/**************************************************
* *
* File *
* *
* ************************************************/
std::string getFilePath() const;
void setFilePath(const std::string &path);
std::string getFileName() const;
void setFileName(const std::string &fname);
int64_t getFileIndex() const;
void setFileIndex(const int64_t file_index);
void incrementFileIndex();
fileFormat getFileFormat() const;
void setFileFormat(const fileFormat f);
int getFramesPerFile() const;
/** 0 will set frames per file to unlimited */
void setFramesPerFile(const int n_frames);
bool getFileWrite() const;
void setFileWrite(const bool value);
bool getMasterFileWrite() const;
void setMasterFileWrite(const bool value);
bool getFileOverWrite() const;
void setFileOverWrite(const bool value);
/**************************************************
* *
* Detector Parameters *
* *
* ************************************************/
void setNumberOfFrames(const int64_t value);
void setNumberOfTriggers(const int64_t value);
void setNumberOfBursts(const int64_t value);
void setNumberOfAnalogSamples(const int value);
void setNumberOfDigitalSamples(const int value);
void setExptime(const int64_t value);
void setPeriod(const int64_t value);
void setSubExptime(const int64_t value);
void setSubDeadTime(const int64_t value);
void setTimingMode(const timingMode value);
void setDynamicRange(const int n);
void setReadoutMode(const readoutMode mode);
void setQuad(const bool enable);
void setReadNLines(const int value);
void setADCEnableMask(const uint32_t mask);
void setTenGigaADCEnableMask(const uint32_t mask);
void setBurstMode(const burstMode value);
void setROI(const slsDetectorDefs::ROI arg);
void clearROI();
std::vector<int> getDbitList() const;
/** digital data bits enable (CTB only) */
void setDbitList(const std::vector<int>& list);
int getDbitOffset() const;
/** Set digital data offset in bytes (CTB only) */
void setDbitOffset(const int value);
void setActivate(const bool enable);
void setTenGiga(const bool enable);
void setCounterMask(const uint32_t mask);
/**************************************************
* *
* Json *
* *
* ************************************************/
std::map<std::string, std::string> getAdditionalJsonHeader() const;
/** empty vector deletes entire additional json header */
void setAdditionalJsonHeader(const std::map<std::string, std::string> &jsonHeader);
std::string getAdditionalJsonParameter(const std::string &key) const;
/** Sets the value for the additional json header parameter key if found,
else append it. If value empty, then deletes parameter */
void setAdditionalJsonParameter(const std::string &key, const std::string &value);
private:
void sendToReceiver(int fnum, const void *args, size_t args_size,
void *retval, size_t retval_size);
void sendToReceiver(int fnum, const void *args, size_t args_size,
void *retval, size_t retval_size) const;
template <typename Arg, typename Ret>
void sendToReceiver(int fnum, const Arg &args, Ret &retval);
template <typename Arg, typename Ret>
void sendToReceiver(int fnum, const Arg &args, Ret &retval) const;
template <typename Arg>
void sendToReceiver(int fnum, const Arg &args, std::nullptr_t);
template <typename Arg>
void sendToReceiver(int fnum, const Arg &args, std::nullptr_t) const;
template <typename Ret>
void sendToReceiver(int fnum, std::nullptr_t, Ret &retval);
template <typename Ret>
void sendToReceiver(int fnum, std::nullptr_t, Ret &retval) const;
template <typename Ret>
Ret sendToReceiver(int fnum);
template <typename Ret>
Ret sendToReceiver(int fnum) const;
template <typename Ret, typename Arg>
Ret sendToReceiver(int fnum, const Arg &args);
template <typename Ret, typename Arg>
Ret sendToReceiver(int fnum, const Arg &args) const;
void checkVersionCompatibility();
const int receiverId{0};
const int interfaceId{0};
const int moduleId{0};
std::string indexString;
mutable sls::SharedMemory<sharedReceiver> shm{0, 0, 0, 0};
std::unique_ptr<ZmqSocket> zmqSocket;
};
} // sls

View File

@ -23,7 +23,8 @@
#include <unistd.h>
#define SHM_MULTI_PREFIX "/slsDetectorPackage_multi_"
#define SHM_SLS_PREFIX "_sls_"
#define SHM_MODULE_PREFIX "_module_"
#define SHM_RECEIVER_PREFIX "_receiver_"
#define SHM_ENV_NAME "SLSDETNAME"
#include <iostream>
@ -39,10 +40,12 @@ class SharedMemory {
* Constructor
* creates the single/multi detector shared memory name
* @param multiId multi detector id
* @param slsId sls detector id, -1 if a multi detector shared memory
* @param moduleId module detectr id, -1 if a multi detector shared memory
* @param interfaceId 0 for primary interface, 1 for secondary
* @param receiverId receiver id, -1 if not a rxr shm, else round robin entry
*/
SharedMemory(int multiId, int slsId) {
name = ConstructSharedMemoryName(multiId, slsId);
SharedMemory(int multiId, int moduleId, int interfaceId = 0, int receiverId = -1) {
name = ConstructSharedMemoryName(multiId, moduleId, interfaceId, receiverId);
}
/**
@ -184,7 +187,8 @@ class SharedMemory {
// silent exit if shm did not exist anyway
if (errno == ENOENT)
return;
std::string msg = "Free Shared Memory " + name + " Failed: " + strerror(errno);
std::string msg = "Free Shared Memory " + name + " Failed: " +
strerror(errno);
LOG(logERROR) << msg;
throw SharedMemoryError(msg);
}
@ -215,10 +219,13 @@ class SharedMemory {
* Create Shared memory name
* throws exception if name created is longer than required 255(manpages)
* @param multiId multi detector id
* @param slsId sls detector id, -1 if a multi detector shared memory
* @param moduleId module detector id, -1 if a multi detector shared memory
* @param interfaceId 0 for primary interface, 1 for secondary
* @param receiverId receiver id, -1 if not a rxr shm, else round robin entry
* @returns shared memory name
*/
std::string ConstructSharedMemoryName(int multiId, int slsId) {
std::string ConstructSharedMemoryName(int multiId, int moduleId,
int interfaceId = 0, int receiverId = -1) {
// using environment path
std::string sEnvPath = "";
@ -229,14 +236,22 @@ class SharedMemory {
}
std::stringstream ss;
if (slsId < 0)
if (moduleId < 0 && receiverId < 0)
ss << SHM_MULTI_PREFIX << multiId << sEnvPath;
else if (receiverId < 0)
ss << SHM_MULTI_PREFIX << multiId <<
SHM_MODULE_PREFIX << moduleId << sEnvPath;
else
ss << SHM_MULTI_PREFIX << multiId << SHM_SLS_PREFIX << slsId << sEnvPath;
ss << SHM_MULTI_PREFIX << multiId <<
SHM_MODULE_PREFIX << moduleId <<
SHM_RECEIVER_PREFIX << (char)(interfaceId + 97) << '_' << receiverId << sEnvPath;
std::string temp = ss.str();
if (temp.length() > NAME_MAX_LENGTH) {
std::string msg = "Shared memory initialization failed. " + temp + " has " + std::to_string(temp.length()) + " characters. \n" + "Maximum is " + std::to_string(NAME_MAX_LENGTH) + ". Change the environment variable " + SHM_ENV_NAME;
std::string msg = "Shared memory initialization failed. " +
temp + " has " + std::to_string(temp.length()) + " characters. \n" +
"Maximum is " + std::to_string(NAME_MAX_LENGTH) +
". Change the environment variable " + SHM_ENV_NAME;
LOG(logERROR) << msg;
throw SharedMemoryError(msg);
}
@ -250,9 +265,11 @@ class SharedMemory {
*/
T *MapSharedMemory() {
void *addr = mmap(nullptr, sizeof(T), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
void *addr = mmap(nullptr, sizeof(T), PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0);
if (addr == MAP_FAILED) {
std::string msg = "Mapping shared memory " + name + " failed: " + strerror(errno);
std::string msg = "Mapping shared memory " + name + " failed: " +
strerror(errno);
LOG(logERROR) << msg;
close(fd);
throw SharedMemoryError(msg);
@ -271,7 +288,8 @@ class SharedMemory {
struct stat sb;
// could not fstat
if (fstat(fd, &sb) < 0) {
std::string msg = "Could not verify existing shared memory " + name + " size match " + "(could not fstat): " + strerror(errno);
std::string msg = "Could not verify existing shared memory " +
name + " size match " + "(could not fstat): " + strerror(errno);
LOG(logERROR) << msg;
close(fd);
throw SharedMemoryError(msg);
@ -280,7 +298,9 @@ class SharedMemory {
//size does not match
auto sz = static_cast<size_t>(sb.st_size);
if (sz != expectedSize) {
std::string msg = "Existing shared memory " + name + " size does not match" + "Expected " + std::to_string(expectedSize) + ", found " + std::to_string(sz);
std::string msg = "Existing shared memory " + name +
" size does not match" + "Expected " +
std::to_string(expectedSize) + ", found " + std::to_string(sz);
LOG(logERROR) << msg;
throw SharedMemoryError(msg);
return 1;

File diff suppressed because it is too large Load Diff

View File

@ -10,8 +10,18 @@ class ServerInterface;
#include <future>
class ClientInterface : private virtual slsDetectorDefs {
private:
enum numberMode { DEC, HEX };
detectorType myDetectorType;
int portNumber{0};
sls::ServerSocket server;
std::unique_ptr<Implementation> receiver;
std::unique_ptr<std::thread> tcpThread;
int ret{OK};
int fnum{-1};
int lockedByClient{0};
std::atomic<bool> killTcpThread{false};
public:
virtual ~ClientInterface();
@ -49,15 +59,15 @@ class ClientInterface : private virtual slsDetectorDefs {
void verifyLock();
void verifyIdle(sls::ServerInterface &socket);
int exec_command(sls::ServerInterface &socket);
int exit_server(sls::ServerInterface &socket);
int lock_receiver(sls::ServerInterface &socket);
int set_lock_server(sls::ServerInterface &socket);
int get_lock_server(sls::ServerInterface &socket);
int get_last_client_ip(sls::ServerInterface &socket);
int set_port(sls::ServerInterface &socket);
int get_version(sls::ServerInterface &socket);
int set_detector_type(sls::ServerInterface &socket);
int set_detector_hostname(sls::ServerInterface &socket);
int setup_receiver(sls::ServerInterface &socket);
void setDetectorType(detectorType arg);
int set_roi(sls::ServerInterface &socket);
int set_num_frames(sls::ServerInterface &socket);
int set_num_triggers(sls::ServerInterface &socket);
@ -95,15 +105,16 @@ class ClientInterface : private virtual slsDetectorDefs {
int get_overwrite(sls::ServerInterface &socket);
int enable_tengiga(sls::ServerInterface &socket);
int set_fifo_depth(sls::ServerInterface &socket);
int get_fifo_depth(sls::ServerInterface &socket);
int set_activate(sls::ServerInterface &socket);
int set_streaming(sls::ServerInterface &socket);
int get_streaming(sls::ServerInterface &socket);
int set_streaming_timer(sls::ServerInterface &socket);
int get_streaming_timer(sls::ServerInterface &socket);
int set_flipped_data(sls::ServerInterface &socket);
int get_flipped_data(sls::ServerInterface &socket);
int set_file_format(sls::ServerInterface &socket);
int get_file_format(sls::ServerInterface &socket);
int set_detector_posid(sls::ServerInterface &socket);
int set_multi_detector_size(sls::ServerInterface &socket);
int set_streaming_port(sls::ServerInterface &socket);
int get_streaming_port(sls::ServerInterface &socket);
int set_streaming_source_ip(sls::ServerInterface &socket);
@ -114,6 +125,7 @@ class ClientInterface : private virtual slsDetectorDefs {
int set_additional_json_header(sls::ServerInterface &socket);
int get_additional_json_header(sls::ServerInterface &socket);
int set_udp_socket_buffer_size(sls::ServerInterface &socket);
int get_udp_socket_buffer_size(sls::ServerInterface &socket);
int get_real_udp_socket_buffer_size(sls::ServerInterface &socket);
int set_frames_per_file(sls::ServerInterface &socket);
int get_frames_per_file(sls::ServerInterface &socket);
@ -132,10 +144,9 @@ class ClientInterface : private virtual slsDetectorDefs {
int get_dbit_offset(sls::ServerInterface &socket);
int set_quad_type(sls::ServerInterface &socket);
int set_read_n_lines(sls::ServerInterface &socket);
sls::MacAddr setUdpIp(sls::IpAddr arg);
int set_udp_ip(sls::ServerInterface &socket);
int set_udp_ip2(sls::ServerInterface &socket);
int set_udp_port(sls::ServerInterface &socket);
int set_udp_port2(sls::ServerInterface &socket);
int set_num_interfaces(sls::ServerInterface &socket);
int set_adc_mask_10g(sls::ServerInterface &socket);
int set_num_counters(sls::ServerInterface &socket);
@ -144,7 +155,6 @@ class ClientInterface : private virtual slsDetectorDefs {
int get_additional_json_parameter(sls::ServerInterface &socket);
int get_progress(sls::ServerInterface &socket);
Implementation *impl() {
if (receiver != nullptr) {
return receiver.get();
@ -154,19 +164,9 @@ class ClientInterface : private virtual slsDetectorDefs {
}
}
detectorType myDetectorType;
std::unique_ptr<Implementation> receiver{nullptr};
int (ClientInterface::*flist[NUM_REC_FUNCTIONS])(
sls::ServerInterface &socket);
int ret{OK};
int fnum{-1};
int lockedByClient{0};
int portNumber{0};
std::atomic<bool> killTcpThread{false};
std::unique_ptr<std::thread> tcpThread;
//***callback parameters***
int (*startAcquisitionCallBack)(std::string, std::string, uint64_t, uint32_t,
@ -179,6 +179,6 @@ class ClientInterface : private virtual slsDetectorDefs {
void *) = nullptr;
void *pRawDataReady{nullptr};
protected:
std::unique_ptr<sls::ServerSocket> server{nullptr};
};

View File

@ -29,13 +29,9 @@ DataProcessor::DataProcessor(int ind, detectorType dtype, Fifo* f,
uint32_t* freq, uint32_t* timer,
bool* fp, bool* act, bool* depaden, bool* sm, bool* qe,
std::vector <int> * cdl, int* cdo, int* cad) :
ThreadObject(ind, TypeName),
runningFlag(false),
generalData(nullptr),
fifo(f),
myDetectorType(dtype),
file(nullptr),
dataStreamEnable(dsEnable),
fileFormatType(ftype),
fileWriteEnable(fwenable),
@ -43,7 +39,6 @@ DataProcessor::DataProcessor(int ind, detectorType dtype, Fifo* f,
dynamicRange(dr),
streamingFrequency(freq),
streamingTimerInMs(timer),
currentFreqCount(0),
activated(act),
deactivatedPaddingEnable(depaden),
silentMode(sm),
@ -51,14 +46,7 @@ DataProcessor::DataProcessor(int ind, detectorType dtype, Fifo* f,
framePadding(fp),
ctbDbitList(cdl),
ctbDbitOffset(cdo),
ctbAnalogDataBytes(cad),
startedFlag(false),
firstIndex(0),
numFramesCaught(0),
currentFrameIndex(0),
rawDataReadyCallBack(nullptr),
rawDataModifyReadyCallBack(nullptr),
pRawDataReady(nullptr)
ctbAnalogDataBytes(cad)
{
LOG(logDEBUG) << "DataProcessor " << ind << " created";
memset((void*)&timerBegin, 0, sizeof(timespec));
@ -71,10 +59,6 @@ DataProcessor::~DataProcessor() {
/** getters */
bool DataProcessor::IsRunning() {
return runningFlag;
}
bool DataProcessor::GetStartedFlag(){
return startedFlag;
}
@ -91,24 +75,12 @@ uint64_t DataProcessor::GetProcessedIndex() {
return currentFrameIndex - firstIndex;
}
/** setters */
void DataProcessor::StartRunning() {
runningFlag = true;
}
void DataProcessor::StopRunning() {
runningFlag = false;
}
void DataProcessor::SetFifo(Fifo* f) {
fifo = f;
}
void DataProcessor::ResetParametersforNewAcquisition(){
runningFlag = false;
StopRunning();
startedFlag = false;
numFramesCaught = 0;
firstIndex = 0;

View File

@ -59,11 +59,6 @@ class DataProcessor : private virtual slsDetectorDefs, public ThreadObject {
//*** getters ***
/**
* Returns if the thread is currently running
* @returns true if thread is running, else false
*/
bool IsRunning() override;
/**
* Get acquisition started flag
@ -89,17 +84,6 @@ class DataProcessor : private virtual slsDetectorDefs, public ThreadObject {
*/
uint64_t GetProcessedIndex();
//*** setters ***
/**
* Set bit in RunningMask to allow thread to run
*/
void StartRunning();
/**
* Reset bit in RunningMask to prevent thread from running
*/
void StopRunning();
/**
* Set Fifo pointer to the one given
* @param f address of Fifo pointer
@ -254,11 +238,8 @@ class DataProcessor : private virtual slsDetectorDefs, public ThreadObject {
/** type of thread */
static const std::string TypeName;
/** Object running status */
std::atomic<bool> runningFlag;
/** GeneralData (Detector Data) object */
const GeneralData* generalData;
const GeneralData* generalData{nullptr};
/** Fifo structure */
Fifo* fifo;
@ -269,7 +250,7 @@ class DataProcessor : private virtual slsDetectorDefs, public ThreadObject {
detectorType myDetectorType;
/** File writer implemented as binary or hdf5 File */
File* file;
File* file{nullptr};
/** Data Stream Enable */
bool* dataStreamEnable;
@ -293,7 +274,7 @@ class DataProcessor : private virtual slsDetectorDefs, public ThreadObject {
uint32_t* streamingTimerInMs;
/** Current frequency count */
uint32_t currentFreqCount;
uint32_t currentFreqCount{0};
/** timer beginning stamp for random streaming */
struct timespec timerBegin;
@ -324,21 +305,18 @@ class DataProcessor : private virtual slsDetectorDefs, public ThreadObject {
//acquisition start
/** Aquisition Started flag */
bool startedFlag;
std::atomic<bool> startedFlag{false};
/** Frame Number of First Frame */
uint64_t firstIndex;
std::atomic<uint64_t> firstIndex{0};
//for statistics
/** Number of complete frames caught */
uint64_t numFramesCaught;
uint64_t numFramesCaught{0};
/** Frame Number of latest processed frame number */
uint64_t currentFrameIndex;
std::atomic<uint64_t> currentFrameIndex{0};
//call back
/**
@ -349,7 +327,7 @@ class DataProcessor : private virtual slsDetectorDefs, public ThreadObject {
* dataSize in bytes is the size of the data in bytes.
*/
void (*rawDataReadyCallBack)(char*,
char*, uint32_t, void*);
char*, uint32_t, void*) = nullptr;
/**
* Call back for raw data (modified)
@ -359,9 +337,9 @@ class DataProcessor : private virtual slsDetectorDefs, public ThreadObject {
* revDatasize is the reference of data size in bytes. Can be modified to the new size to be written/streamed. (only smaller value).
*/
void (*rawDataModifyReadyCallBack)(char*,
char*, uint32_t &, void*);
char*, uint32_t &, void*) = nullptr;
void *pRawDataReady;
void *pRawDataReady{nullptr};

View File

@ -17,25 +17,18 @@ const std::string DataStreamer::TypeName = "DataStreamer";
DataStreamer::DataStreamer(int ind, Fifo* f, uint32_t* dr, ROI* r,
uint64_t* fi, int fd, int* nd, bool* qe, uint64_t* tot) :
uint64_t* fi, int fd, int* nr, bool* qe, uint64_t* tot) :
ThreadObject(ind, TypeName),
runningFlag(0),
generalData(nullptr),
fifo(f),
zmqSocket(nullptr),
dynamicRange(dr),
roi(r),
adcConfigured(-1),
fileIndex(fi),
flippedDataX(fd),
startedFlag(false),
firstIndex(0),
completeBuffer(nullptr),
quadEnable(qe),
totalNumFrames(tot)
{
numDet[0] = nd[0];
numDet[1] = nd[1];
numRx[0] = nr[0];
numRx[1] = nr[1];
LOG(logDEBUG) << "DataStreamer " << ind << " created";
}
@ -46,29 +39,12 @@ DataStreamer::~DataStreamer() {
delete [] completeBuffer;
}
/** getters */
bool DataStreamer::IsRunning() {
return runningFlag;
}
/** setters */
void DataStreamer::StartRunning() {
runningFlag = true;
}
void DataStreamer::StopRunning() {
runningFlag = false;
}
void DataStreamer::SetFifo(Fifo* f) {
fifo = f;
}
void DataStreamer::ResetParametersforNewAcquisition(const std::string& fname){
runningFlag = false;
StopRunning();
startedFlag = false;
firstIndex = 0;
@ -98,9 +74,9 @@ void DataStreamer::SetGeneralData(GeneralData* g) {
generalData->Print();
}
void DataStreamer::SetNumberofDetectors(int* nd) {
numDet[0] = nd[0];
numDet[1] = nd[1];
void DataStreamer::SetReceiverShape(int* nr) {
numRx[0] = nr[0];
numRx[1] = nr[1];
}
void DataStreamer::SetFlippedDataX(int fd) {
@ -235,8 +211,8 @@ int DataStreamer::SendHeader(sls_receiver_header* rheader, uint32_t size, uint32
zHeader.dynamicRange = *dynamicRange;
zHeader.fileIndex = *fileIndex;
zHeader.ndetx = numDet[0];
zHeader.ndety = numDet[1];
zHeader.nSocketX = numRx[0];
zHeader.nSocketY = numRx[1];
zHeader.npixelsx = nx;
zHeader.npixelsy = ny;
zHeader.imageSize = size;

View File

@ -29,12 +29,12 @@ class DataStreamer : private virtual slsDetectorDefs, public ThreadObject {
* @param r roi
* @param fi pointer to file index
* @param fd flipped data enable for x dimension
* @param nd pointer to number of detectors in each dimension
* @param nd pointer to number of receivers in each dimension
* @param qe pointer to quad Enable
* @param tot pointer to total number of frames
*/
DataStreamer(int ind, Fifo* f, uint32_t* dr, ROI* r,
uint64_t* fi, int fd, int* nd, bool* qe, uint64_t* tot);
uint64_t* fi, int fd, int* nr, bool* qe, uint64_t* tot);
/**
* Destructor
@ -42,25 +42,6 @@ class DataStreamer : private virtual slsDetectorDefs, public ThreadObject {
*/
~DataStreamer();
//*** getters ***
/**
* Returns if the thread is currently running
* @returns true if thread is running, else false
*/
bool IsRunning();
//*** setters ***
/**
* Set bit in RunningMask to allow thread to run
*/
void StartRunning();
/**
* Reset bit in RunningMask to prevent thread from running
*/
void StopRunning();
/**
* Set Fifo pointer to the one given
* @param f address of Fifo pointer
@ -79,10 +60,10 @@ class DataStreamer : private virtual slsDetectorDefs, public ThreadObject {
void SetGeneralData(GeneralData* g);
/**
* Set number of detectors
* @param number of detectors in both dimensions
* Set receiver shape
* @param number of receivers in both dimensions
*/
void SetNumberofDetectors(int* nd);
void SetReceiverShape(int* nr);
/**
* Set Flipped data enable across x dimension
@ -158,19 +139,14 @@ class DataStreamer : private virtual slsDetectorDefs, public ThreadObject {
/** type of thread */
static const std::string TypeName;
/** Object running status */
bool runningFlag;
/** GeneralData (Detector Data) object */
const GeneralData* generalData;
const GeneralData* generalData{nullptr};
/** Fifo structure */
Fifo* fifo;
/** ZMQ Socket - Receiver to Client */
ZmqSocket* zmqSocket;
ZmqSocket* zmqSocket{nullptr};
/** Pointer to dynamic range */
uint32_t* dynamicRange;
@ -179,7 +155,7 @@ class DataStreamer : private virtual slsDetectorDefs, public ThreadObject {
ROI* roi;
/** adc Configured */
int adcConfigured;
int adcConfigured{-1};
/** Pointer to file index */
uint64_t* fileIndex;
@ -191,19 +167,19 @@ class DataStreamer : private virtual slsDetectorDefs, public ThreadObject {
std::map<std::string, std::string> additionJsonHeader;
/** Aquisition Started flag */
bool startedFlag;
bool startedFlag{nullptr};
/** Frame Number of First Frame */
uint64_t firstIndex;
uint64_t firstIndex{0};
/* File name to stream */
std::string fileNametoStream;
/** Complete buffer used for roi, eg. shortGotthard */
char* completeBuffer;
char* completeBuffer{nullptr};
/** Number of Detectors in X and Y dimension */
int numDet[2];
/** Number of Recievers in X and Y dimension */
int numRx[2];
/** Quad Enable */
bool* quadEnable;

View File

@ -64,9 +64,6 @@ public:
/** Default Fifo depth */
uint32_t defaultFifoDepth;
/** Threads per receiver */
uint32_t threadsPerReceiver;
/** Size of a header packet */
uint32_t headerPacketSize;
@ -105,7 +102,6 @@ public:
maxFramesPerFile(0),
fifoBufferHeaderSize(0),
defaultFifoDepth(0),
threadsPerReceiver(1),
headerPacketSize(0),
nPixelsXComplete(0),
nPixelsYComplete(0),
@ -233,7 +229,6 @@ public:
LOG(level) << "Max Frames Per File: " << maxFramesPerFile;
LOG(level) << "Fifo Buffer Header Size: " << fifoBufferHeaderSize;
LOG(level) << "Default Fifo Depth: " << defaultFifoDepth;
LOG(level) << "Threads Per Receiver: " << threadsPerReceiver;
LOG(level) << "Header Packet Size: " << headerPacketSize;
LOG(level) << "Complete Pixels X: " << nPixelsXComplete;
LOG(level) << "Complete Pixels Y: " << nPixelsYComplete;
@ -415,7 +410,6 @@ class EigerData : public GeneralData {
maxFramesPerFile = EIGER_MAX_FRAMES_PER_FILE;
fifoBufferHeaderSize= FIFO_HEADER_NUMBYTES + sizeof(slsDetectorDefs::sls_receiver_header);
defaultFifoDepth = 1000;
threadsPerReceiver = 2;
headerPacketSize = 40;
standardheader = true;
};
@ -479,7 +473,6 @@ class JungfrauData : public GeneralData {
nPixelsY = 256;
packetsPerFrame = 64;
imageSize = dataSize * packetsPerFrame;
threadsPerReceiver = 2;
defaultUdpSocketBufferSize = (500 * 1024 * 1024);
}
@ -488,7 +481,6 @@ class JungfrauData : public GeneralData {
nPixelsY = 512;
packetsPerFrame = 128;
imageSize = dataSize * packetsPerFrame;
threadsPerReceiver = 1;
defaultUdpSocketBufferSize = (1000 * 1024 * 1024);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -29,7 +29,7 @@ class Implementation : private virtual slsDetectorDefs {
void setDetectorType(const detectorType d);
int *getMultiDetectorSize() const;
void setMultiDetectorSize(const int *size);
void setDetectorSize(const int *size);
int getDetectorPositionId() const;
void setDetectorPositionId(const int id);
std::string getDetectorHostname() const;
@ -76,12 +76,12 @@ class Implementation : private virtual slsDetectorDefs {
uint64_t getFramesCaught() const;
uint64_t getAcquisitionIndex() const;
int getProgress() const;
std::vector<uint64_t> getNumMissingPackets() const;
uint64_t getNumMissingPackets() const;
void startReceiver();
void setStoppedFlag(bool stopped);
void stopReceiver();
void startReadout();
void shutDownUDPSockets();
void shutDownUDPSocket();
void closeFiles();
void restreamStop();
@ -91,19 +91,15 @@ class Implementation : private virtual slsDetectorDefs {
* Network Configuration (UDP) *
* *
* ************************************************/
int getInterfaceId() const;
void setInterfaceId(const int value);
int getNumberofUDPInterfaces() const;
/* [Jungfrau] */
void setNumberofUDPInterfaces(const int n);
std::string getEthernetInterface() const;
void setEthernetInterface(const std::string &c);
std::string getEthernetInterface2() const;
/* [Jungfrau] */
void setEthernetInterface2(const std::string &c);
uint32_t getUDPPortNumber() const;
void setUDPPortNumber(const uint32_t i);
uint32_t getUDPPortNumber2() const;
/* [Eiger][Jungfrau] */
void setUDPPortNumber2(const uint32_t i);
int64_t getUDPSocketBufferSize() const;
void setUDPSocketBufferSize(const int64_t s);
int64_t getActualUDPSocketBufferSize() const;
@ -226,7 +222,7 @@ class Implementation : private virtual slsDetectorDefs {
void SetupFifoStructure();
void ResetParametersforNewAcquisition();
void CreateUDPSockets();
void CreateUDPSocket();
void SetupWriter();
void StartRunning();
@ -238,9 +234,9 @@ class Implementation : private virtual slsDetectorDefs {
* ************************************************/
// config parameters
int numThreads;
detectorType myDetectorType;
int numDet[MAX_DIMENSIONS];
int numRx[MAX_DIMENSIONS];
int detID;
std::string detHostname;
bool silentMode;
@ -263,9 +259,10 @@ class Implementation : private virtual slsDetectorDefs {
bool stoppedFlag;
// network configuration (UDP)
int interfaceId;
int numUDPInterfaces;
std::vector <std::string> eth;
std::vector <uint32_t> udpPortNum;
std::string eth;
uint32_t udpPortNum;
int64_t udpSocketBufferSize;
int64_t actualUDPSocketBufferSize;
@ -318,8 +315,8 @@ class Implementation : private virtual slsDetectorDefs {
// class objects
GeneralData *generalData;
std::vector<std::unique_ptr<Listener>> listener;
std::vector<std::unique_ptr<DataProcessor>> dataProcessor;
std::vector<std::unique_ptr<DataStreamer>> dataStreamer;
std::vector<std::unique_ptr<Fifo>> fifo;
std::unique_ptr<Listener> listener;
std::unique_ptr<DataProcessor> dataProcessor;
std::unique_ptr<DataStreamer> dataStreamer;
std::unique_ptr<Fifo> fifo;
};

View File

@ -12,6 +12,7 @@
#include "container_utils.h" // For sls::make_unique<>
#include "sls_detector_exceptions.h"
#include "UdpRxSocket.h"
#include "network_utils.h"
#include <cerrno>
#include <cstring>
@ -25,12 +26,9 @@ Listener::Listener(int ind, detectorType dtype, Fifo* f, std::atomic<runStatus>*
int64_t* us, int64_t* as, uint32_t* fpf,
frameDiscardPolicy* fdp, bool* act, bool* depaden, bool* sm) :
ThreadObject(ind, TypeName),
runningFlag(0),
generalData(nullptr),
fifo(f),
myDetectorType(dtype),
status(s),
udpSocket(nullptr),
udpPortNumber(portno),
eth(e),
numImages(nf),
@ -41,45 +39,22 @@ Listener::Listener(int ind, detectorType dtype, Fifo* f, std::atomic<runStatus>*
frameDiscardMode(fdp),
activated(act),
deactivatedPaddingEnable(depaden),
silentMode(sm),
row(0),
column(0),
startedFlag(false),
firstIndex(0),
numPacketsCaught(0),
lastCaughtFrameIndex(0),
currentFrameIndex(0),
carryOverFlag(0),
udpSocketAlive(0),
numPacketsStatistic(0),
numFramesStatistic(0),
oddStartingPacket(true)
silentMode(sm)
{
LOG(logDEBUG) << "Listener " << ind << " created";
}
Listener::~Listener() = default;
Listener::~Listener() {
if (udpSocket){
sem_post(&semaphore_socket);
sem_destroy(&semaphore_socket);
}
}
/** getters */
bool Listener::IsRunning() {
return runningFlag;
}
uint64_t Listener::GetPacketsCaught() {
uint64_t Listener::GetPacketsCaught() const {
return numPacketsCaught;
}
uint64_t Listener::GetLastFrameIndexCaught() {
uint64_t Listener::GetLastFrameIndexCaught() const {
return lastCaughtFrameIndex;
}
uint64_t Listener::GetNumMissingPacket(bool stoppedFlag, uint64_t numPackets) {
uint64_t Listener::GetNumMissingPacket(bool stoppedFlag, uint64_t numPackets) const {
if (!stoppedFlag) {
return (numPackets - numPacketsCaught);
}
@ -89,24 +64,12 @@ uint64_t Listener::GetNumMissingPacket(bool stoppedFlag, uint64_t numPackets) {
return (lastCaughtFrameIndex - firstIndex + 1) * generalData->packetsPerFrame - numPacketsCaught;
}
/** setters */
void Listener::StartRunning() {
runningFlag = true;
}
void Listener::StopRunning() {
runningFlag = false;
}
void Listener::SetFifo(Fifo* f) {
fifo = f;
}
void Listener::ResetParametersforNewAcquisition() {
runningFlag = false;
StopRunning();
startedFlag = false;
numPacketsCaught = 0;
firstIndex = 0;
@ -149,7 +112,7 @@ void Listener::SetGeneralData(GeneralData* g) {
}
void Listener::CreateUDPSockets() {
void Listener::CreateUDPSocket() {
if (!(*activated)) {
return;
}
@ -174,10 +137,9 @@ void Listener::CreateUDPSockets() {
}
udpSocketAlive = true;
sem_init(&semaphore_socket,1,0);
// doubled due to kernel bookkeeping (could also be less due to permissions)
*actualUDPSocketBufferSize = udpSocket->getActualUDPSocketBufferSize();
*actualUDPSocketBufferSize = udpSocket->getBufferSize();
}
@ -185,14 +147,8 @@ void Listener::CreateUDPSockets() {
void Listener::ShutDownUDPSocket() {
if(udpSocket){
udpSocketAlive = false;
udpSocket->ShutDownSocket();
udpSocket->Shutdown();
LOG(logINFO) << "Shut down of UDP port " << *udpPortNumber;
fflush(stdout);
// wait only if the threads have started as it is the threads that
//give a post to semaphore(at stopListening)
if (runningFlag)
sem_wait(&semaphore_socket);
sem_destroy(&semaphore_socket);
}
}
@ -220,7 +176,7 @@ void Listener::CreateDummySocketForUDPSocketBufferSize(int64_t s) {
*udpSocketBufferSize);
// doubled due to kernel bookkeeping (could also be less due to permissions)
*actualUDPSocketBufferSize = g.getActualUDPSocketBufferSize();
*actualUDPSocketBufferSize = g.getBufferSize();
if (*actualUDPSocketBufferSize == -1) {
*udpSocketBufferSize = temp;
} else {
@ -300,10 +256,8 @@ void Listener::StopListening(char* buf) {
(*((uint32_t*)buf)) = DUMMY_PACKET_VALUE;
fifo->PushAddress(buf);
StopRunning();
sem_post(&semaphore_socket);
LOG(logDEBUG1) << index << ": Listening Packets (" << *udpPortNumber << ") : " << numPacketsCaught;
LOG(logDEBUG1) << index << ": Listening Completed";
LOG(logDEBUG1) << index << ": Listening Packets (" << *udpPortNumber << ") : " << numPacketsCaught;
LOG(logDEBUG1) << index << ": Listening Completed";
}

View File

@ -12,13 +12,10 @@
#include <memory>
#include <atomic>
#include "ThreadObject.h"
#include "UdpRxSocket.h"
class GeneralData;
class Fifo;
namespace sls{
class UdpRxSocket;
}
class Listener : private virtual slsDetectorDefs, public ThreadObject {
@ -53,40 +50,20 @@ class Listener : private virtual slsDetectorDefs, public ThreadObject {
*/
~Listener();
//*** getters ***
/**
* Returns if the thread is currently running
* @returns true if thread is running, else false
*/
bool IsRunning() override;
/**
* Get Packets caught
* @return Packets caught
*/
uint64_t GetPacketsCaught();
uint64_t GetPacketsCaught() const;
/**
* Get Last Frame index caught
* @return last frame index caught
*/
uint64_t GetLastFrameIndexCaught();
uint64_t GetLastFrameIndexCaught() const;
/** Get number of missing packets */
uint64_t GetNumMissingPacket(bool stoppedFlag, uint64_t numPackets);
//*** setters ***
/**
* Set bit in RunningMask to allow thread to run
*/
void StartRunning();
/**
* Reset bit in RunningMask to prevent thread from running
*/
void StopRunning();
uint64_t GetNumMissingPacket(bool stoppedFlag, uint64_t numPackets) const;
/**
* Set Fifo pointer to the one given
@ -106,9 +83,9 @@ class Listener : private virtual slsDetectorDefs, public ThreadObject {
void SetGeneralData(GeneralData* g);
/**
* Creates UDP Sockets
* Creates UDP Socket
*/
void CreateUDPSockets();
void CreateUDPSocket();
/**
* Shuts down and deletes UDP Sockets
@ -140,7 +117,7 @@ class Listener : private virtual slsDetectorDefs, public ThreadObject {
void RecordFirstIndex(uint64_t fnum);
/**
* Thread Exeution for Listener Class
* Thread Execution for Listener Class
* Pop free addresses, listen to udp socket,
* write to memory & push the address into fifo
*/
@ -168,16 +145,11 @@ class Listener : private virtual slsDetectorDefs, public ThreadObject {
*/
void PrintFifoStatistics();
/** type of thread */
static const std::string TypeName;
/** Object running status */
std::atomic<bool> runningFlag;
/** GeneralData (Detector Data) object */
GeneralData* generalData;
GeneralData* generalData{nullptr};
/** Fifo structure */
Fifo* fifo;
@ -190,7 +162,7 @@ class Listener : private virtual slsDetectorDefs, public ThreadObject {
std::atomic<runStatus>* status;
/** UDP Socket - Detector to Receiver */
std::unique_ptr<sls::UdpRxSocket> udpSocket;
std::unique_ptr<sls::UdpRxSocket> udpSocket{nullptr};
/** UDP Port Number */
uint32_t* udpPortNumber;
@ -228,36 +200,34 @@ class Listener : private virtual slsDetectorDefs, public ThreadObject {
/** row hardcoded as 1D or 2d,
* if detector does not send them yet or
* missing packets/deactivated (eiger/jungfrau sends 2d pos) **/
uint16_t row;
uint16_t row{0};
/** column hardcoded as 2D,
* deactivated eiger/missing packets (eiger/jungfrau sends 2d pos) **/
uint16_t column;
uint16_t column{0};
// acquisition start
/** Aquisition Started flag */
std::atomic<bool> startedFlag;
std::atomic<bool> startedFlag{false};
/** Frame Number of First Frame */
uint64_t firstIndex;
uint64_t firstIndex{0};
// for acquisition summary
/** Number of complete Packets caught */
std::atomic<uint64_t> numPacketsCaught;
std::atomic<uint64_t> numPacketsCaught{0};
/** Last Frame Index caught from udp network */
std::atomic<uint64_t> lastCaughtFrameIndex;
std::atomic<uint64_t> lastCaughtFrameIndex{0};
// parameters to acquire image
/** Current Frame Index, default value is 0
* ( always check startedFlag for validity first)
*/
uint64_t currentFrameIndex;
uint64_t currentFrameIndex{0};
/** True if there is a packet carry over from previous Image */
bool carryOverFlag;
bool carryOverFlag{false};
/** Carry over packet buffer */
std::unique_ptr<char []> carryOverPacket;
@ -266,22 +236,19 @@ class Listener : private virtual slsDetectorDefs, public ThreadObject {
std::unique_ptr<char []> listeningPacket;
/** if the udp socket is connected */
std::atomic<bool> udpSocketAlive;
std::atomic<bool> udpSocketAlive{false};
/** Semaphore to synchonize deleting udp socket */
sem_t semaphore_socket;
// for print progress during acqusition
// for print progress during acquisition
/** number of packets for statistic */
uint32_t numPacketsStatistic;
uint32_t numPacketsStatistic{0};
/** number of images for statistic */
uint32_t numFramesStatistic;
uint32_t numFramesStatistic{0};
/**
* starting packet number is odd or evern, accordingly increment frame number
* starting packet number is odd or even, accordingly increment frame number
* to get first packet number as 0
* (pecific to gotthard, can vary between modules, hence defined here) */
bool oddStartingPacket;
bool oddStartingPacket{true};
};

View File

@ -42,17 +42,14 @@ int main(int argc, char *argv[]) {
LOG(logERROR) << "Could not set handler function for SIGPIPE";
}
std::unique_ptr<Receiver> receiver = nullptr;
try {
receiver = sls::make_unique<Receiver>(argc, argv);
Receiver r(argc, argv);
LOG(logINFO) << "[ Press \'Ctrl+c\' to exit ]";
sem_wait(&semaphore);
sem_destroy(&semaphore);
} catch (...) {
LOG(logINFOBLUE) << "Exiting [ Tid: " << syscall(SYS_gettid) << " ]";
throw;
//pass
}
LOG(logINFO) << "[ Press \'Ctrl+c\' to exit ]";
sem_wait(&semaphore);
sem_destroy(&semaphore);
LOG(logINFOBLUE) << "Exiting [ Tid: " << syscall(SYS_gettid) << " ]";
LOG(logINFO) << "Exiting Receiver";
return 0;

View File

@ -3,56 +3,51 @@
* @short creates/destroys a thread
***********************************************/
#include "ThreadObject.h"
#include "container_utils.h"
#include <iostream>
#include <sys/syscall.h>
#include <unistd.h>
ThreadObject::ThreadObject(int threadIndex, std::string threadType)
: index(threadIndex), type(threadType) {
LOG(logDEBUG) << type << " thread created: " << index;
sem_init(&semaphore,1,0);
try {
threadObject = sls::make_unique<std::thread>(&ThreadObject::RunningThread, this);
threadObject = std::thread(&ThreadObject::RunningThread, this);
} catch (...) {
throw sls::RuntimeError("Could not create " + type + " thread with index " + std::to_string(index));
}
}
ThreadObject::~ThreadObject() {
killThread = true;
sem_post(&semaphore);
threadObject->join();
threadObject.join();
sem_destroy(&semaphore);
}
bool ThreadObject::IsRunning() const{
return runningFlag;
}
void ThreadObject::StartRunning() {
runningFlag = true;
}
void ThreadObject::StopRunning() {
runningFlag = false;
}
void ThreadObject::RunningThread() {
LOG(logINFOBLUE) << "Created [ " << type << "Thread " << index << ", Tid: " << syscall(SYS_gettid) << "]";
LOG(logDEBUG) << type << " thread " << index << " created successfully.";
while(true) {
while(!killThread) {
while(IsRunning()) {
ThreadExecution();
}
//wait till the next acquisition
sem_wait(&semaphore);
if(killThread) {
break;
}
}
LOG(logDEBUG) << type << " thread with index " << index << " destroyed successfully.";
LOG(logINFOBLUE) << "Exiting [ " << type << " Thread " << index << ", Tid: " << syscall(SYS_gettid) << "]";
}
@ -61,11 +56,10 @@ void ThreadObject::Continue() {
sem_post(&semaphore);
}
void ThreadObject::SetThreadPriority(int priority) {
struct sched_param param;
param.sched_priority = priority;
if (pthread_setschedparam(threadObject->native_handle(), SCHED_FIFO, &param) == EPERM) {
if (pthread_setschedparam(threadObject.native_handle(), SCHED_FIFO, &param) == EPERM) {
if (index == 0) {
LOG(logWARNING) << "Could not prioritize " << type << " thread. "
"(No Root Privileges?)";

View File

@ -7,41 +7,40 @@
*@short creates/destroys a thread
*/
#include "sls_detector_defs.h"
#include "logger.h"
#include "sls_detector_defs.h"
#include <atomic>
#include <thread>
#include <semaphore.h>
#include <string>
#include <atomic>
#include <future>
class ThreadObject : private virtual slsDetectorDefs {
public:
ThreadObject(int threadIndex, std::string threadType);
virtual ~ThreadObject();
virtual bool IsRunning() = 0;
void Continue();
void SetThreadPriority(int priority);
protected:
const int index{0};
protected:
virtual void ThreadExecution() = 0;
private:
std::atomic<bool> killThread{false};
std::atomic<bool> runningFlag{false};
std::thread threadObject;
sem_t semaphore;
const std::string type;
private:
/**
* Thread called: An infinite while loop in which,
* semaphore starts executing its contents as long RunningMask is satisfied
* Then it exits the thread on its own if killThread is true
*/
void RunningThread();
public:
ThreadObject(int threadIndex, std::string threadType);
virtual ~ThreadObject();
bool IsRunning() const;
void StartRunning();
void StopRunning();
void Continue();
void SetThreadPriority(int priority);
protected:
int index{0};
std::string type;
std::atomic<bool> killThread{false};
std::unique_ptr<std::thread> threadObject;
sem_t semaphore;
private:
virtual void ThreadExecution() = 0;
/**
* Thread called: An infinite while loop in which,
* semaphore starts executing its contents as long RunningMask is satisfied
* Then it exits the thread on its own if killThread is true
*/
void RunningThread();
};

View File

@ -8,6 +8,7 @@ set(SOURCES
src/ToString.cpp
src/network_utils.cpp
src/ZmqSocket.cpp
src/UdpRxSocket.cpp
)
set(HEADERS

View File

@ -21,7 +21,7 @@ class DataSocket {
//No copy since the class manage the underlying socket
DataSocket(const DataSocket &) = delete;
DataSocket &operator=(DataSocket const &) = delete;
int getSocketId() const { return socketId_; }
int getSocketId() const { return sockfd_; }
int Send(const void *buffer, size_t size);
@ -51,9 +51,10 @@ class DataSocket {
int setReceiveTimeout(int us);
void close();
void shutDownSocket();
void shutdown();
private:
int socketId_ = -1;
int sockfd_ = -1;
};
}; // namespace sls

View File

@ -1,141 +1,30 @@
#pragma once
/*
UdpRxSocket provies socket control to receive
data on a udp socket.
It provides a drop in replacement for
genericSocket. But please be careful since
this might be deprecated in the future
UDP socket class to receive data. The intended use is in the
receiver listener loop. Should be used RAII style...
*/
#include "network_utils.h"
#include "sls_detector_exceptions.h"
#include <cstdint>
#include <errno.h>
#include <iostream>
#include <netdb.h>
#include <netinet/in.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include <vector>
#include <sys/types.h> //ssize_t
namespace sls {
class UdpRxSocket {
const ssize_t packet_size;
char *buff;
int fd = -1;
const ssize_t packet_size_;
int sockfd_{-1};
public:
UdpRxSocket(int port, ssize_t packet_size, const char *hostname = nullptr,
ssize_t buffer_size = 0)
: packet_size(packet_size) {
/* hostname = nullptr -> wildcard */
size_t kernel_buffer_size = 0);
~UdpRxSocket();
bool ReceivePacket(char *dst) noexcept;
size_t getBufferSize() const;
void setBufferSize(ssize_t size);
ssize_t getPacketSize() const noexcept;
void Shutdown();
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = 0;
hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
struct addrinfo *res = 0;
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));
}
fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (fd == -1) {
throw RuntimeError("Failed to create UDP RX socket");
}
if (bind(fd, res->ai_addr, res->ai_addrlen) == -1) {
throw RuntimeError("Failed to bind UDP RX socket");
}
freeaddrinfo(res);
// If we get a specified buffer size that is larger than the set one
// we set it. Otherwise we leave it there since it could have been
// set by the rx_udpsocksize command
if (buffer_size) {
auto current = getBufferSize() / 2;
if (current < buffer_size) {
setBufferSize(buffer_size);
if (getBufferSize() / 2 < buffer_size) {
LOG(logWARNING)
<< "Could not set buffer size. Got: "
<< getBufferSize() / 2 << " instead of " << buffer_size;
}
}
}
// Allocate at the end to avoid memory leak if we throw
buff = new char[packet_size];
}
~UdpRxSocket() {
delete[] buff;
Shutdown();
}
const char *LastPacket() const noexcept { return buff; }
ssize_t getPacketSize() const noexcept { return packet_size; }
bool ReceivePacket() noexcept { return ReceivePacket(buff); }
bool ReceivePacket(char *dst, int flags = 0) noexcept {
auto bytes_received =
recvfrom(fd, dst, packet_size, flags, nullptr, nullptr);
return bytes_received == packet_size;
}
bool PeekPacket() noexcept{
return ReceivePacket(buff, MSG_PEEK);
}
// Only for backwards compatibility this function will be removed during
// refactoring of the receiver
ssize_t ReceiveDataOnly(char *dst) {
auto r = recvfrom(fd, dst, packet_size, 0, nullptr, nullptr);
constexpr ssize_t eiger_header_packet =
40; // only detector that has this
if (r == eiger_header_packet) {
LOG(logWARNING) << "Got header pkg";
r = recvfrom(fd, dst, packet_size, 0, nullptr, nullptr);
}
return r;
}
ssize_t getBufferSize() const {
uint64_t ret_size = 0;
socklen_t optlen = sizeof(uint64_t);
if (getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &ret_size, &optlen) == -1)
return -1;
else
return ret_size;
}
// Only for backwards compatibility will be removed
ssize_t getActualUDPSocketBufferSize() const { return getBufferSize(); }
// Only for backwards compatibility will be removed
void ShutDownSocket() { Shutdown(); }
void setBufferSize(ssize_t size) {
socklen_t optlen = sizeof(size);
if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, optlen)) {
throw RuntimeError("Could not set socket buffer size");
}
}
void Shutdown() {
shutdown(fd, SHUT_RDWR);
if (fd >= 0) {
close(fd);
fd = -1;
}
}
// Only for backwards compatibility, this drops the EIGER small pkt, may be
// removed
ssize_t ReceiveDataOnly(char *dst) noexcept;
};
} // namespace sls

View File

@ -26,10 +26,10 @@ struct zmqHeader {
uint32_t jsonversion{0};
uint32_t dynamicRange{0};
uint64_t fileIndex{0};
/** number of detectors in x axis */
uint32_t ndetx{0};
/** number of detectors in y axis */
uint32_t ndety{0};
/** number of sockets in x axis */
uint32_t nSocketX{0};
/** number of sockets in y axis */
uint32_t nSocketY{0};
/** number of pixels/channels in x axis for this zmq socket */
uint32_t npixelsx{0};
/** number of pixels/channels in y axis for this zmq socket */

View File

@ -32,6 +32,7 @@
/** default ports */
#define DEFAULT_PORTNO 1952
#define DEFAULT_RX_PORTNO 1954
#define DEFAULT_UDP_PORTNO 50001
#define DEFAULT_ZMQ_CL_PORTNO 30001
#define DEFAULT_ZMQ_RX_PORTNO 30001
@ -175,7 +176,7 @@ class slsDetectorDefs {
struct ROI {
int xmin{-1}; /**< is the roi xmin (in channel number) */
int xmax{-1}; /**< is the roi xmax (in channel number)*/
};
}__attribute__((packed));
#else
typedef struct {
int xmin; /**< is the roi xmin (in channel number) */
@ -203,7 +204,7 @@ class slsDetectorDefs {
int y{0};
xy() = default;
xy(int x, int y):x(x),y(y){};
};
}__attribute__((packed));
#endif
@ -460,6 +461,46 @@ class slsDetectorDefs {
TIMING_EXTERNAL
};
#ifdef __cplusplus
/**
* structure to udpate receiver
*/
struct rxParameters {
detectorType detType{GENERIC};
xy detectorSize;
int moduleId{0};
char hostname[MAX_STR_LENGTH];
int interfaceId{0};
uint32_t zmq_ip{0U};
int udpInterfaces{1};
int udp_dstport{0};
uint32_t udp_dstip{0U};
uint64_t udp_dstmac{0LU};
int udp_dstport2{0};
uint32_t udp_dstip2{0U};
uint64_t udp_dstmac2{0LU};
int64_t frames{0};
int64_t triggers{0};
int64_t bursts{0};
int analogSamples{0};
int digitalSamples{0};
int64_t expTimeNs{0};
int64_t periodNs{0};
int64_t subExpTimeNs{0};
int64_t subDeadTimeNs{0};
int activate{0};
int quad{0};
int dynamicRange{16};
timingMode timMode{AUTO_TIMING};
int tenGiga{0};
readoutMode roMode{ANALOG_ONLY};
uint32_t adcMask{0};
uint32_t adc10gMask{0};
ROI roi;
uint32_t countermask{0};
burstMode burstType{BURST_OFF};
}__attribute__((packed));
#endif
#ifdef __cplusplus
protected:

View File

@ -197,18 +197,18 @@ enum detFuncs{
F_SET_TIMING_SOURCE,
F_GET_NUM_CHANNELS,
F_UPDATE_RATE_CORRECTION,
F_GET_RECEIVER_PARAMETERS,
NUM_DET_FUNCTIONS,
RECEIVER_ENUM_START = 256, /**< detector function should not exceed this (detector server should not compile anyway) */
F_EXEC_RECEIVER_COMMAND,
F_EXIT_RECEIVER,
F_LOCK_RECEIVER,
F_SET_LOCK_RECEIVER,
F_GET_LOCK_RECEIVER,
F_GET_LAST_RECEIVER_CLIENT_IP,
F_SET_RECEIVER_PORT,
F_GET_RECEIVER_VERSION,
F_GET_RECEIVER_TYPE,
F_SEND_RECEIVER_DETHOSTNAME,
F_RECEIVER_SET_ROI,
F_RECEIVER_SET_NUM_FRAMES,
F_SET_RECEIVER_NUM_TRIGGERS,
@ -245,15 +245,16 @@ enum detFuncs{
F_GET_RECEIVER_OVERWRITE,
F_ENABLE_RECEIVER_TEN_GIGA,
F_SET_RECEIVER_FIFO_DEPTH,
F_GET_RECEIVER_FIFO_DEPTH,
F_RECEIVER_ACTIVATE,
F_SET_RECEIVER_STREAMING,
F_GET_RECEIVER_STREAMING,
F_RECEIVER_STREAMING_TIMER,
F_SET_RECEIVER_STREAMING_TIMER,
F_GET_RECEIVER_STREAMING_TIMER,
F_SET_FLIPPED_DATA_RECEIVER,
F_GET_FLIPPED_DATA_RECEIVER,
F_SET_RECEIVER_FILE_FORMAT,
F_GET_RECEIVER_FILE_FORMAT,
F_SEND_RECEIVER_DETPOSID,
F_SEND_RECEIVER_MULTIDETSIZE,
F_SET_RECEIVER_STREAMING_PORT,
F_GET_RECEIVER_STREAMING_PORT,
F_SET_RECEIVER_STREAMING_SRC_IP,
@ -263,8 +264,9 @@ enum detFuncs{
F_RESTREAM_STOP_FROM_RECEIVER,
F_SET_ADDITIONAL_JSON_HEADER,
F_GET_ADDITIONAL_JSON_HEADER,
F_RECEIVER_UDP_SOCK_BUF_SIZE,
F_RECEIVER_REAL_UDP_SOCK_BUF_SIZE,
F_SET_RECEIVER_UDP_SOCK_BUF_SIZE,
F_GET_RECEIVER_UDP_SOCK_BUF_SIZE,
F_GET_RECEIVER_REAL_UDP_SOCK_BUF_SIZE,
F_SET_RECEIVER_FRAMES_PER_FILE,
F_GET_RECEIVER_FRAMES_PER_FILE,
F_RECEIVER_CHECK_VERSION,
@ -283,9 +285,7 @@ enum detFuncs{
F_SET_RECEIVER_QUAD,
F_SET_RECEIVER_READ_N_LINES,
F_SET_RECEIVER_UDP_IP,
F_SET_RECEIVER_UDP_IP2,
F_SET_RECEIVER_UDP_PORT,
F_SET_RECEIVER_UDP_PORT2,
F_SET_RECEIVER_NUM_INTERFACES,
F_RECEIVER_SET_ADC_MASK_10G,
F_RECEIVER_SET_NUM_COUNTERS,
@ -293,6 +293,7 @@ enum detFuncs{
F_SET_ADDITIONAL_JSON_PARAMETER,
F_GET_ADDITIONAL_JSON_PARAMETER,
F_GET_RECEIVER_PROGRESS,
F_SETUP_RECEIVER,
NUM_REC_FUNCTIONS
};
@ -487,18 +488,19 @@ static const char* getFunctionNameFromEnum(enum detFuncs func) {
case F_SET_TIMING_SOURCE: return "F_SET_TIMING_SOURCE";
case F_GET_NUM_CHANNELS: return "F_GET_NUM_CHANNELS";
case F_UPDATE_RATE_CORRECTION: return "F_UPDATE_RATE_CORRECTION";
case F_GET_RECEIVER_PARAMETERS: return "F_GET_RECEIVER_PARAMETERS";
case NUM_DET_FUNCTIONS: return "NUM_DET_FUNCTIONS";
case RECEIVER_ENUM_START: return "RECEIVER_ENUM_START";
case F_EXEC_RECEIVER_COMMAND: return "F_EXEC_RECEIVER_COMMAND";
case F_EXIT_RECEIVER: return "F_EXIT_RECEIVER";
case F_LOCK_RECEIVER: return "F_LOCK_RECEIVER";
case F_SET_LOCK_RECEIVER: return "F_SET_LOCK_RECEIVER";
case F_GET_LOCK_RECEIVER: return "F_GET_LOCK_RECEIVER";
case F_GET_LAST_RECEIVER_CLIENT_IP: return "F_GET_LAST_RECEIVER_CLIENT_IP";
case F_SET_RECEIVER_PORT: return "F_SET_RECEIVER_PORT";
case F_GET_RECEIVER_VERSION: return "F_GET_RECEIVER_VERSION";
case F_GET_RECEIVER_TYPE: return "F_GET_RECEIVER_TYPE";
case F_SEND_RECEIVER_DETHOSTNAME: return "F_SEND_RECEIVER_DETHOSTNAME";
case F_SETUP_RECEIVER: return "F_SETUP_RECEIVER";
case F_RECEIVER_SET_ROI: return "F_RECEIVER_SET_ROI";
case F_RECEIVER_SET_NUM_FRAMES: return "F_RECEIVER_SET_NUM_FRAMES";
case F_SET_RECEIVER_NUM_TRIGGERS: return "F_SET_RECEIVER_NUM_TRIGGERS";
@ -535,15 +537,16 @@ static const char* getFunctionNameFromEnum(enum detFuncs func) {
case F_GET_RECEIVER_OVERWRITE: return "F_GET_RECEIVER_OVERWRITE";
case F_ENABLE_RECEIVER_TEN_GIGA: return "F_ENABLE_RECEIVER_TEN_GIGA";
case F_SET_RECEIVER_FIFO_DEPTH: return "F_SET_RECEIVER_FIFO_DEPTH";
case F_GET_RECEIVER_FIFO_DEPTH: return "F_GET_RECEIVER_FIFO_DEPTH";
case F_RECEIVER_ACTIVATE: return "F_RECEIVER_ACTIVATE";
case F_SET_RECEIVER_STREAMING: return "F_SET_RECEIVER_STREAMING";
case F_GET_RECEIVER_STREAMING: return "F_GET_RECEIVER_STREAMING";
case F_RECEIVER_STREAMING_TIMER: return "F_RECEIVER_STREAMING_TIMER";
case F_SET_RECEIVER_STREAMING_TIMER: return "F_SET_RECEIVER_STREAMING_TIMER";
case F_GET_RECEIVER_STREAMING_TIMER: return "F_GET_RECEIVER_STREAMING_TIMER";
case F_SET_FLIPPED_DATA_RECEIVER: return "F_SET_FLIPPED_DATA_RECEIVER";
case F_GET_FLIPPED_DATA_RECEIVER: return "F_GET_FLIPPED_DATA_RECEIVER";
case F_SET_RECEIVER_FILE_FORMAT: return "F_SET_RECEIVER_FILE_FORMAT";
case F_GET_RECEIVER_FILE_FORMAT: return "F_GET_RECEIVER_FILE_FORMAT";
case F_SEND_RECEIVER_DETPOSID: return "F_SEND_RECEIVER_DETPOSID";
case F_SEND_RECEIVER_MULTIDETSIZE: return "F_SEND_RECEIVER_MULTIDETSIZE";
case F_SET_RECEIVER_STREAMING_PORT: return "F_SET_RECEIVER_STREAMING_PORT";
case F_GET_RECEIVER_STREAMING_PORT: return "F_GET_RECEIVER_STREAMING_PORT";
case F_SET_RECEIVER_STREAMING_SRC_IP: return "F_SET_RECEIVER_STREAMING_SRC_IP";
@ -553,8 +556,9 @@ static const char* getFunctionNameFromEnum(enum detFuncs func) {
case F_RESTREAM_STOP_FROM_RECEIVER: return "F_RESTREAM_STOP_FROM_RECEIVER";
case F_SET_ADDITIONAL_JSON_HEADER: return "F_SET_ADDITIONAL_JSON_HEADER";
case F_GET_ADDITIONAL_JSON_HEADER: return "F_GET_ADDITIONAL_JSON_HEADER";
case F_RECEIVER_UDP_SOCK_BUF_SIZE: return "F_RECEIVER_UDP_SOCK_BUF_SIZE";
case F_RECEIVER_REAL_UDP_SOCK_BUF_SIZE: return "F_RECEIVER_REAL_UDP_SOCK_BUF_SIZE";
case F_SET_RECEIVER_UDP_SOCK_BUF_SIZE: return "F_SET_RECEIVER_UDP_SOCK_BUF_SIZE";
case F_GET_RECEIVER_UDP_SOCK_BUF_SIZE: return "F_GET_RECEIVER_UDP_SOCK_BUF_SIZE";
case F_GET_RECEIVER_REAL_UDP_SOCK_BUF_SIZE: return "F_GET_RECEIVER_REAL_UDP_SOCK_BUF_SIZE";
case F_SET_RECEIVER_FRAMES_PER_FILE: return "F_SET_RECEIVER_FRAMES_PER_FILE";
case F_GET_RECEIVER_FRAMES_PER_FILE: return "F_GET_RECEIVER_FRAMES_PER_FILE";
case F_RECEIVER_CHECK_VERSION: return "F_RECEIVER_CHECK_VERSION";
@ -573,9 +577,7 @@ static const char* getFunctionNameFromEnum(enum detFuncs func) {
case F_SET_RECEIVER_QUAD: return "F_SET_RECEIVER_QUAD";
case F_SET_RECEIVER_READ_N_LINES: return "F_SET_RECEIVER_READ_N_LINES";
case F_SET_RECEIVER_UDP_IP: return "F_SET_RECEIVER_UDP_IP";
case F_SET_RECEIVER_UDP_IP2: return "F_SET_RECEIVER_UDP_IP2";
case F_SET_RECEIVER_UDP_PORT: return "F_SET_RECEIVER_UDP_PORT";
case F_SET_RECEIVER_UDP_PORT2: return "F_SET_RECEIVER_UDP_PORT2";
case F_SET_RECEIVER_NUM_INTERFACES: return "F_SET_RECEIVER_NUM_INTERFACES";
case F_RECEIVER_SET_ADC_MASK_10G: return "F_RECEIVER_SET_ADC_MASK_10G";
case F_RECEIVER_SET_NUM_COUNTERS: return "F_RECEIVER_SET_NUM_COUNTERS";

View File

@ -1,12 +1,12 @@
/** API versions */
#define GITBRANCH "removeshm"
#define APILIB 0x200402
#define APIRECEIVER 0x200402
#define APIGUI 0x200331
#define APICTB 0x200407
#define APIGOTTHARD 0x200407
#define APIGOTTHARD2 0x200407
#define APIJUNGFRAU 0x200407
#define APIMYTHEN3 0x200407
#define APIMOENCH 0x200407
#define APIEIGER 0x200408
#define GITBRANCH "setrxhostname"
#define APILIB 0x200409
#define APIRECEIVER 0x200409
#define APIGUI 0x200409
#define APIEIGER 0x200409
#define APICTB 0x200409
#define APIGOTTHARD 0x200409
#define APIGOTTHARD2 0x200409
#define APIJUNGFRAU 0x200409
#define APIMYTHEN3 0x200409
#define APIMOENCH 0x200409

View File

@ -15,13 +15,13 @@
namespace sls {
DataSocket::DataSocket(int socketId) : socketId_(socketId) {
DataSocket::DataSocket(int socketId) : sockfd_(socketId) {
int value = 1;
setsockopt(socketId_, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(value));
setsockopt(sockfd_, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(value));
}
DataSocket::~DataSocket() {
if (socketId_ <= 0) {
if (sockfd_ <= 0) {
return;
} else {
try {
@ -32,7 +32,7 @@ DataSocket::~DataSocket() {
}
void DataSocket::swap(DataSocket &other) noexcept {
std::swap(socketId_, other.socketId_);
std::swap(sockfd_, other.sockfd_);
}
DataSocket::DataSocket(DataSocket &&move) noexcept { move.swap(*this); }
@ -121,19 +121,23 @@ int DataSocket::setTimeOut(int t_seconds) {
}
void DataSocket::close() {
if (socketId_ > 0) {
if (::close(socketId_)) {
if (sockfd_ > 0) {
if (::close(sockfd_)) {
throw SocketError("could not close socket");
}
socketId_ = -1;
sockfd_ = -1;
} else {
throw std::runtime_error("Socket ERROR: close called on bad socket\n");
}
}
void DataSocket::shutDownSocket() {
shutdown(getSocketId(), SHUT_RDWR);
::shutdown(getSocketId(), SHUT_RDWR);
close();
}
void DataSocket::shutdown(){
::shutdown(sockfd_, SHUT_RDWR);
}
} // namespace sls

View File

@ -0,0 +1,96 @@
#include "UdpRxSocket.h"
#include "network_utils.h"
#include "sls_detector_exceptions.h"
#include <cstdint>
#include <errno.h>
#include <iostream>
#include <netdb.h>
#include <netinet/in.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
namespace sls {
UdpRxSocket::UdpRxSocket(int port, ssize_t packet_size, const char *hostname,
size_t kernel_buffer_size)
: packet_size_(packet_size) {
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = 0;
hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
struct addrinfo *res = 0;
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));
}
sockfd_ = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (sockfd_ == -1) {
throw RuntimeError("Failed to create UDP RX socket");
}
if (bind(sockfd_, res->ai_addr, res->ai_addrlen) == -1) {
throw RuntimeError("Failed to bind UDP RX socket");
}
freeaddrinfo(res);
// If we get a specified buffer size that is larger than the set one
// we set it. Otherwise we leave it there since it could have been
// set by the rx_udpsocksize command
if (kernel_buffer_size) {
auto current = getBufferSize() / 2;
if (current < kernel_buffer_size) {
setBufferSize(kernel_buffer_size);
if (getBufferSize() / 2 < kernel_buffer_size) {
LOG(logWARNING)
<< "Could not set buffer size. Got: " << getBufferSize() / 2
<< " instead of " << kernel_buffer_size;
}
}
}
}
UdpRxSocket::~UdpRxSocket() { Shutdown(); }
ssize_t UdpRxSocket::getPacketSize() const noexcept { return packet_size_; }
bool UdpRxSocket::ReceivePacket(char *dst) noexcept{
auto bytes_received =
recvfrom(sockfd_, dst, packet_size_, 0, nullptr, nullptr);
return bytes_received == packet_size_;
}
ssize_t UdpRxSocket::ReceiveDataOnly(char *dst) noexcept {
auto r = recvfrom(sockfd_, dst, packet_size_, 0, nullptr, nullptr);
constexpr ssize_t eiger_header_packet =
40; // only detector that has this
if (r == eiger_header_packet) {
LOG(logWARNING) << "Got header pkg";
r = recvfrom(sockfd_, dst, packet_size_, 0, nullptr, nullptr);
}
return r;
}
size_t UdpRxSocket::getBufferSize() const {
size_t 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");
return ret;
}
void UdpRxSocket::setBufferSize(ssize_t size) {
if (setsockopt(sockfd_, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)))
throw RuntimeError("Could not set socket buffer size");
}
void UdpRxSocket::Shutdown() {
shutdown(sockfd_, SHUT_RDWR);
if (sockfd_ >= 0) {
close(sockfd_);
sockfd_ = -1;
}
}
} // namespace sls

View File

@ -187,8 +187,8 @@ int ZmqSocket::SendHeader(
header.jsonversion,
header.dynamicRange,
header.fileIndex,
header.ndetx,
header.ndety,
header.nSocketX,
header.nSocketY,
header.npixelsx,
header.npixelsy,
header.imageSize,
@ -319,8 +319,8 @@ int ZmqSocket::ParseHeader(const int index, int length, char *buff,
zHeader.data = ((document["data"].GetUint()) == 0) ? false : true;
zHeader.dynamicRange = document["bitmode"].GetUint();
zHeader.fileIndex = document["fileIndex"].GetUint64();
zHeader.ndetx = document["detshape"][0].GetUint();
zHeader.ndety = document["detshape"][1].GetUint();
zHeader.nSocketX = document["detshape"][0].GetUint();
zHeader.nSocketY = document["detshape"][1].GetUint();
zHeader.npixelsx = document["shape"][0].GetUint();
zHeader.npixelsy = document["shape"][1].GetUint();
zHeader.imageSize = document["size"].GetUint();

View File

@ -109,7 +109,7 @@ TEST_CASE("run status"){
using defs = slsDetectorDefs;
REQUIRE(ToString(defs::runStatus::ERROR) == "error");
REQUIRE(ToString(defs::runStatus::WAITING) == "waiting");
REQUIRE(ToString(defs::runStatus::TRANSMITTING) == "data"); //??
REQUIRE(ToString(defs::runStatus::TRANSMITTING) == "transmitting");
REQUIRE(ToString(defs::runStatus::RUN_FINISHED) == "finished");
REQUIRE(ToString(defs::runStatus::STOPPED) == "stopped");
REQUIRE(ToString(defs::runStatus::IDLE) == "idle");

View File

@ -4,6 +4,14 @@
#include <future>
#include <thread>
#include <vector>
#include <cstdint>
#include <errno.h>
#include <iostream>
#include <netdb.h>
#include <netinet/in.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
constexpr int default_port = 50001;
@ -29,46 +37,49 @@ int open_socket(int port) {
throw sls::RuntimeError("Failed to create UDP RX socket");
}
if (connect(fd, res->ai_addr, res->ai_addrlen)){
if (connect(fd, res->ai_addr, res->ai_addrlen)) {
throw sls::RuntimeError("Failed to connect socket");
}
freeaddrinfo(res);
return fd;
}
TEST_CASE("Receive data on localhost") {
TEST_CASE("Get packet size returns the packet size we set in the constructor"){
constexpr int port = 50001;
constexpr ssize_t packet_size = 8000;
sls::UdpRxSocket s{port, packet_size};
CHECK(s.getPacketSize() == packet_size);
}
TEST_CASE("Receive data from a vector") {
constexpr int port = 50001;
std::vector<int> data_to_send{4, 5, 3, 2, 5, 7, 2, 3};
std::vector<int> data_received(data_to_send.size());
ssize_t packet_size =
sizeof(decltype(data_to_send)::value_type) * data_to_send.size();
sls::UdpRxSocket udpsock{port, packet_size};
int fd = open_socket(port);
auto n = write(fd, data_to_send.data(), packet_size);
CHECK(n == packet_size);
CHECK(udpsock.ReceivePacket());
CHECK(udpsock.ReceivePacket((char*)data_received.data()));
close(fd);
// Copy data from buffer and compare values
std::vector<int> data_received(data_to_send.size());
memcpy(data_received.data(), udpsock.LastPacket(), udpsock.getPacketSize());
CHECK(data_received.size() == data_to_send.size()); // sanity check
for (size_t i = 0; i != data_to_send.size(); ++i) {
CHECK(data_to_send[i] == data_received[i]);
}
CHECK(data_to_send == data_received);
}
TEST_CASE("Shutdown socket without hanging when waiting for data") {
constexpr int port = 50001;
constexpr ssize_t packet_size = 8000;
sls::UdpRxSocket s{port, packet_size};
char buff[packet_size];
// Start a thread and wait for package
// if the socket is left open we would block
std::future<bool> ret =
std::async(static_cast<bool (sls::UdpRxSocket::*)()>(
&sls::UdpRxSocket::ReceivePacket),
&s);
std::async(&sls::UdpRxSocket::ReceivePacket, &s, (char *)&buff);
s.Shutdown();
auto r = ret.get();
@ -76,60 +87,23 @@ TEST_CASE("Shutdown socket without hanging when waiting for data") {
CHECK(r == false); // since we didn't get the packet
}
TEST_CASE("Too small packet"){
TEST_CASE("Too small packet") {
constexpr int port = 50001;
sls::UdpRxSocket s(port, 2*sizeof(uint32_t));
sls::UdpRxSocket s(port, 2 * sizeof(uint32_t));
auto fd = open_socket(port);
uint32_t val = 10;
write(fd, &val, sizeof(val));
CHECK(s.ReceivePacket() == false);
uint32_t buff[2];
CHECK(s.ReceivePacket((char *)&buff) == false);
close(fd);
}
TEST_CASE("Receive an int to internal buffer"){
TEST_CASE("Receive an int to an external buffer") {
int to_send = 5;
int received = -1;
auto fd = open_socket(default_port);
sls::UdpRxSocket s(default_port, sizeof(int));
write(fd, &to_send, sizeof(to_send));
CHECK(s.ReceivePacket());
memcpy(&received, s.LastPacket(), sizeof(int));
CHECK(s.ReceivePacket(reinterpret_cast<char *>(&received)));
CHECK(received == to_send);
}
TEST_CASE("Receive an int to an external buffer"){
int to_send = 5;
int received = -1;
auto fd = open_socket(default_port);
sls::UdpRxSocket s(default_port, sizeof(int));
write(fd, &to_send, sizeof(to_send));
CHECK(s.ReceivePacket(reinterpret_cast<char*>(&received)));
CHECK(received == to_send);
}
TEST_CASE("PEEK data"){
int to_send = 5;
int to_send2 = 12;
int received = -1;
auto fd = open_socket(default_port);
sls::UdpRxSocket s(default_port, sizeof(int));
write(fd, &to_send, sizeof(to_send));
write(fd, &to_send2, sizeof(to_send));
CHECK(s.PeekPacket());
memcpy(&received, s.LastPacket(), sizeof(int));
CHECK(received == to_send);
CHECK(s.PeekPacket());
memcpy(&received, s.LastPacket(), sizeof(int));
CHECK(received == to_send);
CHECK(s.ReceivePacket());
memcpy(&received, s.LastPacket(), sizeof(int));
CHECK(received == to_send);
CHECK(s.ReceivePacket());
memcpy(&received, s.LastPacket(), sizeof(int));
CHECK(received == to_send2);
}