artdaq  v3_06_00
SharedMemoryReader.hh
1 #ifndef artdaq_ArtModules_detail_SharedMemoryReader_hh
2 #define artdaq_ArtModules_detail_SharedMemoryReader_hh
3 
4 #include "art/Framework/Core/Frameworkfwd.h"
5 #include "artdaq-core/Utilities/ExceptionHandler.hh"
6 #include "artdaq/DAQdata/Globals.hh"
7 
8 #include <sys/time.h>
9 #include "art/Framework/Core/FileBlock.h"
10 #include "art/Framework/Core/ProductRegistryHelper.h"
11 #include "art/Framework/IO/Sources/SourceHelper.h"
12 #include "art/Framework/IO/Sources/put_product_in_principal.h"
13 #include "art/Framework/Principal/EventPrincipal.h"
14 #include "art/Framework/Principal/RunPrincipal.h"
15 #include "art/Framework/Principal/SubRunPrincipal.h"
16 #include "artdaq-core/Core/SharedMemoryEventReceiver.hh"
17 #include "artdaq-core/Core/SharedMemoryManager.hh"
18 #include "artdaq-core/Data/ContainerFragment.hh"
19 #include "artdaq-core/Data/Fragment.hh"
20 #include "artdaq-core/Utilities/TimeUtils.hh"
21 #include "canvas/Persistency/Provenance/FileFormatVersion.h"
22 #include "fhiclcpp/ParameterSet.h"
23 
24 #include <map>
25 #include <string>
26 #include "artdaq-core/Data/RawEvent.hh"
27 
28 namespace artdaq {
29 namespace detail {
35 {
36 public:
38  : type_map_() {}
39  virtual ~DefaultFragmentTypeTranslator() = default;
40 
44  virtual void SetBasicTypes(std::map<Fragment::type_t, std::string> const& type_map)
45  {
46  type_map_ = type_map;
47  }
48 
52  virtual void AddExtraType(artdaq::Fragment::type_t type_id, std::string type_name)
53  {
54  type_map_[type_id] = type_name;
55  }
56 
61  virtual std::string GetInstanceNameForType(artdaq::Fragment::type_t type_id, std::string unidentified_instance_name)
62  {
63  if (type_map_.count(type_id) > 0) { return type_map_[type_id]; }
64  return unidentified_instance_name;
65  }
66 
72  virtual std::set<std::string> GetAllProductInstanceNames()
73  {
74  std::set<std::string> output;
75  for (const auto& map_iter : type_map_)
76  {
77  std::string instance_name = map_iter.second;
78  if (!output.count(instance_name))
79  {
80  output.insert(instance_name);
81  TLOG_TRACE("DefaultFragmentTypeTranslator") << "Adding product instance name \"" << map_iter.second
82  << "\" to list of expected names";
83  }
84  }
85 
86  auto container_type = type_map_.find(Fragment::type_t(artdaq::Fragment::ContainerFragmentType));
87  if (container_type != type_map_.end())
88  {
89  std::string container_type_name = container_type->second;
90  std::set<std::string> tmp_copy = output;
91  for (const auto& set_iter : tmp_copy)
92  {
93  output.insert(container_type_name + set_iter);
94  }
95  }
96 
97  return output;
98  }
99 
106  virtual std::pair<bool, std::string>
107  GetInstanceNameForFragment(artdaq::Fragment const& fragment, std::string unidentified_instance_name)
108  {
109  auto type_map_end = type_map_.end();
110  bool success_code = true;
111  std::string instance_name;
112 
113  auto primary_type = type_map_.find(fragment.type());
114  if (primary_type != type_map_end)
115  {
116  instance_name = primary_type->second;
117  if (fragment.type() == artdaq::Fragment::ContainerFragmentType)
118  {
119  artdaq::ContainerFragment cf(fragment);
120  auto contained_type = type_map_.find(cf.fragment_type());
121  if (contained_type != type_map_end)
122  {
123  instance_name += contained_type->second;
124  }
125  }
126  }
127  else
128  {
129  instance_name = unidentified_instance_name;
130  success_code = false;
131  }
132 
133  return std::make_pair(success_code, instance_name);
134  }
135 
136 protected:
137  std::map<Fragment::type_t, std::string> type_map_;
138 };
139 
143 template<std::map<artdaq::Fragment::type_t, std::string> getDefaultTypes() = artdaq::Fragment::MakeSystemTypeMap,
144  class FTT = artdaq::detail::DefaultFragmentTypeTranslator>
146 {
150  SharedMemoryReader(SharedMemoryReader const&) = delete;
151 
157 
158  art::SourceHelper const& pmaker;
159  std::unique_ptr<SharedMemoryEventReceiver> incoming_events;
160  double waiting_time;
162  std::string pretend_module_name;
166  size_t bytesRead;
167  std::chrono::steady_clock::time_point last_read_time;
168  //std::unique_ptr<SharedMemoryManager> data_shm; ///< SharedMemoryManager containing data
169  // std::unique_ptr<SharedMemoryManager> broadcast_shm; ///< SharedMemoryManager containing broadcasts (control
170  // Fragments)
171 
186  SharedMemoryReader(fhicl::ParameterSet const& ps,
187  art::ProductRegistryHelper& help,
188  art::SourceHelper const& pm)
189  : pmaker(pm)
190  , waiting_time(ps.get<double>("waiting_time", 86400.0))
191  , resume_after_timeout(ps.get<bool>("resume_after_timeout", true))
192  , pretend_module_name(ps.get<std::string>("raw_data_label", "daq"))
193  , unidentified_instance_name("unidentified")
194  , shutdownMsgReceived(false)
195  , outputFileCloseNeeded(false)
196  , bytesRead(0)
197  , last_read_time(std::chrono::steady_clock::now())
198  , readNext_calls_(0)
199  {
200  // For testing
201  // if (ps.has_key("buffer_count") && (ps.has_key("max_event_size_bytes") ||
202  // (ps.has_key("expected_fragments_per_event") && ps.has_key("max_fragment_size_bytes"))))
203  //{
204  // data_shm.reset(new SharedMemoryManager(ps.get<uint32_t>("shared_memory_key", 0xBEE70000 + getppid()),
205  // ps.get<int>("buffer_count"), ps.has_key("max_event_size_bytes") ? ps.get<size_t>("max_event_size_bytes") :
206  // ps.get<size_t>("expected_fragments_per_event") * ps.get<size_t>("max_fragment_size_bytes")));
207  // broadcast_shm.reset(new SharedMemoryManager(ps.get<uint32_t>("broadcast_shared_memory_key", 0xCEE70000 +
208  // getppid()), ps.get<int>("broadcast_buffer_count", 5), ps.get<size_t>("broadcast_buffer_size", 0x100000)));
209  //}
210  incoming_events.reset(
211  new SharedMemoryEventReceiver(ps.get<uint32_t>("shared_memory_key", 0xBEE70000 + getppid()),
212  ps.get<uint32_t>("broadcast_shared_memory_key", 0xCEE70000 + getppid())));
213  my_rank = incoming_events->GetRank();
214  TLOG(TLVL_INFO, "SharedMemoryReader") << "Rank set to " << my_rank;
215 
216  char const* artapp_env = getenv("ARTDAQ_APPLICATION_NAME");
217  std::string artapp_str = "";
218  if (artapp_env != NULL)
219  {
220  artapp_str = std::string(artapp_env) + "_";
221  }
222 
223  app_name = artapp_str + "art" + std::to_string(incoming_events->GetMyId());
224 
225  artapp_env = getenv("ARTDAQ_RANK");
226  if (artapp_env != NULL && my_rank < 0)
227  {
228  my_rank = std::atoi(artapp_env);
229  }
230  TLOG(TLVL_INFO) << "app_name is " << app_name << ", rank " << my_rank;
231 
232  try
233  {
234  if (metricMan)
235  {
236  metricMan->initialize(ps.get<fhicl::ParameterSet>("metrics", fhicl::ParameterSet()), app_name);
237  metricMan->do_start();
238  }
239  }
240  catch (...)
241  {
242  ExceptionHandler(ExceptionHandlerRethrow::no, "Error loading metrics in SharedMemoryReader()");
243  }
244 
245  help.reconstitutes<Fragments, art::InEvent>(pretend_module_name, unidentified_instance_name);
246 
247  translator_.SetBasicTypes(getDefaultTypes());
248  auto extraTypes = ps.get<std::vector<std::pair<Fragment::type_t, std::string>>>("fragment_type_map", std::vector<std::pair<Fragment::type_t, std::string>>());
249  for (auto it = extraTypes.begin(); it != extraTypes.end(); ++it)
250  {
251  translator_.AddExtraType(it->first, it->second);
252  }
253  std::set<std::string> instance_names = translator_.GetAllProductInstanceNames();
254  for (const auto& set_iter : instance_names)
255  {
256  help.reconstitutes<Fragments, art::InEvent>(pretend_module_name, set_iter);
257  }
258 
259  TLOG_INFO("SharedMemoryReader") << "SharedMemoryReader initialized with ParameterSet: " << ps.to_string();
260  }
261 
262 #if ART_HEX_VERSION < 0x30000
263 
271  SharedMemoryReader(fhicl::ParameterSet const& ps, art::ProductRegistryHelper& help, art::SourceHelper const& pm,
272  art::MasterProductRegistry&)
273  : SharedMemoryReader(ps, help, pm) {}
274 #endif
275 
280 
285 
290  void readFile(std::string const&, art::FileBlock*& fb)
291  {
292  TLOG_ARB(5, "SharedMemoryReader") << "readFile enter/start";
293  fb = new art::FileBlock(art::FileFormatVersion(1, "RawEvent2011"), "nothing");
294  }
295 
300  bool hasMoreData() const { return (!shutdownMsgReceived); }
301 
312  bool readNext(art::RunPrincipal* const& inR, art::SubRunPrincipal* const& inSR, art::RunPrincipal*& outR,
313  art::SubRunPrincipal*& outSR, art::EventPrincipal*& outE)
314  {
315  TLOG_DEBUG("SharedMemoryReader") << "readNext BEGIN";
316  /*if (outputFileCloseNeeded) {
317  outputFileCloseNeeded = false;
318  return false;
319  }*/
320  // Establish default 'results'
321  outR = 0;
322  outSR = 0;
323  outE = 0;
324  // Try to get an event from the queue. We'll continuously loop, either until:
325  // 1) we have read a RawEvent off the queue, or
326  // 2) we have timed out, AND we are told the when we timeout we
327  // should stop.
328  // In any case, if we time out, we emit an informational message.
329 
331  {
332  TLOG_INFO("SharedMemoryReader") << "Shutdown Message received, returning false (should exit art)";
333  return false;
334  }
335 
336  auto read_start_time = std::chrono::steady_clock::now();
337  start:
338  bool keep_looping = true;
339  bool got_event = false;
340  auto sleepTimeUsec = waiting_time * 1000; // waiting_time * 1000000 us/s / 1000 reps = us/rep
341  if (sleepTimeUsec > 100000) sleepTimeUsec = 100000; // Don't wait longer than 1/10th of a second
342  while (keep_looping)
343  {
344  TLOG_TRACE("SharedMemoryReader") << "ReadyForRead loops BEGIN";
345  keep_looping = false;
346  auto start_time = std::chrono::steady_clock::now();
347  while (!got_event && TimeUtils::GetElapsedTimeMicroseconds(start_time) < 1000)
348  {
349  // BURN CPU for 1 ms!
350  got_event = incoming_events->ReadyForRead();
351  }
352  TLOG_TRACE("SharedMemoryReader") << "ReadyForRead spin end, poll begin";
353  while (!got_event && TimeUtils::GetElapsedTime(start_time) < waiting_time)
354  {
355  got_event = incoming_events->ReadyForRead();
356  if (!got_event)
357  {
358  usleep(sleepTimeUsec);
359  // TLOG_INFO("SharedMemoryReader") << "Waited " << TimeUtils::GetElapsedTime(start_time) << " of " <<
360  // waiting_time ;
361  }
362  }
363  TLOG_TRACE("SharedMemoryReader") << "ReadyForRead loops END";
364  if (!got_event)
365  {
366  TLOG_INFO("SharedMemoryReader") << "InputFailure: Reading timed out in SharedMemoryReader::readNext()";
367  keep_looping = resume_after_timeout;
368  }
369  }
370 
371  if (!got_event)
372  {
373  TLOG_INFO("SharedMemoryReader") << "Did not receive an event from Shared Memory, returning false";
374  shutdownMsgReceived = true;
375  return false;
376  }
377  TLOG_DEBUG("SharedMemoryReader") << "Got Event!";
378  auto got_event_time = std::chrono::steady_clock::now();
379 
380  auto errflag = false;
381  auto evtHeader = incoming_events->ReadHeader(errflag);
382  if (errflag) goto start; // Buffer was changed out from under reader!
383  auto fragmentTypes = incoming_events->GetFragmentTypes(errflag);
384  if (errflag) goto start; // Buffer was changed out from under reader!
385  if (fragmentTypes.size() == 0)
386  {
387  TLOG_ERROR("SharedMemoryReader") << "Event has no Fragments! Aborting!";
388  incoming_events->ReleaseBuffer();
389  return false;
390  }
391  auto firstFragmentType = *fragmentTypes.begin();
392  TLOG_DEBUG("SharedMemoryReader") << "First Fragment type is " << (int)firstFragmentType << " ("
393  << translator_.GetInstanceNameForType(firstFragmentType, unidentified_instance_name) << ")";
394  // We return false, indicating we're done reading, if:
395  // 1) we did not obtain an event, because we timed out and were
396  // configured NOT to keep trying after a timeout, or
397  // 2) the event we read was the end-of-data marker: a null
398  // pointer
399  if (firstFragmentType == Fragment::EndOfDataFragmentType)
400  {
401  TLOG_DEBUG("SharedMemoryReader") << "Received shutdown message, returning false";
402  shutdownMsgReceived = true;
403  incoming_events->ReleaseBuffer();
404  return false;
405  }
406 
407  size_t qsize = incoming_events->ReadReadyCount(); // save the qsize at this point
408 
409  // Check the number of fragments in the RawEvent. If we have a single
410  // fragment and that fragment is marked as EndRun or EndSubrun we'll create
411  // the special principals for that.
412  art::Timestamp currentTime = 0;
413 #if 0
414  art::TimeValue_t lo_res_time = time(0);
415  TLOG_ARB(15, "SharedMemoryReader") << "lo_res_time = " << lo_res_time;
416  currentTime = ((lo_res_time & 0xffffffff) << 32);
417 #endif
418  timespec hi_res_time;
419  int retcode = clock_gettime(CLOCK_REALTIME, &hi_res_time);
420  TLOG_ARB(15, "SharedMemoryReader") << "hi_res_time tv_sec = " << hi_res_time.tv_sec
421  << " tv_nsec = " << hi_res_time.tv_nsec << " (retcode = " << retcode << ")";
422  if (retcode == 0)
423  {
424  currentTime = ((hi_res_time.tv_sec & 0xffffffff) << 32) | (hi_res_time.tv_nsec & 0xffffffff);
425  }
426  else
427  {
428  TLOG_ERROR("SharedMemoryReader")
429  << "Unable to fetch a high-resolution time with clock_gettime for art::Event Timestamp. "
430  << "The art::Event Timestamp will be zero for event " << evtHeader->event_id;
431  }
432 
433  // make new run if inR is 0 or if the run has changed
434  if (inR == 0 || inR->run() != evtHeader->run_id)
435  {
436  outR = pmaker.makeRunPrincipal(evtHeader->run_id, currentTime);
437  }
438 
439  if (firstFragmentType == Fragment::EndOfRunFragmentType)
440  {
441  art::EventID const evid(art::EventID::flushEvent());
442  outR = pmaker.makeRunPrincipal(evid.runID(), currentTime);
443  outSR = pmaker.makeSubRunPrincipal(evid.subRunID(), currentTime);
444  outE = pmaker.makeEventPrincipal(evid, currentTime);
445  incoming_events->ReleaseBuffer();
446  return true;
447  }
448  else if (firstFragmentType == Fragment::EndOfSubrunFragmentType)
449  {
450  // Check if inR == 0 or is a new run
451  if (inR == 0 || inR->run() != evtHeader->run_id)
452  {
453  outSR = pmaker.makeSubRunPrincipal(evtHeader->run_id, evtHeader->subrun_id, currentTime);
454 #if ART_HEX_VERSION > 0x30000
455  art::EventID const evid(art::EventID::flushEvent(outSR->subRunID()));
456 #else
457  art::EventID const evid(art::EventID::flushEvent(outSR->id()));
458 #endif
459  outE = pmaker.makeEventPrincipal(evid, currentTime);
460  }
461  else
462  {
463  // If the previous subrun was neither 0 nor flush and was identical with the current
464  // subrun, then it must have been associated with a data event. In that case, we need
465  // to generate a flush event with a valid run but flush subrun and event number in order
466  // to end the subrun.
467 #if ART_HEX_VERSION > 0x30000
468  if (inSR != 0 && !inSR->subRunID().isFlush() && inSR->subRun() == evtHeader->subrun_id)
469 #else
470  if (inSR != 0 && !inSR->id().isFlush() && inSR->subRun() == evtHeader->subrun_id)
471 #endif
472  {
473 #if ART_HEX_VERSION > 0x30000
474  art::EventID const evid(art::EventID::flushEvent(inR->runID()));
475 #else
476  art::EventID const evid(art::EventID::flushEvent(inR->id()));
477 #endif
478  outSR = pmaker.makeSubRunPrincipal(evid.subRunID(), currentTime);
479  outE = pmaker.makeEventPrincipal(evid, currentTime);
480  // If this is either a new or another empty subrun, then generate a flush event with
481  // valid run and subrun numbers but flush event number
482  //} else if(inSR==0 || inSR->id().isFlush()){
483  }
484  else
485  {
486  outSR = pmaker.makeSubRunPrincipal(evtHeader->run_id, evtHeader->subrun_id, currentTime);
487 #if ART_HEX_VERSION > 0x30000
488  art::EventID const evid(art::EventID::flushEvent(outSR->subRunID()));
489 #else
490  art::EventID const evid(art::EventID::flushEvent(outSR->id()));
491 #endif
492  outE = pmaker.makeEventPrincipal(evid, currentTime);
493  // Possible error condition
494  //} else {
495  }
496  outR = 0;
497  }
498  //outputFileCloseNeeded = true;
499  incoming_events->ReleaseBuffer();
500  return true;
501  }
502 
503  // make new subrun if inSR is 0 or if the subrun has changed
504  art::SubRunID subrun_check(evtHeader->run_id, evtHeader->subrun_id);
505 #if ART_HEX_VERSION > 0x30000
506  if (inSR == 0 || subrun_check != inSR->subRunID())
507  {
508 #else
509  if (inSR == 0 || subrun_check != inSR->id())
510  {
511 #endif
512  outSR = pmaker.makeSubRunPrincipal(evtHeader->run_id, evtHeader->subrun_id, currentTime);
513  }
514  outE = pmaker.makeEventPrincipal(evtHeader->run_id, evtHeader->subrun_id, evtHeader->event_id, currentTime);
515 
516  double fragmentLatency = 0;
517  double fragmentLatencyMax = 0.0;
518  size_t fragmentCount = 0;
519 
520  // insert the Fragments of each type into the EventPrincipal
521  for (auto& type_code : fragmentTypes)
522  {
523  TLOG_TRACE("SharedMemoryReader") << "Before GetFragmentsByType call, type is " << (int)type_code;
524  auto product = incoming_events->GetFragmentsByType(errflag, type_code);
525  TLOG_TRACE("SharedMemoryReader") << "After GetFragmentsByType call, number of fragments is " << product->size();
526  if (errflag) goto start; // Buffer was changed out from under reader!
527 
528  std::unordered_map<std::string, std::unique_ptr<Fragments>> derived_fragments;
529  for (auto& frag : *product)
530  {
531  bytesRead += frag.sizeBytes();
532  auto latency_s = frag.getLatency(true);
533  double latency = latency_s.tv_sec + (latency_s.tv_nsec / 1000000000.0);
534 
535  fragmentLatency += latency;
536  fragmentCount++;
537  if (latency > fragmentLatencyMax) fragmentLatencyMax = latency;
538 
539  std::pair<bool, std::string> instance_name_result =
540  translator_.GetInstanceNameForFragment(frag, unidentified_instance_name);
541  std::string label = instance_name_result.second;
542  if (!instance_name_result.first)
543  {
544  TLOG_WARNING("SharedMemoryReader")
545  << "UnknownFragmentType: The product instance name mapping for fragment type \"" << ((int)type_code)
546  << "\" is not known. Fragments of this "
547  << "type will be stored in the event with an instance name of \"" << unidentified_instance_name << "\".";
548  }
549  if (!derived_fragments.count(label))
550  {
551  derived_fragments[label] = std::make_unique<Fragments>();
552  }
553  derived_fragments[label]->emplace_back(std::move(frag));
554  }
555  for (auto& type : derived_fragments)
556  {
557  put_product_in_principal(std::move(type.second),
558  *outE,
560  type.first);
561  }
562  }
563  TLOG_TRACE("SharedMemoryReader") << "After putting fragments in event";
564 
565  auto read_finish_time = std::chrono::steady_clock::now();
566  incoming_events->ReleaseBuffer();
567  auto qcap = incoming_events->size();
568  TLOG_ARB(10, "SharedMemoryReader") << "readNext: bytesRead=" << bytesRead << " qsize=" << qsize << " cap=" << qcap
569  << " metricMan=" << (void*)metricMan.get();
570  if (metricMan)
571  {
572  metricMan->sendMetric("Avg Processing Time", artdaq::TimeUtils::GetElapsedTime(last_read_time, read_start_time),
573  "s", 2, MetricMode::Average);
574  metricMan->sendMetric("Avg Input Wait Time", artdaq::TimeUtils::GetElapsedTime(read_start_time, got_event_time),
575  "s", 3, MetricMode::Average);
576  metricMan->sendMetric("Avg Read Time", artdaq::TimeUtils::GetElapsedTime(got_event_time, read_finish_time), "s",
577  3, MetricMode::Average);
578  metricMan->sendMetric("bytesRead", bytesRead, "B", 3, MetricMode::LastPoint);
579  if (qcap > 0)
580  metricMan->sendMetric("queue%Used", static_cast<unsigned long int>(qsize * 100 / qcap), "%", 5,
581  MetricMode::LastPoint);
582 
583  metricMan->sendMetric("SharedMemoryReader Latency", fragmentLatency / fragmentCount, "s", 4, MetricMode::Average);
584  metricMan->sendMetric("SharedMemoryReader Maximum Latency", fragmentLatencyMax, "s", 4, MetricMode::Maximum);
585  }
586 
587  TLOG_TRACE("SharedMemoryReader") << "Returning from readNext";
588  last_read_time = std::chrono::steady_clock::now();
589  return true;
590  }
591 
592  unsigned readNext_calls_;
593  FTT translator_;
594 };
595 } // namespace detail
596 } // namespace artdaq
597 
598 #endif /* artdaq_ArtModules_detail_SharedMemoryReader_hh */
bool hasMoreData() const
Whether more data is expected from the SharedMemoryReader.
void closeCurrentFile()
Emulate closing a file. No-Op.
bool readNext(art::RunPrincipal *const &inR, art::SubRunPrincipal *const &inSR, art::RunPrincipal *&outR, art::SubRunPrincipal *&outSR, art::EventPrincipal *&outE)
Dequeue a RawEvent and declare its Fragment contents to art, creating Run, SubRun, and EventPrincipal objects as necessary.
size_t bytesRead
running total of number of bytes received
The SharedMemoryReader is a class which implements the methods needed by art::Source.
SharedMemoryReader(SharedMemoryReader const &)=delete
Copy Constructor is deleted.
static void CleanUpGlobals()
Clean up statically-allocated Manager class instances.
Definition: Globals.hh:150
std::string pretend_module_name
The module name to store data under.
bool shutdownMsgReceived
Whether a shutdown message has been received.
bool resume_after_timeout
Whether to resume if the dequeue action times out.
double waiting_time
The amount of time to wait for an event from the queue.
std::unique_ptr< SharedMemoryEventReceiver > incoming_events
The events from the EventStore.
SharedMemoryReader(fhicl::ParameterSet const &ps, art::ProductRegistryHelper &help, art::SourceHelper const &pm)
SharedMemoryReader Constructor.
unsigned readNext_calls_
The number of times readNext has been called.
virtual void SetBasicTypes(std::map< Fragment::type_t, std::string > const &type_map)
Sets the basic types to be translated. (Should not include &quot;container&quot; types.)
void readFile(std::string const &, art::FileBlock *&fb)
Emulate opening a file.
bool outputFileCloseNeeded
If an explicit output file close message is needed.
virtual void AddExtraType(artdaq::Fragment::type_t type_id, std::string type_name)
Adds an additional type to be translated.
SharedMemoryReader & operator=(SharedMemoryReader const &)=delete
Copy Assignment operator is deleted.
virtual std::string GetInstanceNameForType(artdaq::Fragment::type_t type_id, std::string unidentified_instance_name)
Returns the basic translation for the specified type. Defaults to the specified unidentified_instance...
art::SourceHelper const & pmaker
An art::SourceHelper instance.
virtual std::pair< bool, std::string > GetInstanceNameForFragment(artdaq::Fragment const &fragment, std::string unidentified_instance_name)
Returns the product instance name for the specified fragment, based on the types that have been speci...
std::string unidentified_instance_name
The name to use for unknown Fragment types.
virtual std::set< std::string > GetAllProductInstanceNames()
Returns the full set of product instance names which may be present in the data, based on the types t...
SharedMemoryReader(fhicl::ParameterSet const &ps, art::ProductRegistryHelper &help, art::SourceHelper const &pm, art::MasterProductRegistry &)
SharedMemoryReader Constructor.
The DefaultFragmentTypeTranslator class provides default behavior for experiment-specific customizati...
std::chrono::steady_clock::time_point last_read_time
Time last read was completed.
virtual ~SharedMemoryReader()
SharedMemoryReader destructor.