artdaq  v3_07_01
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", 1000000))
19 {
20  TLOG(TLVL_TRACE) << "ArtdaqSharedMemoryService CONSTRUCTOR";
21 
22  incoming_events_.reset(new artdaq::SharedMemoryEventReceiver(
23  pset.get<int>("shared_memory_key", build_key(0xEE000000)),
24  pset.get<int>("broadcast_shared_memory_key", build_key(0xBB000000))));
25 
26  char const* artapp_env = getenv("ARTDAQ_APPLICATION_NAME");
27  std::string artapp_str = "";
28  if (artapp_env != NULL)
29  {
30  artapp_str = std::string(artapp_env) + "_";
31  }
32 
33  TLOG(TLVL_TRACE) << "Setting app_name";
34  app_name = artapp_str + "art" + std::to_string(incoming_events_->GetMyId());
35 
36  artapp_env = getenv("ARTDAQ_RANK");
37  if (artapp_env != NULL && my_rank < 0)
38  {
39  TLOG(TLVL_TRACE) << "Setting rank from envrionment";
40  my_rank = std::atoi(artapp_env);
41  }
42  else
43  {
44  TLOG(TLVL_TRACE) << "Setting my_rank from shared memory";
45  my_rank = incoming_events_->GetRank();
46  }
47 
48  try
49  {
50  if (metricMan)
51  {
52  metricMan->initialize(pset.get<fhicl::ParameterSet>("metrics", fhicl::ParameterSet()), app_name);
53  metricMan->do_start();
54  }
55  }
56  catch (...)
57  {
58  artdaq::ExceptionHandler(artdaq::ExceptionHandlerRethrow::no, "Error loading metrics in ArtdaqSharedMemoryService()");
59  }
60 
61  TLOG(TLVL_INFO) << "app_name is " << app_name << ", rank " << my_rank;
62 }
63 
65 {
67 }
68 
69 std::unordered_map<artdaq::Fragment::type_t, std::unique_ptr<artdaq::Fragments>> ArtdaqSharedMemoryService::ReceiveEvent(bool broadcast)
70 {
71  TLOG(TLVL_TRACE) << "ReceiveEvent BEGIN";
72  std::unordered_map<artdaq::Fragment::type_t, std::unique_ptr<artdaq::Fragments>> recvd_fragments;
73 
74  while (recvd_fragments.size() == 0)
75  {
76  TLOG(TLVL_TRACE) << "ReceiveEvent: Waiting for available buffer";
77  bool got_event = false;
78  while (!incoming_events_->IsEndOfData() && !got_event)
79  {
80  got_event = incoming_events_->ReadyForRead(broadcast, read_timeout_);
81  }
82 
83  TLOG(TLVL_TRACE) << "ReceiveEvent: Reading buffer header";
84  auto errflag = false;
85  auto hdrPtr = incoming_events_->ReadHeader(errflag);
86  if (errflag || hdrPtr == nullptr)
87  { // Buffer was changed out from under reader!
88  return recvd_fragments;
89  }
90  evtHeader_ = std::make_shared<artdaq::detail::RawEventHeader>(*hdrPtr);
91  TLOG(TLVL_TRACE) << "ReceiveEvent: Getting Fragment types";
92  auto fragmentTypes = incoming_events_->GetFragmentTypes(errflag);
93  if (errflag)
94  { // Buffer was changed out from under reader!
95  incoming_events_->ReleaseBuffer();
96  return recvd_fragments;
97  }
98  if (fragmentTypes.size() == 0)
99  {
100  TLOG(TLVL_ERROR) << "Event has no Fragments! Aborting!";
101  incoming_events_->ReleaseBuffer();
102  return recvd_fragments;
103  }
104 
105  for (auto const& type : fragmentTypes)
106  {
107  TLOG(TLVL_TRACE) << "receiveMessage: Getting all Fragments of type " << type;
108  recvd_fragments[type] = incoming_events_->GetFragmentsByType(errflag, type);
109  if (!recvd_fragments[type])
110  {
111  TLOG(TLVL_ERROR) << "Error retrieving Fragments from shared memory! Aborting!";
112  incoming_events_->ReleaseBuffer();
113  return recvd_fragments;
114  }
115  /* Events coming out of the EventStore are not sorted but need to be
116  sorted by sequence ID before they can be passed to art.
117  */
118  std::sort(recvd_fragments[type]->begin(), recvd_fragments[type]->end(), artdaq::fragmentSequenceIDCompare);
119  }
120  TLOG(TLVL_TRACE) << "receiveMessage: Releasing buffer";
121  incoming_events_->ReleaseBuffer();
122  }
123 
124  TLOG(TLVL_TRACE) << "receiveMessage END";
125  return recvd_fragments;
126 }
127 
128 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.