CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/IOPool/Input/src/RootFile.cc

Go to the documentation of this file.
00001 /*----------------------------------------------------------------------
00002 ----------------------------------------------------------------------*/
00003 
00004 #include "RootFile.h"
00005 #include "DuplicateChecker.h"
00006 #include "InputFile.h"
00007 #include "ProvenanceAdaptor.h"
00008 
00009 #include "DataFormats/Common/interface/WrapperOwningHolder.h"
00010 #include "DataFormats/Common/interface/RefCoreStreamer.h"
00011 #include "DataFormats/Provenance/interface/BranchDescription.h"
00012 #include "DataFormats/Provenance/interface/BranchIDListHelper.h"
00013 #include "DataFormats/Provenance/interface/BranchType.h"
00014 #include "DataFormats/Provenance/interface/EventEntryInfo.h"
00015 #include "DataFormats/Provenance/interface/FullHistoryToReducedHistoryMap.h"
00016 #include "DataFormats/Provenance/interface/ParameterSetBlob.h"
00017 #include "DataFormats/Provenance/interface/ParentageRegistry.h"
00018 #include "DataFormats/Provenance/interface/ProcessConfigurationRegistry.h"
00019 #include "DataFormats/Provenance/interface/ProcessHistoryID.h"
00020 #include "DataFormats/Provenance/interface/ProcessHistoryRegistry.h"
00021 #include "DataFormats/Provenance/interface/ProductRegistry.h"
00022 #include "DataFormats/Provenance/interface/StoredProductProvenance.h"
00023 #include "DataFormats/Provenance/interface/RunID.h"
00024 #include "FWCore/Framework/interface/FileBlock.h"
00025 #include "FWCore/Framework/interface/EventPrincipal.h"
00026 #include "FWCore/Framework/interface/ProductSelector.h"
00027 #include "FWCore/Framework/interface/LuminosityBlockPrincipal.h"
00028 #include "FWCore/Framework/interface/RunPrincipal.h"
00029 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00030 #include "FWCore/ParameterSet/interface/FillProductRegistryTransients.h"
00031 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00032 #include "FWCore/ParameterSet/interface/Registry.h"
00033 #include "FWCore/Sources/interface/EventSkipperByID.h"
00034 #include "FWCore/Sources/interface/DaqProvenanceHelper.h"
00035 #include "FWCore/Utilities/interface/Algorithms.h"
00036 #include "FWCore/Utilities/interface/do_nothing_deleter.h"
00037 #include "FWCore/Utilities/interface/EDMException.h"
00038 #include "FWCore/Utilities/interface/FriendlyName.h"
00039 #include "FWCore/Utilities/interface/GlobalIdentifier.h"
00040 #include "FWCore/Utilities/interface/ReleaseVersion.h"
00041 #include "FWCore/Version/interface/GetReleaseVersion.h"
00042 
00043 //used for backward compatibility
00044 #include "DataFormats/Provenance/interface/EntryDescriptionRegistry.h"
00045 #include "DataFormats/Provenance/interface/EventAux.h"
00046 #include "DataFormats/Provenance/interface/LuminosityBlockAux.h"
00047 #include "DataFormats/Provenance/interface/RunAux.h"
00048 #include "FWCore/ParameterSet/interface/ParameterSetConverter.h"
00049 
00050 #include "TROOT.h"
00051 #include "Rtypes.h"
00052 #include "TClass.h"
00053 #include "TString.h"
00054 #include "TTree.h"
00055 #include "TTreeCache.h"
00056 
00057 #include <algorithm>
00058 #include <list>
00059 
00060 namespace edm {
00061 
00062   // Algorithm classes for making ProvenanceReader:
00063   class MakeDummyProvenanceReader : public MakeProvenanceReader {
00064   public:
00065     virtual std::unique_ptr<ProvenanceReaderBase> makeReader(RootTree& eventTree, DaqProvenanceHelper const* daqProvenanceHelper) const;
00066   };
00067   class MakeOldProvenanceReader : public MakeProvenanceReader {
00068   public:
00069     virtual std::unique_ptr<ProvenanceReaderBase> makeReader(RootTree& eventTree, DaqProvenanceHelper const* daqProvenanceHelper) const;
00070   };
00071   class MakeFullProvenanceReader : public MakeProvenanceReader {
00072   public:
00073     virtual std::unique_ptr<ProvenanceReaderBase> makeReader(RootTree& eventTree, DaqProvenanceHelper const* daqProvenanceHelper) const;
00074   };
00075   class MakeReducedProvenanceReader : public MakeProvenanceReader {
00076   public:
00077     MakeReducedProvenanceReader(std::vector<ParentageID> const& parentageIDLookup) : parentageIDLookup_(parentageIDLookup) {}
00078     virtual std::unique_ptr<ProvenanceReaderBase> makeReader(RootTree& eventTree, DaqProvenanceHelper const* daqProvenanceHelper) const;
00079   private:
00080     std::vector<ParentageID> const& parentageIDLookup_;
00081   };
00082 
00083   namespace {
00084     int
00085     forcedRunOffset(RunNumber_t const& forcedRunNumber, IndexIntoFile::IndexIntoFileItr inxBegin, IndexIntoFile::IndexIntoFileItr inxEnd) {
00086       if(inxBegin == inxEnd) return 0;
00087       int defaultOffset = (inxBegin.run() != 0 ? 0 : 1);
00088       int offset = (forcedRunNumber != 0U ? forcedRunNumber - inxBegin.run() : defaultOffset);
00089       if(offset < 0) {
00090         throw Exception(errors::Configuration)
00091           << "The value of the 'setRunNumber' parameter must not be\n"
00092           << "less than the first run number in the first input file.\n"
00093           << "'setRunNumber' was " << forcedRunNumber <<", while the first run was "
00094           << forcedRunNumber - offset << ".\n";
00095       }
00096       return offset;
00097     }
00098   }
00099 
00100   // This is a helper class for IndexIntoFile.
00101   class RootFileEventFinder : public IndexIntoFile::EventFinder {
00102   public:
00103     explicit RootFileEventFinder(RootTree& eventTree) : eventTree_(eventTree) {}
00104     virtual ~RootFileEventFinder() {}
00105     virtual
00106     EventNumber_t getEventNumberOfEntry(roottree::EntryNumber entry) const {
00107       roottree::EntryNumber saveEntry = eventTree_.entryNumber();
00108       eventTree_.setEntryNumber(entry);
00109       EventAuxiliary eventAux;
00110       EventAuxiliary *pEvAux = &eventAux;
00111       eventTree_.fillAux<EventAuxiliary>(pEvAux);
00112       eventTree_.setEntryNumber(saveEntry);
00113       return eventAux.event();
00114     }
00115 
00116   private:
00117      RootTree& eventTree_;
00118   };
00119 
00120 //---------------------------------------------------------------------
00121   RootFile::RootFile(std::string const& fileName,
00122                      ProcessConfiguration const& processConfiguration,
00123                      std::string const& logicalFileName,
00124                      boost::shared_ptr<InputFile> filePtr,
00125                      boost::shared_ptr<EventSkipperByID> eventSkipperByID,
00126                      bool skipAnyEvents,
00127                      int remainingEvents,
00128                      int remainingLumis,
00129                      unsigned int treeCacheSize,
00130                      int treeMaxVirtualSize,
00131                      InputSource::ProcessingMode processingMode,
00132                      RunNumber_t const& forcedRunNumber,
00133                      bool noEventSort,
00134                      ProductSelectorRules const& productSelectorRules,
00135                      InputType::InputType inputType,
00136                      boost::shared_ptr<BranchIDListHelper> branchIDListHelper,
00137                      boost::shared_ptr<DuplicateChecker> duplicateChecker,
00138                      bool dropDescendants,
00139                      std::vector<boost::shared_ptr<IndexIntoFile> > const& indexesIntoFiles,
00140                      std::vector<boost::shared_ptr<IndexIntoFile> >::size_type currentIndexIntoFile,
00141                      std::vector<ProcessHistoryID>& orderedProcessHistoryIDs,
00142                      bool labelRawDataLikeMC,
00143                      bool usingGoToEvent,
00144                      bool enablePrefetching) :
00145       file_(fileName),
00146       logicalFile_(logicalFileName),
00147       processConfiguration_(processConfiguration),
00148       processConfigurations_(),
00149       filePtr_(filePtr),
00150       eventSkipperByID_(eventSkipperByID),
00151       fileFormatVersion_(),
00152       fid_(),
00153       indexIntoFileSharedPtr_(new IndexIntoFile),
00154       indexIntoFile_(*indexIntoFileSharedPtr_),
00155       orderedProcessHistoryIDs_(orderedProcessHistoryIDs),
00156       indexIntoFileBegin_(indexIntoFile_.begin(noEventSort ? IndexIntoFile::firstAppearanceOrder : IndexIntoFile::numericalOrder)),
00157       indexIntoFileEnd_(indexIntoFileBegin_),
00158       indexIntoFileIter_(indexIntoFileBegin_),
00159       eventProcessHistoryIDs_(),
00160       eventProcessHistoryIter_(eventProcessHistoryIDs_.begin()),
00161       savedRunAuxiliary_(),
00162       skipAnyEvents_(skipAnyEvents),
00163       noEventSort_(noEventSort),
00164       whyNotFastClonable_(0),
00165       hasNewlyDroppedBranch_(),
00166       branchListIndexesUnchanged_(false),
00167       eventAux_(),
00168       eventTree_(filePtr_, InEvent, treeMaxVirtualSize, treeCacheSize, roottree::defaultLearningEntries, enablePrefetching),
00169       lumiTree_(filePtr_, InLumi, treeMaxVirtualSize, roottree::defaultNonEventCacheSize, roottree::defaultNonEventLearningEntries, enablePrefetching),
00170       runTree_(filePtr_, InRun, treeMaxVirtualSize, roottree::defaultNonEventCacheSize, roottree::defaultNonEventLearningEntries, enablePrefetching),
00171       treePointers_(),
00172       lastEventEntryNumberRead_(-1LL),
00173       productRegistry_(),
00174       branchIDLists_(),
00175       branchIDListHelper_(branchIDListHelper),
00176       processingMode_(processingMode),
00177       forcedRunOffset_(0),
00178       newBranchToOldBranch_(),
00179       eventHistoryTree_(nullptr),
00180       eventSelectionIDs_(new EventSelectionIDVector),
00181       branchListIndexes_(new BranchListIndexes),
00182       history_(),
00183       branchChildren_(new BranchChildren),
00184       duplicateChecker_(duplicateChecker),
00185       provenanceAdaptor_(),
00186       provenanceReaderMaker_(),
00187       eventBranchMapper_(),
00188       parentageIDLookup_(),
00189       daqProvenanceHelper_() {
00190 
00191     hasNewlyDroppedBranch_.fill(false);
00192 
00193     treePointers_[InEvent] = &eventTree_;
00194     treePointers_[InLumi]  = &lumiTree_;
00195     treePointers_[InRun]   = &runTree_;
00196 
00197     // Read the metadata tree.
00198     // We use a smart pointer so the tree will be deleted after use, and not kept for the life of the file.
00199     std::unique_ptr<TTree> metaDataTree(dynamic_cast<TTree *>(filePtr_->Get(poolNames::metaDataTreeName().c_str())));
00200     if(nullptr == metaDataTree.get()) {
00201       throw Exception(errors::FileReadError) << "Could not find tree " << poolNames::metaDataTreeName()
00202                                              << " in the input file.\n";
00203     }
00204 
00205     // To keep things simple, we just read in every possible branch that exists.
00206     // We don't pay attention to which branches exist in which file format versions
00207 
00208     FileFormatVersion *fftPtr = &fileFormatVersion_;
00209     if(metaDataTree->FindBranch(poolNames::fileFormatVersionBranchName().c_str()) != nullptr) {
00210       TBranch *fft = metaDataTree->GetBranch(poolNames::fileFormatVersionBranchName().c_str());
00211       fft->SetAddress(&fftPtr);
00212       roottree::getEntry(fft, 0);
00213       metaDataTree->SetBranchAddress(poolNames::fileFormatVersionBranchName().c_str(), &fftPtr);
00214     }
00215 
00216     FileID *fidPtr = &fid_;
00217     if(metaDataTree->FindBranch(poolNames::fileIdentifierBranchName().c_str()) != nullptr) {
00218       metaDataTree->SetBranchAddress(poolNames::fileIdentifierBranchName().c_str(), &fidPtr);
00219     }
00220 
00221     IndexIntoFile *iifPtr = &indexIntoFile_;
00222     if(metaDataTree->FindBranch(poolNames::indexIntoFileBranchName().c_str()) != nullptr) {
00223       metaDataTree->SetBranchAddress(poolNames::indexIntoFileBranchName().c_str(), &iifPtr);
00224     }
00225 
00226     // Need to read to a temporary registry so we can do a translation of the BranchKeys.
00227     // This preserves backward compatibility against friendly class name algorithm changes.
00228     ProductRegistry inputProdDescReg;
00229     ProductRegistry *ppReg = &inputProdDescReg;
00230     metaDataTree->SetBranchAddress(poolNames::productDescriptionBranchName().c_str(), (&ppReg));
00231 
00232     typedef std::map<ParameterSetID, ParameterSetBlob> PsetMap;
00233     PsetMap psetMap;
00234     PsetMap *psetMapPtr = &psetMap;
00235     if(metaDataTree->FindBranch(poolNames::parameterSetMapBranchName().c_str()) != nullptr) {
00236       //backward compatibility
00237       assert(!fileFormatVersion().parameterSetsTree());
00238       metaDataTree->SetBranchAddress(poolNames::parameterSetMapBranchName().c_str(), &psetMapPtr);
00239     } else {
00240       assert(fileFormatVersion().parameterSetsTree());
00241       // We use a smart pointer so the tree will be deleted after use, and not kept for the life of the file.
00242       std::unique_ptr<TTree> psetTree(dynamic_cast<TTree *>(filePtr_->Get(poolNames::parameterSetsTreeName().c_str())));
00243       if(nullptr == psetTree.get()) {
00244         throw Exception(errors::FileReadError) << "Could not find tree " << poolNames::parameterSetsTreeName()
00245         << " in the input file.\n";
00246       }
00247 
00248       typedef std::pair<ParameterSetID, ParameterSetBlob> IdToBlobs;
00249       IdToBlobs idToBlob;
00250       IdToBlobs* pIdToBlob = &idToBlob;
00251       psetTree->SetBranchAddress(poolNames::idToParameterSetBlobsBranchName().c_str(), &pIdToBlob);
00252 
00253       std::unique_ptr<TTreeCache> psetTreeCache = roottree::trainCache(psetTree.get(), *filePtr_, roottree::defaultNonEventCacheSize, "*");
00254       psetTreeCache->SetEnablePrefetching(false);
00255       filePtr_->SetCacheRead(psetTreeCache.get());
00256       for(Long64_t i = 0; i != psetTree->GetEntries(); ++i) {
00257         psetTree->GetEntry(i);
00258         psetMap.insert(idToBlob);
00259       }
00260       filePtr_->SetCacheRead(0);
00261     }
00262 
00263     // backward compatibility
00264     ProcessHistoryRegistry::collection_type pHistMap;
00265     ProcessHistoryRegistry::collection_type *pHistMapPtr = &pHistMap;
00266     if(metaDataTree->FindBranch(poolNames::processHistoryMapBranchName().c_str()) != nullptr) {
00267       metaDataTree->SetBranchAddress(poolNames::processHistoryMapBranchName().c_str(), &pHistMapPtr);
00268     }
00269 
00270     ProcessHistoryRegistry::vector_type pHistVector;
00271     ProcessHistoryRegistry::vector_type *pHistVectorPtr = &pHistVector;
00272     if(metaDataTree->FindBranch(poolNames::processHistoryBranchName().c_str()) != nullptr) {
00273       metaDataTree->SetBranchAddress(poolNames::processHistoryBranchName().c_str(), &pHistVectorPtr);
00274     }
00275 
00276     ProcessConfigurationVector* procConfigVectorPtr = &processConfigurations_;
00277     if(metaDataTree->FindBranch(poolNames::processConfigurationBranchName().c_str()) != nullptr) {
00278       metaDataTree->SetBranchAddress(poolNames::processConfigurationBranchName().c_str(), &procConfigVectorPtr);
00279     }
00280 
00281     std::unique_ptr<BranchIDLists> branchIDListsAPtr(new BranchIDLists);
00282     BranchIDLists* branchIDListsPtr = branchIDListsAPtr.get();
00283     if(metaDataTree->FindBranch(poolNames::branchIDListBranchName().c_str()) != nullptr) {
00284       metaDataTree->SetBranchAddress(poolNames::branchIDListBranchName().c_str(), &branchIDListsPtr);
00285     }
00286 
00287     BranchChildren* branchChildrenBuffer = branchChildren_.get();
00288     if(metaDataTree->FindBranch(poolNames::productDependenciesBranchName().c_str()) != nullptr) {
00289       metaDataTree->SetBranchAddress(poolNames::productDependenciesBranchName().c_str(), &branchChildrenBuffer);
00290     }
00291 
00292     // backward compatibility
00293     std::vector<EventProcessHistoryID> *eventHistoryIDsPtr = &eventProcessHistoryIDs_;
00294     if(metaDataTree->FindBranch(poolNames::eventHistoryBranchName().c_str()) != nullptr) {
00295       metaDataTree->SetBranchAddress(poolNames::eventHistoryBranchName().c_str(), &eventHistoryIDsPtr);
00296     }
00297 
00298     if(metaDataTree->FindBranch(poolNames::moduleDescriptionMapBranchName().c_str()) != nullptr) {
00299       if(metaDataTree->GetBranch(poolNames::moduleDescriptionMapBranchName().c_str())->GetSplitLevel() != 0) {
00300         metaDataTree->SetBranchStatus((poolNames::moduleDescriptionMapBranchName() + ".*").c_str(), 0);
00301       } else {
00302         metaDataTree->SetBranchStatus(poolNames::moduleDescriptionMapBranchName().c_str(), 0);
00303       }
00304     }
00305 
00306     // Here we read the metadata tree
00307     roottree::getEntry(metaDataTree.get(), 0);
00308 
00309     checkReleaseVersion();
00310 
00311     eventProcessHistoryIter_ = eventProcessHistoryIDs_.begin();
00312 
00313     // Here we read the event history tree, if we have one.
00314     readEventHistoryTree();
00315 
00316     ParameterSetConverter::ParameterSetIdConverter psetIdConverter;
00317     if(!fileFormatVersion().triggerPathsTracked()) {
00318       ParameterSetConverter converter(psetMap, psetIdConverter, fileFormatVersion().parameterSetsByReference());
00319     } else {
00320       // Merge into the parameter set registry.
00321       pset::Registry& psetRegistry = *pset::Registry::instance();
00322       for(auto const& psetEntry : psetMap) {
00323         ParameterSet pset(psetEntry.second.pset());
00324         pset.setID(psetEntry.first);
00325         psetRegistry.insertMapped(pset);
00326       }
00327     }
00328     if(!fileFormatVersion().splitProductIDs()) {
00329       // Old provenance format input file.  Create a provenance adaptor.
00330       provenanceAdaptor_.reset(new ProvenanceAdaptor(
00331             inputProdDescReg, pHistMap, pHistVector, processConfigurations_, psetIdConverter, true));
00332       // Fill in the branchIDLists branch from the provenance adaptor
00333       branchIDLists_ = provenanceAdaptor_->branchIDLists();
00334     } else {
00335       if(!fileFormatVersion().triggerPathsTracked()) {
00336         // New provenance format, but change in ParameterSet Format. Create a provenance adaptor.
00337         provenanceAdaptor_.reset(new ProvenanceAdaptor(
00338             inputProdDescReg, pHistMap, pHistVector, processConfigurations_, psetIdConverter, false));
00339       }
00340       // New provenance format input file. The branchIDLists branch was read directly from the input file.
00341       if(metaDataTree->FindBranch(poolNames::branchIDListBranchName().c_str()) == nullptr) {
00342         throw Exception(errors::EventCorruption)
00343           << "Failed to find branchIDLists branch in metaData tree.\n";
00344       }
00345       branchIDLists_.reset(branchIDListsAPtr.release());
00346     }
00347 
00348     if(labelRawDataLikeMC) {
00349       std::string const rawData("FEDRawDataCollection");
00350       std::string const source("source");
00351       ProductRegistry::ProductList& pList = inputProdDescReg.productListUpdator();
00352       BranchKey finder(rawData, source, "", "");
00353       ProductRegistry::ProductList::iterator it = pList.lower_bound(finder);
00354       if(it != pList.end() && it->first.friendlyClassName_ == rawData && it->first.moduleLabel_ == source) {
00355         // We found raw data with a module label of source.
00356         // We need to change the module label and process name.
00357         // Create helper.
00358         it->second.init();
00359         daqProvenanceHelper_.reset(new DaqProvenanceHelper(it->second.unwrappedTypeID()));
00360         // Create the new branch description
00361         BranchDescription const& newBD = daqProvenanceHelper_->constBranchDescription_.me();
00362         // Save info from the old and new branch descriptions
00363         daqProvenanceHelper_->saveInfo(it->second, newBD);
00364         // Map the new branch name to the old branch name.
00365         it->second.init();
00366         newBranchToOldBranch_.insert(std::make_pair(newBD.branchName(), it->second.branchName()));
00367         // Remove the old branch description from the product Registry.
00368         pList.erase(it);
00369         // Check that there was only one.
00370         it = pList.lower_bound(finder);
00371         assert(!(it != pList.end() && it->first.friendlyClassName_ == rawData && it->first.moduleLabel_ == source));
00372         // Insert the new branch description into the product registry.
00373         inputProdDescReg.copyProduct(newBD);
00374         // Fix up other per file metadata.
00375         daqProvenanceHelper_->fixMetaData(processConfigurations_, pHistVector);
00376         daqProvenanceHelper_->fixMetaData(*branchIDLists_);
00377         daqProvenanceHelper_->fixMetaData(*branchChildren_);
00378       }
00379     }
00380 
00381     ProcessHistoryRegistry::instance()->insertCollection(pHistVector);
00382     ProcessConfigurationRegistry::instance()->insertCollection(processConfigurations_);
00383 
00384     eventTree_.trainCache(BranchTypeToAuxiliaryBranchName(InEvent).c_str());
00385 
00386     validateFile(inputType, usingGoToEvent);
00387 
00388     // Read the parentage tree.  Old format files are handled internally in readParentageTree().
00389     readParentageTree();
00390 
00391     // Merge into the hashed registries.
00392     if(eventSkipperByID_ && eventSkipperByID_->somethingToSkip()) {
00393       whyNotFastClonable_ += FileBlock::EventsOrLumisSelectedByID;
00394     }
00395 
00396     initializeDuplicateChecker(indexesIntoFiles, currentIndexIntoFile);
00397     indexIntoFileIter_ = indexIntoFileBegin_ = indexIntoFile_.begin(noEventSort ? IndexIntoFile::firstAppearanceOrder : IndexIntoFile::numericalOrder);
00398     indexIntoFileEnd_ = indexIntoFile_.end(noEventSort ? IndexIntoFile::firstAppearanceOrder : IndexIntoFile::numericalOrder);
00399     forcedRunOffset_ = forcedRunOffset(forcedRunNumber, indexIntoFileBegin_, indexIntoFileEnd_);
00400     eventProcessHistoryIter_ = eventProcessHistoryIDs_.begin();
00401 
00402     // Set product presence information in the product registry.
00403     ProductRegistry::ProductList const& pList = inputProdDescReg.productList();
00404     for(auto const& product : pList) {
00405       BranchDescription const& prod = product.second;
00406       prod.init();
00407       treePointers_[prod.branchType()]->setPresence(prod, newBranchToOldBranch(prod.branchName()));
00408     }
00409 
00410     fillProductRegistryTransients(processConfigurations_, inputProdDescReg);
00411 
00412     std::unique_ptr<ProductRegistry> newReg(new ProductRegistry);
00413 
00414     // Do the translation from the old registry to the new one
00415     {
00416       ProductRegistry::ProductList const& prodList = inputProdDescReg.productList();
00417       for(auto const& product : prodList) {
00418         BranchDescription const& prod = product.second;
00419         std::string newFriendlyName = friendlyname::friendlyName(prod.className());
00420         if(newFriendlyName == prod.friendlyClassName()) {
00421           newReg->copyProduct(prod);
00422         } else {
00423           if(fileFormatVersion().splitProductIDs()) {
00424             throw Exception(errors::UnimplementedFeature)
00425               << "Cannot change friendly class name algorithm without more development work\n"
00426               << "to update BranchIDLists.  Contact the framework group.\n";
00427           }
00428           BranchDescription newBD(prod);
00429           newBD.updateFriendlyClassName();
00430           newReg->copyProduct(newBD);
00431           newBranchToOldBranch_.insert(std::make_pair(newBD.branchName(), prod.branchName()));
00432         }
00433       }
00434       dropOnInput(*newReg, productSelectorRules, dropDescendants, inputType);
00435       // freeze the product registry
00436       newReg->setFrozen(inputType != InputType::Primary);
00437       productRegistry_.reset(newReg.release());
00438     }
00439 
00440     // Here, we make the class that will make the ProvenanceReader
00441     provenanceReaderMaker_.reset(makeProvenanceReaderMaker().release());
00442 
00443     // Set up information from the product registry.
00444     ProductRegistry::ProductList const& prodList = productRegistry()->productList();
00445     for(auto const& product : prodList) {
00446       BranchDescription const& prod = product.second;
00447       treePointers_[prod.branchType()]->addBranch(product.first, prod,
00448                                                   newBranchToOldBranch(prod.branchName()));
00449     }
00450 
00451     // Determine if this file is fast clonable.
00452     setIfFastClonable(remainingEvents, remainingLumis);
00453 
00454     // Update the branch id info.
00455     if(inputType == InputType::Primary) {
00456       branchListIndexesUnchanged_ = branchIDListHelper_->updateFromInput(*branchIDLists_);
00457     }
00458 
00459     setRefCoreStreamer(true);  // backward compatibility
00460 
00461     // We are done with our initial reading of EventAuxiliary.
00462     indexIntoFile_.doneFileInitialization();
00463 
00464     // Tell the event tree to begin training at the next read.
00465     eventTree_.resetTraining();
00466 
00467     // Train the run and lumi trees.
00468     runTree_.trainCache("*");
00469     lumiTree_.trainCache("*");
00470   }
00471 
00472   RootFile::~RootFile() {
00473   }
00474 
00475   void
00476   RootFile::readEntryDescriptionTree() {
00477     // Called only for old format files.
00478     if(!fileFormatVersion().perEventProductIDs()) return;
00479     // We use a smart pointer so the tree will be deleted after use, and not kept for the life of the file.
00480     std::unique_ptr<TTree> entryDescriptionTree(dynamic_cast<TTree*>(filePtr_->Get(poolNames::entryDescriptionTreeName().c_str())));
00481     if(nullptr == entryDescriptionTree.get()) {
00482       throw Exception(errors::FileReadError) << "Could not find tree " << poolNames::entryDescriptionTreeName()
00483                                              << " in the input file.\n";
00484     }
00485 
00486     EntryDescriptionID idBuffer;
00487     EntryDescriptionID* pidBuffer = &idBuffer;
00488     entryDescriptionTree->SetBranchAddress(poolNames::entryDescriptionIDBranchName().c_str(), &pidBuffer);
00489 
00490     EntryDescriptionRegistry& oldregistry = *EntryDescriptionRegistry::instance();
00491 
00492     EventEntryDescription entryDescriptionBuffer;
00493     EventEntryDescription *pEntryDescriptionBuffer = &entryDescriptionBuffer;
00494     entryDescriptionTree->SetBranchAddress(poolNames::entryDescriptionBranchName().c_str(), &pEntryDescriptionBuffer);
00495 
00496     // Fill in the parentage registry.
00497     ParentageRegistry& registry = *ParentageRegistry::instance();
00498 
00499     for(Long64_t i = 0, numEntries = entryDescriptionTree->GetEntries(); i < numEntries; ++i) {
00500       roottree::getEntry(entryDescriptionTree.get(), i);
00501       if(idBuffer != entryDescriptionBuffer.id()) {
00502         throw Exception(errors::EventCorruption) << "Corruption of EntryDescription tree detected.\n";
00503       }
00504       oldregistry.insertMapped(entryDescriptionBuffer);
00505       Parentage parents;
00506       parents.parents() = entryDescriptionBuffer.parents();
00507       if(daqProvenanceHelper_) {
00508         ParentageID const oldID = parents.id();
00509         daqProvenanceHelper_->fixMetaData(parents.parents());
00510         ParentageID newID = parents.id();
00511         if(newID != oldID) {
00512           daqProvenanceHelper_->parentageIDMap_.insert(std::make_pair(oldID, newID));
00513         }
00514       }
00515       registry.insertMapped(parents);
00516     }
00517     entryDescriptionTree->SetBranchAddress(poolNames::entryDescriptionIDBranchName().c_str(), nullptr);
00518     entryDescriptionTree->SetBranchAddress(poolNames::entryDescriptionBranchName().c_str(), nullptr);
00519   }
00520 
00521   void
00522   RootFile::readParentageTree() {
00523     if(!fileFormatVersion().splitProductIDs()) {
00524       // Old format file.
00525       readEntryDescriptionTree();
00526       return;
00527     }
00528     // New format file
00529     // We use a smart pointer so the tree will be deleted after use, and not kept for the life of the file.
00530     std::unique_ptr<TTree> parentageTree(dynamic_cast<TTree*>(filePtr_->Get(poolNames::parentageTreeName().c_str())));
00531     if(nullptr == parentageTree.get()) {
00532       throw Exception(errors::FileReadError) << "Could not find tree " << poolNames::parentageTreeName()
00533                                              << " in the input file.\n";
00534     }
00535 
00536     Parentage parents;
00537     Parentage *pParentageBuffer = &parents;
00538     parentageTree->SetBranchAddress(poolNames::parentageBranchName().c_str(), &pParentageBuffer);
00539 
00540     ParentageRegistry& registry = *ParentageRegistry::instance();
00541 
00542     parentageIDLookup_.reserve(parentageTree->GetEntries());
00543     for(Long64_t i = 0, numEntries = parentageTree->GetEntries(); i < numEntries; ++i) {
00544       roottree::getEntry(parentageTree.get(), i);
00545       if(daqProvenanceHelper_) {
00546         ParentageID const oldID = parents.id();
00547         daqProvenanceHelper_->fixMetaData(parents.parents());
00548         ParentageID newID = parents.id();
00549         if(newID != oldID) {
00550           daqProvenanceHelper_->parentageIDMap_.insert(std::make_pair(oldID, newID));
00551         }
00552       }
00553       registry.insertMapped(parents);
00554       parentageIDLookup_.push_back(parents.id());
00555     }
00556     parentageTree->SetBranchAddress(poolNames::parentageBranchName().c_str(), nullptr);
00557   }
00558 
00559   void
00560   RootFile::setIfFastClonable(int remainingEvents, int remainingLumis) {
00561     if(fileFormatVersion().noMetaDataTrees() and !fileFormatVersion().storedProductProvenanceUsed()) {
00562       //we must avoid copying the old branch which stored the per product per event provenance
00563       whyNotFastClonable_ += FileBlock::FileTooOld;
00564       return;
00565     }
00566     if(!fileFormatVersion().splitProductIDs()) {
00567       whyNotFastClonable_ += FileBlock::FileTooOld;
00568       return;
00569     }
00570     if(processingMode_ != InputSource::RunsLumisAndEvents) {
00571       whyNotFastClonable_ += FileBlock::NotProcessingEvents;
00572       return;
00573     }
00574     // Find entry for first event in file
00575     IndexIntoFile::IndexIntoFileItr it = indexIntoFileBegin_;
00576     while(it != indexIntoFileEnd_ && it.getEntryType() != IndexIntoFile::kEvent) {
00577       ++it;
00578     }
00579     if(it == indexIntoFileEnd_) {
00580       whyNotFastClonable_ += FileBlock::NoEventsInFile;
00581       return;
00582     }
00583 
00584     // From here on, record all reasons we can't fast clone.
00585     IndexIntoFile::SortOrder sortOrder = (noEventSort_ ? IndexIntoFile::firstAppearanceOrder : IndexIntoFile::numericalOrder);
00586     if(!indexIntoFile_.iterationWillBeInEntryOrder(sortOrder)) {
00587       whyNotFastClonable_ += (noEventSort_ ? FileBlock::RunOrLumiNotContiguous : FileBlock::EventsToBeSorted);
00588     }
00589     if(skipAnyEvents_) {
00590       whyNotFastClonable_ += FileBlock::InitialEventsSkipped;
00591     }
00592     if(remainingEvents >= 0 && eventTree_.entries() > remainingEvents) {
00593       whyNotFastClonable_ += FileBlock::MaxEventsTooSmall;
00594     }
00595     if(remainingLumis >= 0 && lumiTree_.entries() > remainingLumis) {
00596       whyNotFastClonable_ += FileBlock::MaxLumisTooSmall;
00597     }
00598     // We no longer fast copy the EventAuxiliary branch, so there
00599     // is no longer any need to disable fast copying because the run
00600     // number is being modified.   Also, this check did not work anyway
00601     // because this function is called before forcedRunOffset_ is set.
00602 
00603     // if(forcedRunOffset_ != 0) {
00604     //   whyNotFastClonable_ += FileBlock::RunNumberModified;
00605     // }
00606     if(duplicateChecker_ &&
00607       !duplicateChecker_->checkDisabled() &&
00608       !duplicateChecker_->noDuplicatesInFile()) {
00609       whyNotFastClonable_ += FileBlock::DuplicateEventsRemoved;
00610     }
00611   }
00612 
00613   std::unique_ptr<FileBlock>
00614   RootFile::createFileBlock() const {
00615     return std::unique_ptr<FileBlock>(new FileBlock(fileFormatVersion(),
00616                                                      eventTree_.tree(),
00617                                                      eventTree_.metaTree(),
00618                                                      lumiTree_.tree(),
00619                                                      lumiTree_.metaTree(),
00620                                                      runTree_.tree(),
00621                                                      runTree_.metaTree(),
00622                                                      whyNotFastClonable(),
00623                                                      hasNewlyDroppedBranch(),
00624                                                      file_,
00625                                                      branchListIndexesUnchanged(),
00626                                                      modifiedIDs(),
00627                                                      branchChildren_,
00628                                                      branchIDLists_));
00629   }
00630 
00631   std::string const&
00632   RootFile::newBranchToOldBranch(std::string const& newBranch) const {
00633     std::map<std::string, std::string>::const_iterator it = newBranchToOldBranch_.find(newBranch);
00634     if(it != newBranchToOldBranch_.end()) {
00635       return it->second;
00636     }
00637     return newBranch;
00638   }
00639 
00640   IndexIntoFile::IndexIntoFileItr
00641   RootFile::indexIntoFileIter() const {
00642     return indexIntoFileIter_;
00643   }
00644 
00645   void
00646   RootFile::setPosition(IndexIntoFile::IndexIntoFileItr const& position) {
00647     indexIntoFileIter_.copyPosition(position);
00648   }
00649 
00650   bool
00651   RootFile::skipThisEntry() {
00652     if(indexIntoFileIter_ == indexIntoFileEnd_) {
00653         return false;
00654     }
00655     if(eventSkipperByID_ && eventSkipperByID_->somethingToSkip()) {
00656 
00657       // See first if the entire lumi or run is skipped, so we won't have to read the event Auxiliary in that case.
00658       if(eventSkipperByID_->skipIt(indexIntoFileIter_.run(), indexIntoFileIter_.lumi(), 0U)) {
00659         return true;
00660       }
00661 
00662       // The Lumi is not skipped.  If this is an event, see if the event is skipped.
00663       if(indexIntoFileIter_.getEntryType() == IndexIntoFile::kEvent) {
00664         fillEventAuxiliary();
00665         if(eventSkipperByID_->skipIt(indexIntoFileIter_.run(),
00666                                       indexIntoFileIter_.lumi(),
00667                                       eventAux_.id().event())) {
00668           return true;
00669         }
00670       }
00671 
00672       // Skip runs with no lumis if either lumisToSkip or lumisToProcess have been set to select lumis
00673       if(indexIntoFileIter_.getEntryType() == IndexIntoFile::kRun &&
00674           eventSkipperByID_->skippingLumis()) {
00675         IndexIntoFile::IndexIntoFileItr iterLumi = indexIntoFileIter_;
00676 
00677         // There are no lumis in this run, not even ones we will skip
00678         if(iterLumi.peekAheadAtLumi() == IndexIntoFile::invalidLumi) {
00679           return true;
00680         }
00681         // If we get here there are lumis in the run, check to see if we are skipping all of them
00682         do {
00683           if(!eventSkipperByID_->skipIt(iterLumi.run(), iterLumi.peekAheadAtLumi(), 0U)) {
00684             return false;
00685           }
00686         }
00687         while(iterLumi.skipLumiInRun());
00688         return true;
00689       }
00690     }
00691     return false;
00692   }
00693 
00694   IndexIntoFile::EntryType
00695   RootFile::getEntryTypeWithSkipping() {
00696     while(skipThisEntry()) {
00697       if(indexIntoFileIter_.getEntryType() == IndexIntoFile::kRun) {
00698         indexIntoFileIter_.advanceToNextRun();
00699       }
00700       else if(indexIntoFileIter_.getEntryType() == IndexIntoFile::kLumi) {
00701         indexIntoFileIter_.advanceToNextLumiOrRun();
00702       }
00703       else {
00704         ++indexIntoFileIter_;
00705       }
00706     }
00707     return indexIntoFileIter_.getEntryType();
00708   }
00709 
00710   bool
00711   RootFile::isDuplicateEvent() {
00712     assert(indexIntoFileIter_.getEntryType() == IndexIntoFile::kEvent);
00713     if(duplicateChecker_.get() == nullptr) {
00714       return false;
00715     }
00716     fillEventAuxiliary();
00717     return duplicateChecker_->isDuplicateAndCheckActive(indexIntoFileIter_.processHistoryIDIndex(),
00718         indexIntoFileIter_.run(), indexIntoFileIter_.lumi(), eventAux_.id().event(), file_);
00719   }
00720 
00721   IndexIntoFile::EntryType
00722   RootFile::getNextEntryTypeWanted() {
00723     IndexIntoFile::EntryType entryType = getEntryTypeWithSkipping();
00724     if(entryType == IndexIntoFile::kEnd) {
00725       return IndexIntoFile::kEnd;
00726     }
00727     if(entryType == IndexIntoFile::kRun) {
00728       return IndexIntoFile::kRun;
00729     } else if(processingMode_ == InputSource::Runs) {
00730       indexIntoFileIter_.advanceToNextRun();
00731       return getNextEntryTypeWanted();
00732     }
00733     if(entryType == IndexIntoFile::kLumi) {
00734       return IndexIntoFile::kLumi;
00735     } else if(processingMode_ == InputSource::RunsAndLumis) {
00736       indexIntoFileIter_.advanceToNextLumiOrRun();
00737       return getNextEntryTypeWanted();
00738     }
00739     if(isDuplicateEvent()) {
00740       ++indexIntoFileIter_;
00741       return getNextEntryTypeWanted();
00742     }
00743     return IndexIntoFile::kEvent;
00744   }
00745 
00746   bool
00747   RootFile::wasLastEventJustRead() const {
00748     IndexIntoFile::IndexIntoFileItr itr(indexIntoFileIter_);
00749     itr.advanceToEvent();
00750     return itr.getEntryType() == IndexIntoFile::kEnd;
00751   }
00752 
00753   bool
00754   RootFile::wasFirstEventJustRead() const {
00755     IndexIntoFile::IndexIntoFileItr itr(indexIntoFileIter_);
00756     int phIndex;
00757     RunNumber_t run;
00758     LuminosityBlockNumber_t lumi;
00759     IndexIntoFile::EntryNumber_t eventEntry;
00760     itr.skipEventBackward(phIndex,
00761                           run,
00762                           lumi,
00763                           eventEntry);
00764     itr.skipEventBackward(phIndex,
00765                           run,
00766                           lumi,
00767                           eventEntry);
00768     return eventEntry == IndexIntoFile::invalidEntry;
00769   }
00770 
00771   namespace {
00772     typedef IndexIntoFile::EntryNumber_t  EntryNumber_t;
00773     struct RunItem {
00774       RunItem(ProcessHistoryID const& phid, RunNumber_t const& run) :
00775         phid_(phid), run_(run) {}
00776       ProcessHistoryID phid_;
00777       RunNumber_t run_;
00778     };
00779     struct RunItemSortByRun {
00780       bool operator()(RunItem const& a, RunItem const& b) const {
00781         return a.run_ < b.run_;
00782       }
00783     };
00784     struct RunItemSortByRunPhid {
00785       bool operator()(RunItem const& a, RunItem const& b) const {
00786         return a.run_ < b.run_ || (!(b.run_ < a.run_) && a.phid_ < b.phid_);
00787       }
00788     };
00789     struct LumiItem {
00790       LumiItem(ProcessHistoryID const& phid, RunNumber_t const& run,
00791                  LuminosityBlockNumber_t const& lumi, EntryNumber_t const& entry) :
00792         phid_(phid), run_(run), lumi_(lumi), firstEventEntry_(entry),
00793         lastEventEntry_(entry == -1LL ? -1LL : entry + 1) {}
00794       ProcessHistoryID phid_;
00795       RunNumber_t run_;
00796       LuminosityBlockNumber_t lumi_;
00797       EntryNumber_t firstEventEntry_;
00798       EntryNumber_t lastEventEntry_;
00799     };
00800     struct LumiItemSortByRunLumi {
00801       bool operator()(LumiItem const& a, LumiItem const& b) const {
00802         return a.run_ < b.run_ || (!(b.run_ < a.run_) && a.lumi_ < b.lumi_);
00803       }
00804     };
00805     struct LumiItemSortByRunLumiPhid {
00806       bool operator()(LumiItem const& a, LumiItem const& b) const {
00807         if(a.run_ < b.run_) return true;
00808         if(b.run_ < a.run_) return false;
00809         if(a.lumi_ < b.lumi_) return true;
00810         if(b.lumi_ < a.lumi_) return false;
00811         return a.phid_ < b.phid_;
00812       }
00813     };
00814   }
00815 
00816   void
00817   RootFile::fillIndexIntoFile() {
00818     // This function is for backward compatibility.
00819     // If reading a current format file, indexIntoFile_ is read from the input
00820     // file and should always be there. Note that the algorithm below will work
00821     // sometimes but often fail with the new format introduced in release 3_8_0.
00822     // If it ever becomes necessary to rebuild IndexIntoFile from the new format,
00823     // probably a separate function should be written to deal with the task.
00824     // This is possible just not implemented yet.
00825     assert(!fileFormatVersion().hasIndexIntoFile());
00826 
00827     typedef std::list<LumiItem> LumiList;
00828     LumiList lumis; // (declare 1)
00829 
00830     typedef std::set<LuminosityBlockID> RunLumiSet;
00831     RunLumiSet runLumiSet; // (declare 2)
00832 
00833     typedef std::list<RunItem> RunList;
00834     RunList runs; // (declare 5)
00835 
00836     typedef std::set<RunNumber_t> RunSet;
00837     RunSet runSet; // (declare 4)
00838 
00839     typedef std::set<RunItem, RunItemSortByRunPhid> RunItemSet;
00840     RunItemSet runItemSet; // (declare 3)
00841 
00842     typedef std::map<RunNumber_t, ProcessHistoryID> PHIDMap;
00843     PHIDMap phidMap;
00844 
00845     RunNumber_t prevRun = 0;
00846     LuminosityBlockNumber_t prevLumi = 0;
00847     ProcessHistoryID prevPhid;
00848     bool iFirst = true;
00849 
00850     indexIntoFile_.unsortedEventNumbers().clear(); // should already be empty, just being careful
00851     indexIntoFile_.unsortedEventNumbers().reserve(eventTree_.entries());
00852 
00853     // First, loop through the event tree.
00854     while(eventTree_.next()) {
00855       bool newRun = false;
00856       bool newLumi = false;
00857       fillThisEventAuxiliary();
00858       fillHistory();
00859 
00860       // Save the event numbers as we loop through the event auxiliary to avoid
00861       // having to read through the event auxiliary again later. These event numbers
00862       // are not actually used in this function, but could be needed elsewhere.
00863       indexIntoFile_.unsortedEventNumbers().push_back(eventAux().event());
00864 
00865       ProcessHistoryID reducedPHID = ProcessHistoryRegistry::instance()->extra().reduceProcessHistoryID(eventAux().processHistoryID());
00866 
00867       if(iFirst || prevPhid != reducedPHID || prevRun != eventAux().run()) {
00868         iFirst = false;
00869         newRun = newLumi = true;
00870       } else if(prevLumi != eventAux().luminosityBlock()) {
00871         newLumi = true;
00872       }
00873       prevPhid = reducedPHID;
00874       prevRun = eventAux().run();
00875       prevLumi = eventAux().luminosityBlock();
00876       if(newLumi) {
00877         lumis.emplace_back(reducedPHID,
00878           eventAux().run(), eventAux().luminosityBlock(), eventTree_.entryNumber()); // (insert 1)
00879         runLumiSet.insert(LuminosityBlockID(eventAux().run(), eventAux().luminosityBlock())); // (insert 2)
00880       } else {
00881         LumiItem& currentLumi = lumis.back();
00882         assert(currentLumi.lastEventEntry_ == eventTree_.entryNumber());
00883         ++currentLumi.lastEventEntry_;
00884       }
00885       if(newRun) {
00886         // Insert run in list if it is not already there.
00887         RunItem item(reducedPHID, eventAux().run());
00888         if(runItemSet.insert(item).second) { // (check 3, insert 3)
00889           runs.push_back(std::move(item)); // (insert 5)
00890           runSet.insert(eventAux().run()); // (insert 4)
00891           phidMap.insert(std::make_pair(eventAux().run(), reducedPHID));
00892         }
00893       }
00894     }
00895     // now clean up.
00896     eventTree_.setEntryNumber(-1);
00897     eventAux_ = EventAuxiliary();
00898     lastEventEntryNumberRead_ = -1LL;
00899 
00900     // Loop over run entries and fill information.
00901 
00902     typedef std::map<RunNumber_t, EntryNumber_t> RunMap;
00903     RunMap runMap; // (declare 11)
00904 
00905     typedef std::vector<RunItem> RunVector;
00906     RunVector emptyRuns; // (declare 12)
00907 
00908     if(runTree_.isValid()) {
00909       while(runTree_.next()) {
00910         // Note: adjacent duplicates will be skipped without an explicit check.
00911 
00912         boost::shared_ptr<RunAuxiliary> runAux = fillRunAuxiliary();
00913         ProcessHistoryID reducedPHID = ProcessHistoryRegistry::instance()->extra().reduceProcessHistoryID(runAux->processHistoryID());
00914 
00915         if(runSet.insert(runAux->run()).second) { // (check 4, insert 4)
00916           // This run was not associated with any events.
00917           emptyRuns.emplace_back(reducedPHID, runAux->run()); // (insert 12)
00918         }
00919         runMap.insert(std::make_pair(runAux->run(), runTree_.entryNumber())); // (insert 11)
00920         phidMap.insert(std::make_pair(runAux->run(), reducedPHID));
00921       }
00922       // now clean up.
00923       runTree_.setEntryNumber(-1);
00924     }
00925 
00926     // Insert the ordered empty runs into the run list.
00927     RunItemSortByRun runItemSortByRun;
00928     stable_sort_all(emptyRuns, runItemSortByRun);
00929 
00930     RunList::iterator itRuns = runs.begin(), endRuns = runs.end();
00931     for(auto const& emptyRun : emptyRuns) {
00932       for(; itRuns != endRuns; ++itRuns) {
00933         if(runItemSortByRun(emptyRun, *itRuns)) {
00934           break;
00935         }
00936       }
00937       runs.insert(itRuns, emptyRun);
00938     }
00939 
00940     // Loop over luminosity block entries and fill information.
00941 
00942     typedef std::vector<LumiItem> LumiVector;
00943     LumiVector emptyLumis; // (declare 7)
00944 
00945     typedef std::map<LuminosityBlockID, EntryNumber_t> RunLumiMap;
00946     RunLumiMap runLumiMap; // (declare 6)
00947 
00948     if(lumiTree_.isValid()) {
00949       while(lumiTree_.next()) {
00950         // Note: adjacent duplicates will be skipped without an explicit check.
00951         boost::shared_ptr<LuminosityBlockAuxiliary> lumiAux = fillLumiAuxiliary();
00952         LuminosityBlockID lumiID = LuminosityBlockID(lumiAux->run(), lumiAux->luminosityBlock());
00953         if(runLumiSet.insert(lumiID).second) { // (check 2, insert 2)
00954           // This lumi was not associated with any events.
00955           // Use the process history ID from the corresponding run.  In cases of practical
00956           // importance, this should be the correct process history ID,  but it is possible
00957           // to construct files where this is not the correct process history ID ...
00958           PHIDMap::const_iterator iPhidMap = phidMap.find(lumiAux->run());
00959           assert(iPhidMap != phidMap.end());
00960           emptyLumis.emplace_back(iPhidMap->second, lumiAux->run(), lumiAux->luminosityBlock(), -1LL); // (insert 7)
00961         }
00962         runLumiMap.insert(std::make_pair(lumiID, lumiTree_.entryNumber()));
00963       }
00964       // now clean up.
00965       lumiTree_.setEntryNumber(-1);
00966     }
00967 
00968     // Insert the ordered empty lumis into the lumi list.
00969     LumiItemSortByRunLumi lumiItemSortByRunLumi;
00970     stable_sort_all(emptyLumis, lumiItemSortByRunLumi);
00971 
00972     LumiList::iterator itLumis = lumis.begin(), endLumis = lumis.end();
00973     for(auto const& emptyLumi : emptyLumis) {
00974       for(; itLumis != endLumis; ++itLumis) {
00975         if(lumiItemSortByRunLumi(emptyLumi, *itLumis)) {
00976           break;
00977         }
00978       }
00979       lumis.insert(itLumis, emptyLumi);
00980     }
00981 
00982     // Create a map of RunItems that gives the order of first appearance in the list.
00983     // Also fill in the vector of process history IDs
00984     typedef std::map<RunItem, int, RunItemSortByRunPhid> RunCountMap;
00985     RunCountMap runCountMap; // Declare (17)
00986     std::vector<ProcessHistoryID>& phids = indexIntoFile_.setProcessHistoryIDs();
00987     assert(phids.empty());
00988     std::vector<IndexIntoFile::RunOrLumiEntry>& entries = indexIntoFile_.setRunOrLumiEntries();
00989     assert(entries.empty());
00990     int rcount = 0;
00991     for(auto& run : runs) {
00992       RunCountMap::const_iterator countMapItem = runCountMap.find(run);
00993       if(countMapItem == runCountMap.end()) {
00994         countMapItem = runCountMap.insert(std::make_pair(run, rcount)).first; // Insert (17)
00995         assert(countMapItem != runCountMap.end());
00996         ++rcount;
00997       }
00998       std::vector<ProcessHistoryID>::const_iterator phidItem = find_in_all(phids, run.phid_);
00999       if(phidItem == phids.end()) {
01000         phids.push_back(run.phid_);
01001         phidItem = phids.end() - 1;
01002       }
01003       entries.emplace_back(
01004         countMapItem->second, // use (17)
01005         -1LL,
01006         runMap[run.run_], // use (11)
01007         phidItem - phids.begin(),
01008         run.run_,
01009         0U,
01010         -1LL,
01011         -1LL);
01012     }
01013 
01014     // Create a map of LumiItems that gives the order of first appearance in the list.
01015     typedef std::map<LumiItem, int, LumiItemSortByRunLumiPhid> LumiCountMap;
01016     LumiCountMap lumiCountMap; // Declare (19)
01017     int lcount = 0;
01018     for(auto& lumi : lumis) {
01019       RunCountMap::const_iterator runCountMapItem = runCountMap.find(RunItem(lumi.phid_, lumi.run_));
01020       assert(runCountMapItem != runCountMap.end());
01021       LumiCountMap::const_iterator countMapItem = lumiCountMap.find(lumi);
01022       if(countMapItem == lumiCountMap.end()) {
01023         countMapItem = lumiCountMap.insert(std::make_pair(lumi, lcount)).first; // Insert (17)
01024         assert(countMapItem != lumiCountMap.end());
01025         ++lcount;
01026       }
01027       std::vector<ProcessHistoryID>::const_iterator phidItem = find_in_all(phids, lumi.phid_);
01028       assert(phidItem != phids.end());
01029       entries.emplace_back(
01030         runCountMapItem->second,
01031         countMapItem->second,
01032         runLumiMap[LuminosityBlockID(lumi.run_, lumi.lumi_)],
01033         phidItem - phids.begin(),
01034         lumi.run_,
01035         lumi.lumi_,
01036         lumi.firstEventEntry_,
01037         lumi.lastEventEntry_);
01038     }
01039     stable_sort_all(entries);
01040   }
01041 
01042   void
01043   RootFile::validateFile(InputType::InputType inputType, bool usingGoToEvent) {
01044     if(!fid_.isValid()) {
01045       fid_ = FileID(createGlobalIdentifier());
01046     }
01047     if(!eventTree_.isValid()) {
01048       throw Exception(errors::EventCorruption) <<
01049          "'Events' tree is corrupted or not present\n" << "in the input file.\n";
01050     }
01051 
01052     if(fileFormatVersion().hasIndexIntoFile()) {
01053       if(runTree().entries() > 0) {
01054         assert(!indexIntoFile_.empty());
01055       }
01056       if(!fileFormatVersion().useReducedProcessHistoryID()) {
01057         if(daqProvenanceHelper_) {
01058           std::vector<ProcessHistoryID>& phidVec = indexIntoFile_.setProcessHistoryIDs();
01059           for(auto& phid : phidVec) {
01060             phid = daqProvenanceHelper_->mapProcessHistoryID(phid);
01061           }
01062         }
01063         indexIntoFile_.reduceProcessHistoryIDs();
01064       }
01065     }
01066     else {
01067       assert(indexIntoFile_.empty());
01068       fillIndexIntoFile();
01069     }
01070 
01071     indexIntoFile_.fixIndexes(orderedProcessHistoryIDs_);
01072     indexIntoFile_.setNumberOfEvents(eventTree_.entries());
01073     indexIntoFile_.setEventFinder(boost::shared_ptr<IndexIntoFile::EventFinder>(new RootFileEventFinder(eventTree_)));
01074     // We fill the event numbers explicitly if we need to find events in closed files,
01075     // such as for secondary files (or secondary sources) or if duplicate checking across files.
01076     bool needEventNumbers = false;
01077     bool needIndexesForDuplicateChecker = duplicateChecker_ && duplicateChecker_->checkingAllFiles() && !duplicateChecker_->checkDisabled();
01078     if(inputType != InputType::Primary || needIndexesForDuplicateChecker || usingGoToEvent) {
01079       needEventNumbers = true;
01080     }
01081     bool needEventEntries = false;
01082     if(inputType != InputType::Primary || !noEventSort_) {
01083       // We need event entries for sorting or for secondary files or sources.
01084       needEventEntries = true;
01085     }
01086     indexIntoFile_.fillEventNumbersOrEntries(needEventNumbers, needEventEntries);
01087   }
01088 
01089   void
01090   RootFile::reportOpened(std::string const& inputType) {
01091     // Report file opened.
01092     std::string const label = "source";
01093     std::string moduleName = "PoolSource";
01094     filePtr_->inputFileOpened(
01095               logicalFile_,
01096               inputType,
01097               moduleName,
01098               label,
01099               fid_.fid(),
01100               eventTree_.branchNames());
01101   }
01102 
01103   void
01104   RootFile::close() {
01105     // Just to play it safe, zero all pointers to objects in the InputFile to be closed.
01106     eventHistoryTree_ = nullptr;
01107     for(auto& treePointer : treePointers_) {
01108       treePointer->close();
01109       treePointer = nullptr;
01110     }
01111     filePtr_->Close();
01112     filePtr_.reset();
01113   }
01114 
01115   void
01116   RootFile::fillThisEventAuxiliary() {
01117     if(lastEventEntryNumberRead_ == eventTree_.entryNumber()) {
01118       // Already read.
01119       return;
01120     }
01121     if(fileFormatVersion().newAuxiliary()) {
01122       EventAuxiliary *pEvAux = &eventAux_;
01123       eventTree_.fillAux<EventAuxiliary>(pEvAux);
01124     } else {
01125       // for backward compatibility.
01126       EventAux eventAux;
01127       EventAux *pEvAux = &eventAux;
01128       eventTree_.fillAux<EventAux>(pEvAux);
01129       conversion(eventAux, eventAux_);
01130     }
01131     lastEventEntryNumberRead_ = eventTree_.entryNumber();
01132   }
01133 
01134   void
01135   RootFile::fillEventAuxiliary() {
01136     eventTree_.setEntryNumber(indexIntoFileIter_.entry());
01137     fillThisEventAuxiliary();
01138   }
01139 
01140   void
01141   RootFile::fillHistory() {
01142     // We could consider doing delayed reading, but because we have to
01143     // store this History object in a different tree than the event
01144     // data tree, this is too hard to do in this first version.
01145 
01146     if(fileFormatVersion().eventHistoryBranch()) {
01147       // Lumi block number was not in EventID for the relevant releases.
01148       EventID id(eventAux().id().run(), 0, eventAux().id().event());
01149       if(eventProcessHistoryIter_->eventID() != id) {
01150         EventProcessHistoryID target(id, ProcessHistoryID());
01151         eventProcessHistoryIter_ = lower_bound_all(eventProcessHistoryIDs_, target);
01152         assert(eventProcessHistoryIter_->eventID() == id);
01153       }
01154       eventAux_.setProcessHistoryID(eventProcessHistoryIter_->processHistoryID());
01155       ++eventProcessHistoryIter_;
01156     } else if(fileFormatVersion().eventHistoryTree()) {
01157       // for backward compatibility.
01158       History* pHistory = history_.get();
01159       TBranch* eventHistoryBranch = eventHistoryTree_->GetBranch(poolNames::eventHistoryBranchName().c_str());
01160       if(!eventHistoryBranch) {
01161         throw Exception(errors::EventCorruption)
01162           << "Failed to find history branch in event history tree.\n";
01163       }
01164       eventHistoryBranch->SetAddress(&pHistory);
01165       roottree::getEntry(eventHistoryTree_, eventTree_.entryNumber());
01166       eventAux_.setProcessHistoryID(history_->processHistoryID());
01167       eventSelectionIDs_.reset(&history_->eventSelectionIDs(), do_nothing_deleter());
01168       branchListIndexes_.reset(&history_->branchListIndexes(), do_nothing_deleter());
01169     } else if(fileFormatVersion().noMetaDataTrees()) {
01170       // Current format
01171       EventSelectionIDVector* pESV = eventSelectionIDs_.get();
01172       TBranch* eventSelectionIDBranch = eventTree_.tree()->GetBranch(poolNames::eventSelectionsBranchName().c_str());
01173       assert(eventSelectionIDBranch != nullptr);
01174       eventTree_.fillBranchEntry(eventSelectionIDBranch, pESV);
01175       BranchListIndexes* pBLI = branchListIndexes_.get();
01176       TBranch* branchListIndexesBranch = eventTree_.tree()->GetBranch(poolNames::branchListIndexesBranchName().c_str());
01177       assert(branchListIndexesBranch != nullptr);
01178       eventTree_.fillBranchEntry(branchListIndexesBranch, pBLI);
01179     }
01180     if(provenanceAdaptor_) {
01181       eventAux_.setProcessHistoryID(provenanceAdaptor_->convertID(eventAux().processHistoryID()));
01182       for(auto& esID : *eventSelectionIDs_) {
01183         esID = provenanceAdaptor_->convertID(esID);
01184       }
01185     }
01186     if(daqProvenanceHelper_) {
01187       eventAux_.setProcessHistoryID(daqProvenanceHelper_->mapProcessHistoryID(eventAux_.processHistoryID()));
01188     }
01189     if(!fileFormatVersion().splitProductIDs()) {
01190       // old format.  branchListIndexes_ must be filled in from the ProvenanceAdaptor.
01191       provenanceAdaptor_->branchListIndexes(*branchListIndexes_);
01192     }
01193     branchIDListHelper_->fixBranchListIndexes(*branchListIndexes_);
01194   }
01195 
01196   boost::shared_ptr<LuminosityBlockAuxiliary>
01197   RootFile::fillLumiAuxiliary() {
01198     boost::shared_ptr<LuminosityBlockAuxiliary> lumiAuxiliary(new LuminosityBlockAuxiliary);
01199     if(fileFormatVersion().newAuxiliary()) {
01200       LuminosityBlockAuxiliary *pLumiAux = lumiAuxiliary.get();
01201       lumiTree_.fillAux<LuminosityBlockAuxiliary>(pLumiAux);
01202     } else {
01203       LuminosityBlockAux lumiAux;
01204       LuminosityBlockAux *pLumiAux = &lumiAux;
01205       lumiTree_.fillAux<LuminosityBlockAux>(pLumiAux);
01206       conversion(lumiAux, *lumiAuxiliary);
01207     }
01208     if(provenanceAdaptor_) {
01209       lumiAuxiliary->setProcessHistoryID(provenanceAdaptor_->convertID(lumiAuxiliary->processHistoryID()));
01210     }
01211     if(daqProvenanceHelper_) {
01212       lumiAuxiliary->setProcessHistoryID(daqProvenanceHelper_->mapProcessHistoryID(lumiAuxiliary->processHistoryID()));
01213     }
01214     if(lumiAuxiliary->luminosityBlock() == 0 && !fileFormatVersion().runsAndLumis()) {
01215       lumiAuxiliary->id() = LuminosityBlockID(RunNumber_t(1), LuminosityBlockNumber_t(1));
01216     }
01217     return lumiAuxiliary;
01218   }
01219 
01220   boost::shared_ptr<RunAuxiliary>
01221   RootFile::fillRunAuxiliary() {
01222     boost::shared_ptr<RunAuxiliary> runAuxiliary(new RunAuxiliary);
01223     if(fileFormatVersion().newAuxiliary()) {
01224       RunAuxiliary *pRunAux = runAuxiliary.get();
01225       runTree_.fillAux<RunAuxiliary>(pRunAux);
01226     } else {
01227       RunAux runAux;
01228       RunAux *pRunAux = &runAux;
01229       runTree_.fillAux<RunAux>(pRunAux);
01230       conversion(runAux, *runAuxiliary);
01231     }
01232     if(provenanceAdaptor_) {
01233       runAuxiliary->setProcessHistoryID(provenanceAdaptor_->convertID(runAuxiliary->processHistoryID()));
01234     }
01235     if(daqProvenanceHelper_) {
01236       runAuxiliary->setProcessHistoryID(daqProvenanceHelper_->mapProcessHistoryID(runAuxiliary->processHistoryID()));
01237     }
01238     return runAuxiliary;
01239   }
01240 
01241   bool
01242   RootFile::skipEvents(int& offset) {
01243     while(offset > 0 && indexIntoFileIter_ != indexIntoFileEnd_) {
01244 
01245       int phIndexOfSkippedEvent = IndexIntoFile::invalidIndex;
01246       RunNumber_t runOfSkippedEvent = IndexIntoFile::invalidRun;
01247       LuminosityBlockNumber_t lumiOfSkippedEvent = IndexIntoFile::invalidLumi;
01248       IndexIntoFile::EntryNumber_t skippedEventEntry = IndexIntoFile::invalidEntry;
01249 
01250       indexIntoFileIter_.skipEventForward(phIndexOfSkippedEvent,
01251                                           runOfSkippedEvent,
01252                                           lumiOfSkippedEvent,
01253                                           skippedEventEntry);
01254 
01255       // At the end of the file and there were no more events to skip
01256       if(skippedEventEntry == IndexIntoFile::invalidEntry) break;
01257 
01258       if(eventSkipperByID_ && eventSkipperByID_->somethingToSkip()) {
01259         eventTree_.setEntryNumber(skippedEventEntry);
01260         fillThisEventAuxiliary();
01261         if(eventSkipperByID_->skipIt(runOfSkippedEvent, lumiOfSkippedEvent, eventAux_.id().event())) {
01262             continue;
01263         }
01264       }
01265       if(duplicateChecker_ &&
01266          !duplicateChecker_->checkDisabled() &&
01267          !duplicateChecker_->noDuplicatesInFile()) {
01268 
01269         eventTree_.setEntryNumber(skippedEventEntry);
01270         fillThisEventAuxiliary();
01271         if(duplicateChecker_->isDuplicateAndCheckActive(phIndexOfSkippedEvent,
01272                                                          runOfSkippedEvent,
01273                                                          lumiOfSkippedEvent,
01274                                                          eventAux_.id().event(),
01275                                                          file_)) {
01276           continue;
01277         }
01278       }
01279       --offset;
01280     }
01281 
01282     while(offset < 0) {
01283 
01284       if(duplicateChecker_) {
01285         duplicateChecker_->disable();
01286       }
01287 
01288       int phIndexOfEvent = IndexIntoFile::invalidIndex;
01289       RunNumber_t runOfEvent =  IndexIntoFile::invalidRun;
01290       LuminosityBlockNumber_t lumiOfEvent = IndexIntoFile::invalidLumi;
01291       EntryNumber_t eventEntry = IndexIntoFile::invalidEntry;
01292 
01293       indexIntoFileIter_.skipEventBackward(phIndexOfEvent,
01294                                            runOfEvent,
01295                                            lumiOfEvent,
01296                                            eventEntry);
01297 
01298       if(eventEntry == IndexIntoFile::invalidEntry) break;
01299 
01300       if(eventSkipperByID_ && eventSkipperByID_->somethingToSkip()) {
01301         eventTree_.setEntryNumber(eventEntry);
01302         fillEventAuxiliary();
01303         if(eventSkipperByID_->skipIt(runOfEvent, lumiOfEvent, eventAux_.id().event())) {
01304           continue;
01305         }
01306       }
01307       ++offset;
01308     }
01309     return(indexIntoFileIter_ == indexIntoFileEnd_);
01310   }
01311 
01312   bool
01313   RootFile::goToEvent(EventID const& eventID) {
01314 
01315     indexIntoFile_.fillEventNumbers();
01316 
01317     if(duplicateChecker_) {
01318       duplicateChecker_->disable();
01319     }
01320 
01321     IndexIntoFile::SortOrder sortOrder = IndexIntoFile::numericalOrder;
01322     if(noEventSort_) sortOrder = IndexIntoFile::firstAppearanceOrder;
01323 
01324     IndexIntoFile::IndexIntoFileItr iter =
01325       indexIntoFile_.findPosition(sortOrder, eventID.run(), eventID.luminosityBlock(), eventID.event());
01326 
01327     if(iter == indexIntoFile_.end(sortOrder)) {
01328       return false;
01329     }
01330     indexIntoFileIter_ = iter;
01331     return true;
01332   }
01333 
01334   // readEvent() is responsible for creating, and setting up, the
01335   // EventPrincipal.
01336   //
01337   //   1. create an EventPrincipal with a unique EventID
01338   //   2. For each entry in the provenance, put in one ProductHolder,
01339   //      holding the Provenance for the corresponding EDProduct.
01340   //   3. set up the caches in the EventPrincipal to know about this
01341   //      ProductHolder.
01342   //
01343   // We do *not* create the EDProduct instance (the equivalent of reading
01344   // the branch containing this EDProduct. That will be done by the Delayed Reader,
01345   //  when it is asked to do so.
01346   //
01347   EventPrincipal*
01348   RootFile::readEvent(EventPrincipal& cache) {
01349     assert(indexIntoFileIter_ != indexIntoFileEnd_);
01350     assert(indexIntoFileIter_.getEntryType() == IndexIntoFile::kEvent);
01351     // Set the entry in the tree, and read the event at that entry.
01352     eventTree_.setEntryNumber(indexIntoFileIter_.entry());
01353     EventPrincipal* ep = readCurrentEvent(cache);
01354 
01355     assert(ep != nullptr);
01356     assert(eventAux().run() == indexIntoFileIter_.run() + forcedRunOffset_);
01357     assert(eventAux().luminosityBlock() == indexIntoFileIter_.lumi());
01358 
01359     // If this next assert shows up in performance profiling or significantly affects memory, then these three lines should be deleted.
01360     // The IndexIntoFile should guarantee that it never fails.
01361     ProcessHistoryID idToCheck = (daqProvenanceHelper_ && fileFormatVersion().useReducedProcessHistoryID() ? *daqProvenanceHelper_->oldProcessHistoryID_ : eventAux().processHistoryID());
01362     ProcessHistoryID const& reducedPHID = ProcessHistoryRegistry::instance()->extra().reduceProcessHistoryID(idToCheck);
01363     assert(reducedPHID == indexIntoFile_.processHistoryID(indexIntoFileIter_.processHistoryIDIndex()));
01364 
01365     ++indexIntoFileIter_;
01366     return ep;
01367   }
01368 
01369   // Reads event at the current entry in the event tree
01370   EventPrincipal*
01371   RootFile::readCurrentEvent(EventPrincipal& cache) {
01372     if(!eventTree_.current()) {
01373       return nullptr;
01374     }
01375     fillThisEventAuxiliary();
01376     if(!fileFormatVersion().lumiInEventID()) {
01377         //ugly, but will disappear when the backward compatibility is done with schema evolution.
01378         const_cast<EventID&>(eventAux_.id()).setLuminosityBlockNumber(eventAux_.oldLuminosityBlock());
01379         eventAux_.resetObsoleteInfo();
01380     }
01381     fillHistory();
01382     overrideRunNumber(eventAux_.id(), eventAux().isRealData());
01383 
01384     // We're not done ... so prepare the EventPrincipal
01385     cache.fillEventPrincipal(eventAux(),
01386                              eventSelectionIDs_,
01387                              branchListIndexes_,
01388                              makeBranchMapper(),
01389                              eventTree_.rootDelayedReader());
01390 
01391     // report event read from file
01392     filePtr_->eventReadFromFile(eventID().run(), eventID().event());
01393     return &cache;
01394   }
01395 
01396   void
01397   RootFile::setAtEventEntry(IndexIntoFile::EntryNumber_t entry) {
01398     eventTree_.setEntryNumber(entry);
01399   }
01400 
01401   boost::shared_ptr<RunAuxiliary>
01402   RootFile::readRunAuxiliary_() {
01403     assert(indexIntoFileIter_ != indexIntoFileEnd_);
01404     assert(indexIntoFileIter_.getEntryType() == IndexIntoFile::kRun);
01405 
01406     // Begin code for backward compatibility before the existence of run trees.
01407     if(!runTree_.isValid()) {
01408 
01409       // prior to the support of run trees.
01410       // RunAuxiliary did not contain a valid timestamp.  Take it from the next event.
01411       IndexIntoFile::EntryNumber_t eventEntry = indexIntoFileIter_.firstEventEntryThisRun();
01412       assert(eventEntry != IndexIntoFile::invalidEntry);
01413       RootTree::EntryNumber savedEntry = eventTree_.entryNumber();
01414       eventTree_.setEntryNumber(eventEntry);
01415       assert(eventTree_.current());
01416       fillThisEventAuxiliary();
01417       eventTree_.setEntryNumber(savedEntry);
01418 
01419       RunID run = RunID(indexIntoFileIter_.run());
01420       overrideRunNumber(run);
01421       return boost::shared_ptr<RunAuxiliary>(new RunAuxiliary(run.run(), eventAux().time(), Timestamp::invalidTimestamp()));
01422     }
01423     // End code for backward compatibility before the existence of run trees.
01424     runTree_.setEntryNumber(indexIntoFileIter_.entry());
01425     boost::shared_ptr<RunAuxiliary> runAuxiliary = fillRunAuxiliary();
01426     assert(runAuxiliary->run() == indexIntoFileIter_.run());
01427     overrideRunNumber(runAuxiliary->id());
01428     filePtr_->reportInputRunNumber(runAuxiliary->run());
01429     // If RunAuxiliary did not contain a valid begin timestamp, invalidate any end timestamp.
01430     if(runAuxiliary->beginTime() == Timestamp::invalidTimestamp()) {
01431       runAuxiliary->setEndTime(Timestamp::invalidTimestamp());
01432     }
01433 
01434     // If RunAuxiliary did not contain a valid timestamp, or if this an old format file from
01435     // when the Run's ProcessHistory included only processes where products were added to the Run itself,
01436     // we attempt to read the first event in the run to get appropriate info.
01437     if(runAuxiliary->beginTime() == Timestamp::invalidTimestamp() ||
01438        !fileFormatVersion().processHistorySameWithinRun()) {
01439 
01440       IndexIntoFile::EntryNumber_t eventEntry = indexIntoFileIter_.firstEventEntryThisRun();
01441       // If we have a valid event, use its information.
01442       if(eventEntry != IndexIntoFile::invalidEntry) {
01443         RootTree::EntryNumber savedEntry = eventTree_.entryNumber();
01444         eventTree_.setEntryNumber(eventEntry);
01445         assert(eventTree_.current());
01446         fillThisEventAuxiliary();
01447 
01448         // RunAuxiliary did not contain a valid timestamp.  Take it from the next event in this run if there is one.
01449         if(runAuxiliary->beginTime() == Timestamp::invalidTimestamp()) {
01450           runAuxiliary->setBeginTime(eventAux().time());
01451         }
01452 
01453         // For backwards compatibility when the Run's ProcessHistory included only processes where products were added to the
01454         // Run, and then the Run and Event auxiliaries could be different.  Use the event ProcessHistoryID if there is one. It should
01455         // almost always be correct by the current definition (processes included if any products are added. This makes the run, lumi,
01456         // and event ProcessHistory's always be the same if no file merging occurs).
01457         if(!fileFormatVersion().processHistorySameWithinRun()) {
01458           fillHistory();
01459           runAuxiliary->setProcessHistoryID(eventAux().processHistoryID());
01460           savedRunAuxiliary_ = runAuxiliary;
01461         }
01462         eventTree_.setEntryNumber(savedEntry);
01463       } else {
01464         // No valid event, just use what is there, because it is the best we can do.
01465         savedRunAuxiliary_ = runAuxiliary;
01466       }
01467     }
01468     return runAuxiliary;
01469   }
01470 
01471   boost::shared_ptr<RunPrincipal>
01472   RootFile::readRun_(boost::shared_ptr<RunPrincipal> runPrincipal) {
01473     assert(indexIntoFileIter_ != indexIntoFileEnd_);
01474     assert(indexIntoFileIter_.getEntryType() == IndexIntoFile::kRun);
01475     // Begin code for backward compatibility before the existence of run trees.
01476     if(!runTree_.isValid()) {
01477       ++indexIntoFileIter_;
01478       return runPrincipal;
01479     }
01480     // End code for backward compatibility before the existence of run trees.
01481     runPrincipal->fillRunPrincipal(runTree_.rootDelayedReader());
01482     // Read in all the products now.
01483     runPrincipal->readImmediate();
01484     ++indexIntoFileIter_;
01485     return runPrincipal;
01486   }
01487 
01488   boost::shared_ptr<LuminosityBlockAuxiliary>
01489   RootFile::readLuminosityBlockAuxiliary_() {
01490     assert(indexIntoFileIter_ != indexIntoFileEnd_);
01491     assert(indexIntoFileIter_.getEntryType() == IndexIntoFile::kLumi);
01492     // Begin code for backward compatibility before the existence of lumi trees.
01493     if(!lumiTree_.isValid()) {
01494       IndexIntoFile::EntryNumber_t eventEntry = indexIntoFileIter_.firstEventEntryThisLumi();
01495       assert(eventEntry != IndexIntoFile::invalidEntry);
01496       RootTree::EntryNumber savedEntry = eventTree_.entryNumber();
01497       eventTree_.setEntryNumber(eventEntry);
01498       assert(eventTree_.current());
01499       fillThisEventAuxiliary();
01500       eventTree_.setEntryNumber(savedEntry);
01501 
01502       LuminosityBlockID lumi = LuminosityBlockID(indexIntoFileIter_.run(), indexIntoFileIter_.lumi());
01503       overrideRunNumber(lumi);
01504       return boost::shared_ptr<LuminosityBlockAuxiliary>(new LuminosityBlockAuxiliary(lumi.run(), lumi.luminosityBlock(), eventAux().time(), Timestamp::invalidTimestamp()));
01505     }
01506     // End code for backward compatibility before the existence of lumi trees.
01507     lumiTree_.setEntryNumber(indexIntoFileIter_.entry());
01508     boost::shared_ptr<LuminosityBlockAuxiliary> lumiAuxiliary = fillLumiAuxiliary();
01509     assert(lumiAuxiliary->run() == indexIntoFileIter_.run());
01510     assert(lumiAuxiliary->luminosityBlock() == indexIntoFileIter_.lumi());
01511     overrideRunNumber(lumiAuxiliary->id());
01512     filePtr_->reportInputLumiSection(lumiAuxiliary->run(), lumiAuxiliary->luminosityBlock());
01513     if(lumiAuxiliary->beginTime() == Timestamp::invalidTimestamp()) {
01514       IndexIntoFile::EntryNumber_t eventEntry = indexIntoFileIter_.firstEventEntryThisLumi();
01515       if(eventEntry != IndexIntoFile::invalidEntry) {
01516         RootTree::EntryNumber savedEntry = eventTree_.entryNumber();
01517         eventTree_.setEntryNumber(eventEntry);
01518         assert(eventTree_.current());
01519         fillThisEventAuxiliary();
01520         eventTree_.setEntryNumber(savedEntry);
01521 
01522         lumiAuxiliary->setBeginTime(eventAux().time());
01523       }
01524       lumiAuxiliary->setEndTime(Timestamp::invalidTimestamp());
01525     }
01526     if(!fileFormatVersion().processHistorySameWithinRun() && savedRunAuxiliary_) {
01527       lumiAuxiliary->setProcessHistoryID(savedRunAuxiliary_->processHistoryID());
01528     }
01529     return lumiAuxiliary;
01530   }
01531 
01532   boost::shared_ptr<LuminosityBlockPrincipal>
01533   RootFile::readLumi(boost::shared_ptr<LuminosityBlockPrincipal> lumiPrincipal) {
01534     assert(indexIntoFileIter_ != indexIntoFileEnd_);
01535     assert(indexIntoFileIter_.getEntryType() == IndexIntoFile::kLumi);
01536     // Begin code for backward compatibility before the existence of lumi trees.
01537     if(!lumiTree_.isValid()) {
01538       ++indexIntoFileIter_;
01539       return lumiPrincipal;
01540     }
01541     // End code for backward compatibility before the existence of lumi trees.
01542     lumiTree_.setEntryNumber(indexIntoFileIter_.entry());
01543     lumiPrincipal->fillLuminosityBlockPrincipal(lumiTree_.rootDelayedReader());
01544     // Read in all the products now.
01545     lumiPrincipal->readImmediate();
01546     ++indexIntoFileIter_;
01547     return lumiPrincipal;
01548   }
01549 
01550   bool
01551   RootFile::setEntryAtEvent(RunNumber_t run, LuminosityBlockNumber_t lumi, EventNumber_t event) {
01552     indexIntoFileIter_ = indexIntoFile_.findEventPosition(run, lumi, event);
01553     if(indexIntoFileIter_ == indexIntoFileEnd_) return false;
01554     eventTree_.setEntryNumber(indexIntoFileIter_.entry());
01555     return true;
01556   }
01557 
01558   bool
01559   RootFile::setEntryAtLumi(RunNumber_t run, LuminosityBlockNumber_t lumi) {
01560     indexIntoFileIter_ = indexIntoFile_.findLumiPosition(run, lumi);
01561     if(indexIntoFileIter_ == indexIntoFileEnd_) return false;
01562     lumiTree_.setEntryNumber(indexIntoFileIter_.entry());
01563     return true;
01564   }
01565 
01566   bool
01567   RootFile::setEntryAtRun(RunNumber_t run) {
01568     indexIntoFileIter_ = indexIntoFile_.findRunPosition(run);
01569     if(indexIntoFileIter_ == indexIntoFileEnd_) return false;
01570     runTree_.setEntryNumber(indexIntoFileIter_.entry());
01571     return true;
01572   }
01573 
01574   bool
01575   RootFile::setEntryAtNextEventInLumi(RunNumber_t run, LuminosityBlockNumber_t lumi) {
01576     if(indexIntoFileIter_.getEntryType() == IndexIntoFile::kEvent) {
01577       ++indexIntoFileIter_;
01578     }
01579     indexIntoFileIter_.advanceToEvent();
01580     if(indexIntoFileIter_.getEntryType() != IndexIntoFile::kEvent) return false;
01581     if(run != indexIntoFileIter_.run()) return false;
01582     if(lumi != indexIntoFileIter_.lumi()) return false;
01583     eventTree_.setEntryNumber(indexIntoFileIter_.entry());
01584     return true;
01585   }
01586 
01587   void
01588   RootFile::overrideRunNumber(RunID& id) {
01589     if(forcedRunOffset_ != 0) {
01590       id = RunID(id.run() + forcedRunOffset_);
01591     }
01592     if(id < RunID::firstValidRun()) id = RunID::firstValidRun();
01593   }
01594 
01595   void
01596   RootFile::overrideRunNumber(LuminosityBlockID& id) {
01597     if(forcedRunOffset_ != 0) {
01598       id = LuminosityBlockID(id.run() + forcedRunOffset_, id.luminosityBlock());
01599     }
01600     if(RunID(id.run()) < RunID::firstValidRun()) id = LuminosityBlockID(RunID::firstValidRun().run(), id.luminosityBlock());
01601   }
01602 
01603   void
01604   RootFile::overrideRunNumber(EventID& id, bool isRealData) {
01605     if(forcedRunOffset_ != 0) {
01606       if(isRealData) {
01607         throw Exception(errors::Configuration, "RootFile::RootFile()")
01608           << "The 'setRunNumber' parameter of PoolSource cannot be used with real data.\n";
01609       }
01610       id = EventID(id.run() + forcedRunOffset_, id.luminosityBlock(), id.event());
01611     }
01612     if(RunID(id.run()) < RunID::firstValidRun()) {
01613       id = EventID(RunID::firstValidRun().run(), LuminosityBlockID::firstValidLuminosityBlock().luminosityBlock(), id.event());
01614     }
01615   }
01616 
01617 
01618   void
01619   RootFile::readEventHistoryTree() {
01620     // Read in the event history tree, if we have one...
01621     if(fileFormatVersion().eventHistoryTree()) {
01622       history_.reset(new History);
01623       eventHistoryTree_ = dynamic_cast<TTree*>(filePtr_->Get(poolNames::eventHistoryTreeName().c_str()));
01624       if(!eventHistoryTree_) {
01625         throw Exception(errors::EventCorruption)
01626           << "Failed to find the event history tree.\n";
01627       }
01628     }
01629   }
01630 
01631   void
01632   RootFile::checkReleaseVersion() {
01633     std::string releaseVersion = getReleaseVersion();
01634     releaseversion::DecomposedReleaseVersion currentRelease(releaseVersion);
01635     for(auto const& pc : processConfigurations_) {
01636       if(releaseversion::isEarlierRelease(currentRelease, pc.releaseVersion())) {
01637         throw Exception(errors::FormatIncompatibility)
01638           << "The release you are using, " << getReleaseVersion() << " , predates\n"
01639           << "a release (" << pc.releaseVersion() << ") used in writing the input file, " << file() <<".\n"
01640           << "Forward compatibility cannot be supported.\n";
01641       }
01642     }
01643   }
01644 
01645   void
01646   RootFile::initializeDuplicateChecker(
01647     std::vector<boost::shared_ptr<IndexIntoFile> > const& indexesIntoFiles,
01648     std::vector<boost::shared_ptr<IndexIntoFile> >::size_type currentIndexIntoFile) {
01649     if(duplicateChecker_) {
01650       if(eventTree_.next()) {
01651         fillThisEventAuxiliary();
01652         duplicateChecker_->inputFileOpened(eventAux().isRealData(),
01653                                            indexIntoFile_,
01654                                            indexesIntoFiles,
01655                                            currentIndexIntoFile);
01656       }
01657       eventTree_.setEntryNumber(-1);
01658     }
01659   }
01660 
01661   void
01662   RootFile::dropOnInput (ProductRegistry& reg, ProductSelectorRules const& rules, bool dropDescendants, InputType::InputType inputType) {
01663     // This is the selector for drop on input.
01664     ProductSelector productSelector;
01665     productSelector.initialize(rules, reg.allBranchDescriptions());
01666 
01667     ProductRegistry::ProductList& prodList = reg.productListUpdator();
01668     // Do drop on input. On the first pass, just fill in a set of branches to be dropped.
01669     std::set<BranchID> branchesToDrop;
01670     for(auto const& product : prodList) {
01671       BranchDescription const& prod = product.second;
01672       if(!productSelector.selected(prod)) {
01673         if(dropDescendants) {
01674           branchChildren_->appendToDescendants(prod.branchID(), branchesToDrop);
01675         } else {
01676           branchesToDrop.insert(prod.branchID());
01677         }
01678       }
01679     }
01680 
01681     // On this pass, actually drop the branches.
01682     std::set<BranchID>::const_iterator branchesToDropEnd = branchesToDrop.end();
01683     for(ProductRegistry::ProductList::iterator it = prodList.begin(), itEnd = prodList.end(); it != itEnd;) {
01684       BranchDescription const& prod = it->second;
01685       bool drop = branchesToDrop.find(prod.branchID()) != branchesToDropEnd;
01686       if(drop) {
01687         if(productSelector.selected(prod)) {
01688           LogWarning("RootFile")
01689             << "Branch '" << prod.branchName() << "' is being dropped from the input\n"
01690             << "of file '" << file_ << "' because it is dependent on a branch\n"
01691             << "that was explicitly dropped.\n";
01692         }
01693         treePointers_[prod.branchType()]->dropBranch(newBranchToOldBranch(prod.branchName()));
01694         hasNewlyDroppedBranch_[prod.branchType()] = true;
01695         ProductRegistry::ProductList::iterator icopy = it;
01696         ++it;
01697         prodList.erase(icopy);
01698       } else {
01699         ++it;
01700       }
01701     }
01702 
01703     // Drop on input mergeable run and lumi products, this needs to be invoked for secondary file input
01704     if(inputType == InputType::SecondaryFile) {
01705       TString tString;
01706       for(ProductRegistry::ProductList::iterator it = prodList.begin(), itEnd = prodList.end(); it != itEnd;) {
01707         BranchDescription const& prod = it->second;
01708         if(prod.branchType() != InEvent) {
01709           TClass *cp = gROOT->GetClass(prod.wrappedName().c_str());
01710           WrapperOwningHolder edp(cp->New(), prod.getInterface());
01711           if(edp.isMergeable()) {
01712             treePointers_[prod.branchType()]->dropBranch(newBranchToOldBranch(prod.branchName()));
01713             ProductRegistry::ProductList::iterator icopy = it;
01714             ++it;
01715             prodList.erase(icopy);
01716           } else {
01717             ++it;
01718           }
01719         }
01720         else ++it;
01721       }
01722     }
01723   }
01724 
01725   std::unique_ptr<MakeProvenanceReader>
01726   RootFile::makeProvenanceReaderMaker() const {
01727     if(fileFormatVersion_.storedProductProvenanceUsed()) {
01728       return std::unique_ptr<MakeProvenanceReader>(new MakeReducedProvenanceReader(parentageIDLookup_));
01729     } else if(fileFormatVersion_.splitProductIDs()) {
01730       return std::unique_ptr<MakeProvenanceReader>(new MakeFullProvenanceReader);
01731     } else if(fileFormatVersion_.perEventProductIDs()) {
01732       return std::unique_ptr<MakeProvenanceReader>(new MakeOldProvenanceReader);
01733     } else {
01734       return std::unique_ptr<MakeProvenanceReader>(new MakeDummyProvenanceReader);
01735     }
01736   }
01737 
01738   boost::shared_ptr<BranchMapper>
01739   RootFile::makeBranchMapper() {
01740     if(!eventBranchMapper_) {
01741       eventBranchMapper_.reset(new BranchMapper(provenanceReaderMaker_->makeReader(eventTree_, daqProvenanceHelper_.get())));
01742     }
01743     eventBranchMapper_->reset();
01744     return eventBranchMapper_;
01745   }
01746 
01747   class ReducedProvenanceReader : public ProvenanceReaderBase {
01748   public:
01749     ReducedProvenanceReader(RootTree* iRootTree, std::vector<ParentageID> const& iParentageIDLookup, DaqProvenanceHelper const* daqProvenanceHelper);
01750   private:
01751     virtual void readProvenance(BranchMapper const& mapper) const;
01752     RootTree* rootTree_;
01753     TBranch* provBranch_;
01754     StoredProductProvenanceVector provVector_;
01755     StoredProductProvenanceVector* pProvVector_;
01756     std::vector<ParentageID> const& parentageIDLookup_;
01757     DaqProvenanceHelper const* daqProvenanceHelper_;
01758   };
01759 
01760   ReducedProvenanceReader::ReducedProvenanceReader(
01761                                               RootTree* iRootTree,
01762                                               std::vector<ParentageID> const& iParentageIDLookup,
01763                                               DaqProvenanceHelper const* daqProvenanceHelper) :
01764       ProvenanceReaderBase(),
01765       rootTree_(iRootTree),
01766       pProvVector_(&provVector_),
01767       parentageIDLookup_(iParentageIDLookup),
01768       daqProvenanceHelper_(daqProvenanceHelper) {
01769     provBranch_ = rootTree_->tree()->GetBranch(BranchTypeToProductProvenanceBranchName(rootTree_->branchType()).c_str());
01770   }
01771 
01772   void
01773   ReducedProvenanceReader::readProvenance(BranchMapper const& mapper) const {
01774     ReducedProvenanceReader* me = const_cast<ReducedProvenanceReader*>(this);
01775     me->rootTree_->fillBranchEntry(me->provBranch_, me->pProvVector_);
01776     setRefCoreStreamer(true);
01777     if(daqProvenanceHelper_) {
01778       for(auto const& prov : provVector_) {
01779         BranchID bid(prov.branchID_);
01780         mapper.insertIntoSet(ProductProvenance(daqProvenanceHelper_->mapBranchID(BranchID(prov.branchID_)),
01781                                                daqProvenanceHelper_->mapParentageID(parentageIDLookup_[prov.parentageIDIndex_])));
01782       }
01783     } else {
01784       for(auto const& prov : provVector_) {
01785         if(prov.parentageIDIndex_ >= parentageIDLookup_.size()) {
01786           throw edm::Exception(errors::LogicError)
01787             << "ReducedProvenanceReader::ReadProvenance\n"
01788             << "The parentage ID index value " << prov.parentageIDIndex_ << " is out of bounds.  The maximum value is " << parentageIDLookup_.size()-1 << ".\n"
01789             << "This should never happen.\n"
01790             << "Please report this to the framework hypernews forum 'hn-cms-edmFramework@cern.ch'.\n";
01791         }
01792         mapper.insertIntoSet(ProductProvenance(BranchID(prov.branchID_), parentageIDLookup_[prov.parentageIDIndex_]));
01793       }
01794     }
01795   }
01796 
01797   class FullProvenanceReader : public ProvenanceReaderBase {
01798   public:
01799     explicit FullProvenanceReader(RootTree* rootTree, DaqProvenanceHelper const* daqProvenanceHelper);
01800     virtual ~FullProvenanceReader() {}
01801   private:
01802     virtual void readProvenance(BranchMapper const& mapper) const;
01803     RootTree* rootTree_;
01804     ProductProvenanceVector infoVector_;
01805     mutable ProductProvenanceVector* pInfoVector_;
01806     DaqProvenanceHelper const* daqProvenanceHelper_;
01807   };
01808 
01809   FullProvenanceReader::FullProvenanceReader(RootTree* rootTree, DaqProvenanceHelper const* daqProvenanceHelper) :
01810          ProvenanceReaderBase(),
01811          rootTree_(rootTree),
01812          infoVector_(),
01813          pInfoVector_(&infoVector_),
01814          daqProvenanceHelper_(daqProvenanceHelper) {
01815   }
01816 
01817   void
01818   FullProvenanceReader::readProvenance(BranchMapper const& mapper) const {
01819     rootTree_->fillBranchEntryMeta(rootTree_->branchEntryInfoBranch(), pInfoVector_);
01820     setRefCoreStreamer(true);
01821     if(daqProvenanceHelper_) {
01822       for(auto const& info : infoVector_) {
01823         mapper.insertIntoSet(ProductProvenance(daqProvenanceHelper_->mapBranchID(info.branchID()),
01824                                                daqProvenanceHelper_->mapParentageID(info.parentageID())));
01825       }
01826     } else {
01827       for(auto const& info : infoVector_) {
01828         mapper.insertIntoSet(info);
01829       }
01830     }
01831   }
01832 
01833   class OldProvenanceReader : public ProvenanceReaderBase {
01834   public:
01835     explicit OldProvenanceReader(RootTree* rootTree, DaqProvenanceHelper const* daqProvenanceHelper);
01836     virtual ~OldProvenanceReader() {}
01837   private:
01838     virtual void readProvenance(BranchMapper const& mapper) const;
01839     RootTree* rootTree_;
01840     std::vector<EventEntryInfo> infoVector_;
01841     mutable std::vector<EventEntryInfo> *pInfoVector_;
01842     DaqProvenanceHelper const* daqProvenanceHelper_;
01843   };
01844 
01845   OldProvenanceReader::OldProvenanceReader(RootTree* rootTree, DaqProvenanceHelper const* daqProvenanceHelper) :
01846          ProvenanceReaderBase(),
01847          rootTree_(rootTree),
01848          infoVector_(),
01849          pInfoVector_(&infoVector_),
01850          daqProvenanceHelper_(daqProvenanceHelper) {
01851   }
01852 
01853   void
01854   OldProvenanceReader::readProvenance(BranchMapper const& mapper) const {
01855     rootTree_->branchEntryInfoBranch()->SetAddress(&pInfoVector_);
01856     roottree::getEntry(rootTree_->branchEntryInfoBranch(), rootTree_->entryNumber());
01857     setRefCoreStreamer(true);
01858     for(auto const& info : infoVector_) {
01859       EventEntryDescription eed;
01860       EntryDescriptionRegistry::instance()->getMapped(info.entryDescriptionID(), eed);
01861       Parentage parentage(eed.parents());
01862       if(daqProvenanceHelper_) {
01863         ProductProvenance entry(daqProvenanceHelper_->mapBranchID(info.branchID()),
01864                                 daqProvenanceHelper_->mapParentageID(parentage.id()));
01865         mapper.insertIntoSet(entry);
01866       } else {
01867         ProductProvenance entry(info.branchID(), parentage.id());
01868         mapper.insertIntoSet(entry);
01869       }
01870     
01871     }
01872   }
01873 
01874   class DummyProvenanceReader : public ProvenanceReaderBase {
01875   public:
01876     DummyProvenanceReader();
01877     virtual ~DummyProvenanceReader() {}
01878   private:
01879     virtual void readProvenance(BranchMapper const& mapper) const;
01880   };
01881 
01882   DummyProvenanceReader::DummyProvenanceReader() :
01883       ProvenanceReaderBase() {
01884   }
01885 
01886   void
01887   DummyProvenanceReader::readProvenance(BranchMapper const&) const {
01888     // Not providing parentage!!!
01889   }
01890 
01891   std::unique_ptr<ProvenanceReaderBase>
01892   MakeDummyProvenanceReader::makeReader(RootTree&, DaqProvenanceHelper const*) const {
01893      return std::unique_ptr<ProvenanceReaderBase>(new DummyProvenanceReader);
01894   }
01895 
01896   std::unique_ptr<ProvenanceReaderBase>
01897   MakeOldProvenanceReader::makeReader(RootTree& rootTree, DaqProvenanceHelper const* daqProvenanceHelper) const {
01898     return std::unique_ptr<ProvenanceReaderBase>(new OldProvenanceReader(&rootTree, daqProvenanceHelper));
01899   }
01900 
01901   std::unique_ptr<ProvenanceReaderBase>
01902   MakeFullProvenanceReader::makeReader(RootTree& rootTree, DaqProvenanceHelper const* daqProvenanceHelper) const {
01903     return std::unique_ptr<ProvenanceReaderBase>(new FullProvenanceReader(&rootTree, daqProvenanceHelper));
01904   }
01905 
01906   std::unique_ptr<ProvenanceReaderBase>
01907   MakeReducedProvenanceReader::makeReader(RootTree& rootTree, DaqProvenanceHelper const* daqProvenanceHelper) const {
01908     return std::unique_ptr<ProvenanceReaderBase>(new ReducedProvenanceReader(&rootTree, parentageIDLookup_, daqProvenanceHelper));
01909   }
01910 }