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