artdaq  v3_02_00
RequestSender_t.cc
1 #define TRACE_NAME "RequestSender_t"
2 
3 #include "artdaq/DAQrate/RequestSender.hh"
4 
5 #define BOOST_TEST_MODULE RequestSender_t
6 #include "cetlib/quiet_unit_test.hpp"
7 #include "cetlib_except/exception.h"
9 #include "artdaq/DAQrate/detail/RoutingPacket.hh"
11 #include <sys/poll.h>
12 
13 
14 BOOST_AUTO_TEST_SUITE(RequestSender_test)
15 
16 #define TRACE_REQUIRE_EQUAL(l,r) do { \
17 if(l == r) { \
18 TLOG(TLVL_DEBUG) << __LINE__ << ": Checking if " << #l << " (" << std::to_string(l) << ") equals " << #r << " (" << std::to_string(r) << ")...YES!" ; \
19 } \
20 else \
21 { \
22  TLOG(TLVL_ERROR) << __LINE__ << ": Checking if " << #l << " (" << std::to_string(l) << ") equals " << #r << " (" << std::to_string(r) << ")...NO!" ; \
23 } \
24  BOOST_REQUIRE_EQUAL(l, r); \
25 } while(0)
26 
27 BOOST_AUTO_TEST_CASE(Construct)
28 {
29  artdaq::configureMessageFacility("RequestSender_t", true, true);
30  TLOG(TLVL_INFO) << "Construct Test Case BEGIN" ;
31  fhicl::ParameterSet pset;
32  artdaq::RequestSender t(pset);
33  BOOST_REQUIRE_EQUAL(t.GetRequestMode(), artdaq::detail::RequestMessageMode::Normal);
34  TLOG(TLVL_INFO) << "Construct Test Case END";
35 }
36 
37 BOOST_AUTO_TEST_CASE(Tokens)
38 {
39  artdaq::configureMessageFacility("RequestSender_t", true, true);
40  TLOG(TLVL_INFO) << "Tokens Test Case BEGIN" ;
41  const int TOKEN_PORT = (seedAndRandom() % (32768 - 1024)) + 1024;
42  TLOG(TLVL_DEBUG) << "Opening token listener socket" ;
43  auto token_socket = TCP_listen_fd(TOKEN_PORT, 3 * sizeof(artdaq::detail::RoutingToken));
44 
45  fhicl::ParameterSet token_pset;
46  token_pset.put("routing_token_port", TOKEN_PORT);
47  token_pset.put("use_routing_master", true);
48  fhicl::ParameterSet pset;
49  pset.put("routing_token_config", token_pset);
50  artdaq::RequestSender t(pset);
51 
52  my_rank = 0;
53 
54 
55  BOOST_REQUIRE(token_socket != -1);
56  if (token_socket == -1)
57  {
58  TLOG(TLVL_ERROR) << "Token listener socket was not opened successfully." ;
59  BOOST_REQUIRE_EQUAL(false, true);
60  return;
61  }
62 
63  TLOG(TLVL_DEBUG) << "Accepting new connection on token_socket" ;
64  sockaddr_in addr;
65  socklen_t arglen = sizeof(addr);
66  auto conn_sock = accept(token_socket, (struct sockaddr*)&addr, &arglen);
67 
68  t.SendRoutingToken(120);
69 
71  auto sts = read(conn_sock, &buff, sizeof(artdaq::detail::RoutingToken));
72 
73  TRACE_REQUIRE_EQUAL(sts, sizeof(artdaq::detail::RoutingToken));
74  TRACE_REQUIRE_EQUAL(buff.header, TOKEN_MAGIC);
75  TRACE_REQUIRE_EQUAL(buff.new_slots_free, 120);
76  TRACE_REQUIRE_EQUAL(buff.rank, 0);
77 
78  my_rank = 13;
79  t.SendRoutingToken(335);
80 
81  sts = read(conn_sock, &buff, sizeof(artdaq::detail::RoutingToken));
82 
83  TRACE_REQUIRE_EQUAL(sts, sizeof(artdaq::detail::RoutingToken));
84  TRACE_REQUIRE_EQUAL(buff.header, TOKEN_MAGIC);
85  TRACE_REQUIRE_EQUAL(buff.new_slots_free, 335);
86  TRACE_REQUIRE_EQUAL(buff.rank, 13);
87 
88  close(conn_sock);
89  close(token_socket);
90  TLOG(TLVL_INFO) << "Tokens Test Case END";
91 }
92 
93 BOOST_AUTO_TEST_CASE(Requests)
94 {
95  artdaq::configureMessageFacility("RequestSender_t", true, true);
96  TLOG(TLVL_INFO) << "Requests Test Case BEGIN" ;
97  const int REQUEST_PORT = (seedAndRandom() % (32768 - 1024)) + 1024;
98  const int DELAY_TIME = 100;
99 #if 0
100  const std::string MULTICAST_IP = "227.28.12.28";
101 #else
102  const std::string MULTICAST_IP = "localhost";
103 #endif
104  fhicl::ParameterSet pset;
105  pset.put("request_port", REQUEST_PORT);
106  pset.put("request_delay_ms", DELAY_TIME);
107  pset.put("send_requests", true);
108  pset.put("request_address", MULTICAST_IP);
109  artdaq::RequestSender t(pset);
110 
111 
112  TLOG(TLVL_DEBUG) << "Opening request listener socket" ;
113  auto request_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
114 
115  struct sockaddr_in si_me_request;
116 
117  int yes = 1;
118  if (setsockopt(request_socket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0)
119  {
120  TLOG(TLVL_ERROR) << "Unable to set reuse on request socket" ;
121  BOOST_REQUIRE_EQUAL(true, false);
122  return;
123  }
124  memset(&si_me_request, 0, sizeof(si_me_request));
125  si_me_request.sin_family = AF_INET;
126  si_me_request.sin_port = htons(REQUEST_PORT);
127  si_me_request.sin_addr.s_addr = htonl(INADDR_ANY);
128  if (bind(request_socket, (struct sockaddr *)&si_me_request, sizeof(si_me_request)) == -1)
129  {
130  TLOG(TLVL_ERROR) << "Cannot bind request socket to port " << std::to_string(REQUEST_PORT) ;
131  BOOST_REQUIRE_EQUAL(true, false);
132  return;
133  }
134 
135  if (MULTICAST_IP != "localhost")
136  {
137  struct ip_mreq mreq;
138  int sts = ResolveHost(MULTICAST_IP.c_str(), mreq.imr_multiaddr);
139  if (sts == -1)
140  {
141  TLOG(TLVL_ERROR) << "Unable to resolve multicast request address" ;
142  BOOST_REQUIRE_EQUAL(true, false);
143  return;
144  }
145  mreq.imr_interface.s_addr = htonl(INADDR_ANY);
146  if (setsockopt(request_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
147  {
148  TLOG(TLVL_ERROR) << "Unable to join multicast group" ;
149  BOOST_REQUIRE_EQUAL(true, false);
150  return;
151  }
152  }
153 
154  TLOG(TLVL_DEBUG) << "Sending request" ;
155  auto start_time = std::chrono::steady_clock::now();
156  t.AddRequest(0, 0x10);
157  struct pollfd ufds[1];
158 
159  TLOG(TLVL_DEBUG) << "Receiving Request" ;
160  ufds[0].fd = request_socket;
161  ufds[0].events = POLLIN | POLLPRI;
162  int rv = poll(ufds, 1, 10000);
163  if (rv > 0)
164  {
165  if (ufds[0].revents == POLLIN || ufds[0].revents == POLLPRI)
166  {
167  auto delay_time = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start_time).count();
168  BOOST_REQUIRE_GE(delay_time, DELAY_TIME);
169  TLOG(TLVL_TRACE) << "Recieved packet on Request channel";
171  recv(request_socket, &hdr_buffer, sizeof(hdr_buffer), 0);
172  TRACE_REQUIRE_EQUAL(hdr_buffer.isValid(), true);
173  TRACE_REQUIRE_EQUAL(static_cast<uint8_t>(hdr_buffer.mode),
174  static_cast<uint8_t>(artdaq::detail::RequestMessageMode::Normal));
175  TRACE_REQUIRE_EQUAL(hdr_buffer.packet_count, 1);
176  if (hdr_buffer.isValid())
177  {
178 
179  std::vector<artdaq::detail::RequestPacket> pkt_buffer(hdr_buffer.packet_count);
180  recv(request_socket, &pkt_buffer[0], sizeof(artdaq::detail::RequestPacket) * hdr_buffer.packet_count, 0);
181 
182  for (auto& buffer : pkt_buffer)
183  {
184  TRACE_REQUIRE_EQUAL(buffer.isValid(), true);
185  TRACE_REQUIRE_EQUAL(buffer.sequence_id, 0);
186  TRACE_REQUIRE_EQUAL(buffer.timestamp, 0x10);
187  }
188  }
189  else
190  {
191  TLOG(TLVL_ERROR) << "Invalid header received" ;
192  BOOST_REQUIRE_EQUAL(false, true);
193  return;
194  }
195  }
196  else
197  {
198  TLOG(TLVL_ERROR) << "Wrong event type from poll" ;
199  BOOST_REQUIRE_EQUAL(false, true);
200  return;
201  }
202  }
203  else
204  {
205  TLOG(TLVL_ERROR) << "Timeout occured waiting for request" ;
206  BOOST_REQUIRE_EQUAL(false, true);
207  return;
208  }
209 
210  // SetRequestMode and AddRequest BOTH send requests...
211  start_time = std::chrono::steady_clock::now();
213  t.AddRequest(2, 0x20);
214  rv = poll(ufds, 1, 1000);
215  if (rv > 0)
216  {
217  if (ufds[0].revents == POLLIN || ufds[0].revents == POLLPRI)
218  {
219  auto delay_time = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start_time).count();
220  BOOST_REQUIRE_GE(delay_time, DELAY_TIME);
221  TLOG(TLVL_TRACE) << "Recieved packet on Request channel";
223  auto sts = recv(request_socket, &hdr_buffer, sizeof(hdr_buffer), 0);
224  TRACE_REQUIRE_EQUAL(sts, sizeof(hdr_buffer));
225  TRACE_REQUIRE_EQUAL(hdr_buffer.isValid(), true);
226  TRACE_REQUIRE_EQUAL(static_cast<uint8_t>(hdr_buffer.mode),
227  static_cast<uint8_t>(artdaq::detail::RequestMessageMode::EndOfRun));
228  TRACE_REQUIRE_EQUAL(hdr_buffer.packet_count, 2);
229  if (hdr_buffer.isValid())
230  {
231 
232  std::vector<artdaq::detail::RequestPacket> pkt_buffer(hdr_buffer.packet_count);
233  sts = recv(request_socket, &pkt_buffer[0], sizeof(artdaq::detail::RequestPacket) * hdr_buffer.packet_count, 0);
234  TRACE_REQUIRE_EQUAL(static_cast<size_t>(sts), static_cast<size_t>(sizeof(artdaq::detail::RequestPacket) * hdr_buffer.packet_count));
235 
236  TRACE_REQUIRE_EQUAL(pkt_buffer[0].isValid(), true);
237  TRACE_REQUIRE_EQUAL(pkt_buffer[0].sequence_id, 0);
238  TRACE_REQUIRE_EQUAL(pkt_buffer[0].timestamp, 0x10);
239  TRACE_REQUIRE_EQUAL(pkt_buffer[1].isValid(), true);
240  TRACE_REQUIRE_EQUAL(pkt_buffer[1].sequence_id, 2);
241  TRACE_REQUIRE_EQUAL(pkt_buffer[1].timestamp, 0x20);
242 
243  }
244  else
245  {
246  TLOG(TLVL_ERROR) << "Invalid header received" ;
247  BOOST_REQUIRE_EQUAL(false, true);
248  return;
249  }
250  }
251  else
252  {
253  TLOG(TLVL_ERROR) << "Wrong event type from poll" ;
254  BOOST_REQUIRE_EQUAL(false, true);
255  return;
256  }
257  }
258  else
259  {
260  TLOG(TLVL_ERROR) << "Timeout occured waiting for request" ;
261  BOOST_REQUIRE_EQUAL(false, true);
262  return;
263  }
264  rv = poll(ufds, 1, 1000);
265  if (rv > 0)
266  {
267  if (ufds[0].revents == POLLIN || ufds[0].revents == POLLPRI)
268  {
269  auto delay_time = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start_time).count();
270  BOOST_REQUIRE_GE(delay_time, DELAY_TIME);
271  TLOG(TLVL_TRACE) << "Recieved packet on Request channel";
273  recv(request_socket, &hdr_buffer, sizeof(hdr_buffer), 0);
274  TRACE_REQUIRE_EQUAL(hdr_buffer.isValid(), true);
275  TRACE_REQUIRE_EQUAL(static_cast<uint8_t>(hdr_buffer.mode),
276  static_cast<uint8_t>(artdaq::detail::RequestMessageMode::EndOfRun));
277  TRACE_REQUIRE_EQUAL(hdr_buffer.packet_count, 2);
278  if (hdr_buffer.isValid())
279  {
280 
281  std::vector<artdaq::detail::RequestPacket> pkt_buffer(hdr_buffer.packet_count);
282  recv(request_socket, &pkt_buffer[0], sizeof(artdaq::detail::RequestPacket) * hdr_buffer.packet_count, 0);
283 
284  TRACE_REQUIRE_EQUAL(pkt_buffer[0].isValid(), true);
285  TRACE_REQUIRE_EQUAL(pkt_buffer[0].sequence_id, 0);
286  TRACE_REQUIRE_EQUAL(pkt_buffer[0].timestamp, 0x10);
287  TRACE_REQUIRE_EQUAL(pkt_buffer[1].isValid(), true);
288  TRACE_REQUIRE_EQUAL(pkt_buffer[1].sequence_id, 2);
289  TRACE_REQUIRE_EQUAL(pkt_buffer[1].timestamp, 0x20);
290 
291  }
292  else
293  {
294  TLOG(TLVL_ERROR) << "Invalid header received" ;
295  BOOST_REQUIRE_EQUAL(false, true);
296  return;
297  }
298  }
299  else
300  {
301  TLOG(TLVL_ERROR) << "Wrong event type from poll" ;
302  BOOST_REQUIRE_EQUAL(false, true);
303  return;
304  }
305  }
306  else
307  {
308  TLOG(TLVL_ERROR) << "Timeout occured waiting for request" ;
309  BOOST_REQUIRE_EQUAL(false, true);
310  return;
311  }
312 
313  t.RemoveRequest(0);
314  t.RemoveRequest(2);
315  t.AddRequest(3, 0x30);
316  start_time = std::chrono::steady_clock::now();
317  rv = poll(ufds, 1, 1000);
318  if (rv > 0)
319  {
320  if (ufds[0].revents == POLLIN || ufds[0].revents == POLLPRI)
321  {
322  auto delay_time = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start_time).count();
323  BOOST_REQUIRE_GE(delay_time, DELAY_TIME);
324  TLOG(TLVL_TRACE) << "Recieved packet on Request channel";
326  recv(request_socket, &hdr_buffer, sizeof(hdr_buffer), 0);
327  TRACE_REQUIRE_EQUAL(hdr_buffer.isValid(), true);
328  TRACE_REQUIRE_EQUAL(static_cast<uint8_t>(hdr_buffer.mode),
329  static_cast<uint8_t>(artdaq::detail::RequestMessageMode::EndOfRun));
330  TRACE_REQUIRE_EQUAL(hdr_buffer.packet_count, 1);
331  if (hdr_buffer.isValid())
332  {
333 
334  std::vector<artdaq::detail::RequestPacket> pkt_buffer(hdr_buffer.packet_count);
335  recv(request_socket, &pkt_buffer[0], sizeof(artdaq::detail::RequestPacket) * hdr_buffer.packet_count, 0);
336 
337  TRACE_REQUIRE_EQUAL(pkt_buffer[0].isValid(), true);
338  TRACE_REQUIRE_EQUAL(pkt_buffer[0].sequence_id, 3);
339  TRACE_REQUIRE_EQUAL(pkt_buffer[0].timestamp, 0x30);
340 
341  }
342  else
343  {
344  TLOG(TLVL_ERROR) << "Invalid header received" ;
345  BOOST_REQUIRE_EQUAL(false, true);
346  return;
347  }
348  }
349  else
350  {
351  TLOG(TLVL_ERROR) << "Wrong event type from poll" ;
352  BOOST_REQUIRE_EQUAL(false, true);
353  return;
354  }
355  }
356  else
357  {
358  TLOG(TLVL_ERROR) << "Timeout occured waiting for request" ;
359  BOOST_REQUIRE_EQUAL(false, true);
360  return;
361  }
362 
363  close(request_socket);
364  TLOG(TLVL_INFO) << "Requests Test Case END";
365 }
366 
367 BOOST_AUTO_TEST_SUITE_END()
int ResolveHost(char const *host_in, in_addr &addr)
Convert a string hostname to a in_addr suitable for socket communication.
Definition: TCPConnect.cc:32
End of Run mode (Used to end request processing on receiver)
The RequestSender contains methods used to send data requests and Routing tokens. ...
RequestMessageMode mode
Communicates additional information to the Request receiver.
bool isValid() const
Check the magic bytes of the packet.
unsigned new_slots_free
The number of slots free in the token sender (usually 1)
Header of a RequestMessage. Contains magic bytes for validation and a count of expected RequestPacket...
uint32_t packet_count
The number of RequestPackets in this Request message.
The RoutingToken contains the magic bytes, the rank of the token sender, and the number of slots free...
int TCP_listen_fd(int port, int rcvbuf)
Create a TCP listening socket on the given port and INADDR_ANY, with the given receive buffer...
The RequestPacket contains information about a single data request.
int rank
The rank from which the RoutingToken came.
uint32_t header
The magic bytes that help validate the RoutingToken.