artdaq  v3_08_00
ShmemWrapper.cc
1 #include "tracemf.h"
2 #define TRACE_NAME "ShmemWrapper"
3 
4 #include "artdaq/ArtModules/detail/ShmemWrapper.hh"
5 #include "art/Framework/Services/Registry/ServiceHandle.h"
6 #include "artdaq/ArtModules/ArtdaqSharedMemoryService.h"
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(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.size() == 0)
37  {
38  auto eventMap = shm->ReceiveEvent(false);
39 
40  if (eventMap.size() == 0)
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)))
47  {
48  TLOG(TLVL_DEBUG) << "Received shutdown message, returning";
49  return output;
50  }
51  if (eventMap.count(artdaq::Fragment::type_t(artdaq::Fragment::DataFragmentType)))
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(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.size() == 0)
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.size() == 0)
122  {
123  eventMap = shm->ReceiveEvent(true);
124 
125  if (eventMap.count(artdaq::Fragment::type_t(artdaq::Fragment::EndOfDataFragmentType)))
126  {
127  TLOG(TLVL_DEBUG) << "Received shutdown message, returning";
128  return artdaq::FragmentPtrs();
129  }
130  else if (!eventMap.count(artdaq::Fragment::type_t(artdaq::Fragment::InitFragmentType)) && eventMap.size() > 0)
131  {
132  TLOG(TLVL_WARNING) << "Did NOT receive Init Fragment as first broadcast! Type="
133  << artdaq::detail::RawFragmentHeader::SystemTypeToString(eventMap.begin()->first);
134  eventMap.clear();
135  }
136  else if (artdaq::TimeUtils::GetElapsedTime(start) > init_timeout_s_)
137  {
138  TLOG(TLVL_WARNING) << "Did not receive Init fragment after init_fragment_timeout_seconds (" << artdaq::TimeUtils::GetElapsedTime(start) << ")!";
139  return artdaq::FragmentPtrs();
140  }
141  }
142 
143  // We return false, indicating we're done reading, if:
144  // 1) we did not obtain an event, because we timed out and were
145  // configured NOT to keep trying after a timeout, or
146  // 2) the event we read was the end-of-data marker: a null
147  // pointer
148 
149  TLOG(TLVL_TRACE) << "receiveInitMessage: Returning top Fragment";
150  artdaq::FragmentPtrs output;
151  for (auto& frag : *eventMap[artdaq::Fragment::InitFragmentType])
152  {
153  output.emplace_back(new artdaq::Fragment(std::move(frag)));
154  }
155 
156 #if DUMP_RECEIVE_MESSAGE
157  std::string fileName = "receiveInitMessage_" + std::to_string(getpid()) + ".bin";
158  std::fstream ostream(fileName.c_str(), std::ios::out | std::ios::binary);
159  ostream.write(buffer, header->data_length);
160  ostream.close();
161 #endif
162 
163  TLOG(TLVL_TRACE) << "receiveInitMessage END";
164  init_received_ = true;
165 
166  TLOG(5) << "Done Receiving Init Fragment from NetMonTransportService";
167  return output;
168 }
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.