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