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