CMS 3D CMS Logo

CMSSW_4_4_3_patch1/src/IOPool/Input/src/RootFile.cc

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