mirror of
https://github.com/slsdetectorgroup/slsDetectorPackage.git
synced 2026-11-03 14:52:25 +01:00
dev: zmq hwm rebind (#1480)
* move hwm into the zmq constructor and reconstruct the socket instead of rebind. seems to work better than rebind (most connections cant bind so fast?) * fix after merge * added tests to reconnect zmq sockets when setting rx zmqport and rx zmqhwm, changed the tests scripts a bit to make the receiver starting tcp port configurable * tests: slsreceiver also starting up with 2000 as default tcp port, using latest cli args for receiver and multi receiver * releasr notes --------- Co-authored-by: AliceMazzoleni99 <alice.mazzoleni@psi.ch>
This commit is contained in:
1 parent
3a780271c6
commit
9c0bfe3517
13 files changed
+231
-121
No files matched your search
@@ -15,10 +15,11 @@ namespace sls {
|
||||
|
||||
using namespace rapidjson;
|
||||
ZmqSocket::ZmqSocket(const char *const hostname_or_ip,
|
||||
const uint16_t portnumber)
|
||||
const uint16_t portnumber, int hwm)
|
||||
: portno(portnumber), sockfd(false) {
|
||||
// Extra check that throws if conversion fails, could be removed
|
||||
auto ipstr = HostnameToIp(hostname_or_ip).str();
|
||||
|
||||
std::ostringstream oss;
|
||||
oss << "tcp://" << ipstr << ":" << portno;
|
||||
sockfd.serverAddress = oss.str();
|
||||
@@ -27,20 +28,23 @@ ZmqSocket::ZmqSocket(const char *const hostname_or_ip,
|
||||
// create context
|
||||
sockfd.contextDescriptor = zmq_ctx_new();
|
||||
if (sockfd.contextDescriptor == nullptr)
|
||||
throw ZmqSocketError("Could not create contextDescriptor");
|
||||
throw ZmqSocketError("Could not create contextDescriptor for " +
|
||||
sockfd.serverAddress);
|
||||
|
||||
// create subscriber
|
||||
sockfd.socketDescriptor = zmq_socket(sockfd.contextDescriptor, ZMQ_SUB);
|
||||
if (sockfd.socketDescriptor == nullptr) {
|
||||
PrintError();
|
||||
throw ZmqSocketError("Could not create socket");
|
||||
throw ZmqSocketError("Could not create socket for " +
|
||||
sockfd.serverAddress);
|
||||
}
|
||||
|
||||
// Socket Options provided above
|
||||
// an empty string implies receiving any messages
|
||||
if (zmq_setsockopt(sockfd.socketDescriptor, ZMQ_SUBSCRIBE, "", 0)) {
|
||||
PrintError();
|
||||
throw ZmqSocketError("Could set socket opt");
|
||||
throw ZmqSocketError("Could set socket opt for " +
|
||||
sockfd.serverAddress);
|
||||
}
|
||||
// ZMQ_LINGER default is already -1 means no messages discarded. use this
|
||||
// options if optimizing required ZMQ_SNDHWM default is 0 means no limit.
|
||||
@@ -49,7 +53,8 @@ ZmqSocket::ZmqSocket(const char *const hostname_or_ip,
|
||||
if (zmq_setsockopt(sockfd.socketDescriptor, ZMQ_LINGER, &value,
|
||||
sizeof(value))) {
|
||||
PrintError();
|
||||
throw ZmqSocketError("Could not set ZMQ_LINGER");
|
||||
throw ZmqSocketError("Could not set ZMQ_LINGER for " +
|
||||
sockfd.serverAddress);
|
||||
}
|
||||
LOG(logDEBUG) << "Default receive high water mark:"
|
||||
<< GetReceiveHighWaterMark();
|
||||
@@ -59,38 +64,47 @@ ZmqSocket::ZmqSocket(const char *const hostname_or_ip,
|
||||
if (zmq_setsockopt(sockfd.socketDescriptor, ZMQ_IPV6, &ipv6,
|
||||
sizeof(ipv6))) {
|
||||
PrintError();
|
||||
throw ZmqSocketError("Could not set ZMQ_IPV6");
|
||||
throw ZmqSocketError("Could not set ZMQ_IPV6 for " +
|
||||
sockfd.serverAddress);
|
||||
}
|
||||
|
||||
// set hwm if not default
|
||||
if (hwm >= 0) {
|
||||
SetReceiveHighWaterMark(hwm);
|
||||
}
|
||||
}
|
||||
|
||||
ZmqSocket::ZmqSocket(const uint16_t portnumber)
|
||||
ZmqSocket::ZmqSocket(const uint16_t portnumber, int hwm)
|
||||
: portno(portnumber), sockfd(true) {
|
||||
|
||||
// create context
|
||||
sockfd.contextDescriptor = zmq_ctx_new();
|
||||
if (sockfd.contextDescriptor == nullptr)
|
||||
throw ZmqSocketError("Could not create contextDescriptor");
|
||||
|
||||
// create publisher
|
||||
sockfd.socketDescriptor = zmq_socket(sockfd.contextDescriptor, ZMQ_PUB);
|
||||
if (sockfd.socketDescriptor == nullptr) {
|
||||
PrintError();
|
||||
throw ZmqSocketError("Could not create socket");
|
||||
}
|
||||
LOG(logDEBUG) << "Default send high water mark:" << GetSendHighWaterMark();
|
||||
|
||||
// construct address, can be refactored with libfmt
|
||||
std::ostringstream oss;
|
||||
oss << "tcp://" << ZMQ_PUBLISHER_IP << ":" << portno;
|
||||
sockfd.serverAddress = oss.str();
|
||||
LOG(logDEBUG) << "zmq address: " << sockfd.serverAddress;
|
||||
|
||||
// create context
|
||||
sockfd.contextDescriptor = zmq_ctx_new();
|
||||
if (sockfd.contextDescriptor == nullptr)
|
||||
throw ZmqSocketError("Could not create contextDescriptor for " +
|
||||
sockfd.serverAddress);
|
||||
|
||||
// create publisher
|
||||
sockfd.socketDescriptor = zmq_socket(sockfd.contextDescriptor, ZMQ_PUB);
|
||||
if (sockfd.socketDescriptor == nullptr) {
|
||||
PrintError();
|
||||
throw ZmqSocketError("Could not create socket for " +
|
||||
sockfd.serverAddress);
|
||||
}
|
||||
LOG(logDEBUG) << "Default send high water mark:" << GetSendHighWaterMark();
|
||||
|
||||
// enable IPv6 addresses
|
||||
int ipv6 = 1;
|
||||
if (zmq_setsockopt(sockfd.socketDescriptor, ZMQ_IPV6, &ipv6,
|
||||
sizeof(ipv6))) {
|
||||
PrintError();
|
||||
throw ZmqSocketError("Could not set ZMQ_IPV6");
|
||||
throw ZmqSocketError("Could not set ZMQ_IPV6 for " +
|
||||
sockfd.serverAddress);
|
||||
}
|
||||
|
||||
// Socket Options for keepalive
|
||||
@@ -99,34 +113,45 @@ ZmqSocket::ZmqSocket(const uint16_t portnumber)
|
||||
if (zmq_setsockopt(sockfd.socketDescriptor, ZMQ_TCP_KEEPALIVE, &keepalive,
|
||||
sizeof(keepalive))) {
|
||||
PrintError();
|
||||
throw ZmqSocketError("Could set socket opt ZMQ_TCP_KEEPALIVE");
|
||||
throw ZmqSocketError("Could set socket opt ZMQ_TCP_KEEPALIVE for " +
|
||||
sockfd.serverAddress);
|
||||
}
|
||||
// set the number of keepalives before death
|
||||
keepalive = 10;
|
||||
if (zmq_setsockopt(sockfd.socketDescriptor, ZMQ_TCP_KEEPALIVE_CNT,
|
||||
&keepalive, sizeof(keepalive))) {
|
||||
PrintError();
|
||||
throw ZmqSocketError("Could set socket opt ZMQ_TCP_KEEPALIVE_CNT");
|
||||
throw ZmqSocketError("Could set socket opt ZMQ_TCP_KEEPALIVE_CNT for " +
|
||||
sockfd.serverAddress);
|
||||
}
|
||||
// set the time before the first keepalive
|
||||
keepalive = 60;
|
||||
if (zmq_setsockopt(sockfd.socketDescriptor, ZMQ_TCP_KEEPALIVE_IDLE,
|
||||
&keepalive, sizeof(keepalive))) {
|
||||
PrintError();
|
||||
throw ZmqSocketError("Could set socket opt ZMQ_TCP_KEEPALIVE_IDLE");
|
||||
throw ZmqSocketError(
|
||||
"Could set socket opt ZMQ_TCP_KEEPALIVE_IDLE for " +
|
||||
sockfd.serverAddress);
|
||||
}
|
||||
// set the interval between keepalives
|
||||
keepalive = 1;
|
||||
if (zmq_setsockopt(sockfd.socketDescriptor, ZMQ_TCP_KEEPALIVE_INTVL,
|
||||
&keepalive, sizeof(keepalive))) {
|
||||
PrintError();
|
||||
throw ZmqSocketError("Could set socket opt ZMQ_TCP_KEEPALIVE_INTVL");
|
||||
throw ZmqSocketError(
|
||||
"Could set socket opt ZMQ_TCP_KEEPALIVE_INTVL for " +
|
||||
sockfd.serverAddress);
|
||||
}
|
||||
// set hwm if not default
|
||||
if (hwm >= 0) {
|
||||
SetSendHighWaterMark(hwm);
|
||||
}
|
||||
|
||||
// bind address
|
||||
if (zmq_bind(sockfd.socketDescriptor, sockfd.serverAddress.c_str())) {
|
||||
PrintError();
|
||||
throw ZmqSocketError("Could not bind socket");
|
||||
throw ZmqSocketError("Could not bind socket for " +
|
||||
sockfd.serverAddress);
|
||||
}
|
||||
// sleep to allow a slow-joiner
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
||||
@@ -138,7 +163,8 @@ int ZmqSocket::GetSendHighWaterMark() {
|
||||
if (zmq_getsockopt(sockfd.socketDescriptor, ZMQ_SNDHWM, &value,
|
||||
&value_size)) {
|
||||
PrintError();
|
||||
throw ZmqSocketError("Could not get ZMQ_SNDHWM");
|
||||
throw ZmqSocketError("Could not get ZMQ_SNDHWM for " +
|
||||
sockfd.serverAddress);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
@@ -147,10 +173,13 @@ void ZmqSocket::SetSendHighWaterMark(int limit) {
|
||||
if (zmq_setsockopt(sockfd.socketDescriptor, ZMQ_SNDHWM, &limit,
|
||||
sizeof(limit))) {
|
||||
PrintError();
|
||||
throw ZmqSocketError("Could not set ZMQ_SNDHWM");
|
||||
throw ZmqSocketError("Could not set ZMQ_SNDHWM for " +
|
||||
sockfd.serverAddress + " to " +
|
||||
std::to_string(limit));
|
||||
}
|
||||
if (GetSendHighWaterMark() != limit) {
|
||||
throw ZmqSocketError("Could not set ZMQ_SNDHWM to " +
|
||||
throw ZmqSocketError("Could not set ZMQ_SNDHWM for " +
|
||||
sockfd.serverAddress + " to " +
|
||||
std::to_string(limit));
|
||||
}
|
||||
|
||||
@@ -167,7 +196,8 @@ int ZmqSocket::GetReceiveHighWaterMark() {
|
||||
if (zmq_getsockopt(sockfd.socketDescriptor, ZMQ_RCVHWM, &value,
|
||||
&value_size)) {
|
||||
PrintError();
|
||||
throw ZmqSocketError("Could not get ZMQ_RCVHWM");
|
||||
throw ZmqSocketError("Could not get ZMQ_RCVHWM for " +
|
||||
sockfd.serverAddress);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
@@ -176,10 +206,13 @@ void ZmqSocket::SetReceiveHighWaterMark(int limit) {
|
||||
if (zmq_setsockopt(sockfd.socketDescriptor, ZMQ_RCVHWM, &limit,
|
||||
sizeof(limit))) {
|
||||
PrintError();
|
||||
throw ZmqSocketError("Could not set ZMQ_RCVHWM");
|
||||
throw ZmqSocketError("Could not set ZMQ_RCVHWM for " +
|
||||
sockfd.serverAddress + " to " +
|
||||
std::to_string(limit));
|
||||
}
|
||||
if (GetReceiveHighWaterMark() != limit) {
|
||||
throw ZmqSocketError("Could not set ZMQ_RCVHWM to " +
|
||||
throw ZmqSocketError("Could not set ZMQ_RCVHWM for " +
|
||||
sockfd.serverAddress + " to " +
|
||||
std::to_string(limit));
|
||||
}
|
||||
int bufsize = DEFAULT_ZMQ_BUFFERSIZE;
|
||||
@@ -195,7 +228,8 @@ int ZmqSocket::GetSendBuffer() {
|
||||
if (zmq_getsockopt(sockfd.socketDescriptor, ZMQ_SNDBUF, &value,
|
||||
&value_size)) {
|
||||
PrintError();
|
||||
throw ZmqSocketError("Could not get ZMQ_SNDBUF");
|
||||
throw ZmqSocketError("Could not get ZMQ_SNDBUF for " +
|
||||
sockfd.serverAddress);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
@@ -204,10 +238,13 @@ void ZmqSocket::SetSendBuffer(int limit) {
|
||||
if (zmq_setsockopt(sockfd.socketDescriptor, ZMQ_SNDBUF, &limit,
|
||||
sizeof(limit))) {
|
||||
PrintError();
|
||||
throw ZmqSocketError("Could not set ZMQ_SNDBUF");
|
||||
throw ZmqSocketError("Could not set ZMQ_SNDBUF for " +
|
||||
sockfd.serverAddress + " to " +
|
||||
std::to_string(limit));
|
||||
}
|
||||
if (GetSendBuffer() != limit) {
|
||||
throw ZmqSocketError("Could not set ZMQ_SNDBUF to " +
|
||||
throw ZmqSocketError("Could not set ZMQ_SNDBUF for " +
|
||||
sockfd.serverAddress + " to " +
|
||||
std::to_string(limit));
|
||||
}
|
||||
}
|
||||
@@ -218,7 +255,8 @@ int ZmqSocket::GetReceiveBuffer() {
|
||||
if (zmq_getsockopt(sockfd.socketDescriptor, ZMQ_RCVBUF, &value,
|
||||
&value_size)) {
|
||||
PrintError();
|
||||
throw ZmqSocketError("Could not get ZMQ_RCVBUF");
|
||||
throw ZmqSocketError("Could not get ZMQ_RCVBUF for " +
|
||||
sockfd.serverAddress);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
@@ -227,10 +265,13 @@ void ZmqSocket::SetReceiveBuffer(int limit) {
|
||||
if (zmq_setsockopt(sockfd.socketDescriptor, ZMQ_RCVBUF, &limit,
|
||||
sizeof(limit))) {
|
||||
PrintError();
|
||||
throw ZmqSocketError("Could not set ZMQ_RCVBUF");
|
||||
throw ZmqSocketError("Could not set ZMQ_RCVBUF for " +
|
||||
sockfd.serverAddress + " to " +
|
||||
std::to_string(limit));
|
||||
}
|
||||
if (GetReceiveBuffer() != limit) {
|
||||
throw ZmqSocketError("Could not set ZMQ_RCVBUF to " +
|
||||
throw ZmqSocketError("Could not set ZMQ_RCVBUF for " +
|
||||
sockfd.serverAddress + " to " +
|
||||
std::to_string(limit));
|
||||
}
|
||||
}
|
||||
@@ -242,12 +283,14 @@ void ZmqSocket::Rebind() {
|
||||
// unbbind
|
||||
if (zmq_unbind(sockfd.socketDescriptor, sockfd.serverAddress.c_str())) {
|
||||
PrintError();
|
||||
throw ZmqSocketError("Could not unbind socket");
|
||||
throw ZmqSocketError("Could not unbind socket for " +
|
||||
sockfd.serverAddress);
|
||||
}
|
||||
// bind address
|
||||
if (zmq_bind(sockfd.socketDescriptor, sockfd.serverAddress.c_str())) {
|
||||
PrintError();
|
||||
throw ZmqSocketError("Could not bind socket");
|
||||
throw ZmqSocketError("Could not bind socket for " +
|
||||
sockfd.serverAddress);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user