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