CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_1_8_patch12/src/IOPool/Input/src/RootFile.cc

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