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