artdaq  v3_09_01
ShmemWrapper.cc
1 #include "tracemf.h"
2 #define TRACE_NAME "ShmemWrapper"
3 
4 #include "art/Framework/Services/Registry/ServiceHandle.h"
5 #include "artdaq/ArtModules/ArtdaqSharedMemoryService.h"
6 #include "artdaq/ArtModules/detail/ShmemWrapper.hh"
7 #include "artdaq/DAQdata/NetMonHeader.hh"
8 
9 art::ShmemWrapper::ShmemWrapper(fhicl::ParameterSet const& ps)
10 {
11  init_timeout_s_ = ps.get<double>("init_fragment_timeout_seconds", 600.0);
12  // Make sure the ArtdaqSharedMemoryService is available
13  art::ServiceHandle<ArtdaqSharedMemoryServiceInterface> shm;
14 }
15 
16 artdaq::FragmentPtrs art::ShmemWrapper::receiveMessage()
17 {
18  TLOG(5) << "Receiving Fragment from NetMonTransportService";
19  TLOG(TLVL_TRACE) << "receiveMessage BEGIN";
20  art::ServiceHandle<ArtdaqSharedMemoryServiceInterface> shm;
21  artdaq::FragmentPtrs output;
22 
23  // Do not process data until Init Fragment received!
24  auto start = std::chrono::steady_clock::now();
25  while (!init_received_ && artdaq::TimeUtils::GetElapsedTime(start) < init_timeout_s_)
26  {
27  usleep(static_cast<unsigned>(init_timeout_s_ * 1000000 / 100)); // Check 100 times
28  }
29  if (!init_received_)
30  {
31  TLOG(TLVL_ERROR) << "Did not receive Init Fragment after " << init_timeout_s_ << " seconds.";
32  return output;
33  }
34 
35  artdaq::Fragments recvd_fragments;
36  while (recvd_fragments.empty())
37  {
38  auto eventMap = shm->ReceiveEvent(false);
39 
40  if (eventMap.empty())
41  {
42  TLOG(TLVL_DEBUG) << "Did not receive event after timeout, returning from receiveMessage ";
43  return output;
44  }
45 
46  if (eventMap.count(artdaq::Fragment::type_t(artdaq::Fragment::EndOfDataFragmentType)) != 0u)
47  {
48  TLOG(TLVL_DEBUG) << "Received shutdown message, returning";
49  return output;
50  }
51  if (eventMap.count(artdaq::Fragment::type_t(artdaq::Fragment::DataFragmentType)) != 0u)
52  {
53  std::move(eventMap[artdaq::Fragment::type_t(artdaq::Fragment::DataFragmentType)]->begin(), eventMap[artdaq::Fragment::type_t(artdaq::Fragment::DataFragmentType)]->end(), std::back_inserter(recvd_fragments));
54  }
55  std::sort(recvd_fragments.begin(), recvd_fragments.end(), artdaq::fragmentSequenceIDCompare);
56  }
57 
58  TLOG(TLVL_TRACE) << "receiveMessage: Returning top Fragment";
59  for (auto& frag : recvd_fragments)
60  {
61  TLOG(TLVL_TRACE) << "receiveMessage: Returning Fragment, length="
62  << frag.metadata<artdaq::NetMonHeader>()->data_length;
63  output.emplace_back(new artdaq::Fragment(std::move(frag)));
64  }
65 
66 #if DUMP_RECEIVE_MESSAGE
67  std::string fileName = "receiveMessage_" + std::to_string(my_rank) + "_" + std::to_string(getpid()) + "_" +
68  std::to_string(topFrag.sequenceID()) + ".bin";
69  std::fstream ostream(fileName.c_str(), std::ios::out | std::ios::binary);
70  ostream.write(buffer, header->data_length);
71  ostream.close();
72 #endif
73 
74  TLOG(TLVL_TRACE) << "receiveMessage END";
75 
76  TLOG(5) << "Done Receiving Fragment from NetMonTransportService";
77  return output;
78 }
79 
80 std::unordered_map<artdaq::Fragment::type_t, std::unique_ptr<artdaq::Fragments>> art::ShmemWrapper::receiveMessages()
81 {
82  TLOG(5) << "Receiving Fragment from NetMonTransportService";
83  TLOG(TLVL_TRACE) << "receiveMessage BEGIN";
84  art::ServiceHandle<ArtdaqSharedMemoryServiceInterface> shm;
85  std::unordered_map<artdaq::Fragment::type_t, std::unique_ptr<artdaq::Fragments>> output;
86 
87  // Do not process data until Init Fragment received!
88  auto start = std::chrono::steady_clock::now();
89  while (!init_received_ && artdaq::TimeUtils::GetElapsedTime(start) < init_timeout_s_)
90  {
91  usleep(static_cast<unsigned>(init_timeout_s_ * 1000000 / 100)); // Check 100 times
92  }
93  if (!init_received_)
94  {
95  TLOG(TLVL_ERROR) << "Did not receive Init Fragment after " << init_timeout_s_ << " seconds.";
96  }
97 
98  output = shm->ReceiveEvent(false);
99 
100  if (output.empty())
101  {
102  TLOG(TLVL_DEBUG) << "Did not receive event after timeout, returning from receiveMessage ";
103  return output;
104  }
105 
106  hdr_ptr_ = shm->GetEventHeader();
107  TLOG(TLVL_TRACE) << "receiveMessage END";
108 
109  TLOG(5) << "Done Receiving Fragments from Shared Memory";
110  return output;
111 }
112 
114 {
115  TLOG(5) << "Receiving Init Fragment from NetMonTransportService";
116 
117  TLOG(TLVL_TRACE) << "receiveInitMessage BEGIN";
118  art::ServiceHandle<ArtdaqSharedMemoryServiceInterface> shm;
119  auto start = std::chrono::steady_clock::now();
120  std::unordered_map<artdaq::Fragment::type_t, std::unique_ptr<artdaq::Fragments>> eventMap;
121  while (eventMap.empty())
122  {
123  eventMap = shm->ReceiveEvent(true);
124 
125  if (eventMap.count(artdaq::Fragment::type_t(artdaq::Fragment::EndOfDataFragmentType)) != 0u)
126  {
127  TLOG(TLVL_DEBUG) << "Received shutdown message, returning";
128  artdaq::FragmentPtrs output;
129  for (auto& frag : *eventMap[artdaq::Fragment::EndOfDataFragmentType])
130  {
131  output.emplace_back(new artdaq::Fragment(std::move(frag)));
132  }
133  return output;
134  }
135  if ((eventMap.count(artdaq::Fragment::type_t(artdaq::Fragment::InitFragmentType)) == 0u) && !eventMap.empty())
136  {
137  TLOG(TLVL_WARNING) << "Did NOT receive Init Fragment as first broadcast! Type="
138  << artdaq::detail::RawFragmentHeader::SystemTypeToString(eventMap.begin()->first);
139  eventMap.clear();
140  }
141  else if (artdaq::TimeUtils::GetElapsedTime(start) > init_timeout_s_)
142  {
143  TLOG(TLVL_WARNING) << "Did not receive Init fragment after init_fragment_timeout_seconds (" << artdaq::TimeUtils::GetElapsedTime(start) << ")!";
144  return artdaq::FragmentPtrs();
145  }
146  }
147 
148  // We return false, indicating we're done reading, if:
149  // 1) we did not obtain an event, because we timed out and were
150  // configured NOT to keep trying after a timeout, or
151  // 2) the event we read was the end-of-data marker: a null
152  // pointer
153 
154  TLOG(TLVL_TRACE) << "receiveInitMessage: Returning top Fragment";
155  artdaq::FragmentPtrs output;
156  for (auto& frag : *eventMap[artdaq::Fragment::InitFragmentType])
157  {
158  output.emplace_back(new artdaq::Fragment(std::move(frag)));
159  }
160 
161 #if DUMP_RECEIVE_MESSAGE
162  std::string fileName = "receiveInitMessage_" + std::to_string(getpid()) + ".bin";
163  std::fstream ostream(fileName.c_str(), std::ios::out | std::ios::binary);
164  ostream.write(buffer, header->data_length);
165  ostream.close();
166 #endif
167 
168  TLOG(TLVL_TRACE) << "receiveInitMessage END";
169  init_received_ = true;
170 
171  TLOG(5) << "Done Receiving Init Fragment from NetMonTransportService";
172  return output;
173 }
std::unordered_map< artdaq::Fragment::type_t, std::unique_ptr< artdaq::Fragments > > receiveMessages()
Receive all messsages for an event from ArtdaqSharedMemoryService.
Definition: ShmemWrapper.cc:80
Header with length information for NetMonTransport messages.
Definition: NetMonHeader.hh:13
artdaq::FragmentPtrs receiveMessage()
Receive a message from the ArtdaqSharedMemoryService.
Definition: ShmemWrapper.cc:16
ShmemWrapper(fhicl::ParameterSet const &ps)
ShmemWrapper Constructor.
Definition: ShmemWrapper.cc:9
artdaq::FragmentPtrs receiveInitMessage()
Receive an init message from the ArtdaqSharedMemoryService.