artdaq  v3_07_01
NetMonWrapper.cc
1 #define TRACE_NAME "NetMonWrapper"
2 
3 #include "artdaq/ArtModules/NetMonWrapper.hh"
4 #include "art/Framework/Services/Registry/ServiceHandle.h"
5 #include "artdaq/ArtModules/ArtdaqSharedMemoryService.h"
6 #include "artdaq/DAQdata/NetMonHeader.hh"
7 
8 #include <TBufferFile.h>
9 
10 art::NetMonWrapper::NetMonWrapper(fhicl::ParameterSet const& ps)
11 {
12  init_timeout_s_ = ps.get<double>("init_fragment_timeout_seconds", 1.0);
13  // Make sure the ArtdaqSharedMemoryService is available
14  art::ServiceHandle<ArtdaqSharedMemoryService> shm;
15 }
16 
17 void art::NetMonWrapper::receiveMessage(std::unique_ptr<TBufferFile>& msg_ptr)
18 {
19  TLOG(5) << "Receiving Fragment from NetMonTransportService";
20  TBufferFile* msg(nullptr);
21  TLOG(TLVL_TRACE) << "receiveMessage BEGIN";
22  art::ServiceHandle<ArtdaqSharedMemoryService> shm;
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(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. Art will crash.";
33  msg = nullptr;
34  return;
35  }
36 
37  artdaq::Fragments recvd_fragments;
38  while (recvd_fragments.size() == 0)
39  {
40  auto eventMap = shm->ReceiveEvent(false);
41 
42  if (eventMap.size() == 0)
43  {
44  TLOG(TLVL_DEBUG) << "Did not receive event after timeout, returning from receiveMessage ";
45  return;
46  }
47 
48  if (eventMap.count(artdaq::Fragment::type_t(artdaq::Fragment::EndOfDataFragmentType)))
49  {
50  TLOG(TLVL_DEBUG) << "Received shutdown message, returning";
51  msg = nullptr;
52  return;
53  }
54  if (eventMap.count(artdaq::Fragment::type_t(artdaq::Fragment::DataFragmentType)))
55  {
56  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));
57  }
58  std::sort(recvd_fragments.begin(), recvd_fragments.end(), artdaq::fragmentSequenceIDCompare);
59  }
60 
61  TLOG(TLVL_TRACE) << "receiveMessage: Returning top Fragment";
62  artdaq::Fragment topFrag = std::move(recvd_fragments.at(0));
63  recvd_fragments.erase(recvd_fragments.begin());
64 
65  TLOG(TLVL_TRACE) << "receiveMessage: Copying Fragment into TBufferFile, length="
66  << topFrag.metadata<artdaq::NetMonHeader>()->data_length;
67  auto header = topFrag.metadata<artdaq::NetMonHeader>();
68  auto buffer = static_cast<char*>(malloc(header->data_length));
69  memcpy(buffer, &*topFrag.dataBegin(), header->data_length);
70  msg = new TBufferFile(TBuffer::kRead, header->data_length, buffer, kTRUE, 0);
71 
72 #if DUMP_RECEIVE_MESSAGE
73  std::string fileName = "receiveMessage_" + std::to_string(my_rank) + "_" + std::to_string(getpid()) + "_" +
74  std::to_string(topFrag.sequenceID()) + ".bin";
75  std::fstream ostream(fileName.c_str(), std::ios::out | std::ios::binary);
76  ostream.write(buffer, header->data_length);
77  ostream.close();
78 #endif
79 
80  TLOG(TLVL_TRACE) << "receiveMessage END";
81 
82  msg_ptr.reset(msg);
83  TLOG(5) << "Done Receiving Fragment from NetMonTransportService";
84 }
85 
86 void art::NetMonWrapper::receiveInitMessage(std::unique_ptr<TBufferFile>& msg_ptr)
87 {
88  TLOG(5) << "Receiving Init Fragment from NetMonTransportService";
89  TBufferFile* msg(nullptr);
90 
91  TLOG(TLVL_TRACE) << "receiveInitMessage BEGIN";
92  art::ServiceHandle<ArtdaqSharedMemoryService> shm;
93  std::unordered_map<artdaq::Fragment::type_t, std::unique_ptr<artdaq::Fragments>> eventMap;
94  while (eventMap.size() == 0)
95  {
96  eventMap = shm->ReceiveEvent(true);
97 
98  if (eventMap.count(artdaq::Fragment::type_t(artdaq::Fragment::EndOfDataFragmentType)))
99  {
100  TLOG(TLVL_DEBUG) << "Received shutdown message, returning";
101  msg = nullptr;
102  return;
103  }
104  else if (!eventMap.count(artdaq::Fragment::type_t(artdaq::Fragment::InitFragmentType)) && eventMap.size() > 0)
105  {
106  TLOG(TLVL_WARNING) << "Did NOT receive Init Fragment as first broadcast! Type="
107  << artdaq::detail::RawFragmentHeader::SystemTypeToString(eventMap.begin()->first);
108  eventMap.clear();
109  }
110  }
111 
112  // We return false, indicating we're done reading, if:
113  // 1) we did not obtain an event, because we timed out and were
114  // configured NOT to keep trying after a timeout, or
115  // 2) the event we read was the end-of-data marker: a null
116  // pointer
117 
118  TLOG(TLVL_TRACE) << "receiveInitMessage: Returning top Fragment";
119  artdaq::Fragment topFrag = std::move(eventMap[artdaq::Fragment::type_t(artdaq::Fragment::InitFragmentType)]->at(0));
120 
121  auto header = topFrag.metadata<artdaq::NetMonHeader>();
122  TLOG(TLVL_TRACE) << "receiveInitMessage: Copying Fragment into TBufferFile: message length: " << header->data_length;
123  auto buffer = new char[header->data_length];
124  // auto buffer = static_cast<char *>(malloc(header->data_length)); // Fix alloc-dealloc-mismatch
125  memcpy(buffer, &*topFrag.dataBegin(), header->data_length);
126 
127 #if DUMP_RECEIVE_MESSAGE
128  std::string fileName = "receiveInitMessage_" + std::to_string(getpid()) + ".bin";
129  std::fstream ostream(fileName.c_str(), std::ios::out | std::ios::binary);
130  ostream.write(buffer, header->data_length);
131  ostream.close();
132 #endif
133 
134  msg = new TBufferFile(TBuffer::kRead, header->data_length, buffer, kTRUE, 0);
135 
136  TLOG(TLVL_TRACE) << "receiveInitMessage END";
137  init_received_ = true;
138 
139  msg_ptr.reset(msg);
140  TLOG(5) << "Done Receiving Init Fragment from NetMonTransportService";
141 }
NetMonWrapper(fhicl::ParameterSet const &ps)
NetMonWrapper Constructor.
void receiveMessage(std::unique_ptr< TBufferFile > &msg)
Receive a message from the NetMonTransportService.
Header with length information for NetMonTransport messages.
Definition: NetMonHeader.hh:13
void receiveInitMessage(std::unique_ptr< TBufferFile > &msg)
Receive an init message from the NetMonTransportService.
uint64_t data_length
The length of the message.
Definition: NetMonHeader.hh:15