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