artdaq  v3_09_01
ArtdaqSharedMemoryService_service.cc
1 #define TRACE_NAME "ArtdaqSharedMemoryService"
2 
3 #include <memory>
4 #include <cstdint>
5 
6 #include "art/Framework/Services/Registry/ServiceHandle.h"
7 #include "artdaq-core/Core/SharedMemoryEventReceiver.hh"
8 #include "artdaq-core/Utilities/ExceptionHandler.hh"
9 #include "artdaq/ArtModules/ArtdaqSharedMemoryService.h"
10 
11 #include "artdaq/DAQdata/Globals.hh"
12 
13 #define build_key(seed) ((seed) + ((GetPartitionNumber() + 1) << 16) + (getppid() & 0xFFFF))
14 
15 static fhicl::ParameterSet empty_pset;
16 
17 ArtdaqSharedMemoryService::ArtdaqSharedMemoryService(fhicl::ParameterSet const& pset, art::ActivityRegistry& /*unused*/)
18  : incoming_events_(nullptr)
19  , evtHeader_(nullptr)
20  , read_timeout_(pset.get<size_t>("read_timeout_us", static_cast<size_t>(pset.get<double>("waiting_time", 600.0) * 1000000)))
21  , resume_after_timeout_(pset.get<bool>("resume_after_timeout", true))
22 {
23  TLOG(TLVL_TRACE) << "ArtdaqSharedMemoryService CONSTRUCTOR";
24 
25  incoming_events_ = std::make_unique<artdaq::SharedMemoryEventReceiver>(
26  pset.get<int>("shared_memory_key", build_key(0xEE000000)),
27  pset.get<int>("broadcast_shared_memory_key", build_key(0xBB000000)));
28 
29  char const* artapp_env = getenv("ARTDAQ_APPLICATION_NAME");
30  std::string artapp_str;
31  if (artapp_env != nullptr)
32  {
33  artapp_str = std::string(artapp_env) + "_";
34  }
35 
36  TLOG(TLVL_TRACE) << "Setting app_name";
37  app_name = artapp_str + "art" + std::to_string(incoming_events_->GetMyId());
38  artdaq::configureMessageFacility(app_name.c_str());
39 
40  artapp_env = getenv("ARTDAQ_RANK");
41  if (artapp_env != nullptr && my_rank < 0)
42  {
43  TLOG(TLVL_TRACE) << "Setting rank from envrionment";
44  my_rank = strtol(artapp_env, nullptr, 10);
45  }
46  else
47  {
48  TLOG(TLVL_TRACE) << "Setting my_rank from shared memory";
49  my_rank = incoming_events_->GetRank();
50  }
51 
52  try
53  {
54  if (metricMan)
55  {
56  metricMan->initialize(pset.get<fhicl::ParameterSet>("metrics", fhicl::ParameterSet()), app_name);
57  metricMan->do_start();
58  }
59  }
60  catch (...)
61  {
62  artdaq::ExceptionHandler(artdaq::ExceptionHandlerRethrow::no, "Error loading metrics in ArtdaqSharedMemoryService()");
63  }
64 
65  TLOG(TLVL_INFO) << "app_name is " << app_name << ", rank " << my_rank;
66 }
67 
69 {
71 }
72 
73 std::unordered_map<artdaq::Fragment::type_t, std::unique_ptr<artdaq::Fragments>> ArtdaqSharedMemoryService::ReceiveEvent(bool broadcast)
74 {
75  TLOG(TLVL_TRACE) << "ReceiveEvent BEGIN";
76  std::unordered_map<artdaq::Fragment::type_t, std::unique_ptr<artdaq::Fragments>> recvd_fragments;
77 
78  while (recvd_fragments.empty())
79  {
80  TLOG(TLVL_TRACE) << "ReceiveEvent: Waiting for available buffer";
81  bool got_event = false;
82  while (!incoming_events_->IsEndOfData() && !got_event)
83  {
84  got_event = incoming_events_->ReadyForRead(broadcast, read_timeout_);
85  if (!got_event && (!resume_after_timeout_ || broadcast)) // Only try broadcasts once!
86  {
87  TLOG(TLVL_ERROR) << "Timeout occurred! No data received after " << read_timeout_ << " us. Returning empty Fragment list!";
88  return recvd_fragments;
89  }
90  if (!got_event)
91  {
92  TLOG(TLVL_WARNING) << "Timeout occurred! No data received after " << read_timeout_ << " us. Retrying.";
93  }
94  }
95  if (incoming_events_->IsEndOfData())
96  {
97  TLOG(TLVL_INFO) << "End of Data signal received, exiting";
98  return recvd_fragments;
99  }
100 
101  TLOG(TLVL_TRACE) << "ReceiveEvent: Reading buffer header";
102  auto errflag = false;
103  auto hdrPtr = incoming_events_->ReadHeader(errflag);
104  if (errflag || hdrPtr == nullptr)
105  { // Buffer was changed out from under reader!
106  incoming_events_->ReleaseBuffer();
107  continue;//retry
108  //return recvd_fragments;
109  }
110  evtHeader_ = std::make_shared<artdaq::detail::RawEventHeader>(*hdrPtr);
111  TLOG(TLVL_TRACE) << "ReceiveEvent: Getting Fragment types";
112  auto fragmentTypes = incoming_events_->GetFragmentTypes(errflag);
113  if (errflag)
114  { // Buffer was changed out from under reader!
115  incoming_events_->ReleaseBuffer();
116  continue; //retry
117  //return recvd_fragments;
118  }
119  if (fragmentTypes.empty())
120  {
121  TLOG(TLVL_ERROR) << "Event has no Fragments! Aborting!";
122  incoming_events_->ReleaseBuffer();
123  return recvd_fragments;
124  }
125 
126  for (auto const& type : fragmentTypes)
127  {
128  TLOG(TLVL_TRACE) << "receiveMessage: Getting all Fragments of type " << type;
129  recvd_fragments[type] = incoming_events_->GetFragmentsByType(errflag, type);
130  if (!recvd_fragments[type])
131  {
132  TLOG(TLVL_ERROR) << "Error retrieving Fragments from shared memory! Aborting!";
133  incoming_events_->ReleaseBuffer();
134  return recvd_fragments;
135  }
136  /* Events coming out of the EventStore are not sorted but need to be
137  sorted by sequence ID before they can be passed to art.
138  */
139  std::sort(recvd_fragments[type]->begin(), recvd_fragments[type]->end(), artdaq::fragmentSequenceIDCompare);
140  }
141  TLOG(TLVL_TRACE) << "receiveMessage: Releasing buffer";
142  incoming_events_->ReleaseBuffer();
143  }
144 
145  TLOG(TLVL_TRACE) << "receiveMessage END";
146  return recvd_fragments;
147 }
148 
149 DEFINE_ART_SERVICE_INTERFACE_IMPL(ArtdaqSharedMemoryService, ArtdaqSharedMemoryServiceInterface)
Interface for ArtdaqSharedMemoryService. This interface is declared to art as part of the required re...
static void CleanUpGlobals()
Clean up statically-allocated Manager class instances.
Definition: Globals.hh:150
virtual ~ArtdaqSharedMemoryService()
NetMonTransportService Destructor. Calls disconnect().
ArtdaqSharedMemoryService(fhicl::ParameterSet const &pset, art::ActivityRegistry &)
NetMonTransportService Constructor.
ArtdaqSharedMemoryService extends ArtdaqSharedMemoryServiceInterface. It receives events from shared ...
std::unordered_map< artdaq::Fragment::type_t, std::unique_ptr< artdaq::Fragments > > ReceiveEvent(bool broadcast) override
Receive an event from the shared memory.