artdaq  v3_12_02
transfer_plugin_receiver.cc
1 #include "artdaq/TransferPlugins/TransferInterface.hh"
2 
3 #include "artdaq-core/Data/Fragment.hh"
4 #include "artdaq-core/Utilities/ExceptionHandler.hh"
5 
6 #include "cetlib/BasicPluginFactory.h"
7 #include "cetlib/filepath_maker.h"
8 #include "cetlib_except/exception.h"
9 #include "fhiclcpp/ParameterSet.h"
10 
11 #include <boost/asio.hpp>
12 
13 #include <iostream>
14 #include <limits>
15 #include <string>
16 
17 // DUPLICATED CODE: also found in transfer_plugin_sender.cpp. Not as egregious as
18 // normal in that this function is unlikely to be changed, and this is
19 // a standalone app (not part of artdaq)
20 
21 fhicl::ParameterSet ReadParameterSet(const std::string& fhicl_filename)
22 {
23  if (std::getenv("FHICL_FILE_PATH") == nullptr)
24  {
25  std::cerr
26  << "INFO: environment variable FHICL_FILE_PATH was not set. Using \".\"\n";
27  setenv("FHICL_FILE_PATH", ".", 0);
28  }
29 
30  cet::filepath_lookup_after1 lookup_policy("FHICL_FILE_PATH");
31  auto pset = fhicl::ParameterSet::make(fhicl_filename, lookup_policy);
32 
33  return pset;
34 }
35 
36 int do_check(const artdaq::Fragment& frag);
37 
38 int main(int argc, char* argv[])
39 try
40 {
41  if (argc != 2)
42  {
43  std::cerr << "Usage: transfer_plugin_receiver <fhicl document>" << std::endl;
44  return 1;
45  }
46 
47  auto fhicl_filename = boost::lexical_cast<std::string>(argv[1]); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
48 
49  std::unique_ptr<artdaq::TransferInterface> transfer;
50  auto pset = ReadParameterSet(fhicl_filename);
51 
52  try
53  {
54  static cet::BasicPluginFactory bpf("transfer", "make");
55 
56  transfer =
57  bpf.makePlugin<std::unique_ptr<artdaq::TransferInterface>,
58  const fhicl::ParameterSet&,
60  pset.get<std::string>("transfer_plugin_type"),
61  pset,
63  }
64  catch (...)
65  {
66  artdaq::ExceptionHandler(artdaq::ExceptionHandlerRethrow::no,
67  "Error creating transfer plugin");
68  return 1;
69  }
70 
71  while (true)
72  {
73  artdaq::Fragment myfrag;
74  size_t timeout = 10000000;
75 
76  auto retval = transfer->receiveFragment(myfrag, timeout);
77 
79  {
80  std::cout << "Returned from call to transfer_->receiveFragmentFrom; fragment with seqID == " << myfrag.sequenceID() << ", fragID == " << myfrag.fragmentID() << " has size " << myfrag.sizeBytes() << " bytes" << std::endl;
81  }
82  else
83  {
84  std::cerr << "RECV_TIMEOUT received from call to transfer->receiveFragmentFrom" << std::endl;
85  continue;
86  }
87 
88  if (do_check(myfrag) != 0)
89  {
90  std::cerr << "Error: do_check indicates fragment failed to transmit correctly" << std::endl;
91  }
92  else
93  {
94  std::cerr << "Success: do_check indicates fragment transmitted correctly" << std::endl;
95  }
96  }
97 
98  return 0;
99 }
100 catch (...)
101 {
102  return -1;
103 }
104 
105 // JCF, Jun-22-2016
106 
107 // do_check assumes std::iota was used to fill the sent fragment with
108 // monotonically incrementing 64-bit unsigned integers
109 
110 int do_check(const artdaq::Fragment& frag)
111 {
112  uint64_t variable_to_compare = 0;
113 
114  for (auto ptr_into_frag = reinterpret_cast<const uint64_t*>(frag.dataBeginBytes()); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
115  ptr_into_frag != reinterpret_cast<const uint64_t*>(frag.dataEndBytes()); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
116  ++ptr_into_frag, ++variable_to_compare)
117  {
118  if (variable_to_compare != *ptr_into_frag)
119  {
120  std::cerr << "ERROR for fragment with sequence ID " << frag.sequenceID() << ", fragment ID " << frag.fragmentID() << ": expected ADC value of " << variable_to_compare << ", got " << *ptr_into_frag << std::endl;
121  return 1;
122  }
123  }
124 
125  return 0;
126 }
This TransferInterface is a Receiver.
Role
Used to determine if a TransferInterface is a Sender or Receiver.
For code clarity, things checking for successful receive should check retval &gt;= NO_RANK_INFO.