artdaq  v3_11_00
BrokenTransferTest.cc
1 #include "BrokenTransferTest.hh"
2 
3 #include "artdaq-core/Data/detail/RawFragmentHeader.hh"
4 #include "artdaq/TransferPlugins/MakeTransferPlugin.hh"
5 
6 #include <memory>
7 #include <thread>
8 #include "artdaq/DAQdata/Globals.hh"
9 #define TRACE_NAME "BrokenTransferTest"
10 
11 #define TLVL_MAKE_TRANSFER_PS TLVL_DEBUG + 5
12 #define TLVL_START_TEST TLVL_DEBUG + 6
13 #define TLVL_STOP_TEST TLVL_DEBUG + 7
14 #define TLVL_SENDER TLVL_DEBUG + 8
15 #define TLVL_SENDER_TOKEN_WAIT TLVL_DEBUG + 9
16 #define TLVL_RECEIVER TLVL_DEBUG + 10
17 
19  : sender_ready_()
20  , receiver_ready_()
21  , sender_current_fragment_()
22  , ps_(ps)
23  , test_start_time_(std::chrono::steady_clock::now())
24  , test_end_time_(std::chrono::steady_clock::now())
25  , test_end_requested_(false)
26  , fragment_rate_hz_(ps.get<size_t>("fragment_rate_hz", 10))
27  , pause_first_sender_(false)
28  , pause_receiver_(false)
29  , kill_first_sender_(false)
30  , kill_receiver_(false)
31  , reliable_mode_(ps.get<bool>("reliable_mode", true))
32  , fragment_size_(ps.get<size_t>("fragment_size", 0x10000))
33  , send_timeout_us_(ps.get<size_t>("send_timeout_us", 100000))
34  , transfer_buffer_count_(ps.get<size_t>("transfer_buffer_count", 10))
35  , event_buffer_count_(ps.get<size_t>("event_buffer_count", 20))
36  , event_buffer_timeout_us_(ps.get<size_t>("event_buffer_timeout_us", 1000000))
37  , send_throttle_us_(0)
38 {
39  if (fragment_rate_hz_ == 0 || fragment_rate_hz_ > 100000)
40  {
41  TLOG(TLVL_WARNING) << "Invalid rate " << fragment_rate_hz_ << " Hz specified, setting to " << (fragment_rate_hz_ == 0 ? 1 : 1000) << " Hz";
42  fragment_rate_hz_ = (fragment_rate_hz_ == 0 ? 1 : 1000);
43  }
44 }
45 
47 {
48  TLOG(TLVL_INFO) << "TestSenderPause BEGIN";
49  auto start_time = std::chrono::steady_clock::now();
50  start_test_();
51  usleep_for_n_buffer_epochs_(2);
52 
53  TLOG(TLVL_INFO) << "Pausing First Sender";
54  pause_first_sender_ = true;
55  usleep_for_n_buffer_epochs_(2);
56  usleep(2 * event_buffer_timeout_us_);
57 
58  TLOG(TLVL_INFO) << "Resuming First Sender";
59  pause_first_sender_ = false;
60  usleep_for_n_buffer_epochs_(2);
61 
62  stop_test_();
63  TLOG(TLVL_INFO) << "TestSenderPause END, duration=" << artdaq::TimeUtils::GetElapsedTime(start_time);
64 }
65 
67 {
68  TLOG(TLVL_INFO) << "TestReceiverPause BEGIN";
69  auto start_time = std::chrono::steady_clock::now();
70  start_test_();
71  usleep_for_n_buffer_epochs_(2);
72 
73  TLOG(TLVL_INFO) << "Pausing Recevier";
74  pause_receiver_ = true;
75  usleep_for_n_buffer_epochs_(2);
76  usleep(2 * event_buffer_timeout_us_);
77 
78  TLOG(TLVL_INFO) << "Resuming Receiver";
79  pause_receiver_ = false;
80  usleep_for_n_buffer_epochs_(2);
81 
82  stop_test_();
83  TLOG(TLVL_INFO) << "TestReceiverPause END, duration=" << artdaq::TimeUtils::GetElapsedTime(start_time);
84 }
85 
87 {
88  TLOG(TLVL_INFO) << "TestSenderReconnect BEGIN";
89  auto start_time = std::chrono::steady_clock::now();
90  start_test_();
91  usleep_for_n_buffer_epochs_(2);
92 
93  TLOG(TLVL_INFO) << "Killing first Sender";
94  kill_first_sender_ = true;
95  if (sender_threads_[0].joinable())
96  {
97  sender_threads_[0].join();
98  }
99  kill_first_sender_ = false;
100 
101  usleep_for_n_buffer_epochs_(2);
102  usleep(2 * event_buffer_timeout_us_);
103 
104  TLOG(TLVL_INFO) << "Restarting First Sender";
105  boost::thread::attributes attrs;
106  attrs.set_stack_size(4096 * 2000); // 2000 KB
107  try
108  {
109  sender_threads_[0] = boost::thread(attrs, boost::bind(&BrokenTransferTest::do_sending_, this, 0));
110  }
111  catch (const boost::exception& e)
112  {
113  TLOG(TLVL_ERROR) << "Caught boost::exception starting Sender thread: " << boost::diagnostic_information(e) << ", errno=" << errno;
114  std::cerr << "Caught boost::exception starting Sender thread: " << boost::diagnostic_information(e) << ", errno=" << errno << std::endl;
115  exit(5);
116  }
117 
118  usleep_for_n_buffer_epochs_(2);
119 
120  stop_test_();
121  TLOG(TLVL_INFO) << "TestSenderReconnect END, duration=" << artdaq::TimeUtils::GetElapsedTime(start_time);
122 }
123 
125 {
126  TLOG(TLVL_INFO) << "TestReceiverReconnect BEGIN";
127  auto start_time = std::chrono::steady_clock::now();
128  send_throttle_us_ = send_throttle_factor * 1000000 / fragment_rate_hz_;
129  start_test_();
130  usleep_for_n_buffer_epochs_(2);
131 
132  TLOG(TLVL_INFO) << "Killing Receiver duration=" << artdaq::TimeUtils::GetElapsedTime(start_time);;
133  kill_receiver_ = true;
134  if (receiver_threads_[0].joinable())
135  {
136  receiver_threads_[0].join();
137  }
138  if (receiver_threads_[1].joinable())
139  {
140  receiver_threads_[1].join();
141  }
142  kill_receiver_ = false;
143 
144  usleep_for_n_buffer_epochs_(2);
145  usleep(2 * event_buffer_timeout_us_);
146 
147  TLOG(TLVL_INFO) << "Restarting Receiver duration=" << artdaq::TimeUtils::GetElapsedTime(start_time);
148  boost::thread::attributes attrs;
149  attrs.set_stack_size(4096 * 2000); // 2000 KB
150  try
151  {
152  receiver_threads_[0] = boost::thread(attrs, boost::bind(&BrokenTransferTest::do_receiving_, this, 0, 2));
153  receiver_threads_[1] = boost::thread(attrs, boost::bind(&BrokenTransferTest::do_receiving_, this, 1, 2));
154  }
155  catch (const boost::exception& e)
156  {
157  TLOG(TLVL_ERROR) << "Caught boost::exception starting Receiver thread: " << boost::diagnostic_information(e) << ", errno=" << errno;
158  std::cerr << "Caught boost::exception starting Receiver thread: " << boost::diagnostic_information(e) << ", errno=" << errno << std::endl;
159  exit(5);
160  }
161 
162  usleep_for_n_buffer_epochs_(2);
163 
164  TLOG(TLVL_INFO) << "Stopping test, duration=" << artdaq::TimeUtils::GetElapsedTime(start_time);
165  stop_test_();
166  TLOG(TLVL_INFO) << "TestReceiverReconnect END, duration=" << artdaq::TimeUtils::GetElapsedTime(start_time);
167 }
168 
169 fhicl::ParameterSet artdaqtest::BrokenTransferTest::make_transfer_ps_(int sender_rank, int receiver_rank, const std::string& name)
170 {
171  auto thePs = ps_.get<fhicl::ParameterSet>("default_transfer_ps", fhicl::ParameterSet());
172 
173  thePs.put_or_replace("transferPluginType", ps_.get<std::string>("transfer_to_use", "Shmem"));
174  thePs.put_or_replace("destination_rank", receiver_rank);
175  thePs.put_or_replace("source_rank", sender_rank);
176  thePs.put_or_replace("buffer_count", transfer_buffer_count_);
177  if (!thePs.has_key("max_fragment_size_words"))
178  {
179  thePs.put("max_fragment_size_words", fragment_size_ + artdaq::detail::RawFragmentHeader::num_words() + 1);
180  }
181  fhicl::ParameterSet outputPs;
182 
183  TLOG(TLVL_MAKE_TRANSFER_PS) << "Configuring transfer between " << sender_rank << " and " << receiver_rank << " with ParameterSet: " << thePs.to_string();
184 
185  outputPs.put(name, thePs);
186  return outputPs;
187 }
188 
189 void artdaqtest::BrokenTransferTest::start_test_()
190 {
191  TLOG(TLVL_START_TEST) << "start_test_ BEGIN";
192 
193  sender_ready_[0] = false;
194  sender_ready_[1] = false;
195 
196  receiver_ready_[0] = false;
197  receiver_ready_[1] = false;
198 
199  sender_current_fragment_[0] = 0;
200  sender_current_fragment_[1] = 0;
201 
202  test_start_time_ = std::chrono::steady_clock::now();
203  test_end_time_ = std::chrono::steady_clock::now();
204 
205  test_end_requested_ = false;
206  pause_first_sender_ = false;
207  pause_receiver_ = false;
208  kill_first_sender_ = false;
209  kill_receiver_ = false;
210 
211  event_buffer_.clear();
212  complete_events_.clear();
213  timeout_events_.clear();
214 
215  TLOG(TLVL_START_TEST) << "start_test_: Starting receiver threads";
216  boost::thread::attributes attrs;
217  attrs.set_stack_size(4096 * 2000); // 2000 KB
218  try
219  {
220  receiver_threads_[0] = boost::thread(attrs, boost::bind(&BrokenTransferTest::do_receiving_, this, 0, 2));
221  receiver_threads_[1] = boost::thread(attrs, boost::bind(&BrokenTransferTest::do_receiving_, this, 1, 2));
222  }
223  catch (const boost::exception& e)
224  {
225  TLOG(TLVL_ERROR) << "Caught boost::exception starting Receiver thread: " << boost::diagnostic_information(e) << ", errno=" << errno;
226  std::cerr << "Caught boost::exception starting Receiver thread: " << boost::diagnostic_information(e) << ", errno=" << errno << std::endl;
227  exit(5);
228  }
229 
230  TLOG(TLVL_START_TEST) << "start_test_: Waiting for receiver_ready_";
231  while (!receiver_ready_[0] || !receiver_ready_[1])
232  {
233  usleep(10000);
234  }
235 
236  TLOG(TLVL_START_TEST) << "start_test_: Starting sender threads";
237  try
238  {
239  sender_threads_[0] = boost::thread(attrs, boost::bind(&BrokenTransferTest::do_sending_, this, 0));
240  sender_threads_[1] = boost::thread(attrs, boost::bind(&BrokenTransferTest::do_sending_, this, 1));
241  }
242  catch (const boost::exception& e)
243  {
244  TLOG(TLVL_ERROR) << "Caught boost::exception starting Sender thread: " << boost::diagnostic_information(e) << ", errno=" << errno;
245  std::cerr << "Caught boost::exception starting Sender thread: " << boost::diagnostic_information(e) << ", errno=" << errno << std::endl;
246  exit(5);
247  }
248 
249  TLOG(TLVL_START_TEST) << "start_test_: Waiting for sender_ready_";
250  while (!sender_ready_[0] || !sender_ready_[1])
251  {
252  usleep(1000);
253  }
254 
255  TLOG(TLVL_START_TEST) << "start_test_ DONE";
256 }
257 
258 void artdaqtest::BrokenTransferTest::stop_test_()
259 {
260  TLOG(TLVL_STOP_TEST) << "stop_test_ BEGIN";
261  test_end_time_ = std::chrono::steady_clock::now();
262  test_end_requested_ = true;
263 
264  TLOG(TLVL_STOP_TEST) << "stop_test_: Waiting for sender threads to shut down";
265  while (sender_ready_[0] || sender_ready_[1])
266  {
267  usleep(1000);
268  }
269 
270  TLOG(TLVL_STOP_TEST) << "stop_test_: Joining sender threads";
271  if (sender_threads_[0].joinable())
272  {
273  sender_threads_[0].join();
274  }
275  if (sender_threads_[1].joinable())
276  {
277  sender_threads_[1].join();
278  }
279 
280  TLOG(TLVL_STOP_TEST) << "stop_test_: Waiting for receiver threads to shut down";
281  while (receiver_ready_[0] || receiver_ready_[1])
282  {
283  usleep(1000);
284  }
285 
286  TLOG(TLVL_STOP_TEST) << "stop_test_: Joining receiver threads";
287  if (receiver_threads_[0].joinable())
288  {
289  receiver_threads_[0].join();
290  }
291  if (receiver_threads_[1].joinable())
292  {
293  receiver_threads_[1].join();
294  }
295 
296  TLOG(TLVL_INFO) << "Sent " << sender_current_fragment_[0] << " events from rank 0 and " << sender_current_fragment_[1] << " events from rank 1.";
297 
298  artdaq::Fragment::sequence_id_t expected_events = sender_current_fragment_[0];
299  if (sender_current_fragment_[1] > expected_events)
300  {
301  expected_events = sender_current_fragment_[1];
302  }
303 
304  auto complete_events = complete_events_.size();
305  auto incomplete_events = timeout_events_.size();
306  auto missing_events = expected_events - complete_events - incomplete_events;
307 
308  TLOG(TLVL_INFO) << "Received " << complete_events << " complete events in " << fm_(artdaq::TimeUtils::GetElapsedTime(test_start_time_), "s")
309  << ", Incomplete: " << incomplete_events << ", Missing: " << missing_events;
310  TLOG(TLVL_STOP_TEST) << "stop_test_ END";
311 }
312 
313 void artdaqtest::BrokenTransferTest::do_sending_(int sender_rank)
314 {
315  std::unique_ptr<artdaq::TransferInterface> theTransfer = artdaq::MakeTransferPlugin(make_transfer_ps_(sender_rank, 2, "d2"),
317 
318  TLOG(TLVL_SENDER) << "Sender " << sender_rank << " setting sender_ready_";
319  sender_ready_[sender_rank] = true;
320 
321  while (sender_current_fragment_[sender_rank] < sequence_id_target_() || !test_end_requested_)
322  {
323  if (sender_rank == 0 && kill_first_sender_)
324  {
325  break;
326  }
327  while (sender_rank == 0 && pause_first_sender_)
328  {
329  std::this_thread::yield();
330  usleep(10000);
331  }
332 
333  artdaq::Fragment frag(fragment_size_);
334  frag.setSequenceID(sender_current_fragment_[sender_rank]);
335  frag.setFragmentID(sender_rank);
336  frag.setSystemType(artdaq::Fragment::DataFragmentType);
337 
338  auto start_time = std::chrono::steady_clock::now();
340 
341  if (sender_tokens_[sender_rank].load() == 0)
342  {
343  TLOG(TLVL_SENDER_TOKEN_WAIT) << "Sender " << sender_rank << " waiting for token from receiver";
344  while (sender_tokens_[sender_rank].load() == 0 && !test_end_requested_) { usleep(10000); }
345  if (test_end_requested_)
346  {
347  continue;
348  }
349  TLOG(TLVL_SENDER_TOKEN_WAIT) << "Sender " << sender_rank << " waited " << fm_(artdaq::TimeUtils::GetElapsedTime(start_time), "s") << " for token from receiver";
350  }
351 
352  if (reliable_mode_)
353  {
354  sts = theTransfer->transfer_fragment_reliable_mode(std::move(frag));
355  }
356  else
357  {
358  sts = theTransfer->transfer_fragment_min_blocking_mode(frag, send_timeout_us_);
359  }
360 
362  {
363  TLOG(TLVL_ERROR) << "Error sending Fragment " << sender_current_fragment_[sender_rank] << " from sender rank " << sender_rank << ": "
365  }
366  auto duration = artdaq::TimeUtils::GetElapsedTime(start_time);
367  TLOG(TLVL_SENDER) << "Sender " << sender_rank << " Transferred Fragment " << sender_current_fragment_[sender_rank]
368  << " with size " << fragment_size_ << " words in " << fm_(duration, "s")
369  << " (approx " << fm_(static_cast<double>(fragment_size_ * sizeof(artdaq::detail::RawFragmentHeader::RawDataType)) / duration, "B/s")
370  << ") throttle " << send_throttle_us_;
371  ++sender_current_fragment_[sender_rank];
372  sender_tokens_[sender_rank]--;
373  throttle_sender_(sender_rank);
374  }
375 
376  TLOG(TLVL_SENDER) << "Sender " << sender_rank << " shutting down...";
377  theTransfer.reset(nullptr);
378  sender_ready_[sender_rank] = false;
379  TLOG(TLVL_SENDER) << "Sender " << sender_rank << " DONE";
380 }
381 
382 void artdaqtest::BrokenTransferTest::do_receiving_(int sender_rank, int receiver_rank)
383 {
384  std::unique_ptr<artdaq::TransferInterface> theTransfer =
385  artdaq::MakeTransferPlugin(make_transfer_ps_(sender_rank, receiver_rank, "s" + std::to_string(sender_rank)),
386  "s" + std::to_string(sender_rank), artdaq::TransferInterface::Role::kReceive);
387  artdaq::FragmentPtr dropFrag = nullptr;
388 
389  TLOG(TLVL_RECEIVER) << "Receiver " << sender_rank << "->" << receiver_rank << " setting receiver_ready_";
390  receiver_ready_[sender_rank] = true;
391  sender_tokens_[sender_rank] = event_buffer_count_;
392 
393  while (!event_buffer_.empty() || !test_end_requested_ || sender_ready_[0] || sender_ready_[1])
394  {
395  if (kill_receiver_)
396  {
397  break;
398  }
399  while (pause_receiver_)
400  {
401  std::this_thread::yield();
402  usleep(10000);
403  }
404 
405  artdaq::detail::RawFragmentHeader hdr;
406  auto rank = theTransfer->receiveFragmentHeader(hdr, 100000);
407 
408  if (rank == artdaq::TransferInterface::RECV_TIMEOUT || event_buffer_.count(hdr.sequence_id) == 0)
409  {
410  std::unique_lock<std::mutex> lk(event_buffer_mutex_);
411  do
412  {
413  event_buffer_cv_.wait_for(lk, std::chrono::microseconds(10000));
414 
415  auto it = event_buffer_.begin();
416  while (it != event_buffer_.end())
417  {
418  if (artdaq::TimeUtils::GetElapsedTimeMicroseconds(it->second.open_time) > event_buffer_timeout_us_)
419  {
420  TLOG(TLVL_WARNING) << "Receiver " << sender_rank << "->" << receiver_rank << ": Event " << it->first
421  << " has timed out after " << artdaq::TimeUtils::GetElapsedTime(it->second.open_time) << " s, removing...";
422  timeout_events_.insert(it->first);
423  it = event_buffer_.erase(it);
424  sender_tokens_[0]++;
425  sender_tokens_[1]++;
426  }
427  else
428  {
429  ++it;
430  }
431  }
432  } while (event_buffer_.size() > event_buffer_count_);
433  }
434 
435  if (rank != sender_rank)
436  {
437  continue;
438  }
439 
440  artdaq::RawDataType* ptr = nullptr;
441  bool first = true;
442  {
443  std::unique_lock<std::mutex> lk(event_buffer_mutex_);
444  if (timeout_events_.count(hdr.sequence_id) != 0u)
445  {
446  TLOG(TLVL_WARNING) << "Event " << hdr.sequence_id << " has timed out, discarding";
447  if (!dropFrag || dropFrag->size() < hdr.word_count)
448  {
449  dropFrag = std::make_unique<artdaq::Fragment>(hdr.word_count - hdr.num_words());
450  }
451  ptr = dropFrag->headerAddress() + hdr.num_words(); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
452  }
453  else
454  {
455  if (event_buffer_.count(hdr.sequence_id) == 0u)
456  {
457  event_buffer_[hdr.sequence_id].open_time = std::chrono::steady_clock::now();
458  event_buffer_[hdr.sequence_id].first_frag.reset(new artdaq::Fragment(hdr.word_count - hdr.num_words()));
459  ptr = event_buffer_[hdr.sequence_id].first_frag->headerAddress() + hdr.num_words(); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
460  TLOG(TLVL_RECEIVER) << "Receiver " << sender_rank << "->" << receiver_rank << " opened event " << hdr.sequence_id
461  << " with Fragment from rank " << sender_rank;
462  }
463  else
464  {
465  event_buffer_[hdr.sequence_id].second_frag.reset(new artdaq::Fragment(hdr.word_count - hdr.num_words()));
466  ptr = event_buffer_[hdr.sequence_id].second_frag->headerAddress() + hdr.num_words(); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
467  first = false;
468  }
469  }
470  }
471 
472  rank = theTransfer->receiveFragmentData(ptr, hdr.word_count - hdr.num_words());
473  if (rank != sender_rank)
474  {
475  TLOG(TLVL_ERROR) << "Error receiving Fragment data after header received successfully!";
476  exit(1);
477  }
478 
479  if (!first)
480  {
481  TLOG(TLVL_RECEIVER) << "Receiver " << sender_rank << "->" << receiver_rank << " completed event " << hdr.sequence_id
482  << " in " << fm_(artdaq::TimeUtils::GetElapsedTime(event_buffer_[hdr.sequence_id].open_time), "s") << ".";
483 
484  std::unique_lock<std::mutex> lk(event_buffer_mutex_);
485  complete_events_.insert(hdr.sequence_id);
486  event_buffer_.erase(hdr.sequence_id);
487  event_buffer_cv_.notify_one();
488  sender_tokens_[0]++;
489  sender_tokens_[1]++;
490  }
491  }
492 
493  TLOG(TLVL_RECEIVER) << "Receiver " << sender_rank << "->" << receiver_rank << " shutting down...";
494  theTransfer->flush_buffers();
495 
496  std::lock_guard<std::mutex> lk(event_buffer_mutex_);
497  theTransfer.reset(nullptr);
498  receiver_ready_[sender_rank] = false;
499  TLOG(TLVL_RECEIVER) << "Receiver " << sender_rank << "->" << receiver_rank << " DONE";
500 }
501 
502 void artdaqtest::BrokenTransferTest::throttle_sender_(int sender_rank)
503 {
504  if (send_throttle_us_ != 0 && sender_current_fragment_[sender_rank] >= sequence_id_target_() - fragment_rate_hz_)
505  {
506  usleep(send_throttle_us_);
507  }
508 }
509 
510 artdaq::Fragment::sequence_id_t artdaqtest::BrokenTransferTest::sequence_id_target_()
511 {
512  auto ret = 1 + (artdaq::TimeUtils::GetElapsedTimeMicroseconds(test_start_time_) * fragment_rate_hz_ / 1000000);
513  if (test_end_requested_)
514  {
515  ret = 1 + (artdaq::TimeUtils::GetElapsedTimeMicroseconds(test_start_time_, test_end_time_) * fragment_rate_hz_ / 1000000);
516  }
517  //TLOG(TLVL_DEBUG) << "sequence_id_target_ is " << ret;
518  return ret;
519 }
520 
521 std::string artdaqtest::BrokenTransferTest::fm_(double data, const std::string& units, int logt)
522 {
523  if (data < 1 && logt > -3)
524  {
525  return fm_(data * 1000, units, logt - 1);
526  }
527  if (data > 1000 && logt < 3)
528  {
529  return fm_(data / 1000, units, logt + 1);
530  }
531 
532  std::stringstream o;
533  o << std::fixed << std::setprecision(2) << data << " ";
534  switch (logt)
535  {
536  case -3:
537  o << "n";
538  break;
539  case -2:
540  o << "u";
541  break;
542  case -1:
543  o << "m";
544  break;
545  case 0:
546  default:
547  break;
548  case 1:
549  o << "K";
550  break;
551  case 2:
552  o << "M";
553  break;
554  case 3:
555  o << "G";
556  break;
557  }
558  o << units;
559  return o.str();
560 }
virtual int receiveFragmentHeader(detail::RawFragmentHeader &header, size_t receiveTimeout)=0
Receive a Fragment Header from the transport mechanism.
BrokenTransferTest(const fhicl::ParameterSet &ps)
BrokenTransferTest Constructor
std::unique_ptr< artdaq::TransferInterface > MakeTransferPlugin(const fhicl::ParameterSet &pset, const std::string &plugin_label, TransferInterface::Role role)
Load a TransferInterface plugin.
This TransferInterface is a Receiver.
virtual void flush_buffers()=0
Flush any in-flight data. This should be used by the receiver after the receive loop has ended...
static std::string CopyStatusToString(CopyStatus in)
Convert a CopyStatus variable to its string represenatation
virtual int receiveFragmentData(RawDataType *destination, size_t wordCount)=0
Receive the body of a Fragment to the given destination pointer.
This TransferInterface is a Sender.
virtual CopyStatus transfer_fragment_reliable_mode(artdaq::Fragment &&fragment)=0
Transfer a Fragment to the destination. This should be reliable, if the underlying transport mechanis...
Some error occurred, but no exception was thrown.
The send operation completed successfully.
virtual CopyStatus transfer_fragment_min_blocking_mode(artdaq::Fragment const &fragment, size_t send_timeout_usec)=0
Transfer a Fragment to the destination. May not necessarily be reliable, but will not block longer th...
void TestSenderReconnect()
Run the &quot;Sender Reconnect&quot; test
void TestSenderPause()
Run the &quot;Sender Paused&quot; test
void TestReceiverReconnect(int send_throttle_factor=0)
Run the &quot;Receiver Reconnect&quot; test
Value to be returned upon receive timeout.
void TestReceiverPause()
Run the &quot;Receiver Paused&quot; test