artdaq  v2_02_03
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Pages
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 #include "art/Persistency/Provenance/BranchIDListHelper.h"
10 #include "art/Persistency/Provenance/BranchIDListRegistry.h"
11 #include "art/Persistency/Provenance/MasterProductRegistry.h"
12 #include "art/Persistency/Provenance/ProcessHistoryRegistry.h"
13 #include "art/Persistency/Provenance/ProductMetaData.h"
14 
15 #include "canvas/Persistency/Common/EDProduct.h"
16 #include "canvas/Persistency/Common/Wrapper.h"
17 #include "canvas/Persistency/Provenance/BranchDescription.h"
18 #include "canvas/Persistency/Provenance/BranchIDList.h"
19 #include "canvas/Persistency/Provenance/BranchKey.h"
20 #include "canvas/Persistency/Provenance/History.h"
21 #include "canvas/Persistency/Provenance/ParentageRegistry.h"
22 #include "canvas/Persistency/Provenance/ProcessConfiguration.h"
23 #include "canvas/Persistency/Provenance/ProcessHistory.h"
24 #include "canvas/Persistency/Provenance/ProcessHistoryID.h"
25 #include "canvas/Persistency/Provenance/ProductList.h"
26 #include "canvas/Persistency/Provenance/ProductProvenance.h"
27 #include "canvas/Utilities/DebugMacros.h"
28 
29 #include "fhiclcpp/make_ParameterSet.h"
30 #include "fhiclcpp/ParameterSet.h"
31 #include "fhiclcpp/ParameterSetID.h"
32 #include "fhiclcpp/ParameterSetRegistry.h"
33 
34 #include "TClass.h"
35 #include "TMessage.h"
36 #include "TBufferFile.h"
37 
38 #include "artdaq/ArtModules/InputUtilities.hh"
39 #include "artdaq-core/Utilities/ExceptionHandler.hh"
40 
41 #include <cstdio>
42 #include <iomanip>
43 #include <memory>
44 #include <sstream>
45 #include <string>
46 #include <vector>
47 #include <sys/time.h>
48 #include <iostream>
49 
50 // JCF, Jul-18-2016
51 
52 // If LOGDEBUG is defined, the TLOG_DEBUG calls will print into the
53 // aggregator logfiles using artdaq v1_13_00; this creates HUGE files
54 // and slows things down considerably, so only define this if you're
55 // troubleshooting
56 
57 // IMPORTANT: if it IS defined, it should be defined in
58 // artdaq/ArtModules/InputUtilities.hh, so the statements there also
59 // get printed
60 
61 namespace art
62 {
63  template <typename U>
64  class ArtdaqInput;
65 }
66 
81 template <typename U>
82 class art::ArtdaqInput
83 {
84 public:
88  ArtdaqInput(const ArtdaqInput&) = delete;
89 
94  ArtdaqInput& operator=(const ArtdaqInput&) = delete;
95 
99  ~ArtdaqInput();
100 
107  ArtdaqInput(const fhicl::ParameterSet& ps, art::ProductRegistryHelper& helper,
108  const art::SourceHelper& pm);
109 
113  void closeCurrentFile();
114 
119  void readFile(const std::string&, art::FileBlock*& fb);
120 
125  bool hasMoreData() const;
126 
136  bool readNext(art::RunPrincipal* const inR,
137  art::SubRunPrincipal* const inSR, art::RunPrincipal*& outR,
138  art::SubRunPrincipal*& outSR, art::EventPrincipal*& outE);
139 
140 private:
141  void
142  readAndConstructPrincipal(std::unique_ptr<TBufferFile>&,
143  unsigned long,
144  art::RunPrincipal* const,
145  art::SubRunPrincipal* const,
146  art::RunPrincipal*&,
147  art::SubRunPrincipal*&,
148  art::EventPrincipal*&);
149 
150  template <class T>
151  void readDataProducts(std::unique_ptr<TBufferFile>&, T*&);
152 
153  void putInPrincipal(RunPrincipal*&, std::unique_ptr<EDProduct>&&, const BranchDescription&, std::unique_ptr<const ProductProvenance>&&);
154 
155  void putInPrincipal(SubRunPrincipal*&, std::unique_ptr<EDProduct>&&, const BranchDescription&, std::unique_ptr<const ProductProvenance>&&);
156 
157  void putInPrincipal(EventPrincipal*&, std::unique_ptr<EDProduct>&&, const BranchDescription&, std::unique_ptr<const ProductProvenance>&&);
158 
159 
160 private:
161  bool shutdownMsgReceived_;
162  bool outputFileCloseNeeded_;
163  const art::SourceHelper& pm_;
164  U communicationWrapper_;
165 };
166 
167 template <typename U>
169 ArtdaqInput(const fhicl::ParameterSet& ps,
170  art::ProductRegistryHelper& helper,
171  const art::SourceHelper& pm)
172  : shutdownMsgReceived_(false)
173  , outputFileCloseNeeded_(false)
174  , pm_(pm)
175  , communicationWrapper_(ps)
176 {
177  // JCF, May-27-2016
178 
179  // Something will have to be done about the labeling of this class,
180  // since it's just a template class- the user will care about the
181  // specific instantiation when it comes to messages
182 
183 #ifdef LOGDEBUG
184  TLOG_DEBUG("ArtdaqInput") << "Begin: ArtdaqInput::ArtdaqInput(" \
185  "const fhicl::ParameterSet& ps, " \
186  "art::ProductRegistryHelper& helper, " \
187  "const art::SourceHelper& pm)\n";
188 #endif
189  (void)helper;
190 
191  std::unique_ptr<TBufferFile> msg(nullptr);
192  communicationWrapper_.receiveMessage(msg);
193 
194  if (!msg)
195  {
196  throw art::Exception(art::errors::DataCorruption) <<
197  "ArtdaqInput: Could not receive message!";
198  }
199 
200  // This first unsigned long is the message type code, ignored here in the constructor
201  unsigned long dummy = 0;
202  msg->ReadULong(dummy);
203 
204  //
205  // Read the ParameterSetRegistry.
206  //
207  unsigned long ps_cnt = 0;
208  msg->ReadULong(ps_cnt);
209 #ifdef LOGDEBUG
210  TLOG_DEBUG("ArtdaqInput") << "ArtdaqInput: parameter set count: " << ps_cnt;
211  TLOG_DEBUG("ArtdaqInput") << "ArtdaqInput: reading parameter sets ...";
212 #endif
213  for (unsigned long I = 0; I < ps_cnt; ++I)
214  {
215  std::string pset_str = "";// = ReadObjectAny<std::string>(msg, "std::string", "ArtdaqInput::ArtdaqInput");
216  msg->ReadStdString(pset_str);
217 
218 #ifdef LOGDEBUG
219  TLOG_DEBUG("ArtdaqInput") << "ArtdaqInput: parameter set: " << pset_str;
220 #endif
221 
222  fhicl::ParameterSet pset;
223  fhicl::make_ParameterSet(pset_str, pset);
224  // Force id calculation.
225  pset.id();
226  fhicl::ParameterSetRegistry::put(pset);
227  }
228 #ifdef LOGDEBUG
229  TLOG_DEBUG("ArtdaqInput") << "ArtdaqInput: finished reading parameter sets.\n";
230 #endif
231  //
232  // Read the MasterProductRegistry.
233  //
234 
235  art::ProductList* productlist = ReadObjectAny<art::ProductList>(msg, "std::map<art::BranchKey,art::BranchDescription>", "ArtdaqInput::ArtdaqInput");
236  helper.productList(productlist);
237 
238 #ifdef LOGDEBUG
239  TLOG_DEBUG("ArtdaqInput") << "ArtdaqInput: got product list\n";
240 #endif
241  if (art::debugit() >= 1)
242  {
243 #ifdef LOGDEBUG
244  TLOG_DEBUG("ArtdaqInput") << "ArtdaqInput: before BranchIDLists\n";
245 #endif
246  BranchIDLists* bil = &BranchIDListRegistry::instance()->data();
247  int max_bli = bil->size();
248 #ifdef LOGDEBUG
249  TLOG_DEBUG("ArtdaqInput") << "ArtdaqInput: max_bli: " << max_bli << '\n';
250 #endif
251  for (int i = 0; i < max_bli; ++i)
252  {
253  int max_prdidx = (*bil)[i].size();
254 #ifdef LOGDEBUG
255  TLOG_DEBUG("ArtdaqInput") << "ArtdaqInput: max_prdidx: "
256  << max_prdidx << '\n';
257 #endif
258  for (int j = 0; j < max_prdidx; ++j)
259  {
260 #ifdef LOGDEBUG
261  TLOG_DEBUG("ArtdaqInput") << "ArtdaqInput:"
262  << " bli: "
263  << i
264  << " prdidx: "
265  << j
266  << " bid: 0x"
267  << std::hex
268  << static_cast<unsigned long>((*bil)[i][j])
269  << std::dec
270  << '\n';
271 #endif
272  }
273  }
274  }
275 
276  art::ProcessHistoryMap* phm = ReadObjectAny<art::ProcessHistoryMap>(msg, "std::map<const art::Hash<2>,art::ProcessHistory>", "ArtdaqInput::ArtdaqInput");
277 
278  printProcessMap(*phm, "ArtdaqInput's ProcessHistoryMap");
279 
280  ProcessHistoryRegistry::put(*phm);
281 
282  printProcessMap(ProcessHistoryRegistry::get(), "ArtdaqInput's ProcessHistoryRegistry");
283  //
284  // Read the ParentageRegistry.
285  //
286 
287  art::ParentageMap* parentageMap = ReadObjectAny<art::ParentageMap>(msg, "std::map<const art::Hash<5>,art::Parentage>", "ArtdaqInput::ArtdaqInput");
288 
289 #ifdef LOGDEBUG
290  TLOG_DEBUG("ArtdaqInput") << "ArtdaqInput: got ParentageMap\n";
291 #endif
292  ParentageRegistry::put(*parentageMap);
293  //
294  // Finished with init message.
295  //
296 #ifdef LOGDEBUG
297  TLOG_DEBUG("ArtdaqInput") << "End: ArtdaqInput::ArtdaqInput("
298  "const fhicl::ParameterSet& ps, "
299  "art::ProductRegistryHelper& helper, "
300  "const art::SourceHelper& pm)\n";
301 #endif
302 }
303 
304 template <typename U>
307 
308 template <typename U>
309 void
312 {
313 #ifdef LOGDEBUG
314  TLOG_DEBUG("ArtdaqInput") << "Begin/End: ArtdaqInput::closeCurrentFile()\n";
315 #endif
316 }
317 
318 template <typename U>
319 void
321 readFile(const std::string&, art::FileBlock*& fb)
322 {
323 #ifdef LOGDEBUG
324  TLOG_DEBUG("ArtdaqInput") << "Begin: ArtdaqInput::"
325  "readFile(const std::string& name, art::FileBlock*& fb)\n";
326 #endif
327  fb = new art::FileBlock(art::FileFormatVersion(1, "ArtdaqInput2013"),
328  "nothing");
329 #ifdef LOGDEBUG
330  TLOG_DEBUG("ArtdaqInput") << "End: ArtdaqInput::"
331  "readFile(const std::string& name, art::FileBlock*& fb)\n";
332 #endif
333 }
334 
335 template <typename U>
336 bool
338 hasMoreData() const
339 {
340 #ifdef LOGDEBUG
341  TLOG_DEBUG("ArtdaqInput") << "Begin: ArtdaqInput::hasMoreData()\n";
342 #endif
343  if (shutdownMsgReceived_)
344  {
345 #ifdef LOGDEBUG
346  TLOG_DEBUG("ArtdaqInput") << "ArtdaqInput::hasMoreData(): "
347  "returning false on shutdownMsgReceived_.\n";
348  TLOG_DEBUG("ArtdaqInput") << "End: ArtdaqInput::hasMoreData()\n";
349 #endif
350  return false;
351  }
352 #ifdef LOGDEBUG
353  TLOG_DEBUG("ArtdaqInput") << "ArtdaqInput::hasMoreData(): "
354  "returning true on not shutdownMsgReceived_.\n";
355  TLOG_DEBUG("ArtdaqInput") << "End: ArtdaqInput::hasMoreData()\n";
356 #endif
357  return true;
358 }
359 
360 template <typename U>
361 void
363 readAndConstructPrincipal(std::unique_ptr<TBufferFile>& msg,
364  unsigned long msg_type_code,
365  art::RunPrincipal* const inR,
366  art::SubRunPrincipal* const inSR,
367  art::RunPrincipal*& outR,
368  art::SubRunPrincipal*& outSR,
369  art::EventPrincipal*& outE)
370 {
371  //
372  // Process the message.
373  //
374  std::unique_ptr<art::RunAuxiliary> run_aux;
375  std::unique_ptr<art::SubRunAuxiliary> subrun_aux;
376  std::unique_ptr<art::EventAuxiliary> event_aux;
377  std::shared_ptr<History> history;
378 
379  if (msg_type_code == 2)
380  { // EndRun message.
381 
382 #ifdef LOGDEBUG
383  TLOG_DEBUG("ArtdaqInput") << "readAndConstructPrincipal: "
384  "processing EndRun message ...\n";
385 #endif
386 
387  run_aux.reset(ReadObjectAny<art::RunAuxiliary>(msg, "art::RunAuxiliary",
388  "ArtdaqInput::readAndConstructPrincipal"));
389  printProcessHistoryID("readAndConstructPrincipal", run_aux.get());
390 
391 #ifdef LOGDEBUG
392  TLOG_DEBUG("ArtdaqInput") << "readAndConstructPrincipal: "
393  "making flush RunPrincipal ...\n";
394 #endif
395  outR = pm_.makeRunPrincipal(RunID::flushRun(), run_aux->beginTime());
396 
397 #ifdef LOGDEBUG
398  TLOG_DEBUG("ArtdaqInput") << "readAndConstructPrincipal: "
399  "making flush SubRunPrincipal ...\n";
400 #endif
401  outSR = pm_.makeSubRunPrincipal(SubRunID::flushSubRun(),
402  run_aux->beginTime());
403 
404 #ifdef LOGDEBUG
405  TLOG_DEBUG("ArtdaqInput") << "readAndConstructPrincipal: "
406  "making flush EventPrincipal ...\n";
407 #endif
408  outE = pm_.makeEventPrincipal(EventID::flushEvent(),
409  run_aux->endTime(), true,
410  EventAuxiliary::Any);
411 
412 #ifdef LOGDEBUG
413  TLOG_DEBUG("ArtdaqInput") << "readAndConstructPrincipal: "
414  "finished processing EndRun message.\n";
415 #endif
416  }
417  else if (msg_type_code == 3)
418  { // EndSubRun message.
419 
420 #ifdef LOGDEBUG
421  TLOG_DEBUG("ArtdaqInput") << "readAndConstructPrincipal: "
422  "processing EndSubRun message ...\n";
423 #endif
424 
425  subrun_aux.reset(ReadObjectAny<art::SubRunAuxiliary>(msg, "art::SubRunAuxiliary",
426  "ArtdaqInput::readAndConstructPrincipal"));
427  printProcessHistoryID("readAndConstructPrincipal", subrun_aux.get());
428 
429 #ifdef LOGDEBUG
430  TLOG_DEBUG("ArtdaqInput") << "readAndConstructPrincipal: "
431  "making flush RunPrincipal ...\n";
432 #endif
433  outR = pm_.makeRunPrincipal(RunID::flushRun(), subrun_aux->beginTime());
434 
435  // 28-Feb-2014, KAB: added the setting of the end time in the *current*
436  // run and subrun. This is how we set the endTime in the RunPrincipal
437  // and SubRunPrincipal objects that are written to the disk file.
438  // This needs to happen here because:
439  // A) setting them in every event doesn't work because the RunPrincipal
440  // only allows us to set an end time value once
441  // B) setting them in the "outputFileCloseNeeded_" block in the readNext()
442  // method below doesn't work because that is too late. When this
443  // method returns an outR with a different run number (flushRun),
444  // the art output system closes the current file then.
445  // C) setting them in the EndRun message block immediately above this
446  // block wouldn't work because a) we're not currently sending endRun
447  // events from the EBs to the AG, and b) because presumably that would
448  // be too late, also.
449 
450  art::Timestamp currentTime = time(0);
451  if (inR != nullptr) { inR->setEndTime(currentTime); }
452  if (inSR != nullptr) { inSR->setEndTime(currentTime); }
453 
454 #ifdef LOGDEBUG
455  TLOG_DEBUG("ArtdaqInput") << "readAndConstructPrincipal: "
456  "making flush SubRunPrincipal ...\n";
457 #endif
458  outSR = pm_.makeSubRunPrincipal(SubRunID::flushSubRun(),
459  subrun_aux->beginTime());
460 
461 #ifdef LOGDEBUG
462  TLOG_DEBUG("ArtdaqInput") << "readAndConstructPrincipal: "
463  "making flush EventPrincipal ...\n";
464 #endif
465  outE = pm_.makeEventPrincipal(EventID::flushEvent(),
466  subrun_aux->endTime(), true,
467  EventAuxiliary::Any);
468 
469 #ifdef LOGDEBUG
470  TLOG_DEBUG("ArtdaqInput") << "readAndConstructPrincipal: "
471  "finished processing EndSubRun message.\n";
472 #endif
473  }
474  else if (msg_type_code == 4)
475  { // Event message.
476 
477 #ifdef LOGDEBUG
478  TLOG_DEBUG("ArtdaqInput") << "readAndConstructPrincipal: "
479  "processing Event message ...\n";
480 #endif
481 
482  run_aux.reset(ReadObjectAny<art::RunAuxiliary>(msg, "art::RunAuxiliary",
483  "ArtdaqInput::readAndConstructPrincipal"));
484  printProcessHistoryID("readAndConstructPrincipal", run_aux.get());
485 
486  subrun_aux.reset(ReadObjectAny<art::SubRunAuxiliary>(msg, "art::SubRunAuxiliary",
487  "ArtdaqInput::readAndConstructPrincipal"));
488  printProcessHistoryID("readAndConstructPrincipal", subrun_aux.get());
489 
490  event_aux.reset(ReadObjectAny<art::EventAuxiliary>(msg, "art::EventAuxiliary",
491  "ArtdaqInput::readAndConstructPrincipal"));
492 
493  history.reset(ReadObjectAny<art::History>(msg, "art::History",
494  "ArtdaqInput::readAndConstructPrincipal"));
495  printProcessHistoryID("readAndConstructPrincipal", history.get());
496 
497  // Can probably improve on error choice of "art::errors:Unknown"
498  if (!history->processHistoryID().isValid())
499  {
500  throw art::Exception(art::errors::Unknown) <<
501  "readAndConstructPrincipal: processHistoryID of history in "
502  "Event message is invalid!";
503  }
504 
505  if ((inR == nullptr) || !inR->id().isValid() ||
506  (inR->run() != event_aux->run()))
507  {
508  // New run, either we have no input RunPrincipal, or the
509  // input run number does not match the event run number.
510 #ifdef LOGDEBUG
511  TLOG_DEBUG("ArtdaqInput") << "readAndConstructPrincipal: making RunPrincipal ...\n";
512 #endif
513  outR = pm_.makeRunPrincipal(*run_aux.get());
514  }
515  if ((inSR == nullptr) || !inSR->id().isValid() ||
516  (inSR->subRun() != event_aux->subRun()))
517  {
518  // New SubRun, either we have no input SubRunPrincipal, or the
519  // input subRun number does not match the event subRun number.
520 #ifdef LOGDEBUG
521  TLOG_DEBUG("ArtdaqInput") << "readAndConstructPrincipal: "
522  "making SubRunPrincipal ...\n";
523 #endif
524  outSR = pm_.makeSubRunPrincipal(*subrun_aux.get());
525  }
526 #ifdef LOGDEBUG
527  TLOG_DEBUG("ArtdaqInput") << "readAndConstructPrincipal: making EventPrincipal ...\n";
528 #endif
529  outE = pm_.makeEventPrincipal(*event_aux.get(), std::move(history));
530 
531 #ifdef LOGDEBUG
532  TLOG_DEBUG("ArtdaqInput") << "readAndConstructPrincipal: "
533  "finished processing Event message.\n";
534 #endif
535  }
536 }
537 
538 template <typename U>
539 template <class T>
540 void
542 readDataProducts(std::unique_ptr<TBufferFile>& msg, T*& outPrincipal)
543 {
544  unsigned long prd_cnt = 0;
545  {
546 #ifdef LOGDEBUG
547  TLOG_DEBUG("ArtdaqInput") << "readDataProducts: reading data product count ...\n";
548 #endif
549  msg->ReadULong(prd_cnt);
550 #ifdef LOGDEBUG
551  TLOG_DEBUG("ArtdaqInput") << "readDataProducts: product count: " << prd_cnt << '\n';
552 #endif
553  }
554  //
555  // Read the data products.
556  //
557  const ProductList& productList = ProductMetaData::instance().productList();
558 
559  for (unsigned long I = 0; I < prd_cnt; ++I)
560  {
561  std::unique_ptr<BranchKey> bk;
562 
563  {
564 #ifdef LOGDEBUG
565  TLOG_DEBUG("ArtdaqInput") << "readDataProducts: Reading branch key.\n";
566 #endif
567  bk.reset(ReadObjectAny<BranchKey>(msg, "art::BranchKey",
568  "ArtdaqInput::readDataProducts"));
569  }
570 
571  if (art::debugit() >= 1)
572  {
573 #ifdef LOGDEBUG
574  TLOG_DEBUG("ArtdaqInput") << "readDataProducts: got product class: '"
575  << bk->friendlyClassName_
576  << "' modlbl: '"
577  << bk->moduleLabel_
578  << "' instnm: '"
579  << bk->productInstanceName_
580  << "' procnm: '"
581  << bk->processName_
582  << "'\n";
583 #endif
584  }
585  ProductList::const_iterator iter;
586  {
587 #ifdef LOGDEBUG
588  TLOG_DEBUG("ArtdaqInput") << "readDataProducts: looking up product ...\n";
589 #endif
590  iter = productList.find(*bk);
591  if (iter == productList.end())
592  {
593  throw art::Exception(art::errors::ProductNotFound)
594  << "No product is registered for\n"
595  << " process name: '"
596  << bk->processName_ << "'\n"
597  << " module label: '"
598  << bk->moduleLabel_ << "'\n"
599  << " product friendly class name: '"
600  << bk->friendlyClassName_ << "'\n"
601  << " product instance name: '"
602  << bk->productInstanceName_ << "'\n";
603  }
604  }
605  // Note: This must be a reference to the unique copy in
606  // the master product registry!
607  const BranchDescription& bd = iter->second;
608  std::unique_ptr<EDProduct> prd;
609  {
610 #ifdef LOGDEBUG
611  TLOG_DEBUG("ArtdaqInput") << "readDataProducts: Reading product.\n";
612 #endif
613 
614  // JCF, May-25-2016
615  // Currently unclear why the templatized version of ReadObjectAny doesn't work here...
616 
617  // prd.reset(ReadObjectAny<EDProduct>(msg, bd.wrappedName()));
618 
619  void* p = msg->ReadObjectAny(TClass::GetClass(bd.wrappedName().c_str()));
620 
621  prd.reset(reinterpret_cast<EDProduct*>(p));
622  p = nullptr;
623  }
624  std::unique_ptr<const ProductProvenance> prdprov;
625  {
626 #ifdef LOGDEBUG
627  TLOG_DEBUG("ArtdaqInput") << "readDataProducts: Reading product provenance.\n";
628 #endif
629  prdprov.reset(ReadObjectAny<ProductProvenance>(msg,
630  "art::ProductProvenance",
631  "ArtdaqInput::readDataProducts"));
632  }
633  {
634 #ifdef LOGDEBUG
635  TLOG_DEBUG("ArtdaqInput") << "readDataProducts: inserting product: class: '"
636  << bd.friendlyClassName()
637  << "' modlbl: '"
638  << bd.moduleLabel()
639  << "' instnm: '"
640  << bd.productInstanceName()
641  << "' procnm: '"
642  << bd.processName()
643  << "'\n";
644 #endif
645  putInPrincipal(outPrincipal, std::move(prd), bd, std::move(prdprov));
646  }
647  }
648 }
649 
650 template <typename U>
651 void
653 putInPrincipal(RunPrincipal*& rp, std::unique_ptr<EDProduct>&& prd, const BranchDescription& bd, std::unique_ptr<const ProductProvenance>&& prdprov)
654 {
655  rp->put(std::move(prd), bd, std::move(prdprov), RangeSet::forRun(rp->id()));
656 }
657 
658 template <typename U>
659 void
661 putInPrincipal(SubRunPrincipal*& srp, std::unique_ptr<EDProduct>&& prd, const BranchDescription& bd, std::unique_ptr<const ProductProvenance>&& prdprov)
662 {
663  srp->put(std::move(prd), bd, std::move(prdprov), RangeSet::forSubRun(srp->id()));
664 }
665 
666 template <typename U>
667 void
669 putInPrincipal(EventPrincipal*& ep, std::unique_ptr<EDProduct>&& prd, const BranchDescription& bd, std::unique_ptr<const ProductProvenance>&& prdprov)
670 {
671  ep->put(std::move(prd), bd, std::move(prdprov));
672 }
673 
674 
675 template <typename U>
676 bool
678 readNext(art::RunPrincipal* const inR, art::SubRunPrincipal* const inSR,
679  art::RunPrincipal*& outR, art::SubRunPrincipal*& outSR,
680  art::EventPrincipal*& outE)
681 {
682 #ifdef LOGDEBUG
683  TLOG_DEBUG("ArtdaqInput") << "Begin: ArtdaqInput::readNext\n";
684 #endif
685  if (outputFileCloseNeeded_)
686  {
687  outputFileCloseNeeded_ = false;
688  // Signal that we need the output file closed by returning false,
689  // but answering true to the hasMoreData() query.
690 #ifdef LOGDEBUG
691  TLOG_DEBUG("ArtdaqInput") << "ArtdaqInput::readNext: "
692  "returning false on outputFileCloseNeeded_\n";
693  TLOG_DEBUG("ArtdaqInput") << "End: ArtdaqInput::readNext\n";
694 #endif
695  return false;
696  }
697 
698  std::unique_ptr<TBufferFile> msg;
699  communicationWrapper_.receiveMessage(msg);
700 
701  if (!msg)
702  {
703  shutdownMsgReceived_ = true;
704  return false;
705  }
706 
707  //
708  // Read message type code.
709  //
710  unsigned long msg_type_code = 0;
711  {
712 #ifdef LOGDEBUG
713  TLOG_DEBUG("ArtdaqInput") << "ArtdaqInput::readNext: "
714  "getting message type code ...\n";
715 #endif
716  msg->ReadULong(msg_type_code);
717 #ifdef LOGDEBUG
718  TLOG_DEBUG("ArtdaqInput") << "ArtdaqInput::readNext: "
719  "message type: " << msg_type_code << '\n';
720 #endif
721  }
722  if (msg_type_code == 5)
723  {
724  // Shutdown message.
725  shutdownMsgReceived_ = true;
726 #ifdef LOGDEBUG
727  TLOG_DEBUG("ArtdaqInput") << "ArtdaqInput::readNext: "
728  "returning false on Shutdown message.\n";
729  TLOG_DEBUG("ArtdaqInput") << "End: ArtdaqInput::readNext\n";
730 #endif
731  return false;
732  }
733 
734  readAndConstructPrincipal(msg, msg_type_code, inR, inSR, outR,
735  outSR, outE);
736  //
737  // Read per-event metadata needed to construct principal.
738  //
739  if (msg_type_code == 2)
740  {
741  // EndRun message.
742  // FIXME: We need to merge these into the input RunPrincipal.
743  readDataProducts(msg, outR);
744  // Signal that we should close the input and output file.
745 #ifdef LOGDEBUG
746  TLOG_DEBUG("ArtdaqInput") << "ArtdaqInput::readNext: "
747  "returning false on EndRun message.\n";
748  TLOG_DEBUG("ArtdaqInput") << "End: ArtdaqInput::readNext\n";
749 #endif
750  return false;
751  }
752  else if (msg_type_code == 3)
753  {
754  // EndSubRun message.
755  // From the code above, EndRun and EndSubRun messages cause
756  // the construction of principals that have:
757  // Run:Subrun:Event=flush:flush:flush.
758  // This is a problem when you have two neighboring EndSubRuns
759  // which are both associated with empty subruns because art will
760  // complain that you a new subrun with a subrun number identical
761  // to that of the previous subrun. So the solution is to not
762  // return new principals.
763  if (inR != 0 && inSR != 0 && outR != 0 && outSR != 0)
764  {
765  if (inR->id().isFlush() && inSR->id().isFlush() &&
766  outR->id().isFlush() && outSR->id().isFlush())
767  {
768  outR = 0;
769  outSR = 0;
770  outputFileCloseNeeded_ = true;
771  return true;
772  }
773  }
774  // FIXME: We need to merge these into the input SubRunPrincipal.
775  readDataProducts(msg, outSR);
776  // Remember that we should ask for file close next time
777  // we are called.
778  outputFileCloseNeeded_ = true;
779 #ifdef LOGDEBUG
780  TLOG_DEBUG("ArtdaqInput") << "readNext: returning true on EndSubRun message.\n";
781  TLOG_DEBUG("ArtdaqInput") << "End: ArtdaqInput::readNext\n";
782 #endif
783  return true;
784  }
785  else if (msg_type_code == 4)
786  {
787  // Event message.
788  readDataProducts(msg, outE);
789 #ifdef LOGDEBUG
790  TLOG_DEBUG("ArtdaqInput") << "readNext: returning true on Event message.\n";
791  TLOG_DEBUG("ArtdaqInput") << "End: ArtdaqInput::readNext\n";
792 #endif
793  return true;
794  }
795  // Unknown message.
796  // FIXME: What do we throw here for invalid message code?
797 #ifdef LOGDEBUG
798  TLOG_DEBUG("ArtdaqInput") << "readNext: returning false on unknown msg_type_code!\n";
799  TLOG_DEBUG("ArtdaqInput") << "End: ArtdaqInput::readNext\n";
800 #endif
801  return false;
802 }
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:321
~ArtdaqInput()
ArtdaqInput Destructor.
Definition: ArtdaqInput.hh:306
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:338
void closeCurrentFile()
Called by art to close the input source. No-Op.
Definition: ArtdaqInput.hh:311
This template class provides a unified interface for reading data into art.
Definition: ArtdaqInput.hh:64
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:678