LArSoft  v07_13_02
Liquid Argon Software toolkit - http://larsoft.org/
RootInputFile.cc
Go to the documentation of this file.
2 // vim: set sw=2:
3 
35 #include "canvas_root_io/Streamers/ProductIDStreamer.h"
36 #include "canvas_root_io/Utilities/DictionaryChecker.h"
37 #include "cetlib/compiler_macros.h"
38 #include "cetlib/container_algorithms.h"
39 #include "fhiclcpp/ParameterSet.h"
44 
45 #include "Rtypes.h"
46 #include "TClass.h"
47 #include "TFile.h"
48 #include "TTree.h"
49 
50 #include <algorithm>
51 #include <utility>
52 
53 extern "C" {
54 #include "sqlite3.h"
55 }
56 
57 #include <iostream>
58 #include <string>
59 #include <tuple>
60 
61 using namespace cet;
62 using namespace std;
63 
64 namespace {
65 
66  bool
67  have_table(sqlite3* db, std::string const& table, std::string const& filename)
68  {
69  bool result = false;
70  sqlite3_stmt* stmt = nullptr;
71  std::string const ddl{
72  "select 1 from sqlite_master where type='table' and name='" + table +
73  "';"};
74  auto rc = sqlite3_prepare_v2(db, ddl.c_str(), -1, &stmt, nullptr);
75  if (rc == SQLITE_OK) {
76  switch (rc = sqlite3_step(stmt)) {
77  case SQLITE_ROW:
78  result = true; // Found the table.
79  FALLTHROUGH;
80  case SQLITE_DONE:
81  rc = SQLITE_OK; // No such table.
82  break;
83  default:
84  break;
85  }
86  }
87  rc = sqlite3_finalize(stmt);
88  if (rc != SQLITE_OK) {
90  << "Error interrogating SQLite3 DB in file " << filename << ".\n";
91  }
92  return result;
93  }
94 }
95 
96 namespace art {
97 
98  RootInputFile::RootInputFile(string const& fileName,
99  string const& catalogName,
100  ProcessConfiguration const& processConfiguration,
101  string const& logicalFileName,
102  unique_ptr<TFile>&& filePtr,
103  EventID const& origEventID,
104  unsigned int eventsToSkip,
105  bool const compactSubRunRanges,
106  FastCloningInfoProvider const& fcip,
107  unsigned int treeCacheSize,
108  int64_t treeMaxVirtualSize,
109  int64_t saveMemoryObjectThreshold,
110  bool delayedReadEventProducts,
111  bool delayedReadSubRunProducts,
112  bool delayedReadRunProducts,
113  InputSource::ProcessingMode processingMode,
114  int forcedRunOffset,
115  bool noEventSort,
116  GroupSelectorRules const& groupSelectorRules,
117  shared_ptr<DuplicateChecker> duplicateChecker,
118  bool dropDescendants,
119  bool const readIncomingParameterSets,
120  exempt_ptr<RootInputFile> primaryFile,
121  vector<string> const& secondaryFileNames,
122  RootInputFileSequence* rifSequence,
123  MasterProductRegistry& mpr)
124  : fileName_{fileName}
125  , catalog_{catalogName}
126  , processConfiguration_{processConfiguration}
127  , logicalFileName_{logicalFileName}
128  , filePtr_{std::move(filePtr)}
129  , origEventID_{origEventID}
130  , eventsToSkip_{eventsToSkip}
131  , compactSubRunRanges_{compactSubRunRanges}
132  , treePointers_{{// Order (and number) must match BranchTypes.h!
133  std::make_unique<RootInputTree>(filePtr_.get(),
134  InEvent,
135  saveMemoryObjectThreshold,
136  this,
137  compactSubRunRanges_,
138  false),
139  std::make_unique<RootInputTree>(filePtr_.get(),
140  InSubRun,
141  saveMemoryObjectThreshold,
142  this,
143  compactSubRunRanges_,
144  false),
145  std::make_unique<RootInputTree>(filePtr_.get(),
146  InRun,
147  saveMemoryObjectThreshold,
148  this,
149  compactSubRunRanges_,
150  false),
151  std::make_unique<RootInputTree>(filePtr_.get(),
152  InResults,
153  saveMemoryObjectThreshold,
154  this,
155  compactSubRunRanges_,
156  true /* missingOK */)}}
157  , delayedReadEventProducts_{delayedReadEventProducts}
158  , delayedReadSubRunProducts_{delayedReadSubRunProducts}
159  , delayedReadRunProducts_{delayedReadRunProducts}
161  , forcedRunOffset_{forcedRunOffset}
162  , noEventSort_{noEventSort}
163  , duplicateChecker_{duplicateChecker}
164  , primaryFile_{primaryFile ? primaryFile : this}
165  , secondaryFileNames_{secondaryFileNames}
166  , rifSequence_{rifSequence}
167  {
168  secondaryFiles_.resize(secondaryFileNames_.size());
169  eventTree().setCacheSize(treeCacheSize);
170  eventTree().setTreeMaxVirtualSize(treeMaxVirtualSize);
171  subRunTree().setTreeMaxVirtualSize(treeMaxVirtualSize);
172  subRunTree().setCacheSize(treeCacheSize);
173  runTree().setTreeMaxVirtualSize(treeMaxVirtualSize);
174  runTree().setCacheSize(treeCacheSize);
175  if (resultsTree()) {
176  resultsTree().setTreeMaxVirtualSize(treeMaxVirtualSize);
177  resultsTree().setCacheSize(treeCacheSize);
178  }
179 
180  // Retrieve the metadata tree.
181  auto metaDataTree =
182  static_cast<TTree*>(filePtr_->Get(rootNames::metaDataTreeName().c_str()));
183  if (!metaDataTree) {
186  }
187  metaDataTree->SetCacheSize(static_cast<Long64_t>(treeCacheSize));
188 
189  using namespace art::rootNames;
190 
191  fileFormatVersion_ = detail::readMetadata<FileFormatVersion>(metaDataTree);
192 
193  // Read file index
194  auto findexPtr = &fileIndex_;
195  detail::readFileIndex(filePtr_.get(), metaDataTree, findexPtr);
196 
197  // To support files that contain BranchIDLists
198  BranchIDLists branchIDLists{};
199  if (detail::readMetadata(metaDataTree, branchIDLists)) {
200  branchIDLists_ =
201  std::make_unique<BranchIDLists>(std::move(branchIDLists));
202  configureProductIDStreamer(branchIDLists_.get());
203  }
204 
205  // Read the ParameterSets if there are any on a branch.
206  {
207  ParameterSetMap psetMap;
208  if (readIncomingParameterSets &&
209  detail::readMetadata(metaDataTree, psetMap)) {
210  // Merge into the hashed registries.
211  for (auto const& psEntry : psetMap) {
212  fhicl::ParameterSet pset;
213  fhicl::make_ParameterSet(psEntry.second.pset_, pset);
214  // Note ParameterSet::id() has the side effect of making
215  // sure the parameter set *has* an ID.
216  pset.id();
218  }
219  }
220  }
221 
222  // Read the ProcessHistory
223  {
224  auto pHistMap = detail::readMetadata<ProcessHistoryMap>(metaDataTree);
225  ProcessHistoryRegistry::put(pHistMap);
226  }
227 
228  // Check the, "Era" of the input file (new since art v0.5.0). If it
229  // does not match what we expect we cannot read the file. Required
230  // since we reset the file versioning since forking off from
231  // CMS. Files written by art prior to v0.5.0 will *also* not be
232  // readable because they do not have this datum and because the run,
233  // subrun and event-number handling has changed significantly.
234  string const& expected_era = art::getFileFormatEra();
235  if (fileFormatVersion_.era_ != expected_era) {
237  << "Can only read files written during the \"" << expected_era
238  << "\" era: "
239  << "Era of "
240  << "\"" << fileName_ << "\" was "
241  << (fileFormatVersion_.era_.empty() ?
242  "not set" :
243  ("set to \"" + fileFormatVersion_.era_ + "\" "))
244  << ".\n";
245  }
246 
247  // Also need to check RootFileDB if we have one.
248  if (fileFormatVersion_.value_ >= 5) {
249  sqliteDB_ = ServiceHandle<DatabaseConnection> {}
250  ->get<TKeyVFSOpenPolicy>("RootFileDB", filePtr_.get());
251  if (readIncomingParameterSets &&
252  have_table(sqliteDB_, "ParameterSets", fileName_)) {
254  }
255  if (art::ServiceRegistry::isAvailable<art::FileCatalogMetadata>() &&
256  have_table(sqliteDB_, "FileCatalog_metadata", fileName_)) {
257  sqlite3_stmt* stmt{nullptr};
258  sqlite3_prepare_v2(sqliteDB_,
259  "SELECT Name, Value from FileCatalog_metadata;",
260  -1,
261  &stmt,
262  nullptr);
263 
264  std::vector<std::pair<std::string, std::string>> md;
265  while (sqlite3_step(stmt) == SQLITE_ROW) {
266  std::string const name{
267  reinterpret_cast<char const*>(sqlite3_column_text(stmt, 0))};
268  std::string const value{
269  reinterpret_cast<char const*>(sqlite3_column_text(stmt, 1))};
270  md.emplace_back(name, value);
271  }
272  int const finalize_status = sqlite3_finalize(stmt);
273  if (finalize_status != SQLITE_OK) {
275  << "Unexpected status from DB status cleanup: "
276  << sqlite3_errmsg(sqliteDB_) << " (0x" << finalize_status << ").\n";
277  }
279  ->setMetadataFromInput(md);
280  }
281  }
282  validateFile();
283 
284  // Read the parentage tree. Old format files are handled
285  // internally in readParentageTree().
286  readParentageTree(treeCacheSize);
287  initializeDuplicateChecker();
288  if (noEventSort_) {
289  fileIndex_.sortBy_Run_SubRun_EventEntry();
290  }
291  fiIter_ = fileIndex_.begin();
292  fiBegin_ = fileIndex_.begin();
293  fiEnd_ = fileIndex_.end();
294  readEventHistoryTree(treeCacheSize);
295 
296  // Read the ProductList
297  productListHolder_ = detail::readMetadata<ProductRegistry>(metaDataTree);
298  auto& prodList = productListHolder_.productList_;
299  dropOnInput(groupSelectorRules, dropDescendants, prodList);
300 
301  auto availableProducts = fillPerBranchTypePresenceFlags(prodList);
302  // Add branches
303  for (auto& prod : prodList) {
304  auto& pd = prod.second;
305  auto const& presenceLookup = availableProducts[pd.branchType()];
306  bool const present{presenceLookup.find(pd.productID()) !=
307  cend(presenceLookup)};
308  auto const validity = present ?
311  pd.setValidity(validity);
312  treePointers_[pd.branchType()]->addBranch(prod.first, pd);
313  }
314 
315  mpr.updateFromInputFile(prodList);
316  auto const& descriptions = make_product_descriptions(prodList);
317  presentProducts_ = ProductTables{descriptions, availableProducts};
318 
319  // Determine if this file is fast clonable.
320  fastClonable_ = setIfFastClonable(fcip);
321  reportOpened();
322 
323  // Check if dictionaries exist for the auxiliary objects
324  root::DictionaryChecker checker{};
325  checker.checkDictionaries<EventAuxiliary>();
326  checker.checkDictionaries<SubRunAuxiliary>();
327  checker.checkDictionaries<RunAuxiliary>();
328  checker.checkDictionaries<ResultsAuxiliary>();
329  checker.reportMissingDictionaries();
330 
331  // FIXME: This probably is unnecessary!
332  configureProductIDStreamer();
333  }
334 
335  void
336  RootInputFile::readParentageTree(unsigned int const treeCacheSize)
337  {
338  //
339  // Auxiliary routine for the constructor.
340  //
341  auto parentageTree = static_cast<TTree*>(
342  filePtr_->Get(rootNames::parentageTreeName().c_str()));
343  if (!parentageTree) {
346  }
347  parentageTree->SetCacheSize(static_cast<Long64_t>(treeCacheSize));
348  auto idBuffer = root::getObjectRequireDict<ParentageID>();
349  auto pidBuffer = &idBuffer;
350  parentageTree->SetBranchAddress(rootNames::parentageIDBranchName().c_str(),
351  &pidBuffer);
352 
353  auto parentageBuffer = root::getObjectRequireDict<Parentage>();
354  auto pParentageBuffer = &parentageBuffer;
355  parentageTree->SetBranchAddress(rootNames::parentageBranchName().c_str(),
356  &pParentageBuffer);
357 
358  // Fill the registry
359  for (EntryNumber i = 0, numEntries = parentageTree->GetEntries();
360  i < numEntries;
361  ++i) {
362  input::getEntry(parentageTree, i);
363  if (idBuffer != parentageBuffer.id()) {
365  << "Corruption of Parentage tree detected.\n";
366  }
367  ParentageRegistry::emplace(parentageBuffer.id(), parentageBuffer);
368  }
369 
370  parentageTree->SetBranchAddress(rootNames::parentageIDBranchName().c_str(),
371  nullptr);
372  parentageTree->SetBranchAddress(rootNames::parentageBranchName().c_str(),
373  nullptr);
374  }
375 
376  EventID
378  {
379  if (fiIter_ == fiEnd_) {
380  return EventID{};
381  }
382  return fiIter_->eventID_;
383  }
384 
385  bool
387  {
388  if (!fcip.fastCloningPermitted()) {
389  return false;
390  }
391  if (secondaryFileNames_.size() != 0) {
392  return false;
393  }
394  if (!fileIndex_.allEventsInEntryOrder()) {
395  return false;
396  }
397  if (eventsToSkip_ != 0) {
398  return false;
399  }
400  if ((fcip.remainingEvents() >= 0) &&
401  (eventTree().entries() > fcip.remainingEvents())) {
402  return false;
403  }
404  if ((fcip.remainingSubRuns() >= 0) &&
405  (subRunTree().entries() > fcip.remainingSubRuns())) {
406  return false;
407  }
409  return false;
410  }
411  if (forcedRunOffset_ != 0) {
412  return false;
413  }
414  // Find entry for first event in file.
415  auto it = fiBegin_;
416  while ((it != fiEnd_) && (it->getEntryType() != FileIndex::kEvent)) {
417  ++it;
418  }
419  if (it == fiEnd_) {
420  return false;
421  }
422  if (it->eventID_ < origEventID_) {
423  return false;
424  }
425  return true;
426  }
427 
428  int
430  {
431  if (fiBegin_ == fiEnd_) {
432  return 0;
433  }
434  forcedRunOffset_ = 0;
435  if (!RunID(forcedRunNumber).isValid()) {
436  return 0;
437  }
438  forcedRunOffset_ = forcedRunNumber - fiBegin_->eventID_.run();
439  if (forcedRunOffset_ != 0) {
440  fastClonable_ = false;
441  }
442  return forcedRunOffset_;
443  }
444 
445  std::unique_ptr<FileBlock>
447  {
448  return std::make_unique<RootFileBlock>(
449  fileFormatVersion_,
450  fileName_,
451  readResults(),
452  cet::make_exempt_ptr(eventTree().tree()),
453  fastClonable());
454  }
455 
458  {
459  if (fiIter_ == fiEnd_) {
460  return FileIndex::kEnd;
461  }
462  return fiIter_->getEntryType();
463  }
464 
467  {
468  auto entryType = getEntryType();
469  if (entryType == FileIndex::kEnd) {
470  return FileIndex::kEnd;
471  }
472  RunID currentRun(fiIter_->eventID_.runID());
473  if (!currentRun.isValid()) {
474  return FileIndex::kEnd;
475  }
476  if (entryType == FileIndex::kRun) {
477  // Skip any runs before the first run specified
478  if (currentRun < origEventID_.runID()) {
479  fiIter_ = fileIndex_.findPosition(origEventID_.runID(), false);
480  return getNextEntryTypeWanted();
481  }
482  return FileIndex::kRun;
483  }
485  fiIter_ = fileIndex_.findPosition(
486  currentRun.isValid() ? currentRun.next() : currentRun, false);
487  return getNextEntryTypeWanted();
488  }
489  SubRunID const& currentSubRun = fiIter_->eventID_.subRunID();
490  if (entryType == FileIndex::kSubRun) {
491  // Skip any subRuns before the first subRun specified
492  if ((currentRun == origEventID_.runID()) &&
493  (currentSubRun < origEventID_.subRunID())) {
494  fiIter_ = fileIndex_.findSubRunOrRunPosition(origEventID_.subRunID());
495  return getNextEntryTypeWanted();
496  }
497  return FileIndex::kSubRun;
498  }
500  fiIter_ = fileIndex_.findSubRunOrRunPosition(currentSubRun.next());
501  return getNextEntryTypeWanted();
502  }
503  assert(entryType == FileIndex::kEvent);
504  // Skip any events before the first event specified
505  if (fiIter_->eventID_ < origEventID_) {
506  fiIter_ = fileIndex_.findPosition(origEventID_);
507  return getNextEntryTypeWanted();
508  }
509  if (duplicateChecker_.get() && duplicateChecker_->isDuplicateAndCheckActive(
510  fiIter_->eventID_, fileName_)) {
511  nextEntry();
512  return getNextEntryTypeWanted();
513  }
514  if (eventsToSkip_ == 0) {
515  return FileIndex::kEvent;
516  }
517  // We have specified a count of events to skip, keep skipping
518  // events in this subRun block until we reach the end of the
519  // subRun block or the full count of the number of events to skip.
520  while ((eventsToSkip_ != 0) && (fiIter_ != fiEnd_) &&
521  (getEntryType() == FileIndex::kEvent)) {
522  nextEntry();
523  --eventsToSkip_;
524  while ((eventsToSkip_ != 0) && (fiIter_ != fiEnd_) &&
525  (fiIter_->getEntryType() == FileIndex::kEvent) &&
526  duplicateChecker_.get() &&
527  duplicateChecker_->isDuplicateAndCheckActive(fiIter_->eventID_,
528  fileName_)) {
529  nextEntry();
530  }
531  }
532  return getNextEntryTypeWanted();
533  }
534 
535  void
537  {
538  if (!fileFormatVersion_.isValid()) {
539  fileFormatVersion_.value_ = 0;
540  }
541  if (!eventTree().isValid()) {
543  << "'Events' tree is corrupted or not present\n"
544  << "in the input file.\n";
545  }
546  if (fileIndex_.empty()) {
548  << "FileIndex information is missing for the input file.\n";
549  }
550  }
551 
552  void
554  {}
555 
556  void
557  RootInputFile::close(bool reallyClose)
558  {
559  if (!reallyClose) {
560  return;
561  }
562  filePtr_->Close();
563  for (auto const& sf : secondaryFiles_) {
564  if (!sf) {
565  continue;
566  }
567  sf->filePtr_->Close();
568  }
569  }
570 
571  void
573  {
574  // We could consider doing delayed reading, but because we have to
575  // store this History object in a different tree than the event
576  // data tree, this is too hard to do in this first version.
577  auto pHistory = history_.get();
578  auto eventHistoryBranch =
579  eventHistoryTree_->GetBranch(rootNames::eventHistoryBranchName().c_str());
580  if (!eventHistoryBranch) {
582  << "Failed to find history branch in event history tree.\n";
583  }
584  eventHistoryBranch->SetAddress(&pHistory);
585  input::getEntry(eventHistoryTree_, eventTree().entryNumber());
586  }
587 
588  int
590  {
591  while ((offset > 0) && (fiIter_ != fiEnd_)) {
592  if (fiIter_->getEntryType() == FileIndex::kEvent) {
593  --offset;
594  }
595  nextEntry();
596  }
597  while ((offset < 0) && (fiIter_ != fiBegin_)) {
598  previousEntry();
599  if (fiIter_->getEntryType() == FileIndex::kEvent) {
600  ++offset;
601  }
602  }
603  while ((fiIter_ != fiEnd_) &&
604  (fiIter_->getEntryType() != FileIndex::kEvent)) {
605  nextEntry();
606  }
607  return offset;
608  }
609 
610  // readEvent() is responsible for creating, and setting up, the
611  // EventPrincipal.
612  //
613  // 1. create an EventPrincipal with a unique EventID
614  // 2. For each entry in the provenance, put in one Group,
615  // holding the Provenance for the corresponding EDProduct.
616  // 3. set up the caches in the EventPrincipal to know about this
617  // Group.
618  //
619  // We do *not* create the EDProduct instance (the equivalent of
620  // reading the branch containing this EDProduct). That will be done
621  // by the Delayed Reader, when it is asked to do so.
622  //
623  unique_ptr<EventPrincipal>
625  {
626  assert(fiIter_ != fiEnd_);
627  assert(fiIter_->getEntryType() == FileIndex::kEvent);
628  assert(fiIter_->eventID_.runID().isValid());
629 
630  auto const& entryNumbers = getEntryNumbers(InEvent);
631  if (!eventTree().current(entryNumbers.first)) {
632  // The supplied entry numbers are not valid.
633  return nullptr;
634  }
635 
636  auto ep = readCurrentEvent(entryNumbers);
637  assert(ep);
638  assert(eventAux().run() == fiIter_->eventID_.run() + forcedRunOffset_);
639  assert(eventAux().subRunID() == fiIter_->eventID_.subRunID());
640  nextEntry();
641  return ep;
642  }
643 
644  // Reads event at the current entry in the tree.
645  // Note: This function neither uses nor sets fiIter_.
646  unique_ptr<EventPrincipal>
648  std::pair<EntryNumbers, bool> const& entryNumbers)
649  {
650  assert(entryNumbers.first.size() == 1ull);
651  fillAuxiliary<InEvent>(entryNumbers.first.front());
652  assert(eventAux().id() == fiIter_->eventID_);
653  fillHistory();
654  overrideRunNumber(const_cast<EventID&>(eventAux().id()),
655  eventAux().isRealData());
656  auto ep = std::make_unique<EventPrincipal>(
657  eventAux(),
658  processConfiguration_,
659  &presentProducts_.get(InEvent),
660  history_,
661  eventTree().makeBranchMapper(),
662  eventTree().makeDelayedReader(
663  fileFormatVersion_,
664  branchIDLists_.get(), // Only for backwards compatibility
665  InEvent,
666  entryNumbers.first,
667  eventAux().id()),
668  entryNumbers.second);
669  eventTree().fillGroups(*ep);
670  if (!delayedReadEventProducts_) {
671  ep->readImmediate();
672  }
673  primaryEP_ = make_exempt_ptr(ep.get());
674  return ep;
675  }
676 
677  bool
679  {
680  // Used just after opening a new secondary file in response to a failed
681  // product lookup. Synchronize the file index to the event needed and
682  // create a secondary EventPrincipal for it.
683  if (!setEntry<InEvent>(eID, /*exact=*/true)) {
684  // Error, could not find specified event in file.
685  return false;
686  }
687  auto const& entryNumbers = getEntryNumbers(InEvent);
688  assert(entryNumbers.first.size() == 1ull);
689  fillAuxiliary<InEvent>(entryNumbers.first.front());
690  fillHistory();
691  overrideRunNumber(const_cast<EventID&>(eventAux().id()),
692  eventAux().isRealData());
693  auto ep = std::make_unique<EventPrincipal>(
694  eventAux(),
695  processConfiguration_,
696  &presentProducts_.get(InEvent),
697  history_,
698  eventTree().makeBranchMapper(),
699  eventTree().makeDelayedReader(
700  fileFormatVersion_,
701  branchIDLists_.get(), // Only for backwards compatibility
702  InEvent,
703  entryNumbers.first,
704  eventAux().id()),
705  entryNumbers.second);
706  eventTree().fillGroups(*ep);
707  primaryFile_->primaryEP_->addSecondaryPrincipal(move(ep));
708  return true;
709  }
710 
711  unique_ptr<RangeSetHandler>
713  {
714  return std::move(runRangeSetHandler_);
715  }
716 
717  unique_ptr<RunPrincipal>
719  {
720  assert(fiIter_ != fiEnd_);
721  assert(fiIter_->getEntryType() == FileIndex::kRun);
722  assert(fiIter_->eventID_.runID().isValid());
723 
724  auto const& entryNumbers = getEntryNumbers(InRun).first;
725  if (!runTree().current(entryNumbers)) {
726  // The supplied entry numbers are not valid.
727  return nullptr;
728  }
729 
730  auto rp = readCurrentRun(entryNumbers);
731  advanceEntry(entryNumbers.size());
732  return rp;
733  }
734 
735  unique_ptr<RunPrincipal>
737  {
738  runRangeSetHandler_ = fillAuxiliary<InRun>(entryNumbers);
739  assert(runAux().id() == fiIter_->eventID_.runID());
740  overrideRunNumber(runAux().id_);
741  if (runAux().beginTime() == Timestamp::invalidTimestamp()) {
742  // RunAuxiliary did not contain a valid timestamp.
743  // Take it from the next event.
744  if (eventTree().next()) {
745  fillAuxiliary<InEvent>(eventTree().entryNumber());
746  // back up, so event will not be skipped.
747  eventTree().previous();
748  }
749  runAux().beginTime_ = eventAux().time();
750  runAux().endTime_ = Timestamp::invalidTimestamp();
751  }
752  auto rp = std::make_unique<RunPrincipal>(
753  runAux(),
754  processConfiguration_,
755  &presentProducts_.get(InRun),
756  runTree().makeBranchMapper(),
757  runTree().makeDelayedReader(fileFormatVersion_,
758  sqliteDB_,
759  nullptr,
760  InRun,
761  entryNumbers,
762  fiIter_->eventID_));
763  runTree().fillGroups(*rp);
764  if (!delayedReadRunProducts_) {
765  rp->readImmediate();
766  }
767  primaryRP_ = make_exempt_ptr(rp.get());
768  return rp;
769  }
770 
771  bool
773  {
774  // Used just after opening a new secondary file in response to a failed
775  // product lookup. Synchronize the file index to the run needed and
776  // create a secondary RunPrincipal for it.
777  if (!setEntry<InRun>(rID)) {
778  // Error, could not find specified run in file.
779  return false;
780  }
781  auto const& entryNumbers = getEntryNumbers(InRun).first;
782  assert(fiIter_ != fiEnd_);
783  assert(fiIter_->getEntryType() == FileIndex::kRun);
784  assert(fiIter_->eventID_.runID().isValid());
785  runRangeSetHandler_ = fillAuxiliary<InRun>(entryNumbers);
786  assert(runAux().id() == fiIter_->eventID_.runID());
787  overrideRunNumber(runAux().id_);
788  if (runAux().beginTime() == Timestamp::invalidTimestamp()) {
789  // RunAuxiliary did not contain a valid timestamp.
790  // Take it from the next event.
791  if (eventTree().next()) {
792  fillAuxiliary<InEvent>(eventTree().entryNumber());
793  // back up, so event will not be skipped.
794  eventTree().previous();
795  }
796  runAux().beginTime_ = eventAux().time();
797  runAux().endTime_ = Timestamp::invalidTimestamp();
798  }
799  auto rp = std::make_unique<RunPrincipal>(
800  runAux(),
801  processConfiguration_,
802  &presentProducts_.get(InRun),
803  runTree().makeBranchMapper(),
804  runTree().makeDelayedReader(fileFormatVersion_,
805  sqliteDB_,
806  nullptr,
807  InRun,
808  entryNumbers,
809  fiIter_->eventID_));
810  runTree().fillGroups(*rp);
811  if (!delayedReadRunProducts_) {
812  rp->readImmediate();
813  }
814  primaryFile_->primaryRP_->addSecondaryPrincipal(move(rp));
815  return true;
816  }
817 
818  unique_ptr<RangeSetHandler>
820  {
821  return std::move(subRunRangeSetHandler_);
822  }
823 
824  unique_ptr<SubRunPrincipal>
825  RootInputFile::readSubRun(cet::exempt_ptr<RunPrincipal> rp)
826  {
827  assert(fiIter_ != fiEnd_);
828  assert(fiIter_->getEntryType() == FileIndex::kSubRun);
829 
830  auto const& entryNumbers = getEntryNumbers(InSubRun).first;
831  if (!subRunTree().current(entryNumbers)) {
832  // The supplied entry numbers are not valid.
833  return nullptr;
834  }
835 
836  auto srp = readCurrentSubRun(entryNumbers, rp);
837  advanceEntry(entryNumbers.size());
838  return srp;
839  }
840 
841  unique_ptr<SubRunPrincipal>
843  EntryNumbers const& entryNumbers,
844  cet::exempt_ptr<RunPrincipal> rp[[gnu::unused]])
845  {
846  subRunRangeSetHandler_ = fillAuxiliary<InSubRun>(entryNumbers);
847  assert(subRunAux().id() == fiIter_->eventID_.subRunID());
848  overrideRunNumber(subRunAux().id_);
849  assert(subRunAux().runID() == rp->id());
850  if (subRunAux().beginTime() == Timestamp::invalidTimestamp()) {
851  // SubRunAuxiliary did not contain a timestamp.
852  // Take it from the next event.
853  if (eventTree().next()) {
854  fillAuxiliary<InEvent>(eventTree().entryNumber());
855  // back up, so event will not be skipped.
856  eventTree().previous();
857  }
858  subRunAux().beginTime_ = eventAux().time();
859  subRunAux().endTime_ = Timestamp::invalidTimestamp();
860  }
861 
862  auto srp = std::make_unique<SubRunPrincipal>(
863  subRunAux(),
864  processConfiguration_,
865  &presentProducts_.get(InSubRun),
866  subRunTree().makeBranchMapper(),
867  subRunTree().makeDelayedReader(fileFormatVersion_,
868  sqliteDB_,
869  nullptr,
870  InSubRun,
871  entryNumbers,
872  fiIter_->eventID_));
873  subRunTree().fillGroups(*srp);
874  if (!delayedReadSubRunProducts_) {
875  srp->readImmediate();
876  }
877  primarySRP_ = make_exempt_ptr(srp.get());
878  return srp;
879  }
880 
881  bool
883  {
884  // Used just after opening a new secondary file in response to a failed
885  // product lookup. Synchronize the file index to the subRun needed and
886  // create a secondary SubRunPrincipal for it.
887  if (!setEntry<InSubRun>(srID)) {
888  // Error, could not find specified subRun in file.
889  return false;
890  }
891  auto const& entryNumbers = getEntryNumbers(InSubRun).first;
892  assert(fiIter_ != fiEnd_);
893  assert(fiIter_->getEntryType() == FileIndex::kSubRun);
894  subRunRangeSetHandler_ = fillAuxiliary<InSubRun>(entryNumbers);
895  assert(subRunAux().id() == fiIter_->eventID_.subRunID());
896  overrideRunNumber(subRunAux().id_);
897  if (subRunAux().beginTime() == Timestamp::invalidTimestamp()) {
898  // SubRunAuxiliary did not contain a timestamp.
899  // Take it from the next event.
900  if (eventTree().next()) {
901  fillAuxiliary<InEvent>(eventTree().entryNumber());
902  // back up, so event will not be skipped.
903  eventTree().previous();
904  }
905  subRunAux().beginTime_ = eventAux().time();
906  subRunAux().endTime_ = Timestamp::invalidTimestamp();
907  }
908  auto srp = std::make_unique<SubRunPrincipal>(
909  subRunAux(),
910  processConfiguration_,
911  &presentProducts_.get(InSubRun),
912  subRunTree().makeBranchMapper(),
913  subRunTree().makeDelayedReader(fileFormatVersion_,
914  sqliteDB_,
915  nullptr,
916  InSubRun,
917  entryNumbers,
918  fiIter_->eventID_));
919  subRunTree().fillGroups(*srp);
920  if (!delayedReadSubRunProducts_) {
921  srp->readImmediate();
922  }
923  primaryFile_->primarySRP_->addSecondaryPrincipal(move(srp));
924  return true;
925  }
926 
927  void
929  {
930  if (forcedRunOffset_ != 0) {
931  id = RunID(id.run() + forcedRunOffset_);
932  }
933  if (id < RunID::firstRun()) {
934  id = RunID::firstRun();
935  }
936  }
937 
938  void
940  {
941  if (forcedRunOffset_ != 0) {
942  id = SubRunID(id.run() + forcedRunOffset_, id.subRun());
943  }
944  }
945 
946  void
948  {
949  if (forcedRunOffset_ == 0) {
950  return;
951  }
952  if (isRealData) {
954  "RootInputFile::overrideRunNumber()"}
955  << "The 'setRunNumber' parameter of RootInput cannot "
956  << "be used with real data.\n";
957  }
958  id = EventID(id.run() + forcedRunOffset_, id.subRun(), id.event());
959  }
960 
961  void
962  RootInputFile::readEventHistoryTree(unsigned int treeCacheSize)
963  {
964  // Read in the event history tree, if we have one...
965  eventHistoryTree_ = static_cast<TTree*>(
966  filePtr_->Get(rootNames::eventHistoryTreeName().c_str()));
967  if (!eventHistoryTree_) {
969  << "Failed to find the event history tree.\n";
970  }
971  eventHistoryTree_->SetCacheSize(static_cast<Long64_t>(treeCacheSize));
972  }
973 
974  void
976  {
977  if (duplicateChecker_.get() == nullptr) {
978  return;
979  }
980  if (eventTree().next()) {
981  fillAuxiliary<InEvent>(eventTree().entryNumber());
982  duplicateChecker_->init(eventAux().isRealData(), fileIndex_);
983  }
984  eventTree().setEntryNumber(-1);
985  }
986 
987  std::pair<RootInputFile::EntryNumbers, bool>
989  {
990  EntryNumbers entries;
991  auto it = fiIter_;
992  if (it == fiEnd_)
993  return std::pair<EntryNumbers, bool>{entries, true};
994 
995  auto const eid = it->eventID_;
996  auto const subrun = eid.subRun();
997  for (; it != fiEnd_ && eid == it->eventID_; ++it) {
998  entries.push_back(it->entry_);
999  }
1000 
1001  if (t == InEvent && entries.size() > 1ul) {
1002  throw Exception{errors::FileReadError} << "File " << fileName_
1003  << " has multiple entries for\n"
1004  << eid << '\n';
1005  }
1006 
1007  bool const lastInSubRun{it == fiEnd_ || it->eventID_.subRun() != subrun};
1008  return std::pair<EntryNumbers, bool>{entries, lastInSubRun};
1009  }
1010 
1011  std::array<AvailableProducts_t, NumBranchTypes>
1013  {
1014  std::array<AvailableProducts_t, NumBranchTypes> result{{}};
1015  for (auto const& prodpr : prodList) {
1016  auto const& desc = prodpr.second;
1017  if (treePointers_[desc.branchType()]->hasBranch(desc.branchName())) {
1018  result[desc.branchType()].emplace(desc.productID());
1019  }
1020  }
1021  return result;
1022  }
1023 
1024  void
1026  bool const dropDescendants,
1027  ProductList& prodList)
1028  {
1029  // This is the selector for drop on input.
1030  GroupSelector const groupSelector{rules, prodList};
1031  // Do drop on input. On the first pass, just fill in a set of
1032  // branches to be dropped. Use the BranchChildren class to
1033  // assemble list of children to drop.
1034  BranchChildren children;
1035  set<ProductID> branchesToDrop;
1036  for (auto const& prod : prodList) {
1037  auto const& pd = prod.second;
1038  if (!groupSelector.selected(pd)) {
1039  if (dropDescendants) {
1040  children.appendToDescendants(pd.productID(), branchesToDrop);
1041  } else {
1042  branchesToDrop.insert(pd.productID());
1043  }
1044  }
1045  }
1046  // On this pass, actually drop the branches.
1047  auto branchesToDropEnd = branchesToDrop.cend();
1048  for (auto I = prodList.begin(), E = prodList.end(); I != E;) {
1049  auto const& pd = I->second;
1050  bool drop = branchesToDrop.find(pd.productID()) != branchesToDropEnd;
1051  if (!drop) {
1052  ++I;
1053  checkDictionaries(pd);
1054  continue;
1055  }
1056  if (groupSelector.selected(pd)) {
1057  mf::LogWarning("RootInputFile")
1058  << "Branch '" << pd.branchName()
1059  << "' is being dropped from the input\n"
1060  << "of file '" << fileName_
1061  << "' because it is dependent on a branch\n"
1062  << "that was explicitly dropped.\n";
1063  }
1064  treePointers_[pd.branchType()]->dropBranch(pd.branchName());
1065  auto icopy = I++;
1066  prodList.erase(icopy);
1067  }
1068  }
1069 
1070  void
1072  {
1073  secondaryFiles_[idx] =
1074  rifSequence_->openSecondaryFile(secondaryFileNames_[idx], this);
1075  }
1076 
1077  std::unique_ptr<art::ResultsPrincipal>
1079  {
1080  std::unique_ptr<art::ResultsPrincipal> resp;
1081  if (resultsTree()) {
1082  resultsTree().rewind();
1083  EntryNumbers const& entryNumbers{resultsTree().entryNumber()};
1084  assert(entryNumbers.size() == 1ull);
1085  fillAuxiliary<InResults>(entryNumbers.front());
1086  resp = std::make_unique<ResultsPrincipal>(
1087  resultsAux(),
1088  processConfiguration_,
1089  &presentProducts_.get(InResults),
1090  resultsTree().makeBranchMapper(),
1091  resultsTree().makeDelayedReader(
1092  fileFormatVersion_, nullptr, InResults, entryNumbers, EventID{}));
1093  resultsTree().fillGroups(*resp);
1094  } else { // Empty
1095  resp = std::make_unique<ResultsPrincipal>(
1096  ResultsAuxiliary{}, processConfiguration_, nullptr);
1097  }
1098  return resp;
1099  }
1100 
1101 } // namespace art
FileIndex::EntryType getNextEntryTypeWanted()
std::unique_ptr< RunPrincipal > readCurrentRun(EntryNumbers const &)
void appendToDescendants(ProductID parent, ProductIDSet &descendants) const
static ParameterSetID const & put(ParameterSet const &ps)
std::unique_ptr< SubRunPrincipal > readCurrentSubRun(EntryNumbers const &, cet::exempt_ptr< RunPrincipal >)
Float_t E
Definition: plot.C:23
RootInputTree::EntryNumbers EntryNumbers
Definition: RootInputFile.h:55
static void put(C const &container)
void readFileIndex(TFile *file, TTree *metaDataTree, FileIndex *&findexPtr)
Definition: readFileIndex.h:20
void readEventHistoryTree(unsigned int treeCacheSize)
std::string const & parentageTreeName()
Definition: rootNames.cc:22
void dropOnInput(GroupSelectorRules const &rules, bool dropDescendants, ProductList &branchDescriptions)
std::map< BranchKey, BranchDescription > ProductList
Definition: ProductList.h:15
std::string const & eventHistoryTreeName()
Definition: rootNames.cc:55
STL namespace.
void make_ParameterSet(intermediate_table const &tbl, ParameterSet &ps)
std::unique_ptr< RangeSetHandler > subRunRangeSetHandler()
void overrideRunNumber(RunID &id)
bool readSubRunForSecondaryFile(SubRunID)
void readParentageTree(unsigned int treeCacheSize)
std::unique_ptr< SubRunPrincipal > readSubRun(cet::exempt_ptr< RunPrincipal >)
std::pair< EntryNumbers, bool > getEntryNumbers(BranchType)
std::unique_ptr< FileBlock > createFileBlock()
EventID eventIDForFileIndexPosition() const
std::string couldNotFindTree(std::string const &treename)
Definition: rootErrMsgs.h:9
bool setIfFastClonable(FastCloningInfoProvider const &fcip) const
std::array< AvailableProducts_t, NumBranchTypes > fillPerBranchTypePresenceFlags(ProductList const &)
SubRunID next() const
Definition: SubRunID.h:110
std::string const & metaDataTreeName()
Definition: rootNames.cc:41
int setForcedRunOffset(RunNumber_t const &forcedRunNumber)
std::unique_ptr< EventPrincipal > readEvent()
void initializeDuplicateChecker()
InputFileCatalog catalog_
Definition: RootInput.h:107
std::string const & parentageBranchName()
Definition: rootNames.cc:34
std::unique_ptr< RangeSetHandler > runRangeSetHandler()
bool readEventForSecondaryFile(EventID eID)
auto const & processConfiguration() const
Definition: InputSource.h:64
std::string const & parentageIDBranchName()
Definition: rootNames.cc:28
int skipEvents(int offset)
ParameterSetID id() const
std::string const & getFileFormatEra()
std::unique_ptr< EventPrincipal > readCurrentEvent(std::pair< EntryNumbers, bool > const &)
bool readRunForSecondaryFile(RunID)
static constexpr Timestamp invalidTimestamp()
Definition: Timestamp.h:83
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
std::unique_ptr< ResultsPrincipal > readResults()
std::string const & eventHistoryBranchName()
Definition: rootNames.cc:62
FileIndex::EntryType getEntryType() const
std::string value(boost::any const &)
void checkDictionaries(BranchDescription const &productDesc)
RootInputTree::EntryNumber EntryNumber
Definition: RootInputFile.h:54
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
BranchType
Definition: BranchType.h:18
HLT enums.
Int_t getEntry(TBranch *branch, EntryNumber entryNumber)
Definition: getEntry.cc:12
ProcessingMode processingMode() const
RunsSubRunsAndEvents (default), RunsAndSubRuns, or Runs.
static RunID firstRun()
Definition: RunID.h:115
std::unique_ptr< RunPrincipal > readRun()
std::map< fhicl::ParameterSetID, ParameterSetBlob > ParameterSetMap
auto make_product_descriptions(ProductList const &productList)
Definition: ProductList.h:19
static auto emplace(value_type const &value)
ProductStatus present()
Definition: ProductStatus.h:16
T readMetadata(TTree *md, bool const requireDict=true)
Definition: readMetadata.h:13
void openSecondaryFile(int const idx)
Event finding and building.
void close(bool reallyClose)
IDNumber_t< Level::Run > RunNumber_t
Definition: IDNumber.h:119
static void importFrom(sqlite3 *db)