artdaq  v3_08_00
ArtdaqInputHelper.hh
1 #include "art/Framework/Core/Frameworkfwd.h"
2 
3 #include "art/Framework/Core/FileBlock.h"
4 #include "art/Framework/Core/InputSourceMacros.h"
5 #include "art/Framework/Core/ProductRegistryHelper.h"
6 #include "art/Framework/IO/Sources/Source.h"
7 #include "art/Framework/IO/Sources/SourceHelper.h"
8 #include "art/Framework/IO/Sources/SourceTraits.h"
9 #include "art/Framework/IO/Sources/put_product_in_principal.h"
10 #include "art/Framework/Principal/EventPrincipal.h"
11 #include "art/Framework/Principal/RunPrincipal.h"
12 #include "art/Framework/Principal/SubRunPrincipal.h"
13 #include "art/Framework/Services/Registry/ServiceHandle.h"
14 
15 #if ART_HEX_VERSION < 0x30000
16 #include "art/Persistency/Provenance/MasterProductRegistry.h"
17 #include "art/Persistency/Provenance/ProductMetaData.h"
18 #endif
19 #if ART_HEX_VERSION >= 0x30200
20 #include "art_root_io/setup.h"
21 #endif
22 #include "art/Persistency/Provenance/ProcessHistoryRegistry.h"
23 
24 #include "canvas/Persistency/Common/EDProduct.h"
25 #include "canvas/Persistency/Common/Wrapper.h"
26 #include "canvas/Persistency/Provenance/BranchDescription.h"
27 #include "canvas/Persistency/Provenance/BranchKey.h"
28 #include "canvas/Persistency/Provenance/FileFormatVersion.h"
29 #include "canvas/Persistency/Provenance/History.h"
30 #include "canvas/Persistency/Provenance/ParentageRegistry.h"
31 #include "canvas/Persistency/Provenance/ProcessConfiguration.h"
32 #include "canvas/Persistency/Provenance/ProcessHistory.h"
33 #include "canvas/Persistency/Provenance/ProcessHistoryID.h"
34 #include "canvas/Persistency/Provenance/ProductList.h"
35 #include "canvas/Persistency/Provenance/ProductProvenance.h"
36 #include "canvas/Persistency/Provenance/ProductTables.h"
37 #include "canvas/Utilities/DebugMacros.h"
38 
39 #include "fhiclcpp/ParameterSet.h"
40 #include "fhiclcpp/ParameterSetID.h"
41 #include "fhiclcpp/ParameterSetRegistry.h"
42 #include "fhiclcpp/make_ParameterSet.h"
43 
44 #include <TBufferFile.h>
45 #include <TClass.h>
46 #include <TList.h>
47 #include <TStreamerInfo.h>
48 
49 #include "artdaq-core/Data/ContainerFragment.hh"
50 #include "artdaq-core/Data/Fragment.hh"
51 #include "artdaq-core/Data/detail/ParentageMap.hh"
52 #include "artdaq-core/Utilities/ExceptionHandler.hh"
53 #include "artdaq-core/Utilities/TimeUtils.hh"
54 #include "artdaq/ArtModules/ArtdaqFragmentNamingService.h"
55 #include "artdaq/ArtModules/ArtdaqSharedMemoryService.h"
56 #include "artdaq/ArtModules/InputUtilities.hh"
57 #include "artdaq/DAQdata/Globals.hh"
58 #include "artdaq/DAQdata/NetMonHeader.hh"
59 
60 #include <sys/time.h>
61 #include <cstdio>
62 #include <iomanip>
63 #include <iostream>
64 #include <map>
65 #include <memory>
66 #include <sstream>
67 #include <string>
68 #include <vector>
69 
70 #if ART_HEX_VERSION < 0x30000
71 #define EVENT_ID id
72 #define SUBRUN_ID id
73 #define RUN_ID id
74 #define HISTORY_PTR_T std::shared_ptr<art::History>
75 #else
76 #define EVENT_ID eventID
77 #define SUBRUN_ID subRunID
78 #define RUN_ID runID
79 #define HISTORY_PTR_T std::unique_ptr<art::History>
80 #endif
81 
82 namespace art {
83 template<typename U>
85 }
86 
101 template<typename U>
103 {
104 public:
108  ArtdaqInputHelper(const ArtdaqInputHelper&) = delete;
109 
115 
120 
127  ArtdaqInputHelper(const fhicl::ParameterSet& ps, art::ProductRegistryHelper& helper, art::SourceHelper const& pm);
128 
132  void closeCurrentFile();
133 
138  void readFile(const std::string&, art::FileBlock*& fb);
139 
144  bool hasMoreData() const;
145 
155  bool readNext(art::RunPrincipal* const inR, art::SubRunPrincipal* const inSR, art::RunPrincipal*& outR,
156  art::SubRunPrincipal*& outSR, art::EventPrincipal*& outE);
157 
158 private:
159  void readAndConstructPrincipal(std::unique_ptr<TBufferFile>&, unsigned long, art::RunPrincipal* const,
160  art::SubRunPrincipal* const, art::RunPrincipal*&, art::SubRunPrincipal*&,
161  art::EventPrincipal*&);
162 
163  bool constructPrincipal(artdaq::Fragment::type_t, art::RunPrincipal* const,
164  art::SubRunPrincipal* const, art::RunPrincipal*&, art::SubRunPrincipal*&,
165  art::EventPrincipal*&);
166 
167  template<class T>
168  void readDataProducts(std::list<std::unique_ptr<TBufferFile>>&, T*&);
169 
170  void putInPrincipal(RunPrincipal*&, std::unique_ptr<EDProduct>&&, const BranchDescription&,
171  std::unique_ptr<const ProductProvenance>&&);
172 
173  void putInPrincipal(SubRunPrincipal*&, std::unique_ptr<EDProduct>&&, const BranchDescription&,
174  std::unique_ptr<const ProductProvenance>&&);
175 
176  void putInPrincipal(EventPrincipal*&, std::unique_ptr<EDProduct>&&, const BranchDescription&,
177  std::unique_ptr<const ProductProvenance>&&);
178 
179  void readFragments(std::unordered_map<artdaq::Fragment::type_t, std::unique_ptr<artdaq::Fragments>> const& eventMap, art::EventPrincipal*& outE);
180 
181 private:
182  bool shutdownMsgReceived_;
183  bool outputFileCloseNeeded_;
184  art::SourceHelper const& pm_;
185  U communicationWrapper_;
186  ProductList* productList_;
187  HISTORY_PTR_T history_to_use_;
188  bool fragmentsOnlyMode_;
189  std::string pretend_module_name;
190  size_t bytesRead;
191  std::chrono::steady_clock::time_point last_read_time;
192 };
193 
194 template<typename U>
195 art::ArtdaqInputHelper<U>::ArtdaqInputHelper(const fhicl::ParameterSet& ps, art::ProductRegistryHelper& helper,
196  art::SourceHelper const& pm)
197  : shutdownMsgReceived_(false)
198  , outputFileCloseNeeded_(false)
199  , pm_(pm)
200  , communicationWrapper_(ps)
201  , productList_()
202  , fragmentsOnlyMode_(false)
203  , pretend_module_name(ps.get<std::string>("raw_data_label", "daq"))
204  , bytesRead(0)
205  , last_read_time(std::chrono::steady_clock::now())
206 {
207 #if ART_HEX_VERSION >= 0x30200
208  root::setup();
209 #endif
210  // Instantiate ArtdaqSharedMemoryService to set up artdaq Globals and MetricManager
211  art::ServiceHandle<ArtdaqSharedMemoryServiceInterface> shm;
212 
213 #if 0
214  volatile bool loop = true;
215  while (loop)
216  {
217  usleep(1000);
218  }
219 #endif
220 
221  // JCF, May-27-2016
222 
223  // Something will have to be done about the labeling of this class,
224  // since it's just a template class- the user will care about the
225  // specific instantiation when it comes to messages
226 
227  TLOG_ARB(5, "ArtdaqInputHelper") << "Begin: ArtdaqInputHelper::ArtdaqInputHelper("
228  << "const fhicl::ParameterSet& ps, "
229  << "art::ProductRegistryHelper& helper, "
230  << "const art::SourceHelper& pm)";
231 
232  TLOG_ARB(5, "ArtdaqInputHelper") << "Going to receive init message";
233  artdaq::FragmentPtrs initFrags = communicationWrapper_.receiveInitMessage();
234  TLOG_ARB(5, "ArtdaqInputHelper") << "Init message received";
235 
236  if (initFrags.size() == 0 || initFrags.back().get()->dataSize() == 0)
237  {
238  TLOG_DEBUG("ArtdaqInputHelper") << "No init message received or zero-size init message: Fragments-only mode activated! This is an EventBuilder!";
239  fragmentsOnlyMode_ = true;
240  }
241  else
242  {
243  std::list<std::unique_ptr<TBufferFile>> msgs;
244  for (auto& initFrag : initFrags)
245  {
246  auto header = initFrag->metadata<artdaq::NetMonHeader>();
247  msgs.emplace_back(new TBufferFile(TBuffer::kRead, header->data_length, initFrag->dataBegin(), kFALSE, 0));
248  }
249 
250  std::list<History*> processHistories;
251 
252  for (auto& msg : msgs)
253  {
254  // This first unsigned long is the message type code, ignored here in the constructor
255  unsigned long dummy = 0;
256  msg->ReadULong(dummy);
257 
258  // ELF: 6/11/2019: This code is taken from TSocket::RecvStreamerInfos
259  TList* list = (TList*)msg->ReadObject(TList::Class());
260 
261  TIter next(list);
262  TStreamerInfo* info;
263  TObjLink* lnk = list->FirstLink();
264  // First call BuildCheck for regular class
265  while (lnk)
266  {
267  info = (TStreamerInfo*)lnk->GetObject();
268  TObject* element = info->GetElements()->UncheckedAt(0);
269  Bool_t isstl = element && strcmp("This", element->GetName()) == 0;
270  if (!isstl)
271  {
272  info->BuildCheck();
273  TLOG_ARB(5, "ArtdaqInputHelper") << "ArtdaqInputHelper: importing TStreamerInfo: " << info->GetName() << ", version = " << info->GetClassVersion();
274  }
275  lnk = lnk->Next();
276  }
277  // Then call BuildCheck for stl class
278  lnk = list->FirstLink();
279  while (lnk)
280  {
281  info = (TStreamerInfo*)lnk->GetObject();
282  TObject* element = info->GetElements()->UncheckedAt(0);
283  Bool_t isstl = element && strcmp("This", element->GetName()) == 0;
284  if (isstl)
285  {
286  info->BuildCheck();
287  TLOG_ARB(5, "ArtdaqInputHelper") << "ArtdaqInputHelper: importing TStreamerInfo: " << info->GetName() << ", version = " << info->GetClassVersion();
288  }
289  lnk = lnk->Next();
290  }
291  // ELF: 6/11/2019: End TSocket snippet
292 
293  //
294  // Read the ParameterSetRegistry.
295  //
296  unsigned long ps_cnt = 0;
297  msg->ReadULong(ps_cnt);
298  TLOG_ARB(5, "ArtdaqInputHelper") << "ArtdaqInputHelper: parameter set count: " << ps_cnt;
299  TLOG_ARB(5, "ArtdaqInputHelper") << "ArtdaqInputHelper: reading parameter sets ...";
300  for (unsigned long I = 0; I < ps_cnt; ++I)
301  {
302  std::string pset_str = ""; // = ReadObjectAny<std::string>(msg, "std::string", "ArtdaqInputHelper::ArtdaqInputHelper");
303  msg->ReadStdString(pset_str);
304 
305  TLOG_ARB(5, "ArtdaqInputHelper") << "ArtdaqInputHelper: parameter set: " << pset_str;
306 
307  fhicl::ParameterSet pset;
308  fhicl::make_ParameterSet(pset_str, pset);
309  // Force id calculation.
310  pset.id();
311  fhicl::ParameterSetRegistry::put(pset);
312  }
313  TLOG_ARB(5, "ArtdaqInputHelper") << "ArtdaqInputHelper: finished reading parameter sets.";
314 
315  //
316  // Read the MasterProductRegistry.
317  //
318  auto thisProductList = ReadObjectAny<art::ProductList>(
319  msg, "std::map<art::BranchKey,art::BranchDescription>", "ArtdaqInputHelper::ArtdaqInputHelper");
320  TLOG_ARB(5, "ArtdaqInputHelper") << "ArtdaqInputHelper: Input Product list sz=" << thisProductList->size();
321 
322  bool productListInitialized = productList_ != nullptr;
323  if (!productListInitialized) productList_ = thisProductList;
324  for (auto I = thisProductList->begin(), E = thisProductList->end(); I != E; ++I)
325  {
326 #ifndef __OPTIMIZE__
327  TLOG_ARB(50, "ArtdaqInputHelper") << "Branch key: class: '" << I->first.friendlyClassName_ << "' modlbl: '"
328  << I->first.moduleLabel_ << "' instnm: '" << I->first.productInstanceName_ << "' procnm: '"
329  << I->first.processName_ << "', branch description name: " << I->second.wrappedName()
330  << ", TClass = " << (void*)TClass::GetClass(I->second.wrappedName().c_str());
331 #endif
332  if (productListInitialized)
333  {
334  productList_->emplace(*I);
335  }
336  }
337 
338  TLOG_ARB(5, "ArtdaqInputHelper") << "ArtdaqInputHelper: Reading ProcessHistory";
339  art::ProcessHistoryMap* phm = ReadObjectAny<art::ProcessHistoryMap>(
340  msg, "std::map<const art::Hash<2>,art::ProcessHistory>", "ArtdaqInputHelper::ArtdaqInputHelper");
341  printProcessMap(*phm, "ArtdaqInputHelper's ProcessHistoryMap");
342 
343  ProcessHistoryRegistry::put(*phm);
344  printProcessMap(ProcessHistoryRegistry::get(), "ArtdaqInputHelper's ProcessHistoryRegistry");
345 
346  //
347  // Read the ParentageRegistry.
348  //
349  TLOG_ARB(5, "ArtdaqInputHelper") << "ArtdaqInputHelper: Reading ParentageMap";
350  ParentageMap* parentageMap = ReadObjectAny<ParentageMap>(msg, "art::ParentageMap", "ArtdaqInputHelper::ArtdaqInputHelper");
351  ParentageRegistry::put(*parentageMap);
352 
353  //
354  // Read the History
355  //
356  TLOG_ARB(5, "ArtdaqInputHelper") << "ArtdaqInputHelper: Reading History";
357  processHistories.push_back(ReadObjectAny<History>(msg, "art::History", "ArtdaqInputHelper::ArtdaqInputHelper"));
358  }
359 
360  // We're going to make a fake History using the collected process histories!
361  art::ProcessHistory fake_process_history;
362  for (auto& hist : processHistories)
363  {
364  auto id = hist->processHistoryID();
365  ProcessHistory thisProcessHistory;
366  if (ProcessHistoryRegistry::get(id, thisProcessHistory))
367  {
368  for (auto& conf : thisProcessHistory)
369  fake_process_history.push_back(conf);
370  }
371  }
372  art::ProcessHistoryMap fake_process_history_map;
373  fake_process_history_map[fake_process_history.id()] = fake_process_history;
374  ProcessHistoryRegistry::put(fake_process_history_map);
375  history_to_use_.reset(new History());
376  history_to_use_->setProcessHistoryID(fake_process_history.id());
377  for (auto& hist : processHistories)
378  {
379  for (auto& es : hist->eventSelectionIDs())
380  {
381  history_to_use_->addEventSelectionEntry(es);
382  }
383  }
384 
385  TLOG_ARB(5, "ArtdaqInputHelper")
386  << "ArtdaqInputHelper: Product list sz=" << productList_->size();
387 
388  // helper now owns productList_!
389 #if ART_HEX_VERSION < 0x30000
390  helper.productList(productList_);
391 #else
392  helper.productList(std::unique_ptr<art::ProductList>(productList_));
393 #endif
394  TLOG_ARB(5, "ArtdaqInputHelper") << "ArtdaqInputHelper: got product list";
395  }
396 
397  if (ps.get<bool>("register_fragment_types", true))
398  {
399  TLOG_DEBUG("ArtdaqInputHelper") << "Registering known Fragment labels from ArtdaqFragmentNamingServiceInterface";
400  art::ServiceHandle<ArtdaqFragmentNamingServiceInterface> translator;
401  helper.reconstitutes<artdaq::Fragments, art::InEvent>(pretend_module_name, translator->GetUnidentifiedInstanceName());
402  // Workaround for #22979
403  helper.reconstitutes<artdaq::Fragments, art::InRun>(pretend_module_name, translator->GetUnidentifiedInstanceName());
404  helper.reconstitutes<artdaq::Fragments, art::InSubRun>(pretend_module_name, translator->GetUnidentifiedInstanceName());
405 
406  std::set<std::string> instance_names = translator->GetAllProductInstanceNames();
407  for (const auto& set_iter : instance_names)
408  {
409  helper.reconstitutes<artdaq::Fragments, art::InEvent>(pretend_module_name, set_iter);
410  }
411  }
412  //
413  // Finished with init message.
414  //
415  TLOG_ARB(5, "ArtdaqInputHelper") << "End: ArtdaqInputHelper::ArtdaqInputHelper("
416  << "const fhicl::ParameterSet& ps, "
417  << "art::ProductRegistryHelper& helper, "
418  << "const art::SourceHelper& pm)";
419 }
420 
421 template<typename U>
423 {}
424 
425 template<typename U>
427 {
428  TLOG_ARB(6, "ArtdaqInputHelper") << "Begin/End: ArtdaqInputHelper::closeCurrentFile()";
429 }
430 
431 template<typename U>
432 void art::ArtdaqInputHelper<U>::readFile(const std::string&, art::FileBlock*& fb)
433 {
434  TLOG_ARB(7, "ArtdaqInputHelper") << "Begin: ArtdaqInputHelper::"
435  "readFile(const std::string& name, art::FileBlock*& fb)";
436  fb = new art::FileBlock(art::FileFormatVersion(1, "ArtdaqInputHelper2013"), "nothing");
437  TLOG_ARB(7, "ArtdaqInputHelper") << "End: ArtdaqInputHelper::"
438  "readFile(const std::string& name, art::FileBlock*& fb)";
439 }
440 
441 template<typename U>
443 {
444  TLOG_ARB(8, "ArtdaqInputHelper") << "Begin: ArtdaqInputHelper::hasMoreData()";
445  if (shutdownMsgReceived_)
446  {
447  TLOG_ARB(8, "ArtdaqInputHelper") << "ArtdaqInputHelper::hasMoreData(): "
448  "returning false on shutdownMsgReceived_.";
449  TLOG_ARB(8, "ArtdaqInputHelper") << "End: ArtdaqInputHelper::hasMoreData()";
450  return false;
451  }
452  TLOG_ARB(8, "ArtdaqInputHelper") << "ArtdaqInputHelper::hasMoreData(): "
453  "returning true on not shutdownMsgReceived_.";
454  TLOG_ARB(8, "ArtdaqInputHelper") << "End: ArtdaqInputHelper::hasMoreData()";
455  return true;
456 }
457 
458 template<typename U>
459 void art::ArtdaqInputHelper<U>::readAndConstructPrincipal(std::unique_ptr<TBufferFile>& msg, unsigned long msg_type_code,
460  art::RunPrincipal* const inR, art::SubRunPrincipal* const inSR,
461  art::RunPrincipal*& outR, art::SubRunPrincipal*& outSR,
462  art::EventPrincipal*& outE)
463 {
464  //
465  // Process the message.
466  //
467  std::unique_ptr<art::RunAuxiliary> run_aux;
468  std::unique_ptr<art::SubRunAuxiliary> subrun_aux;
469  std::unique_ptr<art::EventAuxiliary> event_aux;
470 
471  HISTORY_PTR_T history_from_event;
472 
473  // Establish default 'results'
474  outR = 0;
475  outSR = 0;
476  outE = 0;
477 
478  if (msg_type_code == 2)
479  { // EndRun message.
480 
481  TLOG_ARB(9, "ArtdaqInputHelper") << "readAndConstructPrincipal: "
482  << "processing EndRun message ...";
483 
484  run_aux.reset(ReadObjectAny<art::RunAuxiliary>(msg, "art::RunAuxiliary", "ArtdaqInputHelper::readAndConstructPrincipal"));
485  printProcessHistoryID("readAndConstructPrincipal", run_aux.get());
486 
487  TLOG_ARB(9, "ArtdaqInputHelper") << "readAndConstructPrincipal: "
488  << "making flush RunPrincipal ...";
489  outR = pm_.makeRunPrincipal(RunID::flushRun(), run_aux->beginTime());
490 
491  TLOG_ARB(9, "ArtdaqInputHelper") << "readAndConstructPrincipal: "
492  << "making flush SubRunPrincipal ...";
493  outSR = pm_.makeSubRunPrincipal(SubRunID::flushSubRun(), run_aux->beginTime());
494 
495  TLOG_ARB(9, "ArtdaqInputHelper") << "readAndConstructPrincipal: "
496  << "making flush EventPrincipal ...";
497  outE = pm_.makeEventPrincipal(EventID::flushEvent(), run_aux->endTime(), true, EventAuxiliary::Any);
498 
499  TLOG_ARB(9, "ArtdaqInputHelper") << "readAndConstructPrincipal: "
500  << "finished processing EndRun message.";
501  }
502  else if (msg_type_code == 3)
503  { // EndSubRun message.
504 
505  TLOG_ARB(10, "ArtdaqInputHelper") << "readAndConstructPrincipal: "
506  << "processing EndSubRun message ...";
507 
508  subrun_aux.reset(
509  ReadObjectAny<art::SubRunAuxiliary>(msg, "art::SubRunAuxiliary", "ArtdaqInputHelper::readAndConstructPrincipal"));
510  printProcessHistoryID("readAndConstructPrincipal", subrun_aux.get());
511 
512  TLOG_ARB(10, "ArtdaqInputHelper") << "readAndConstructPrincipal: "
513  << "making flush RunPrincipal ...";
514  outR = pm_.makeRunPrincipal(RunID::flushRun(), subrun_aux->beginTime());
515 
516  // 28-Feb-2014, KAB: added the setting of the end time in the *current*
517  // run and subrun. This is how we set the endTime in the RunPrincipal
518  // and SubRunPrincipal objects that are written to the disk file.
519  // This needs to happen here because:
520  // A) setting them in every event doesn't work because the RunPrincipal
521  // only allows us to set an end time value once
522  // B) setting them in the "outputFileCloseNeeded_" block in the readNext()
523  // method below doesn't work because that is too late. When this
524  // method returns an outR with a different run number (flushRun),
525  // the art output system closes the current file then.
526  // C) setting them in the EndRun message block immediately above this
527  // block wouldn't work because a) we're not currently sending endRun
528  // events from the EBs to the AG, and b) because presumably that would
529  // be too late, also.
530 
531  art::Timestamp currentTime = time(0);
532  if (inR != nullptr)
533  {
534 #if ART_HEX_VERSION < 0x30000
535  inR->setEndTime(currentTime);
536 #else
537  inR->endTime(currentTime);
538 #endif
539  }
540  if (inSR != nullptr)
541  {
542 #if ART_HEX_VERSION < 0x30000
543  inSR->setEndTime(currentTime);
544 #else
545  inSR->endTime(currentTime);
546 #endif
547  }
548 
549  TLOG_ARB(10, "ArtdaqInputHelper") << "readAndConstructPrincipal: "
550  << "making flush SubRunPrincipal ...";
551  outSR = pm_.makeSubRunPrincipal(SubRunID::flushSubRun(), subrun_aux->beginTime());
552 
553  TLOG_ARB(10, "ArtdaqInputHelper") << "readAndConstructPrincipal: "
554  << "making flush EventPrincipal ...";
555  outE = pm_.makeEventPrincipal(EventID::flushEvent(), subrun_aux->endTime(), true, EventAuxiliary::Any);
556 
557  TLOG_ARB(10, "ArtdaqInputHelper") << "readAndConstructPrincipal: "
558  << "finished processing EndSubRun message.";
559  }
560  else if (msg_type_code == 4)
561  { // Event message.
562 
563  TLOG_ARB(11, "ArtdaqInputHelper") << "readAndConstructPrincipal: "
564  << "processing Event message ...";
565 
566  run_aux.reset(ReadObjectAny<art::RunAuxiliary>(msg, "art::RunAuxiliary", "ArtdaqInputHelper::readAndConstructPrincipal"));
567  printProcessHistoryID("readAndConstructPrincipal", run_aux.get());
568 
569  subrun_aux.reset(
570  ReadObjectAny<art::SubRunAuxiliary>(msg, "art::SubRunAuxiliary", "ArtdaqInputHelper::readAndConstructPrincipal"));
571  printProcessHistoryID("readAndConstructPrincipal", subrun_aux.get());
572 
573  event_aux.reset(
574  ReadObjectAny<art::EventAuxiliary>(msg, "art::EventAuxiliary", "ArtdaqInputHelper::readAndConstructPrincipal"));
575 
576  history_from_event.reset(ReadObjectAny<art::History>(msg, "art::History", "ArtdaqInputHelper::readAndConstructPrincipal"));
577  printProcessHistoryID("readAndConstructPrincipal", history_from_event.get());
578 
579  // Every event should have a valid history
580  if (!history_from_event->processHistoryID().isValid())
581  {
582  throw art::Exception(art::errors::Unknown)
583  << "readAndConstructPrincipal: processHistoryID of history in Event message is invalid!";
584  }
585 
586  TLOG_ARB(11, "ArtdaqInputHelper") << "readAndConstructPrincipal: "
587  << "inR: " << (void*)inR << " run/expected "
588  << (inR ? std::to_string(inR->run()) : "invalid") << "/" << event_aux->run();
589  TLOG_ARB(11, "ArtdaqInputHelper") << "readAndConstructPrincipal: "
590  << "inSR: " << (void*)inSR << " run/expected "
591  << (inSR ? std::to_string(inSR->run()) : "invalid") << "/" << event_aux->run()
592  << ", subrun/expected " << (inSR ? std::to_string(inSR->subRun()) : "invalid") << "/"
593  << event_aux->subRun();
594  if ((inR == nullptr) || !inR->RUN_ID().isValid() || (inR->run() != event_aux->run()))
595  {
596  // New run, either we have no input RunPrincipal, or the
597  // input run number does not match the event run number.
598  TLOG_ARB(11, "ArtdaqInputHelper") << "readAndConstructPrincipal: making RunPrincipal ...";
599  outR = pm_.makeRunPrincipal(*run_aux.get());
600  }
601  art::SubRunID subrun_check(event_aux->run(), event_aux->subRun());
602  if (inSR == 0 || subrun_check != inSR->SUBRUN_ID())
603  {
604  // New SubRun, either we have no input SubRunPrincipal, or the
605  // input subRun number does not match the event subRun number.
606  TLOG_ARB(11, "ArtdaqInputHelper") << "readAndConstructPrincipal: "
607  << "making SubRunPrincipal ...";
608  outSR = pm_.makeSubRunPrincipal(*subrun_aux.get());
609  }
610  TLOG_ARB(11, "ArtdaqInputHelper") << "readAndConstructPrincipal: making EventPrincipal ...";
611  auto historyPtr = HISTORY_PTR_T(new History(*(history_to_use_.get())));
612  if (!art::ProcessHistoryRegistry::get().count(history_to_use_->processHistoryID()))
613  {
614  TLOG_WARNING("ArtdaqInputHelper") << "Stored history is not in ProcessHistoryRegistry, this event may have issues!";
615  }
616  outE = pm_.makeEventPrincipal(*event_aux.get(), std::move(historyPtr));
617 
618  TLOG_ARB(11, "ArtdaqInputHelper") << "readAndConstructPrincipal: "
619  << "finished processing Event message.";
620  }
621 }
622 
623 template<typename U>
624 bool art::ArtdaqInputHelper<U>::constructPrincipal(artdaq::Fragment::type_t firstFragmentType, art::RunPrincipal* const inR, art::SubRunPrincipal* const inSR, art::RunPrincipal*& outR, art::SubRunPrincipal*& outSR, art::EventPrincipal*& outE)
625 {
626  // We return false, indicating we're done reading, if:
627  // 1) we did not obtain an event, because we timed out and were
628  // configured NOT to keep trying after a timeout, or
629  // 2) the event we read was the end-of-data marker: a null
630  // pointer
631  if (firstFragmentType == artdaq::Fragment::EndOfDataFragmentType)
632  {
633  TLOG_DEBUG("ArtdaqInputHelper") << "Received shutdown message, returning false";
634  shutdownMsgReceived_ = true;
635  return false;
636  }
637 
638  auto evtHeader = communicationWrapper_.getEventHeader();
639  if (!evtHeader)
640  {
641  TLOG_ERROR("ArtdaqInputHelper") << "No RawEventHeader received, cannot construct principals!";
642  shutdownMsgReceived_ = true;
643  return false;
644  }
645 
646  // Check the number of fragments in the RawEvent. If we have a single
647  // fragment and that fragment is marked as EndRun or EndSubrun we'll create
648  // the special principals for that.
649  art::Timestamp currentTime = 0;
650 #if 0
651  art::TimeValue_t lo_res_time = time(0);
652  TLOG_ARB(15, "ArtdaqInputHelper") << "lo_res_time = " << lo_res_time;
653  currentTime = ((lo_res_time & 0xffffffff) << 32);
654 #endif
655  timespec hi_res_time;
656  int retcode = clock_gettime(CLOCK_REALTIME, &hi_res_time);
657  TLOG_ARB(15, "ArtdaqInputHelper") << "hi_res_time tv_sec = " << hi_res_time.tv_sec
658  << " tv_nsec = " << hi_res_time.tv_nsec << " (retcode = " << retcode << ")";
659  if (retcode == 0)
660  {
661  currentTime = ((hi_res_time.tv_sec & 0xffffffff) << 32) | (hi_res_time.tv_nsec & 0xffffffff);
662  }
663  else
664  {
665  TLOG_ERROR("ArtdaqInputHelper")
666  << "Unable to fetch a high-resolution time with clock_gettime for art::Event Timestamp. "
667  << "The art::Event Timestamp will be zero for event " << evtHeader->event_id;
668  }
669 
670  // make new run if inR is 0 or if the run has changed
671  if (inR == 0 || inR->run() != evtHeader->run_id)
672  {
673  TLOG_ARB(15, "ArtdaqInputHelper") << "Making run principal with run_id " << evtHeader->run_id;
674  outR = pm_.makeRunPrincipal(evtHeader->run_id, currentTime);
675  }
676 
677  if (firstFragmentType == artdaq::Fragment::EndOfRunFragmentType)
678  {
679  TLOG_ARB(15, "ArtdaqInputHelper") << "EndOfRunFragment received, returning Flush event";
680  art::EventID const evid(art::EventID::flushEvent());
681  outR = pm_.makeRunPrincipal(evid.runID(), currentTime);
682  outSR = pm_.makeSubRunPrincipal(evid.subRunID(), currentTime);
683  outE = pm_.makeEventPrincipal(evid, currentTime);
684  return true;
685  }
686  else if (firstFragmentType == artdaq::Fragment::EndOfSubrunFragmentType)
687  {
688  TLOG_ARB(15, "ArtdaqInputHelper") << "EndOfSubrunFragment received, creating new Subrun Principal";
689  // Check if inR == 0 or is a new run
690  if (inR == 0 || inR->run() != evtHeader->run_id)
691  {
692  TLOG_ARB(15, "ArtdaqInputHelper") << "Making subrun principal with subrun_id " << evtHeader->subrun_id;
693  outSR = pm_.makeSubRunPrincipal(evtHeader->run_id, evtHeader->subrun_id, currentTime);
694  art::EventID const evid(art::EventID::flushEvent(outSR->SUBRUN_ID()));
695  outE = pm_.makeEventPrincipal(evid, currentTime);
696  }
697  else
698  {
699  // If the previous subrun was neither 0 nor flush and was identical with the current
700  // subrun, then it must have been associated with a data event. In that case, we need
701  // to generate a flush event with a valid run but flush subrun and event number in order
702  // to end the subrun.
703  if (inSR != 0 && !inSR->SUBRUN_ID().isFlush() && inSR->subRun() == evtHeader->subrun_id)
704  {
705  TLOG_ARB(15, "ArtdaqInputHelper") << "Flushing old run id " << inR->RUN_ID();
706  art::EventID const evid(art::EventID::flushEvent(inR->RUN_ID()));
707  outSR = pm_.makeSubRunPrincipal(evid.subRunID(), currentTime);
708  outE = pm_.makeEventPrincipal(evid, currentTime);
709  // If this is either a new or another empty subrun, then generate a flush event with
710  // valid run and subrun numbers but flush event number
711  //} else if(inSR==0 || inSR->id().isFlush()){
712  }
713  else
714  {
715  TLOG_ARB(15, "ArtdaqInputHelper") << "Making subrun principal with subrun_id " << evtHeader->subrun_id;
716  outSR = pm_.makeSubRunPrincipal(evtHeader->run_id, evtHeader->subrun_id, currentTime);
717  art::EventID const evid(art::EventID::flushEvent(outSR->SUBRUN_ID()));
718  outE = pm_.makeEventPrincipal(evid, currentTime);
719  // Possible error condition
720  //} else {
721  }
722  outR = 0;
723  }
724  // outputFileCloseNeeded = true;
725  return true;
726  }
727 
728  // make new subrun if inSR is 0 or if the subrun has changed
729  art::SubRunID subrun_check(evtHeader->run_id, evtHeader->subrun_id);
730  if (inSR == 0 || subrun_check != inSR->SUBRUN_ID())
731  {
732  TLOG_ARB(15, "ArtdaqInputHelper") << "Making subrun principal with subrun_id " << evtHeader->subrun_id;
733  outSR = pm_.makeSubRunPrincipal(evtHeader->run_id, evtHeader->subrun_id, currentTime);
734  }
735  TLOG_ARB(15, "ArtdaqInputHelper") << "Making event principal with event_id " << evtHeader->event_id;
736  outE = pm_.makeEventPrincipal(evtHeader->run_id, evtHeader->subrun_id, evtHeader->event_id, currentTime);
737  return true;
738 }
739 
740 template<typename U>
741 template<class T>
742 void art::ArtdaqInputHelper<U>::readDataProducts(std::list<std::unique_ptr<TBufferFile>>& msgs, T*& outPrincipal)
743 {
744  for (auto& msg : msgs)
745  {
746  unsigned long prd_cnt = 0;
747  {
748  TLOG_ARB(12, "ArtdaqInputHelper") << "readDataProducts: reading data product count ...";
749  msg->ReadULong(prd_cnt);
750  TLOG_ARB(12, "ArtdaqInputHelper") << "readDataProducts: product count: " << prd_cnt;
751  }
752  //
753  // Read the data products.
754  //
755  for (unsigned long I = 0; I < prd_cnt; ++I)
756  {
757  std::unique_ptr<BranchKey> bk;
758  {
759  TLOG_ARB(12, "ArtdaqInputHelper") << "readDataProducts: Reading branch key.";
760  bk.reset(ReadObjectAny<BranchKey>(msg, "art::BranchKey", "ArtdaqInputHelper::readDataProducts"));
761  }
762 
763 #ifndef __OPTIMIZE__
764  TLOG_ARB(13, "ArtdaqInputHelper") << "readDataProducts: got product class: '" << bk->friendlyClassName_ << "' modlbl: '"
765  << bk->moduleLabel_ << "' instnm: '" << bk->productInstanceName_ << "' procnm: '"
766  << bk->processName_;
767 #endif
768  ProductList::const_iterator iter;
769  {
770  TLOG_ARB(12, "ArtdaqInputHelper") << "readDataProducts: looking up product ...";
771  iter = productList_->find(*bk);
772  if (iter == productList_->end())
773  {
774  throw art::Exception(art::errors::ProductNotFound)
775  << "No product is registered for\n"
776  << " process name: '" << bk->processName_ << "'\n"
777  << " module label: '" << bk->moduleLabel_ << "'\n"
778  << " product friendly class name: '" << bk->friendlyClassName_ << "'\n"
779  << " product instance name: '" << bk->productInstanceName_ << "'\n";
780  }
781  }
782  // Note: This must be a reference to the unique copy in
783  // the master product registry!
784  const BranchDescription& bd = iter->second;
785  std::unique_ptr<EDProduct> prd;
786  {
787  TLOG_ARB(12, "ArtdaqInputHelper") << "readDataProducts: Reading product with wrapped name: " << bd.wrappedName()
788  << ", TClass = " << (void*)TClass::GetClass(bd.wrappedName().c_str());
789 
790  // JCF, May-25-2016
791  // Currently unclear why the templatized version of ReadObjectAny doesn't work here...
792 
793  // prd.reset(ReadObjectAny<EDProduct>(msg, bd.wrappedName()));
794 
795  void* p = msg->ReadObjectAny(TClass::GetClass(bd.wrappedName().c_str()));
796  auto pp = reinterpret_cast<EDProduct*>(p);
797 
798  TLOG_ARB(12, "ArtdaqInputHelper") << "readDataProducts: After ReadObjectAny(prd): p=" << p << ", EDProduct::isPresent: " << pp->isPresent();
799  prd.reset(pp);
800  p = nullptr;
801  }
802  std::unique_ptr<const ProductProvenance> prdprov;
803  {
804  TLOG_ARB(12, "ArtdaqInputHelper") << "readDataProducts: Reading product provenance.";
805  prdprov.reset(ReadObjectAny<ProductProvenance>(msg, "art::ProductProvenance", "ArtdaqInputHelper::readDataProducts"));
806  }
807 
808  {
809  TLOG_ARB(12, "ArtdaqInputHelper") << "readDataProducts: inserting product: class: '" << bd.friendlyClassName()
810  << "' modlbl: '" << bd.moduleLabel() << "' instnm: '" << bd.productInstanceName()
811  << "' procnm: '" << bd.processName() << "' id: '" << bd.productID() << "'";
812  putInPrincipal(outPrincipal, std::move(prd), bd, std::move(prdprov));
813  }
814  }
815  }
816 }
817 
818 template<typename U>
819 void art::ArtdaqInputHelper<U>::putInPrincipal(RunPrincipal*& rp, std::unique_ptr<EDProduct>&& prd,
820  const BranchDescription& bd,
821  std::unique_ptr<const ProductProvenance>&& prdprov)
822 {
823 #if ART_HEX_VERSION < 0x30000
824  rp->put(std::move(prd), bd, std::move(prdprov), RangeSet::forRun(rp->RUN_ID()));
825 #else
826  rp->put(bd, std::move(prdprov), std::move(prd), std::make_unique<RangeSet>(RangeSet::forRun(rp->RUN_ID())));
827 #endif
828 }
829 
830 template<typename U>
831 void art::ArtdaqInputHelper<U>::putInPrincipal(SubRunPrincipal*& srp, std::unique_ptr<EDProduct>&& prd,
832  const BranchDescription& bd,
833  std::unique_ptr<const ProductProvenance>&& prdprov)
834 {
835 #if ART_HEX_VERSION < 0x30000
836  srp->put(std::move(prd), bd, std::move(prdprov), RangeSet::forSubRun(srp->SUBRUN_ID()));
837 #else
838  srp->put(bd, std::move(prdprov), std::move(prd), std::make_unique<RangeSet>(RangeSet::forSubRun(srp->SUBRUN_ID())));
839 #endif
840 }
841 
842 template<typename U>
843 void art::ArtdaqInputHelper<U>::putInPrincipal(EventPrincipal*& ep, std::unique_ptr<EDProduct>&& prd,
844  const BranchDescription& bd,
845  std::unique_ptr<const ProductProvenance>&& prdprov)
846 {
847  TLOG_ARB(14, "ArtdaqInputHelper") << "EventPrincipal size before put: " << ep->size();
848 #if ART_HEX_VERSION < 0x30000
849  ep->put(std::move(prd), bd, std::move(prdprov));
850 #else
851  ep->put(bd, std::move(prdprov), std::move(prd), std::make_unique<RangeSet>(RangeSet::invalid()));
852 #endif
853  TLOG_ARB(14, "ArtdaqInputHelper") << "EventPrincipal size after put: " << ep->size();
854 }
855 
856 template<typename U>
857 void art::ArtdaqInputHelper<U>::readFragments(std::unordered_map<artdaq::Fragment::type_t, std::unique_ptr<artdaq::Fragments>> const& eventMap, art::EventPrincipal*& outE)
858 {
859  // Now read in Fragments
860  double fragmentLatency = 0;
861  double fragmentLatencyMax = 0.0;
862  size_t fragmentCount = 0;
863 
864  art::ServiceHandle<ArtdaqFragmentNamingServiceInterface> translator;
865 
866  // insert the Fragments of each type into the EventPrincipal
867  for (auto& fragmentTypePair : eventMap)
868  {
869  auto type_code = fragmentTypePair.first;
870  if (type_code == artdaq::Fragment::DataFragmentType || type_code == artdaq::Fragment::EndOfDataFragmentType || type_code == artdaq::Fragment::InitFragmentType || type_code == artdaq::Fragment::EndOfRunFragmentType || type_code == artdaq::Fragment::EndOfSubrunFragmentType || type_code == artdaq::Fragment::ShutdownFragmentType)
871  {
872  TLOG_TRACE("ArtdaqInputHelper") << "Skipping system Fragment with type " << (int)type_code << " ( " << translator->GetInstanceNameForType(type_code) << " )";
873  continue;
874  }
875  TLOG_TRACE("ArtdaqInputHelper") << "type is " << (int)type_code << ", number of fragments is " << fragmentTypePair.second->size();
876 
877  std::unordered_map<std::string, std::unique_ptr<artdaq::Fragments>> derived_fragments;
878  for (auto& frag : *fragmentTypePair.second)
879  {
880  TLOG_ARB(16, "ArtdaqInputHelper") << "Processing Fragment with ID " << frag.fragmentID();
881  bytesRead += frag.sizeBytes();
882  auto latency_s = frag.getLatency(true);
883  double latency = latency_s.tv_sec + (latency_s.tv_nsec / 1000000000.0);
884 
885  fragmentLatency += latency;
886  fragmentCount++;
887  if (latency > fragmentLatencyMax) fragmentLatencyMax = latency;
888 
889  std::pair<bool, std::string> instance_name_result =
890  translator->GetInstanceNameForFragment(frag);
891  std::string label = instance_name_result.second;
892  if (!instance_name_result.first)
893  {
894  TLOG_WARNING("ArtdaqInputHelper")
895  << "UnknownFragmentType: The product instance name mapping for fragment type \"" << ((int)type_code)
896  << "\" is not known. Fragments of this "
897  << "type will be stored in the event with an instance name of \"" << label << "\".";
898  }
899  if (!derived_fragments.count(label))
900  {
901  TLOG_ARB(16, "ArtdaqInputHelper") << "Creating output Fragment storage for label " << label;
902  derived_fragments[label] = std::make_unique<artdaq::Fragments>();
903  }
904  TLOG_ARB(16, "ArtdaqInputHelper") << "Adding Fragment " << frag.fragmentID() << " to storage with label " << label << " (sz=" << derived_fragments[label]->size() + 1 << ")";
905  derived_fragments[label]->emplace_back(std::move(frag));
906  }
907  for (auto& type : derived_fragments)
908  {
909  TLOG_ARB(16, "ArtdaqInputHelper") << "Adding " << type.second->size() << " Fragments with label " << type.first << " to event.";
910  put_product_in_principal(std::move(type.second), *outE, pretend_module_name, type.first);
911  }
912  }
913  if (metricMan)
914  {
915  metricMan->sendMetric("bytesRead", bytesRead, "B", 3, artdaq::MetricMode::LastPoint);
916 
917  metricMan->sendMetric("ArtdaqInputHelper Latency", fragmentLatency / fragmentCount, "s", 4, artdaq::MetricMode::Average);
918  metricMan->sendMetric("ArtdaqInputHelper Maximum Latency", fragmentLatencyMax, "s", 4, artdaq::MetricMode::Maximum);
919  }
920 }
921 
922 template<typename U>
923 bool art::ArtdaqInputHelper<U>::readNext(art::RunPrincipal* const inR, art::SubRunPrincipal* const inSR,
924  art::RunPrincipal*& outR, art::SubRunPrincipal*& outSR, art::EventPrincipal*& outE)
925 {
926  TLOG_ARB(15, "ArtdaqInputHelper") << "Begin: ArtdaqInputHelper::readNext";
927  bool ret = false;
928 
929  if (outputFileCloseNeeded_)
930  {
931  outputFileCloseNeeded_ = false;
932  // Signal that we need the output file closed by returning false,
933  // but answering true to the hasMoreData() query.
934  TLOG_ARB(15, "ArtdaqInputHelper") << "ArtdaqInputHelper::readNext: "
935  << "returning false on outputFileCloseNeeded_";
936  TLOG_ARB(15, "ArtdaqInputHelper") << "End: ArtdaqInputHelper::readNext";
937  return false;
938  }
939  auto read_start_time = std::chrono::steady_clock::now();
940 
941  std::unordered_map<artdaq::Fragment::type_t, std::unique_ptr<artdaq::Fragments>> eventMap = communicationWrapper_.receiveMessages();
942  auto got_event_time = std::chrono::steady_clock::now();
943 
944  if (eventMap.size() == 0)
945  {
946  TLOG_ARB(TLVL_ERROR, "ArtdaqInputHelper") << "No Fragments received! Aborting...";
947  shutdownMsgReceived_ = true;
948  TLOG_ARB(17, "ArtdaqInputHelper") << "End: ArtdaqInputHelper::readNext";
949  return false;
950  }
951 
952  if (!fragmentsOnlyMode_ && !eventMap.count(artdaq::Fragment::DataFragmentType))
953  {
954  TLOG_ARB(15, "ArtdaqInputHelper") << "ArtdaqInputHelper::readNext got a message without a DataFragment";
955  shutdownMsgReceived_ = true;
956  TLOG_ARB(17, "ArtdaqInputHelper") << "End: ArtdaqInputHelper::readNext";
957  return false;
958  }
959 
960  if (fragmentsOnlyMode_)
961  {
962  if (eventMap.count(artdaq::Fragment::DataFragmentType))
963  {
964  TLOG_ARB(15, "ArtdaqInputHelper") << "ArtdaqInputHelper::readNext unexpectedly got a message with a DataFragment. This art Event will NOT be reconstructed!";
965  }
966 
967  auto firstFragmentType = eventMap.begin()->first;
968  TLOG_DEBUG("ArtdaqInputHelper") << "First Fragment type is " << (int)firstFragmentType;
969  if (constructPrincipal(firstFragmentType, inR, inSR, outR, outSR, outE))
970  {
971  readFragments(eventMap, outE);
972  ret = true;
973  }
974  else
975  {
976  ret = false;
977  }
978  }
979  else
980  {
981  std::list<std::unique_ptr<TBufferFile>> msgs;
982  for (auto& dataFrag : *(eventMap[artdaq::Fragment::DataFragmentType]))
983  {
984  auto header = dataFrag.metadata<artdaq::NetMonHeader>();
985  msgs.emplace_back(new TBufferFile(TBuffer::kRead, header->data_length, dataFrag.dataBegin(), kFALSE, 0));
986  }
987 
988  //
989  // Read message type code.
990  //
991  unsigned long msg_type_code = 0;
992  unsigned long msg_type_code_tmp = 0;
993  for (auto& msg : msgs)
994  {
995  TLOG_ARB(15, "ArtdaqInputHelper") << "ArtdaqInputHelper::readNext: "
996  << "getting message type code ...";
997  msg->ReadULong(msg_type_code_tmp);
998  TLOG_ARB(15, "ArtdaqInputHelper") << "ArtdaqInputHelper::readNext: "
999  << "message type: " << msg_type_code_tmp;
1000 
1001  if (msg_type_code == 0)
1002  msg_type_code = msg_type_code_tmp;
1003  else if (msg_type_code != msg_type_code_tmp)
1004  {
1005  TLOG_ARB(TLVL_ERROR, "ArtdaqInputHelper") << "ArtdaqInputHelper::readNext: Received conflicting message type codes! Aborting...";
1006 
1007  shutdownMsgReceived_ = true;
1008  TLOG_ARB(17, "ArtdaqInputHelper") << "End: ArtdaqInputHelper::readNext";
1009  return false;
1010  }
1011  }
1012  if (msg_type_code == 5)
1013  {
1014  // Shutdown message.
1015  shutdownMsgReceived_ = true;
1016  TLOG_ARB(16, "ArtdaqInputHelper") << "ArtdaqInputHelper::readNext: "
1017  << "returning false on Shutdown message.";
1018  TLOG_ARB(16, "ArtdaqInputHelper") << "End: ArtdaqInputHelper::readNext";
1019  return false;
1020  }
1021 
1022  for (auto& msg : msgs)
1023  {
1024  readAndConstructPrincipal(msg, msg_type_code, inR, inSR, outR, outSR, outE);
1025  }
1026  //
1027  // Read per-event metadata needed to construct principal.
1028  //
1029  if (msg_type_code == 2)
1030  {
1031  // EndRun message.
1032  // FIXME: We need to merge these into the input RunPrincipal.
1033  readDataProducts(msgs, outR);
1034  // Signal that we should close the input and output file.
1035  TLOG_ARB(17, "ArtdaqInputHelper") << "ArtdaqInputHelper::readNext: "
1036  << "returning false on EndRun message.";
1037  TLOG_ARB(17, "ArtdaqInputHelper") << "End: ArtdaqInputHelper::readNext";
1038  return false;
1039  }
1040  else if (msg_type_code == 3)
1041  {
1042  // EndSubRun message.
1043  // From the code above, EndRun and EndSubRun messages cause
1044  // the construction of principals that have:
1045  // Run:Subrun:Event=flush:flush:flush.
1046  // This is a problem when you have two neighboring EndSubRuns
1047  // which are both associated with empty subruns because art will
1048  // complain that you a new subrun with a subrun number identical
1049  // to that of the previous subrun. So the solution is to not
1050  // return new principals.
1051  if (inR != 0 && inSR != 0 && outR != 0 && outSR != 0)
1052  {
1053  if (inR->RUN_ID().isFlush() && inSR->SUBRUN_ID().isFlush() && outR->RUN_ID().isFlush() &&
1054  outSR->SUBRUN_ID().isFlush())
1055  {
1056  outR = 0;
1057  outSR = 0;
1058  outputFileCloseNeeded_ = true;
1059  return true;
1060  }
1061  }
1062  // FIXME: We need to merge these into the input SubRunPrincipal.
1063  readDataProducts(msgs, outSR);
1064  // Remember that we should ask for file close next time
1065  // we are called.
1066  outputFileCloseNeeded_ = true;
1067  TLOG_ARB(18, "ArtdaqInputHelper") << "readNext: returning true on EndSubRun message.";
1068  ret = true;
1069  }
1070  else if (msg_type_code == 4)
1071  {
1072  // Event message.
1073  readDataProducts(msgs, outE);
1074 
1075  if (eventMap.size() > 1)
1076  {
1077  readFragments(eventMap, outE);
1078  }
1079 
1080  TLOG_ARB(19, "ArtdaqInputHelper") << "readNext: returning true on Event message.";
1081  ret = true;
1082  }
1083  }
1084 
1085  auto read_finish_time = std::chrono::steady_clock::now();
1086  TLOG_ARB(10, "ArtdaqInputHelper") << "readNext: bytesRead=" << bytesRead
1087  << " metricMan=" << (void*)metricMan.get();
1088  if (metricMan)
1089  {
1090  metricMan->sendMetric("Avg Processing Time", artdaq::TimeUtils::GetElapsedTime(last_read_time, read_start_time),
1091  "s", 2, artdaq::MetricMode::Average);
1092  metricMan->sendMetric("Avg Input Wait Time", artdaq::TimeUtils::GetElapsedTime(read_start_time, got_event_time),
1093  "s", 3, artdaq::MetricMode::Average);
1094  metricMan->sendMetric("Avg Read Time", artdaq::TimeUtils::GetElapsedTime(got_event_time, read_finish_time), "s",
1095  3, artdaq::MetricMode::Average);
1096  }
1097 
1098  TLOG_ARB(20, "ArtdaqInputHelper") << "End: ArtdaqInputHelper::readNext ret=" << std::boolalpha << ret;
1099  last_read_time = std::chrono::steady_clock::now();
1100  return ret;
1101 }
void printProcessHistoryID(const std::string &label, const T &object)
Print the processHistoryID from the object.
~ArtdaqInputHelper()
ArtdaqInputHelper Destructor.
bool hasMoreData() const
Whether additional events are expected from the source.
void printProcessMap(const T &mappable, const std::string description)
Print data from a map-like class.
bool readNext(art::RunPrincipal *const inR, art::SubRunPrincipal *const inSR, art::RunPrincipal *&outR, art::SubRunPrincipal *&outSR, art::EventPrincipal *&outE)
Read the next event from the communication wrapper.
void readFile(const std::string &, art::FileBlock *&fb)
Emulate reading a file.
void closeCurrentFile()
Called by art to close the input source. No-Op.
ArtdaqInputHelper & operator=(const ArtdaqInputHelper &)=delete
Copy Assignment operator is deleted.
Header with length information for NetMonTransport messages.
Definition: NetMonHeader.hh:13
ArtdaqInputHelper(const ArtdaqInputHelper &)=delete
Copy Constructor is deleted.
This template class provides a unified interface for reading data into art.