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