Belle II Software light-2607-kasei
ZMQClient Class Reference

A helper class for communicating over ZMQ. Includes a multicast and (if needed) also a data socket. More...

#include <ZMQClient.h>

Collaboration diagram for ZMQClient:

Public Member Functions

template<int AZMQType>
void initialize (const std::string &pubSocketAddress, const std::string &subSocketAddress, const std::string &socketAddress, bool bind)
 Initialize the multicast and a data socket of the given type.
 
void initialize (const std::string &pubSocketAddress, const std::string &subSocketAddress)
 Initialize only the multicast.
 
void terminate (bool sendGoodbye=true)
 Terminate the sockets properly.
 
void reset ()
 Reset the sockets. ATTENTION: this does not close the sockets! Use only after forks to not clean up to times.
 
void subscribe (EMessageTypes messageType)
 Subscribe to the given multicast message type.
 
template<class AZMQMessage>
void send (AZMQMessage message) const
 Send a message over the data socket.
 
void send (zmq::message_t &message) const
 Send a zmq message over the data socket. ATTENTION: we are taking ownership here!
 
template<class AZMQMessage>
void publish (AZMQMessage message) const
 Publish the message to the multicast.
 
bool isOnline () const
 Check if the client was initialized and not terminated.
 
template<class AMulticastAnswer, class ASocketAnswer>
int poll (unsigned int timeout, AMulticastAnswer multicastAnswer, ASocketAnswer socketAnswer) const
 Poll both the multicast and the data socket until, either:
 
template<class ASocketAnswer>
int pollSocket (unsigned int timeout, ASocketAnswer socketAnswer) const
 Poll method to only the data socket.
 
template<class AMulticastAnswer>
int pollMulticast (unsigned int timeout, AMulticastAnswer multicastAnswer) const
 Poll method to only the multicast socket.
 

Static Private Member Functions

static int pollSocketVector (const std::vector< zmq::socket_t * > &socketList, int timeout)
 Internal poll function.
 

Private Attributes

std::unique_ptr< zmq::context_t > m_context
 ZMQ context.
 
std::vector< zmq::socket_t * > m_pollSocketPtrList
 Will use this vector for polling.
 
std::unique_ptr< zmq::socket_t > m_pubSocket
 ZMQ Pub socket.
 
std::unique_ptr< zmq::socket_t > m_subSocket
 ZMQ sub socket.
 
std::unique_ptr< zmq::socket_t > m_socket
 ZMQ socket.
 

Detailed Description

A helper class for communicating over ZMQ. Includes a multicast and (if needed) also a data socket.

Definition at line 22 of file ZMQClient.h.

Member Function Documentation

◆ initialize() [1/2]

void initialize ( const std::string & pubSocketAddress,
const std::string & subSocketAddress )

Initialize only the multicast.

Definition at line 87 of file ZMQClient.cc.

88{
89 m_context = std::make_unique<zmq::context_t>(1);
90 m_pubSocket = std::make_unique<zmq::socket_t>(*m_context, ZMQ_PUB);
91 m_subSocket = std::make_unique<zmq::socket_t>(*m_context, ZMQ_SUB);
92
93 m_pubSocket->connect(pubSocketAddress);
94 m_pubSocket->set(zmq::sockopt::linger, 0);
95
96 m_subSocket->connect(subSocketAddress);
97 m_subSocket->set(zmq::sockopt::linger, 0);
98
99 B2DEBUG(200, "Having initialized multicast with sub on " << subSocketAddress << " and pub on " << pubSocketAddress);
100
101 std::this_thread::sleep_for(std::chrono::milliseconds(10));
102
103 m_pollSocketPtrList.clear();
104 m_pollSocketPtrList.push_back(m_subSocket.get());
105}
std::unique_ptr< zmq::socket_t > m_subSocket
ZMQ sub socket.
Definition ZMQClient.h:107
std::unique_ptr< zmq::socket_t > m_pubSocket
ZMQ Pub socket.
Definition ZMQClient.h:105
std::unique_ptr< zmq::context_t > m_context
ZMQ context.
Definition ZMQClient.h:99
std::vector< zmq::socket_t * > m_pollSocketPtrList
Will use this vector for polling.
Definition ZMQClient.h:102

◆ initialize() [2/2]

template<int AZMQType>
template void initialize< ZMQ_PUB > ( const std::string & pubSocketAddress,
const std::string & subSocketAddress,
const std::string & socketAddress,
bool bind )

Initialize the multicast and a data socket of the given type.

Definition at line 61 of file ZMQClient.cc.

63{
64 initialize(pubSocketAddress, subSocketAddress);
65 m_socket = std::make_unique<zmq::socket_t>(*m_context, AZMQType);
66
67 if (AZMQType == ZMQ_DEALER) {
68 const std::string uniqueID = std::to_string(getpid());
69 m_socket->set(zmq::sockopt::routing_id, uniqueID);
70 }
71
72 m_socket->set(zmq::sockopt::linger, 0);
73 if (bind) {
74 m_socket->bind(socketAddress.c_str());
75 } else {
76 m_socket->connect(socketAddress.c_str());
77 }
78
79 // Give the sockets some time to start
80 std::this_thread::sleep_for(std::chrono::milliseconds(10));
81
82 B2DEBUG(100, "Created socket: " << socketAddress);
83
84 m_pollSocketPtrList.push_back(m_socket.get());
85}
void initialize(const std::string &pubSocketAddress, const std::string &subSocketAddress, const std::string &socketAddress, bool bind)
Initialize the multicast and a data socket of the given type.
Definition ZMQClient.cc:61
std::unique_ptr< zmq::socket_t > m_socket
ZMQ socket.
Definition ZMQClient.h:109

◆ isOnline()

bool isOnline ( ) const
inline

Check if the client was initialized and not terminated.

Definition at line 59 of file ZMQClient.h.

60 {
61 return m_context.get();
62 }

◆ pollSocketVector()

int pollSocketVector ( const std::vector< zmq::socket_t * > & socketList,
int timeout )
staticprivate

Internal poll function.

Definition at line 126 of file ZMQClient.cc.

127{
128 auto start = std::chrono::system_clock::now();
129 int return_bitmask = 0;
130 assert(socketList.size() <= 2);
131 std::vector<zmq::pollitem_t> items(socketList.size());
132
133 for (unsigned int i = 0; i < socketList.size(); i++) {
134 items[i].socket = static_cast<void*>(*socketList[i]);
135 items[i].events = ZMQ_POLLIN;
136 items[i].revents = 0;
137 }
138
139 while (timeout >= 0) {
140 try {
141 zmq::poll(items.data(), socketList.size(), timeout);
142
143 for (unsigned int i = 0; i < socketList.size(); i++) {
144 if (static_cast<bool>(items[i].revents & ZMQ_POLLIN)) {
145 return_bitmask = return_bitmask | 1 << i;
146 }
147 }
148 return return_bitmask;
149 } catch (zmq::error_t& error) {
150 if (error.num() == EINTR) {
151 auto now = std::chrono::system_clock::now();
152 timeout -= std::chrono::duration_cast<std::chrono::milliseconds>(now - start).count();
153 } else {
154 // cannot handle, rethrow exception
155 throw;
156 }
157 }
158 }
159 return 0;
160}

◆ publish()

template<class AZMQMessage>
void publish ( AZMQMessage message) const
inline

Publish the message to the multicast.

Definition at line 53 of file ZMQClient.h.

54 {
55 AZMQMessage::element_type::toSocket(std::move(message), m_pubSocket);
56 }

◆ reset()

void reset ( )

Reset the sockets. ATTENTION: this does not close the sockets! Use only after forks to not clean up to times.

Definition at line 48 of file ZMQClient.cc.

49{
50 // Deliberately give up ownership without destructing: see the comment in terminate().
51 // cppcheck-suppress-begin ignoredReturnValue
52 m_context.release();
53 m_subSocket.release();
54 m_pubSocket.release();
55 m_socket.release();
56 // cppcheck-suppress-end ignoredReturnValue
57}

◆ send() [1/2]

template<class AZMQMessage>
void send ( AZMQMessage message) const
inline

Send a message over the data socket.

Definition at line 43 of file ZMQClient.h.

44 {
45 AZMQMessage::element_type::toSocket(std::move(message), m_socket);
46 }

◆ send() [2/2]

void send ( zmq::message_t & message) const

Send a zmq message over the data socket. ATTENTION: we are taking ownership here!

Definition at line 116 of file ZMQClient.cc.

117{
118 B2ASSERT("Can only run this on started clients", m_socket);
119 m_socket->send(message, zmq::send_flags::none);
120}

◆ subscribe()

void subscribe ( EMessageTypes messageType)

Subscribe to the given multicast message type.

Definition at line 107 of file ZMQClient.cc.

108{
109 B2ASSERT("Can only run this on started clients", m_subSocket);
110 char char_filter[2];
111 char_filter[0] = static_cast<char>(filter);
112 char_filter[1] = 0;
113 m_subSocket->set(zmq::sockopt::subscribe, char_filter);
114}

◆ terminate()

void terminate ( bool sendGoodbye = true)

Terminate the sockets properly.

Definition at line 18 of file ZMQClient.cc.

19{
20 if (m_pubSocket and sendGoodbye) {
21 auto multicastMessage = ZMQMessageFactory::createMessage(EMessageTypes::c_terminateMessage, getpid());
22 publish(std::move(multicastMessage));
23 }
24
25 // The sockets and the context are deliberately released and not destructed:
26 // running the ZMQ destructors in a forked process would also tear down the
27 // file descriptors still used by the parent process.
28 // cppcheck-suppress-begin ignoredReturnValue
29 if (m_socket) {
30 m_socket->close();
31 m_socket.release();
32 }
33 if (m_pubSocket) {
34 m_pubSocket->close();
35 m_pubSocket.release();
36 }
37 if (m_subSocket) {
38 m_subSocket->close();
39 m_subSocket.release();
40 }
41 if (m_context) {
42 m_context->close();
43 m_context.release();
44 }
45 // cppcheck-suppress-end ignoredReturnValue
46}
void publish(AZMQMessage message) const
Publish the message to the multicast.
Definition ZMQClient.h:53
static auto createMessage(const std::string &msgIdentity, const EMessageTypes msgType, const std::unique_ptr< EvtMessage > &eventMessage)
Create an ID Message out of an identity, the type and an event message.

Member Data Documentation

◆ m_context

std::unique_ptr<zmq::context_t> m_context
private

ZMQ context.

Definition at line 99 of file ZMQClient.h.

◆ m_pollSocketPtrList

std::vector<zmq::socket_t*> m_pollSocketPtrList
private

Will use this vector for polling.

Definition at line 102 of file ZMQClient.h.

◆ m_pubSocket

std::unique_ptr<zmq::socket_t> m_pubSocket
private

ZMQ Pub socket.

Definition at line 105 of file ZMQClient.h.

◆ m_socket

std::unique_ptr<zmq::socket_t> m_socket
private

ZMQ socket.

Definition at line 109 of file ZMQClient.h.

◆ m_subSocket

std::unique_ptr<zmq::socket_t> m_subSocket
private

ZMQ sub socket.

Definition at line 107 of file ZMQClient.h.


The documentation for this class was generated from the following files: