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