artdaq  v3_07_02
ArtdaqInput.hh
1 #include "art/Framework/Core/FileBlock.h"
2 #include "art/Framework/Core/InputSourceMacros.h"
3 #include "art/Framework/Core/ProductRegistryHelper.h"
4 #include "art/Framework/IO/Sources/Source.h"
5 #include "art/Framework/IO/Sources/SourceHelper.h"
6 #include "art/Framework/IO/Sources/SourceTraits.h"
7 #include "art/Framework/Services/Registry/ServiceHandle.h"
8 
9 #if ART_HEX_VERSION < 0x30000
10 #include "art/Persistency/Provenance/MasterProductRegistry.h"
11 #include "art/Persistency/Provenance/ProductMetaData.h"
12 #endif
13 #if ART_HEX_VERSION >= 0x30200
14 #include "art_root_io/setup.h"
15 #endif
16 #include "art/Persistency/Provenance/ProcessHistoryRegistry.h"
17 
18 #include "canvas/Persistency/Common/EDProduct.h"
19 #include "canvas/Persistency/Common/Wrapper.h"
20 #include "canvas/Persistency/Provenance/BranchDescription.h"
21 #include "canvas/Persistency/Provenance/BranchKey.h"
22 #include "canvas/Persistency/Provenance/History.h"
23 #include "canvas/Persistency/Provenance/ParentageRegistry.h"
24 #include "canvas/Persistency/Provenance/ProcessConfiguration.h"
25 #include "canvas/Persistency/Provenance/ProcessHistory.h"
26 #include "canvas/Persistency/Provenance/ProcessHistoryID.h"
27 #include "canvas/Persistency/Provenance/ProductList.h"
28 #include "canvas/Persistency/Provenance/ProductProvenance.h"
29 #include "canvas/Persistency/Provenance/ProductTables.h"
30 #include "canvas/Utilities/DebugMacros.h"
31 
32 #include "fhiclcpp/ParameterSet.h"
33 #include "fhiclcpp/ParameterSetID.h"
34 #include "fhiclcpp/ParameterSetRegistry.h"
35 #include "fhiclcpp/make_ParameterSet.h"
36 
37 #include <TBufferFile.h>
38 #include <TClass.h>
39 #include <TList.h>
40 #include <TStreamerInfo.h>
41 
42 #include "artdaq-core/Data/Fragment.hh"
43 #include "artdaq-core/Data/detail/ParentageMap.hh"
44 #include "artdaq-core/Utilities/ExceptionHandler.hh"
45 #include "artdaq/ArtModules/InputUtilities.hh"
46 #include "artdaq/DAQdata/Globals.hh"
47 #include "artdaq/DAQdata/NetMonHeader.hh"
48 
49 #include <sys/time.h>
50 #include <cstdio>
51 #include <iomanip>
52 #include <iostream>
53 #include <memory>
54 #include <sstream>
55 #include <string>
56 #include <vector>
57 
58 #if ART_HEX_VERSION < 0x30000
59 #define EVENT_ID id
60 #define SUBRUN_ID id
61 #define RUN_ID id
62 #define HISTORY_PTR_T std::shared_ptr<art::History>
63 #else
64 #define EVENT_ID eventID
65 #define SUBRUN_ID subRunID
66 #define RUN_ID runID
67 #define HISTORY_PTR_T std::unique_ptr<art::History>
68 #endif
69 
70 namespace art {
71 template<typename U>
73 }
74 
89 template<typename U>
90 class art::ArtdaqInput
91 {
92 public:
96  ArtdaqInput(const ArtdaqInput&) = delete;
97 
102  ArtdaqInput& operator=(const ArtdaqInput&) = delete;
103 
107  ~ArtdaqInput();
108 
115  ArtdaqInput(const fhicl::ParameterSet& ps, art::ProductRegistryHelper& helper, art::SourceHelper const& pm);
116 
120  void closeCurrentFile();
121 
126  void readFile(const std::string&, art::FileBlock*& fb);
127 
132  bool hasMoreData() const;
133 
143  bool readNext(art::RunPrincipal* const inR, art::SubRunPrincipal* const inSR, art::RunPrincipal*& outR,
144  art::SubRunPrincipal*& outSR, art::EventPrincipal*& outE);
145 
146 private:
147  void readAndConstructPrincipal(std::unique_ptr<TBufferFile>&, unsigned long, art::RunPrincipal* const,
148  art::SubRunPrincipal* const, art::RunPrincipal*&, art::SubRunPrincipal*&,
149  art::EventPrincipal*&);
150 
151  template<class T>
152  void readDataProducts(std::unique_ptr<TBufferFile>&, T*&);
153 
154  void putInPrincipal(RunPrincipal*&, std::unique_ptr<EDProduct>&&, const BranchDescription&,
155  std::unique_ptr<const ProductProvenance>&&);
156 
157  void putInPrincipal(SubRunPrincipal*&, std::unique_ptr<EDProduct>&&, const BranchDescription&,
158  std::unique_ptr<const ProductProvenance>&&);
159 
160  void putInPrincipal(EventPrincipal*&, std::unique_ptr<EDProduct>&&, const BranchDescription&,
161  std::unique_ptr<const ProductProvenance>&&);
162 
163 private:
164  bool shutdownMsgReceived_;
165  bool outputFileCloseNeeded_;
166  art::SourceHelper const& pm_;
167  U communicationWrapper_;
168  ProductList* productList_;
169  HISTORY_PTR_T history_to_use_;
170 };
171 
172 template<typename U>
173 art::ArtdaqInput<U>::ArtdaqInput(const fhicl::ParameterSet& ps, art::ProductRegistryHelper& helper,
174  art::SourceHelper const& pm)
175  : shutdownMsgReceived_(false), outputFileCloseNeeded_(false), pm_(pm), communicationWrapper_(ps), productList_()
176 {
177  artdaq::configureMessageFacility("artdaqart");
178 
179 #if ART_HEX_VERSION >= 0x30200
180  root::setup();
181 #endif
182 
183 #if 0
184  volatile bool loop = true;
185  while (loop)
186  {
187  usleep(1000);
188  }
189 #endif
190 
191  // JCF, May-27-2016
192 
193  // Something will have to be done about the labeling of this class,
194  // since it's just a template class- the user will care about the
195  // specific instantiation when it comes to messages
196 
197  TLOG_ARB(5, "ArtdaqInput") << "Begin: ArtdaqInput::ArtdaqInput("
198  << "const fhicl::ParameterSet& ps, "
199  << "art::ProductRegistryHelper& helper, "
200  << "const art::SourceHelper& pm)";
201 
202  TLOG_ARB(5, "ArtdaqInput") << "Going to receive init message";
203  artdaq::FragmentPtr initFrag = communicationWrapper_.receiveInitMessage();
204  TLOG_ARB(5, "ArtdaqInput") << "Init message received";
205 
206  if (!initFrag)
207  {
208  throw art::Exception(art::errors::DataCorruption) << "ArtdaqInput: Could not receive init message!";
209  }
210  auto header = initFrag->metadata<artdaq::NetMonHeader>();
211  std::unique_ptr<TBufferFile> msg(new TBufferFile(TBuffer::kRead, header->data_length, initFrag->dataBegin(), kFALSE, 0));
212 
213  // This first unsigned long is the message type code, ignored here in the constructor
214  unsigned long dummy = 0;
215  msg->ReadULong(dummy);
216 
217  // ELF: 6/11/2019: This code is taken from TSocket::RecvStreamerInfos
218  TList* list = (TList*)msg->ReadObject(TList::Class());
219 
220  TIter next(list);
221  TStreamerInfo* info;
222  TObjLink* lnk = list->FirstLink();
223  // First call BuildCheck for regular class
224  while (lnk)
225  {
226  info = (TStreamerInfo*)lnk->GetObject();
227  TObject* element = info->GetElements()->UncheckedAt(0);
228  Bool_t isstl = element && strcmp("This", element->GetName()) == 0;
229  if (!isstl)
230  {
231  info->BuildCheck();
232  TLOG_ARB(5, "ArtdaqInput") << "ArtdaqInput: importing TStreamerInfo: " << info->GetName() << ", version = " << info->GetClassVersion();
233  }
234  lnk = lnk->Next();
235  }
236  // Then call BuildCheck for stl class
237  lnk = list->FirstLink();
238  while (lnk)
239  {
240  info = (TStreamerInfo*)lnk->GetObject();
241  TObject* element = info->GetElements()->UncheckedAt(0);
242  Bool_t isstl = element && strcmp("This", element->GetName()) == 0;
243  if (isstl)
244  {
245  info->BuildCheck();
246  TLOG_ARB(5, "ArtdaqInput") << "ArtdaqInput: importing TStreamerInfo: " << info->GetName() << ", version = " << info->GetClassVersion();
247  }
248  lnk = lnk->Next();
249  }
250  // ELF: 6/11/2019: End TSocket snippet
251 
252  //
253  // Read the ParameterSetRegistry.
254  //
255  unsigned long ps_cnt = 0;
256  msg->ReadULong(ps_cnt);
257  TLOG_ARB(5, "ArtdaqInput") << "ArtdaqInput: parameter set count: " << ps_cnt;
258  TLOG_ARB(5, "ArtdaqInput") << "ArtdaqInput: reading parameter sets ...";
259  for (unsigned long I = 0; I < ps_cnt; ++I)
260  {
261  std::string pset_str = ""; // = ReadObjectAny<std::string>(msg, "std::string", "ArtdaqInput::ArtdaqInput");
262  msg->ReadStdString(pset_str);
263 
264  TLOG_ARB(5, "ArtdaqInput") << "ArtdaqInput: parameter set: " << pset_str;
265 
266  fhicl::ParameterSet pset;
267  fhicl::make_ParameterSet(pset_str, pset);
268  // Force id calculation.
269  pset.id();
270  fhicl::ParameterSetRegistry::put(pset);
271  }
272  TLOG_ARB(5, "ArtdaqInput") << "ArtdaqInput: finished reading parameter sets.";
273 
274  //
275  // Read the MasterProductRegistry.
276  //
277  productList_ = ReadObjectAny<art::ProductList>(
278  msg, "std::map<art::BranchKey,art::BranchDescription>", "ArtdaqInput::ArtdaqInput");
279  TLOG_ARB(5, "ArtdaqInput") << "ArtdaqInput: Product list sz=" << productList_->size();
280 
281 #ifndef __OPTIMIZE__
282  for (auto I = productList_->begin(), E = productList_->end(); I != E; ++I)
283  {
284  TLOG_ARB(50, "ArtdaqInput") << "Branch key: class: '" << I->first.friendlyClassName_ << "' modlbl: '"
285  << I->first.moduleLabel_ << "' instnm: '" << I->first.productInstanceName_ << "' procnm: '"
286  << I->first.processName_ << "', branch description name: " << I->second.wrappedName()
287  << ", TClass = " << (void*)TClass::GetClass(I->second.wrappedName().c_str());
288  }
289 #endif
290 
291  // helper now owns productList_!
292 #if ART_HEX_VERSION < 0x30000
293  helper.productList(productList_);
294 #else
295  helper.productList(std::unique_ptr<art::ProductList>(productList_));
296 #endif
297  TLOG_ARB(5, "ArtdaqInput") << "ArtdaqInput: got product list";
298 
299  TLOG_ARB(5, "ArtdaqInput") << "ArtdaqInput: Reading ProcessHistory";
300  art::ProcessHistoryMap* phm = ReadObjectAny<art::ProcessHistoryMap>(
301  msg, "std::map<const art::Hash<2>,art::ProcessHistory>", "ArtdaqInput::ArtdaqInput");
302  printProcessMap(*phm, "ArtdaqInput's ProcessHistoryMap");
303 
304  ProcessHistoryRegistry::put(*phm);
305  printProcessMap(ProcessHistoryRegistry::get(), "ArtdaqInput's ProcessHistoryRegistry");
306 
307  //
308  // Read the ParentageRegistry.
309  //
310  TLOG_ARB(5, "ArtdaqInput") << "ArtdaqInput: Reading ParentageMap";
311  ParentageMap* parentageMap = ReadObjectAny<ParentageMap>(msg, "art::ParentageMap", "ArtdaqInput::ArtdaqInput");
312  ParentageRegistry::put(*parentageMap);
313 
314  //
315  // Read the History
316  //
317  TLOG_ARB(5, "ArtdaqInput") << "ArtdaqInput: Reading History";
318  history_to_use_.reset(ReadObjectAny<History>(msg, "art::History", "ArtdaqInput::ArtdaqInput"));
319  if (!history_to_use_->processHistoryID().isValid())
320  {
321  TLOG_ARB(5, "ArtdaqInput") << "ArtdaqInput: History from init message is INVALID!";
322  }
323 
324  //
325  // Finished with init message.
326  //
327  TLOG_ARB(5, "ArtdaqInput") << "End: ArtdaqInput::ArtdaqInput("
328  << "const fhicl::ParameterSet& ps, "
329  << "art::ProductRegistryHelper& helper, "
330  << "const art::SourceHelper& pm)";
331 }
332 
333 template<typename U>
335 {}
336 
337 template<typename U>
339 {
340  TLOG_ARB(6, "ArtdaqInput") << "Begin/End: ArtdaqInput::closeCurrentFile()";
341 }
342 
343 template<typename U>
344 void art::ArtdaqInput<U>::readFile(const std::string&, art::FileBlock*& fb)
345 {
346  TLOG_ARB(7, "ArtdaqInput") << "Begin: ArtdaqInput::"
347  "readFile(const std::string& name, art::FileBlock*& fb)";
348  fb = new art::FileBlock(art::FileFormatVersion(1, "ArtdaqInput2013"), "nothing");
349  TLOG_ARB(7, "ArtdaqInput") << "End: ArtdaqInput::"
350  "readFile(const std::string& name, art::FileBlock*& fb)";
351 }
352 
353 template<typename U>
355 {
356  TLOG_ARB(8, "ArtdaqInput") << "Begin: ArtdaqInput::hasMoreData()";
357  if (shutdownMsgReceived_)
358  {
359  TLOG_ARB(8, "ArtdaqInput") << "ArtdaqInput::hasMoreData(): "
360  "returning false on shutdownMsgReceived_.";
361  TLOG_ARB(8, "ArtdaqInput") << "End: ArtdaqInput::hasMoreData()";
362  return false;
363  }
364  TLOG_ARB(8, "ArtdaqInput") << "ArtdaqInput::hasMoreData(): "
365  "returning true on not shutdownMsgReceived_.";
366  TLOG_ARB(8, "ArtdaqInput") << "End: ArtdaqInput::hasMoreData()";
367  return true;
368 }
369 
370 template<typename U>
371 void art::ArtdaqInput<U>::readAndConstructPrincipal(std::unique_ptr<TBufferFile>& msg, unsigned long msg_type_code,
372  art::RunPrincipal* const inR, art::SubRunPrincipal* const inSR,
373  art::RunPrincipal*& outR, art::SubRunPrincipal*& outSR,
374  art::EventPrincipal*& outE)
375 {
376  //
377  // Process the message.
378  //
379  std::unique_ptr<art::RunAuxiliary> run_aux;
380  std::unique_ptr<art::SubRunAuxiliary> subrun_aux;
381  std::unique_ptr<art::EventAuxiliary> event_aux;
382 
383  HISTORY_PTR_T history_from_event;
384 
385  // Establish default 'results'
386  outR = 0;
387  outSR = 0;
388  outE = 0;
389 
390  if (msg_type_code == 2)
391  { // EndRun message.
392 
393  TLOG_ARB(9, "ArtdaqInput") << "readAndConstructPrincipal: "
394  << "processing EndRun message ...";
395 
396  run_aux.reset(ReadObjectAny<art::RunAuxiliary>(msg, "art::RunAuxiliary", "ArtdaqInput::readAndConstructPrincipal"));
397  printProcessHistoryID("readAndConstructPrincipal", run_aux.get());
398 
399  TLOG_ARB(9, "ArtdaqInput") << "readAndConstructPrincipal: "
400  << "making flush RunPrincipal ...";
401  outR = pm_.makeRunPrincipal(RunID::flushRun(), run_aux->beginTime());
402 
403  TLOG_ARB(9, "ArtdaqInput") << "readAndConstructPrincipal: "
404  << "making flush SubRunPrincipal ...";
405  outSR = pm_.makeSubRunPrincipal(SubRunID::flushSubRun(), run_aux->beginTime());
406 
407  TLOG_ARB(9, "ArtdaqInput") << "readAndConstructPrincipal: "
408  << "making flush EventPrincipal ...";
409  outE = pm_.makeEventPrincipal(EventID::flushEvent(), run_aux->endTime(), true, EventAuxiliary::Any);
410 
411  TLOG_ARB(9, "ArtdaqInput") << "readAndConstructPrincipal: "
412  << "finished processing EndRun message.";
413  }
414  else if (msg_type_code == 3)
415  { // EndSubRun message.
416 
417  TLOG_ARB(10, "ArtdaqInput") << "readAndConstructPrincipal: "
418  << "processing EndSubRun message ...";
419 
420  subrun_aux.reset(
421  ReadObjectAny<art::SubRunAuxiliary>(msg, "art::SubRunAuxiliary", "ArtdaqInput::readAndConstructPrincipal"));
422  printProcessHistoryID("readAndConstructPrincipal", subrun_aux.get());
423 
424  TLOG_ARB(10, "ArtdaqInput") << "readAndConstructPrincipal: "
425  << "making flush RunPrincipal ...";
426  outR = pm_.makeRunPrincipal(RunID::flushRun(), subrun_aux->beginTime());
427 
428  // 28-Feb-2014, KAB: added the setting of the end time in the *current*
429  // run and subrun. This is how we set the endTime in the RunPrincipal
430  // and SubRunPrincipal objects that are written to the disk file.
431  // This needs to happen here because:
432  // A) setting them in every event doesn't work because the RunPrincipal
433  // only allows us to set an end time value once
434  // B) setting them in the "outputFileCloseNeeded_" block in the readNext()
435  // method below doesn't work because that is too late. When this
436  // method returns an outR with a different run number (flushRun),
437  // the art output system closes the current file then.
438  // C) setting them in the EndRun message block immediately above this
439  // block wouldn't work because a) we're not currently sending endRun
440  // events from the EBs to the AG, and b) because presumably that would
441  // be too late, also.
442 
443  art::Timestamp currentTime = time(0);
444  if (inR != nullptr)
445  {
446 #if ART_HEX_VERSION < 0x30000
447  inR->setEndTime(currentTime);
448 #else
449  inR->endTime(currentTime);
450 #endif
451  }
452  if (inSR != nullptr)
453  {
454 #if ART_HEX_VERSION < 0x30000
455  inSR->setEndTime(currentTime);
456 #else
457  inSR->endTime(currentTime);
458 #endif
459  }
460 
461  TLOG_ARB(10, "ArtdaqInput") << "readAndConstructPrincipal: "
462  << "making flush SubRunPrincipal ...";
463  outSR = pm_.makeSubRunPrincipal(SubRunID::flushSubRun(), subrun_aux->beginTime());
464 
465  TLOG_ARB(10, "ArtdaqInput") << "readAndConstructPrincipal: "
466  << "making flush EventPrincipal ...";
467  outE = pm_.makeEventPrincipal(EventID::flushEvent(), subrun_aux->endTime(), true, EventAuxiliary::Any);
468 
469  TLOG_ARB(10, "ArtdaqInput") << "readAndConstructPrincipal: "
470  << "finished processing EndSubRun message.";
471  }
472  else if (msg_type_code == 4)
473  { // Event message.
474 
475  TLOG_ARB(11, "ArtdaqInput") << "readAndConstructPrincipal: "
476  << "processing Event message ...";
477 
478  run_aux.reset(ReadObjectAny<art::RunAuxiliary>(msg, "art::RunAuxiliary", "ArtdaqInput::readAndConstructPrincipal"));
479  printProcessHistoryID("readAndConstructPrincipal", run_aux.get());
480 
481  subrun_aux.reset(
482  ReadObjectAny<art::SubRunAuxiliary>(msg, "art::SubRunAuxiliary", "ArtdaqInput::readAndConstructPrincipal"));
483  printProcessHistoryID("readAndConstructPrincipal", subrun_aux.get());
484 
485  event_aux.reset(
486  ReadObjectAny<art::EventAuxiliary>(msg, "art::EventAuxiliary", "ArtdaqInput::readAndConstructPrincipal"));
487 
488  history_from_event.reset(ReadObjectAny<art::History>(msg, "art::History", "ArtdaqInput::readAndConstructPrincipal"));
489  printProcessHistoryID("readAndConstructPrincipal", history_from_event.get());
490 
491  // Every event should have a valid history
492  if (!history_from_event->processHistoryID().isValid())
493  {
494  throw art::Exception(art::errors::Unknown)
495  << "readAndConstructPrincipal: processHistoryID of history in Event message is invalid!";
496  }
497  // If our stored history is invalid, use this Event's history
498  else if (!history_to_use_->processHistoryID().isValid())
499  {
500  history_to_use_.swap(history_from_event);
501  }
502  // If our stored history doesn't match our ProcessHistoryRegistry, then used this Event's history
503  else if (!art::ProcessHistoryRegistry::get().count(history_to_use_->processHistoryID()) &&
504  art::ProcessHistoryRegistry::get().count(history_from_event->processHistoryID()))
505  {
506  history_to_use_.swap(history_from_event);
507  }
508 
509  TLOG_ARB(11, "ArtdaqInput") << "readAndConstructPrincipal: "
510  << "inR: " << (void*)inR << " run/expected "
511  << (inR ? std::to_string(inR->run()) : "invalid") << "/" << event_aux->run();
512  TLOG_ARB(11, "ArtdaqInput") << "readAndConstructPrincipal: "
513  << "inSR: " << (void*)inSR << " run/expected "
514  << (inSR ? std::to_string(inSR->run()) : "invalid") << "/" << event_aux->run()
515  << ", subrun/expected " << (inSR ? std::to_string(inSR->subRun()) : "invalid") << "/"
516  << event_aux->subRun();
517  if ((inR == nullptr) || !inR->RUN_ID().isValid() || (inR->run() != event_aux->run()))
518  {
519  // New run, either we have no input RunPrincipal, or the
520  // input run number does not match the event run number.
521  TLOG_ARB(11, "ArtdaqInput") << "readAndConstructPrincipal: making RunPrincipal ...";
522  outR = pm_.makeRunPrincipal(*run_aux.get());
523  }
524  art::SubRunID subrun_check(event_aux->run(), event_aux->subRun());
525  if (inSR == 0 || subrun_check != inSR->SUBRUN_ID())
526  {
527  // New SubRun, either we have no input SubRunPrincipal, or the
528  // input subRun number does not match the event subRun number.
529  TLOG_ARB(11, "ArtdaqInput") << "readAndConstructPrincipal: "
530  << "making SubRunPrincipal ...";
531  outSR = pm_.makeSubRunPrincipal(*subrun_aux.get());
532  }
533  TLOG_ARB(11, "ArtdaqInput") << "readAndConstructPrincipal: making EventPrincipal ...";
534  auto historyPtr = HISTORY_PTR_T(new History(*(history_to_use_.get())));
535  if (!art::ProcessHistoryRegistry::get().count(history_to_use_->processHistoryID()))
536  {
537  TLOG_WARNING("ArtdaqInput") << "Stored history is not in ProcessHistoryRegistry, this event may have issues!";
538  }
539  outE = pm_.makeEventPrincipal(*event_aux.get(), std::move(historyPtr));
540 
541  TLOG_ARB(11, "ArtdaqInput") << "readAndConstructPrincipal: "
542  << "finished processing Event message.";
543  }
544 }
545 
546 template<typename U>
547 template<class T>
548 void art::ArtdaqInput<U>::readDataProducts(std::unique_ptr<TBufferFile>& msg, T*& outPrincipal)
549 {
550  unsigned long prd_cnt = 0;
551  {
552  TLOG_ARB(12, "ArtdaqInput") << "readDataProducts: reading data product count ...";
553  msg->ReadULong(prd_cnt);
554  TLOG_ARB(12, "ArtdaqInput") << "readDataProducts: product count: " << prd_cnt;
555  }
556  //
557  // Read the data products.
558  //
559  for (unsigned long I = 0; I < prd_cnt; ++I)
560  {
561  std::unique_ptr<BranchKey> bk;
562  {
563  TLOG_ARB(12, "ArtdaqInput") << "readDataProducts: Reading branch key.";
564  bk.reset(ReadObjectAny<BranchKey>(msg, "art::BranchKey", "ArtdaqInput::readDataProducts"));
565  }
566 
567 #ifndef __OPTIMIZE__
568  TLOG_ARB(13, "ArtdaqInput") << "readDataProducts: got product class: '" << bk->friendlyClassName_ << "' modlbl: '"
569  << bk->moduleLabel_ << "' instnm: '" << bk->productInstanceName_ << "' procnm: '"
570  << bk->processName_;
571 #endif
572  ProductList::const_iterator iter;
573  {
574  TLOG_ARB(12, "ArtdaqInput") << "readDataProducts: looking up product ...";
575  iter = productList_->find(*bk);
576  if (iter == productList_->end())
577  {
578  throw art::Exception(art::errors::ProductNotFound)
579  << "No product is registered for\n"
580  << " process name: '" << bk->processName_ << "'\n"
581  << " module label: '" << bk->moduleLabel_ << "'\n"
582  << " product friendly class name: '" << bk->friendlyClassName_ << "'\n"
583  << " product instance name: '" << bk->productInstanceName_ << "'\n";
584  }
585  }
586  // Note: This must be a reference to the unique copy in
587  // the master product registry!
588  const BranchDescription& bd = iter->second;
589  std::unique_ptr<EDProduct> prd;
590  {
591  TLOG_ARB(12, "ArtdaqInput") << "readDataProducts: Reading product with wrapped name: " << bd.wrappedName()
592  << ", TClass = " << (void*)TClass::GetClass(bd.wrappedName().c_str());
593 
594  // JCF, May-25-2016
595  // Currently unclear why the templatized version of ReadObjectAny doesn't work here...
596 
597  // prd.reset(ReadObjectAny<EDProduct>(msg, bd.wrappedName()));
598 
599  void* p = msg->ReadObjectAny(TClass::GetClass(bd.wrappedName().c_str()));
600  auto pp = reinterpret_cast<EDProduct*>(p);
601 
602  TLOG_ARB(12, "ArtdaqInput") << "readDataProducts: After ReadObjectAny(prd): p=" << p << ", EDProduct::isPresent: " << pp->isPresent();
603  prd.reset(pp);
604  p = nullptr;
605  }
606  std::unique_ptr<const ProductProvenance> prdprov;
607  {
608  TLOG_ARB(12, "ArtdaqInput") << "readDataProducts: Reading product provenance.";
609  prdprov.reset(ReadObjectAny<ProductProvenance>(msg, "art::ProductProvenance", "ArtdaqInput::readDataProducts"));
610  }
611 
612  {
613  TLOG_ARB(12, "ArtdaqInput") << "readDataProducts: inserting product: class: '" << bd.friendlyClassName()
614  << "' modlbl: '" << bd.moduleLabel() << "' instnm: '" << bd.productInstanceName()
615  << "' procnm: '" << bd.processName() << "' id: '" << bd.productID() << "'";
616  putInPrincipal(outPrincipal, std::move(prd), bd, std::move(prdprov));
617  }
618  }
619 }
620 
621 template<typename U>
622 void art::ArtdaqInput<U>::putInPrincipal(RunPrincipal*& rp, std::unique_ptr<EDProduct>&& prd,
623  const BranchDescription& bd,
624  std::unique_ptr<const ProductProvenance>&& prdprov)
625 {
626 #if ART_HEX_VERSION < 0x30000
627  rp->put(std::move(prd), bd, std::move(prdprov), RangeSet::forRun(rp->RUN_ID()));
628 #else
629  rp->put(bd, std::move(prdprov), std::move(prd), std::make_unique<RangeSet>(RangeSet::forRun(rp->RUN_ID())));
630 #endif
631 }
632 
633 template<typename U>
634 void art::ArtdaqInput<U>::putInPrincipal(SubRunPrincipal*& srp, std::unique_ptr<EDProduct>&& prd,
635  const BranchDescription& bd,
636  std::unique_ptr<const ProductProvenance>&& prdprov)
637 {
638 #if ART_HEX_VERSION < 0x30000
639  srp->put(std::move(prd), bd, std::move(prdprov), RangeSet::forSubRun(srp->SUBRUN_ID()));
640 #else
641  srp->put(bd, std::move(prdprov), std::move(prd), std::make_unique<RangeSet>(RangeSet::forSubRun(srp->SUBRUN_ID())));
642 #endif
643 }
644 
645 template<typename U>
646 void art::ArtdaqInput<U>::putInPrincipal(EventPrincipal*& ep, std::unique_ptr<EDProduct>&& prd,
647  const BranchDescription& bd,
648  std::unique_ptr<const ProductProvenance>&& prdprov)
649 {
650  TLOG_ARB(14, "ArtdaqInput") << "EventPrincipal size before put: " << ep->size();
651 #if ART_HEX_VERSION < 0x30000
652  ep->put(std::move(prd), bd, std::move(prdprov));
653 #else
654  ep->put(bd, std::move(prdprov), std::move(prd), std::make_unique<RangeSet>(RangeSet::invalid()));
655 #endif
656  TLOG_ARB(14, "ArtdaqInput") << "EventPrincipal size after put: " << ep->size();
657 }
658 
659 template<typename U>
660 bool art::ArtdaqInput<U>::readNext(art::RunPrincipal* const inR, art::SubRunPrincipal* const inSR,
661  art::RunPrincipal*& outR, art::SubRunPrincipal*& outSR, art::EventPrincipal*& outE)
662 {
663  TLOG_ARB(15, "ArtdaqInput") << "Begin: ArtdaqInput::readNext";
664  if (outputFileCloseNeeded_)
665  {
666  outputFileCloseNeeded_ = false;
667  // Signal that we need the output file closed by returning false,
668  // but answering true to the hasMoreData() query.
669  TLOG_ARB(15, "ArtdaqInput") << "ArtdaqInput::readNext: "
670  << "returning false on outputFileCloseNeeded_";
671  TLOG_ARB(15, "ArtdaqInput") << "End: ArtdaqInput::readNext";
672  return false;
673  }
674 
675  artdaq::FragmentPtr dataFrag = communicationWrapper_.receiveMessage();
676  if (!dataFrag)
677  {
678  TLOG_ARB(15, "ArtdaqInput") << "ArtdaqInput::readNext got an empty message";
679  shutdownMsgReceived_ = true;
680  return false;
681  }
682  auto header = dataFrag->metadata<artdaq::NetMonHeader>();
683  std::unique_ptr<TBufferFile> msg(new TBufferFile(TBuffer::kRead, header->data_length, dataFrag->dataBegin(), kFALSE, 0));
684 
685  //
686  // Read message type code.
687  //
688  unsigned long msg_type_code = 0;
689  {
690  TLOG_ARB(15, "ArtdaqInput") << "ArtdaqInput::readNext: "
691  << "getting message type code ...";
692  msg->ReadULong(msg_type_code);
693  TLOG_ARB(15, "ArtdaqInput") << "ArtdaqInput::readNext: "
694  << "message type: " << msg_type_code;
695  }
696  if (msg_type_code == 5)
697  {
698  // Shutdown message.
699  shutdownMsgReceived_ = true;
700  TLOG_ARB(16, "ArtdaqInput") << "ArtdaqInput::readNext: "
701  << "returning false on Shutdown message.";
702  TLOG_ARB(16, "ArtdaqInput") << "End: ArtdaqInput::readNext";
703  return false;
704  }
705 
706  readAndConstructPrincipal(msg, msg_type_code, inR, inSR, outR, outSR, outE);
707  //
708  // Read per-event metadata needed to construct principal.
709  //
710  if (msg_type_code == 2)
711  {
712  // EndRun message.
713  // FIXME: We need to merge these into the input RunPrincipal.
714  readDataProducts(msg, outR);
715  // Signal that we should close the input and output file.
716  TLOG_ARB(17, "ArtdaqInput") << "ArtdaqInput::readNext: "
717  << "returning false on EndRun message.";
718  TLOG_ARB(17, "ArtdaqInput") << "End: ArtdaqInput::readNext";
719  return false;
720  }
721  else if (msg_type_code == 3)
722  {
723  // EndSubRun message.
724  // From the code above, EndRun and EndSubRun messages cause
725  // the construction of principals that have:
726  // Run:Subrun:Event=flush:flush:flush.
727  // This is a problem when you have two neighboring EndSubRuns
728  // which are both associated with empty subruns because art will
729  // complain that you a new subrun with a subrun number identical
730  // to that of the previous subrun. So the solution is to not
731  // return new principals.
732  if (inR != 0 && inSR != 0 && outR != 0 && outSR != 0)
733  {
734  if (inR->RUN_ID().isFlush() && inSR->SUBRUN_ID().isFlush() && outR->RUN_ID().isFlush() &&
735  outSR->SUBRUN_ID().isFlush())
736  {
737  outR = 0;
738  outSR = 0;
739  outputFileCloseNeeded_ = true;
740  return true;
741  }
742  }
743  // FIXME: We need to merge these into the input SubRunPrincipal.
744  readDataProducts(msg, outSR);
745  // Remember that we should ask for file close next time
746  // we are called.
747  outputFileCloseNeeded_ = true;
748  TLOG_ARB(18, "ArtdaqInput") << "readNext: returning true on EndSubRun message.";
749  TLOG_ARB(18, "ArtdaqInput") << "End: ArtdaqInput::readNext";
750  return true;
751  }
752  else if (msg_type_code == 4)
753  {
754  // Event message.
755  readDataProducts(msg, outE);
756  TLOG_ARB(19, "ArtdaqInput") << "readNext: returning true on Event message.";
757  TLOG_ARB(19, "ArtdaqInput") << "End: ArtdaqInput::readNext";
758  return true;
759  }
760  // Unknown message.
761  // FIXME: What do we throw here for invalid message code?
762  TLOG_ARB(20, "ArtdaqInput") << "readNext: returning false on unknown msg_type_code!";
763  TLOG_ARB(20, "ArtdaqInput") << "End: ArtdaqInput::readNext";
764  return false;
765 }
void printProcessHistoryID(const std::string &label, const T &object)
Print the processHistoryID from the object.
void readFile(const std::string &, art::FileBlock *&fb)
Emulate reading a file.
Definition: ArtdaqInput.hh:344
~ArtdaqInput()
ArtdaqInput Destructor.
Definition: ArtdaqInput.hh:334
void printProcessMap(const T &mappable, const std::string description)
Print data from a map-like class.
bool hasMoreData() const
Whether additional events are expected from the source.
Definition: ArtdaqInput.hh:354
void closeCurrentFile()
Called by art to close the input source. No-Op.
Definition: ArtdaqInput.hh:338
This template class provides a unified interface for reading data into art.
Definition: ArtdaqInput.hh:72
Header with length information for NetMonTransport messages.
Definition: NetMonHeader.hh:13
ArtdaqInput(const ArtdaqInput &)=delete
Copy Constructor is deleted.
ArtdaqInput & operator=(const ArtdaqInput &)=delete
Copy Assignment operator is deleted.
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.
Definition: ArtdaqInput.hh:660