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