CMS 3D CMS Logo

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