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