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