CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_2_9_HLT1_bphpatch4/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/EDProduct.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/History.h"
00017 #include "DataFormats/Provenance/interface/ParameterSetBlob.h"
00018 #include "DataFormats/Provenance/interface/ParentageRegistry.h"
00019 #include "DataFormats/Provenance/interface/ProcessConfigurationRegistry.h"
00020 #include "DataFormats/Provenance/interface/ProcessHistoryRegistry.h"
00021 #include "DataFormats/Provenance/interface/ProductRegistry.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/ServiceRegistry/interface/Service.h"
00033 #include "FWCore/Sources/interface/EventSkipperByID.h"
00034 #include "FWCore/Utilities/interface/Algorithms.h"
00035 #include "FWCore/Utilities/interface/do_nothing_deleter.h"
00036 #include "FWCore/Utilities/interface/EDMException.h"
00037 #include "FWCore/Utilities/interface/FriendlyName.h"
00038 #include "FWCore/Utilities/interface/GlobalIdentifier.h"
00039 
00040 //used for backward compatibility
00041 #include "DataFormats/Provenance/interface/BranchEntryDescription.h"
00042 #include "DataFormats/Provenance/interface/EntryDescriptionRegistry.h"
00043 #include "DataFormats/Provenance/interface/EventAux.h"
00044 #include "DataFormats/Provenance/interface/LuminosityBlockAux.h"
00045 #include "DataFormats/Provenance/interface/RunAux.h"
00046 #include "DataFormats/Provenance/interface/RunLumiEntryInfo.h"
00047 #include "FWCore/ParameterSet/interface/ParameterSetConverter.h"
00048 
00049 #include "TROOT.h"
00050 #include "Rtypes.h"
00051 #include "TClass.h"
00052 #include "TTree.h"
00053 #include "TTreeCache.h"
00054 
00055 #include <algorithm>
00056 #include <map>
00057 #include <list>
00058 
00059 namespace edm {
00060   namespace {
00061     int
00062     forcedRunOffset(RunNumber_t const& forcedRunNumber, IndexIntoFile::IndexIntoFileItr inxBegin, IndexIntoFile::IndexIntoFileItr inxEnd) {
00063       if(inxBegin == inxEnd) return 0;
00064       int defaultOffset = (inxBegin.run() != 0 ? 0 : 1);
00065       int offset = (forcedRunNumber != 0U ? forcedRunNumber - inxBegin.run() : defaultOffset);
00066       if(offset < 0) {
00067         throw Exception(errors::Configuration)
00068           << "The value of the 'setRunNumber' parameter must not be\n"
00069           << "less than the first run number in the first input file.\n"
00070           << "'setRunNumber' was " << forcedRunNumber <<", while the first run was "
00071           << forcedRunNumber - offset << ".\n";
00072       }
00073       return offset;
00074     }
00075   }
00076 
00077   // This is a helper class for IndexIntoFile.
00078   class RootFileEventFinder : public IndexIntoFile::EventFinder {
00079   public:
00080     explicit RootFileEventFinder(RootTree& eventTree) : eventTree_(eventTree) {}
00081     virtual ~RootFileEventFinder() {}
00082     virtual
00083     EventNumber_t getEventNumberOfEntry(roottree::EntryNumber entry) const {
00084       roottree::EntryNumber saveEntry = eventTree_.entryNumber();
00085       eventTree_.setEntryNumber(entry);
00086       EventAuxiliary eventAux;
00087       EventAuxiliary *pEvAux = &eventAux;
00088       eventTree_.fillAux<EventAuxiliary>(pEvAux);
00089       eventTree_.setEntryNumber(saveEntry);
00090       return eventAux.event();
00091     }
00092 
00093   private:
00094      RootTree& eventTree_;
00095   };
00096 
00097 
00098 //---------------------------------------------------------------------
00099   RootFile::RootFile(std::string const& fileName,
00100                      ProcessConfiguration const& processConfiguration,
00101                      std::string const& logicalFileName,
00102                      boost::shared_ptr<InputFile> filePtr,
00103                      boost::shared_ptr<EventSkipperByID> eventSkipperByID,
00104                      bool skipAnyEvents,
00105                      int remainingEvents,
00106                      int remainingLumis,
00107                      unsigned int treeCacheSize,
00108                      int treeMaxVirtualSize,
00109                      InputSource::ProcessingMode processingMode,
00110                      RunNumber_t const& forcedRunNumber,
00111                      bool noEventSort,
00112                      GroupSelectorRules const& groupSelectorRules,
00113                      bool secondaryFile,
00114                      boost::shared_ptr<DuplicateChecker> duplicateChecker,
00115                      bool dropDescendants,
00116                      std::vector<boost::shared_ptr<IndexIntoFile> > const& indexesIntoFiles,
00117                      std::vector<boost::shared_ptr<IndexIntoFile> >::size_type currentIndexIntoFile,
00118                      std::vector<ProcessHistoryID>& orderedProcessHistoryIDs,
00119                      bool usingGoToEvent) :
00120       file_(fileName),
00121       logicalFile_(logicalFileName),
00122       processConfiguration_(processConfiguration),
00123       filePtr_(filePtr),
00124       eventSkipperByID_(eventSkipperByID),
00125       fileFormatVersion_(),
00126       fid_(),
00127       indexIntoFileSharedPtr_(new IndexIntoFile),
00128       indexIntoFile_(*indexIntoFileSharedPtr_),
00129       orderedProcessHistoryIDs_(orderedProcessHistoryIDs),
00130       indexIntoFileBegin_(indexIntoFile_.begin(noEventSort ? IndexIntoFile::firstAppearanceOrder : IndexIntoFile::numericalOrder)),
00131       indexIntoFileEnd_(indexIntoFileBegin_),
00132       indexIntoFileIter_(indexIntoFileBegin_),
00133       eventProcessHistoryIDs_(),
00134       eventProcessHistoryIter_(eventProcessHistoryIDs_.begin()),
00135       skipAnyEvents_(skipAnyEvents),
00136       noEventSort_(noEventSort),
00137       whyNotFastClonable_(0),
00138       hasNewlyDroppedBranch_(),
00139       branchListIndexesUnchanged_(false),
00140       eventAux_(),
00141       eventTree_(filePtr_, InEvent, treeMaxVirtualSize, treeCacheSize, roottree::defaultLearningEntries),
00142       lumiTree_(filePtr_, InLumi, treeMaxVirtualSize, roottree::defaultNonEventCacheSize, roottree::defaultNonEventLearningEntries),
00143       runTree_(filePtr_, InRun, treeMaxVirtualSize, roottree::defaultNonEventCacheSize, roottree::defaultNonEventLearningEntries),
00144       treePointers_(),
00145       lastEventEntryNumberRead_(-1LL),
00146       productRegistry_(),
00147       branchIDLists_(),
00148       processingMode_(processingMode),
00149       forcedRunOffset_(0),
00150       newBranchToOldBranch_(),
00151       eventHistoryTree_(0),
00152       eventSelectionIDs_(new EventSelectionIDVector),
00153       branchListIndexes_(new BranchListIndexes),
00154       history_(),
00155       branchChildren_(new BranchChildren),
00156       duplicateChecker_(duplicateChecker),
00157       provenanceAdaptor_() {
00158 
00159     hasNewlyDroppedBranch_.assign(false);
00160 
00161     treePointers_[InEvent] = &eventTree_;
00162     treePointers_[InLumi]  = &lumiTree_;
00163     treePointers_[InRun]   = &runTree_;
00164 
00165     // Read the metadata tree.
00166     TTree *metaDataTree = dynamic_cast<TTree *>(filePtr_->Get(poolNames::metaDataTreeName().c_str()));
00167     if(!metaDataTree)
00168       throw Exception(errors::FileReadError) << "Could not find tree " << poolNames::metaDataTreeName()
00169                                              << " in the input file.\n";
00170 
00171     // To keep things simple, we just read in every possible branch that exists.
00172     // We don't pay attention to which branches exist in which file format versions
00173 
00174     FileFormatVersion *fftPtr = &fileFormatVersion_;
00175     if(metaDataTree->FindBranch(poolNames::fileFormatVersionBranchName().c_str()) != 0) {
00176       TBranch *fft = metaDataTree->GetBranch(poolNames::fileFormatVersionBranchName().c_str());
00177       fft->SetAddress(&fftPtr);
00178       roottree::getEntry(fft, 0);
00179       metaDataTree->SetBranchAddress(poolNames::fileFormatVersionBranchName().c_str(), &fftPtr);
00180     }
00181 
00182     setRefCoreStreamer(0, !fileFormatVersion().splitProductIDs(), !fileFormatVersion().productIDIsInt()); // backward compatibility
00183 
00184     FileID *fidPtr = &fid_;
00185     if(metaDataTree->FindBranch(poolNames::fileIdentifierBranchName().c_str()) != 0) {
00186       metaDataTree->SetBranchAddress(poolNames::fileIdentifierBranchName().c_str(), &fidPtr);
00187     }
00188 
00189     IndexIntoFile *iifPtr = &indexIntoFile_;
00190     if(metaDataTree->FindBranch(poolNames::indexIntoFileBranchName().c_str()) != 0) {
00191       metaDataTree->SetBranchAddress(poolNames::indexIntoFileBranchName().c_str(), &iifPtr);
00192     }
00193 
00194     // Need to read to a temporary registry so we can do a translation of the BranchKeys.
00195     // This preserves backward compatibility against friendly class name algorithm changes.
00196     ProductRegistry inputProdDescReg;
00197     ProductRegistry *ppReg = &inputProdDescReg;
00198     metaDataTree->SetBranchAddress(poolNames::productDescriptionBranchName().c_str(), (&ppReg));
00199 
00200     typedef std::map<ParameterSetID, ParameterSetBlob> PsetMap;
00201     PsetMap psetMap;
00202     PsetMap *psetMapPtr = &psetMap;
00203     if(metaDataTree->FindBranch(poolNames::parameterSetMapBranchName().c_str()) != 0) {
00204       //backward compatibility
00205       assert(!fileFormatVersion().parameterSetsTree());
00206       metaDataTree->SetBranchAddress(poolNames::parameterSetMapBranchName().c_str(), &psetMapPtr);
00207     } else {
00208       assert(fileFormatVersion().parameterSetsTree());
00209       TTree* psetTree = dynamic_cast<TTree *>(filePtr_->Get(poolNames::parameterSetsTreeName().c_str()));
00210       if(0 == psetTree) {
00211         throw Exception(errors::FileReadError) << "Could not find tree " << poolNames::parameterSetsTreeName()
00212         << " in the input file.\n";
00213       }
00214 
00215       typedef std::pair<ParameterSetID, ParameterSetBlob> IdToBlobs;
00216       IdToBlobs idToBlob;
00217       IdToBlobs* pIdToBlob = &idToBlob;
00218       psetTree->SetBranchAddress(poolNames::idToParameterSetBlobsBranchName().c_str(), &pIdToBlob);
00219 
00220       std::auto_ptr<TTreeCache> psetTreeCache = roottree::trainCache(psetTree, *filePtr_, roottree::defaultNonEventCacheSize, "*");
00221       filePtr_->SetCacheRead(psetTreeCache.get());
00222       for(Long64_t i = 0; i != psetTree->GetEntries(); ++i) {
00223         psetTree->GetEntry(i);
00224         psetMap.insert(idToBlob);
00225       }
00226       filePtr_->SetCacheRead(0);
00227     }
00228 
00229     // backward compatibility
00230     ProcessHistoryRegistry::collection_type pHistMap;
00231     ProcessHistoryRegistry::collection_type *pHistMapPtr = &pHistMap;
00232     if(metaDataTree->FindBranch(poolNames::processHistoryMapBranchName().c_str()) != 0) {
00233       metaDataTree->SetBranchAddress(poolNames::processHistoryMapBranchName().c_str(), &pHistMapPtr);
00234     }
00235 
00236     ProcessHistoryRegistry::vector_type pHistVector;
00237     ProcessHistoryRegistry::vector_type *pHistVectorPtr = &pHistVector;
00238     if(metaDataTree->FindBranch(poolNames::processHistoryBranchName().c_str()) != 0) {
00239       metaDataTree->SetBranchAddress(poolNames::processHistoryBranchName().c_str(), &pHistVectorPtr);
00240     }
00241 
00242     ProcessConfigurationVector procConfigVector;
00243     ProcessConfigurationVector* procConfigVectorPtr = &procConfigVector;
00244     if(metaDataTree->FindBranch(poolNames::processConfigurationBranchName().c_str()) != 0) {
00245       metaDataTree->SetBranchAddress(poolNames::processConfigurationBranchName().c_str(), &procConfigVectorPtr);
00246     }
00247 
00248     std::auto_ptr<BranchIDListRegistry::collection_type> branchIDListsAPtr(new BranchIDListRegistry::collection_type);
00249     BranchIDListRegistry::collection_type *branchIDListsPtr = branchIDListsAPtr.get();
00250     if(metaDataTree->FindBranch(poolNames::branchIDListBranchName().c_str()) != 0) {
00251       metaDataTree->SetBranchAddress(poolNames::branchIDListBranchName().c_str(), &branchIDListsPtr);
00252     }
00253 
00254     BranchChildren* branchChildrenBuffer = branchChildren_.get();
00255     if(metaDataTree->FindBranch(poolNames::productDependenciesBranchName().c_str()) != 0) {
00256       metaDataTree->SetBranchAddress(poolNames::productDependenciesBranchName().c_str(), &branchChildrenBuffer);
00257     }
00258 
00259     // backward compatibility
00260     std::vector<EventProcessHistoryID> *eventHistoryIDsPtr = &eventProcessHistoryIDs_;
00261     if(metaDataTree->FindBranch(poolNames::eventHistoryBranchName().c_str()) != 0) {
00262       metaDataTree->SetBranchAddress(poolNames::eventHistoryBranchName().c_str(), &eventHistoryIDsPtr);
00263     }
00264 
00265     if(metaDataTree->FindBranch(poolNames::moduleDescriptionMapBranchName().c_str()) != 0) {
00266       if(metaDataTree->GetBranch(poolNames::moduleDescriptionMapBranchName().c_str())->GetSplitLevel() != 0) {
00267         metaDataTree->SetBranchStatus((poolNames::moduleDescriptionMapBranchName() + ".*").c_str(), 0);
00268       } else {
00269         metaDataTree->SetBranchStatus(poolNames::moduleDescriptionMapBranchName().c_str(), 0);
00270       }
00271     }
00272 
00273     // Here we read the metadata tree
00274     roottree::getEntry(metaDataTree, 0);
00275 
00276     eventProcessHistoryIter_ = eventProcessHistoryIDs_.begin();
00277 
00278     // Here we read the event history tree, if we have one.
00279     readEventHistoryTree();
00280 
00281     ParameterSetConverter::ParameterSetIdConverter psetIdConverter;
00282     if(!fileFormatVersion().triggerPathsTracked()) {
00283       ParameterSetConverter converter(psetMap, psetIdConverter, fileFormatVersion().parameterSetsByReference());
00284     } else {
00285       // Merge into the parameter set registry.
00286       pset::Registry& psetRegistry = *pset::Registry::instance();
00287       for(PsetMap::const_iterator i = psetMap.begin(), iEnd = psetMap.end(); i != iEnd; ++i) {
00288         ParameterSet pset(i->second.pset());
00289         pset.setID(i->first);
00290         psetRegistry.insertMapped(pset);
00291       }
00292     }
00293     if(!fileFormatVersion().splitProductIDs()) {
00294       // Old provenance format input file.  Create a provenance adaptor.
00295       provenanceAdaptor_.reset(new ProvenanceAdaptor(
00296             inputProdDescReg, pHistMap, pHistVector, procConfigVector, psetIdConverter, true));
00297       // Fill in the branchIDLists branch from the provenance adaptor
00298       branchIDLists_ = provenanceAdaptor_->branchIDLists();
00299     } else {
00300       if(!fileFormatVersion().triggerPathsTracked()) {
00301         // New provenance format, but change in ParameterSet Format. Create a provenance adaptor.
00302         provenanceAdaptor_.reset(new ProvenanceAdaptor(
00303             inputProdDescReg, pHistMap, pHistVector, procConfigVector, psetIdConverter, false));
00304       }
00305       // New provenance format input file. The branchIDLists branch was read directly from the input file.
00306       if(metaDataTree->FindBranch(poolNames::branchIDListBranchName().c_str()) == 0) {
00307         throw Exception(errors::EventCorruption)
00308           << "Failed to find branchIDLists branch in metaData tree.\n";
00309       }
00310       branchIDLists_.reset(branchIDListsAPtr.release());
00311     }
00312 
00313     // Merge into the hashed registries.
00314     ProcessHistoryRegistry::instance()->insertCollection(pHistVector);
00315     ProcessConfigurationRegistry::instance()->insertCollection(procConfigVector);
00316 
00317     eventTree_.trainCache(BranchTypeToAuxiliaryBranchName(InEvent).c_str());
00318 
00319     validateFile(secondaryFile, usingGoToEvent);
00320 
00321     // Read the parentage tree.  Old format files are handled internally in readParentageTree().
00322     readParentageTree();
00323 
00324     if(eventSkipperByID_ && eventSkipperByID_->somethingToSkip()) {
00325       whyNotFastClonable_ += FileBlock::EventsOrLumisSelectedByID;
00326     }
00327 
00328     initializeDuplicateChecker(indexesIntoFiles, currentIndexIntoFile);
00329     indexIntoFileIter_ = indexIntoFileBegin_ = indexIntoFile_.begin(noEventSort ? IndexIntoFile::firstAppearanceOrder : IndexIntoFile::numericalOrder);
00330     indexIntoFileEnd_ = indexIntoFile_.end(noEventSort ? IndexIntoFile::firstAppearanceOrder : IndexIntoFile::numericalOrder);
00331     forcedRunOffset_ = forcedRunOffset(forcedRunNumber, indexIntoFileBegin_, indexIntoFileEnd_);
00332     eventProcessHistoryIter_ = eventProcessHistoryIDs_.begin();
00333 
00334     // Set product presence information in the product registry.
00335     ProductRegistry::ProductList const& pList = inputProdDescReg.productList();
00336     for(ProductRegistry::ProductList::const_iterator it = pList.begin(), itEnd = pList.end();
00337         it != itEnd; ++it) {
00338       BranchDescription const& prod = it->second;
00339       treePointers_[prod.branchType()]->setPresence(prod);
00340     }
00341 
00342     fillProductRegistryTransients(procConfigVector, inputProdDescReg);
00343 
00344     std::auto_ptr<ProductRegistry> newReg(new ProductRegistry);
00345 
00346     // Do the translation from the old registry to the new one
00347     {
00348       ProductRegistry::ProductList const& prodList = inputProdDescReg.productList();
00349       for(ProductRegistry::ProductList::const_iterator it = prodList.begin(), itEnd = prodList.end();
00350            it != itEnd; ++it) {
00351         BranchDescription const& prod = it->second;
00352         std::string newFriendlyName = friendlyname::friendlyName(prod.className());
00353         if(newFriendlyName == prod.friendlyClassName()) {
00354           newReg->copyProduct(prod);
00355         } else {
00356           if(fileFormatVersion().splitProductIDs()) {
00357             throw Exception(errors::UnimplementedFeature)
00358               << "Cannot change friendly class name algorithm without more development work\n"
00359               << "to update BranchIDLists.  Contact the framework group.\n";
00360           }
00361           BranchDescription newBD(prod);
00362           newBD.updateFriendlyClassName();
00363           newReg->copyProduct(newBD);
00364           newBranchToOldBranch_.insert(std::make_pair(newBD.branchName(), prod.branchName()));
00365         }
00366       }
00367       dropOnInput(*newReg, groupSelectorRules, dropDescendants, secondaryFile);
00368       // freeze the product registry
00369       newReg->setFrozen();
00370       productRegistry_.reset(newReg.release());
00371     }
00372 
00373 
00374     // Set up information from the product registry.
00375     ProductRegistry::ProductList const& prodList = productRegistry()->productList();
00376     for(ProductRegistry::ProductList::const_iterator it = prodList.begin(), itEnd = prodList.end();
00377         it != itEnd; ++it) {
00378       BranchDescription const& prod = it->second;
00379       treePointers_[prod.branchType()]->addBranch(it->first, prod,
00380                                                   newBranchToOldBranch(prod.branchName()));
00381     }
00382 
00383     // Determine if this file is fast clonable.
00384     setIfFastClonable(remainingEvents, remainingLumis);
00385 
00386     // Update the branch id info.
00387     if(!secondaryFile) {
00388       branchListIndexesUnchanged_ = BranchIDListHelper::updateFromInput(*branchIDLists_, file_);
00389     }
00390 
00391     setRefCoreStreamer(true);  // backward compatibility
00392 
00393     // We are done with our initial reading of EventAuxiliary.
00394     indexIntoFile_.doneFileInitialization();
00395 
00396     // Tell the event tree to begin training at the next read.
00397     eventTree_.resetTraining();
00398 
00399     // Train the run and lumi trees.
00400     runTree_.trainCache("*");
00401     lumiTree_.trainCache("*");
00402   }
00403 
00404   RootFile::~RootFile() {
00405   }
00406 
00407   void
00408   RootFile::readEntryDescriptionTree() {
00409     // Called only for old format files.
00410     if(!fileFormatVersion().perEventProductIDs()) return;
00411     TTree* entryDescriptionTree = dynamic_cast<TTree*>(filePtr_->Get(poolNames::entryDescriptionTreeName().c_str()));
00412     if(!entryDescriptionTree)
00413       throw Exception(errors::FileReadError) << "Could not find tree " << poolNames::entryDescriptionTreeName()
00414                                              << " in the input file.\n";
00415 
00416 
00417     EntryDescriptionID idBuffer;
00418     EntryDescriptionID* pidBuffer = &idBuffer;
00419     entryDescriptionTree->SetBranchAddress(poolNames::entryDescriptionIDBranchName().c_str(), &pidBuffer);
00420 
00421     EntryDescriptionRegistry& oldregistry = *EntryDescriptionRegistry::instance();
00422 
00423     EventEntryDescription entryDescriptionBuffer;
00424     EventEntryDescription *pEntryDescriptionBuffer = &entryDescriptionBuffer;
00425     entryDescriptionTree->SetBranchAddress(poolNames::entryDescriptionBranchName().c_str(), &pEntryDescriptionBuffer);
00426 
00427     // Fill in the parentage registry.
00428     ParentageRegistry& registry = *ParentageRegistry::instance();
00429 
00430     for(Long64_t i = 0, numEntries = entryDescriptionTree->GetEntries(); i < numEntries; ++i) {
00431       roottree::getEntry(entryDescriptionTree, i);
00432       if(idBuffer != entryDescriptionBuffer.id())
00433         throw Exception(errors::EventCorruption) << "Corruption of EntryDescription tree detected.\n";
00434       oldregistry.insertMapped(entryDescriptionBuffer);
00435       Parentage parents;
00436       parents.parents() = entryDescriptionBuffer.parents();
00437       registry.insertMapped(parents);
00438     }
00439     entryDescriptionTree->SetBranchAddress(poolNames::entryDescriptionIDBranchName().c_str(), 0);
00440     entryDescriptionTree->SetBranchAddress(poolNames::entryDescriptionBranchName().c_str(), 0);
00441   }
00442 
00443   void
00444   RootFile::readParentageTree() {
00445     if(!fileFormatVersion().splitProductIDs()) {
00446       // Old format file.
00447       readEntryDescriptionTree();
00448       return;
00449     }
00450     // New format file
00451     TTree* parentageTree = dynamic_cast<TTree*>(filePtr_->Get(poolNames::parentageTreeName().c_str()));
00452     if(!parentageTree)
00453       throw Exception(errors::FileReadError) << "Could not find tree " << poolNames::parentageTreeName()
00454                                              << " in the input file.\n";
00455 
00456     Parentage parentageBuffer;
00457     Parentage *pParentageBuffer = &parentageBuffer;
00458     parentageTree->SetBranchAddress(poolNames::parentageBranchName().c_str(), &pParentageBuffer);
00459 
00460     ParentageRegistry& registry = *ParentageRegistry::instance();
00461 
00462     for(Long64_t i = 0, numEntries = parentageTree->GetEntries(); i < numEntries; ++i) {
00463       roottree::getEntry(parentageTree, i);
00464       registry.insertMapped(parentageBuffer);
00465     }
00466     parentageTree->SetBranchAddress(poolNames::parentageBranchName().c_str(), 0);
00467   }
00468 
00469   void
00470   RootFile::setIfFastClonable(int remainingEvents, int remainingLumis) {
00471     if(!fileFormatVersion().splitProductIDs()) {
00472       whyNotFastClonable_ += FileBlock::FileTooOld;
00473       return;
00474     }
00475     if(processingMode_ != InputSource::RunsLumisAndEvents) {
00476       whyNotFastClonable_ += FileBlock::NotProcessingEvents;
00477       return;
00478     }
00479     // Find entry for first event in file
00480     IndexIntoFile::IndexIntoFileItr it = indexIntoFileBegin_;
00481     while(it != indexIntoFileEnd_ && it.getEntryType() != IndexIntoFile::kEvent) {
00482       ++it;
00483     }
00484     if(it == indexIntoFileEnd_) {
00485       whyNotFastClonable_ += FileBlock::NoEventsInFile;
00486       return;
00487     }
00488 
00489     // From here on, record all reasons we can't fast clone.
00490     IndexIntoFile::SortOrder sortOrder = IndexIntoFile::numericalOrder;
00491     if(noEventSort_) sortOrder = IndexIntoFile::firstAppearanceOrder;
00492     if(!indexIntoFile_.iterationWillBeInEntryOrder(sortOrder)) {
00493       whyNotFastClonable_ += FileBlock::EventsToBeSorted;
00494     }
00495     if(skipAnyEvents_) {
00496       whyNotFastClonable_ += FileBlock::InitialEventsSkipped;
00497     }
00498     if(remainingEvents >= 0 && eventTree_.entries() > remainingEvents) {
00499       whyNotFastClonable_ += FileBlock::MaxEventsTooSmall;
00500     }
00501     if(remainingLumis >= 0 && lumiTree_.entries() > remainingLumis) {
00502       whyNotFastClonable_ += FileBlock::MaxLumisTooSmall;
00503     }
00504     // We no longer fast copy the EventAuxiliary branch, so there
00505     // is no longer any need to disable fast copying because the run
00506     // number is being modified.   Also, this check did not work anyway
00507     // because this function is called before forcedRunOffset_ is set.
00508 
00509     // if(forcedRunOffset_ != 0) {
00510     //   whyNotFastClonable_ += FileBlock::RunNumberModified;
00511     // }
00512     if(duplicateChecker_ &&
00513       !duplicateChecker_->checkDisabled() &&
00514       !duplicateChecker_->noDuplicatesInFile()) {
00515       whyNotFastClonable_ += FileBlock::DuplicateEventsRemoved;
00516     }
00517   }
00518 
00519   boost::shared_ptr<FileBlock>
00520   RootFile::createFileBlock() const {
00521     return boost::shared_ptr<FileBlock>(new FileBlock(fileFormatVersion(),
00522                                                      eventTree_.tree(),
00523                                                      eventTree_.metaTree(),
00524                                                      lumiTree_.tree(),
00525                                                      lumiTree_.metaTree(),
00526                                                      runTree_.tree(),
00527                                                      runTree_.metaTree(),
00528                                                      whyNotFastClonable(),
00529                                                      hasNewlyDroppedBranch(),
00530                                                      file_,
00531                                                      branchListIndexesUnchanged(),
00532                                                      branchChildren_));
00533   }
00534 
00535   std::string const&
00536   RootFile::newBranchToOldBranch(std::string const& newBranch) const {
00537     std::map<std::string, std::string>::const_iterator it = newBranchToOldBranch_.find(newBranch);
00538     if(it != newBranchToOldBranch_.end()) {
00539       return it->second;
00540     }
00541     return newBranch;
00542   }
00543 
00544   IndexIntoFile::IndexIntoFileItr
00545   RootFile::indexIntoFileIter() const {
00546     return indexIntoFileIter_;
00547   }
00548 
00549   void
00550   RootFile::setPosition(IndexIntoFile::IndexIntoFileItr const& position) {
00551     indexIntoFileIter_.copyPosition(position);
00552   }
00553 
00554   bool
00555   RootFile::skipThisEntry() {
00556     if(indexIntoFileIter_ == indexIntoFileEnd_) {
00557         return false;
00558     }
00559     if(eventSkipperByID_ && eventSkipperByID_->somethingToSkip()) {
00560 
00561       // See first if the entire lumi or run is skipped, so we won't have to read the event Auxiliary in that case.
00562       if(eventSkipperByID_->skipIt(indexIntoFileIter_.run(), indexIntoFileIter_.lumi(), 0U)) {
00563         return true;
00564       }
00565 
00566       // The Lumi is not skipped.  If this is an event, see if the event is skipped.
00567       if(indexIntoFileIter_.getEntryType() == IndexIntoFile::kEvent) {
00568         fillEventAuxiliary();
00569         if(eventSkipperByID_->skipIt(indexIntoFileIter_.run(),
00570                                       indexIntoFileIter_.lumi(),
00571                                       eventAux_.id().event())) {
00572           return true;
00573         }
00574       }
00575 
00576       // Skip runs with no lumis if either lumisToSkip or lumisToProcess have been set to select lumis
00577       if(indexIntoFileIter_.getEntryType() == IndexIntoFile::kRun &&
00578           eventSkipperByID_->skippingLumis()) {
00579         IndexIntoFile::IndexIntoFileItr iterLumi = indexIntoFileIter_;
00580 
00581         // There are no lumis in this run, not even ones we will skip
00582         if(iterLumi.peekAheadAtLumi() == IndexIntoFile::invalidLumi) {
00583           return true;
00584         }
00585         // If we get here there are lumis in the run, check to see if we are skipping all of them
00586         do {
00587           if(!eventSkipperByID_->skipIt(iterLumi.run(), iterLumi.peekAheadAtLumi(), 0U)) {
00588             return false;
00589           }
00590         }
00591         while(iterLumi.skipLumiInRun());
00592         return true;
00593       }
00594     }
00595     return false;
00596   }
00597 
00598   IndexIntoFile::EntryType
00599   RootFile::getEntryTypeWithSkipping() {
00600     while(skipThisEntry()) {
00601       if(indexIntoFileIter_.getEntryType() == IndexIntoFile::kRun) {
00602         indexIntoFileIter_.advanceToNextRun();
00603       }
00604       else if(indexIntoFileIter_.getEntryType() == IndexIntoFile::kLumi) {
00605         indexIntoFileIter_.advanceToNextLumiOrRun();
00606       }
00607       else {
00608         ++indexIntoFileIter_;
00609       }
00610     }
00611     return indexIntoFileIter_.getEntryType();
00612   }
00613 
00614   bool
00615   RootFile::isDuplicateEvent() {
00616     assert (indexIntoFileIter_.getEntryType() == IndexIntoFile::kEvent);
00617     if(duplicateChecker_.get() == 0) {
00618       return false;
00619     }
00620     fillEventAuxiliary();
00621     return duplicateChecker_->isDuplicateAndCheckActive(indexIntoFileIter_.processHistoryIDIndex(),
00622         indexIntoFileIter_.run(), indexIntoFileIter_.lumi(), eventAux_.id().event(), file_);
00623   }
00624 
00625   IndexIntoFile::EntryType
00626   RootFile::getNextEntryTypeWanted() {
00627     IndexIntoFile::EntryType entryType = getEntryTypeWithSkipping();
00628     if(entryType == IndexIntoFile::kEnd) {
00629       return IndexIntoFile::kEnd;
00630     }
00631     if(entryType == IndexIntoFile::kRun) {
00632       return IndexIntoFile::kRun;
00633     } else if(processingMode_ == InputSource::Runs) {
00634       indexIntoFileIter_.advanceToNextRun();
00635       return getNextEntryTypeWanted();
00636     }
00637     if(entryType == IndexIntoFile::kLumi) {
00638       return IndexIntoFile::kLumi;
00639     } else if(processingMode_ == InputSource::RunsAndLumis) {
00640       indexIntoFileIter_.advanceToNextLumiOrRun();
00641       return getNextEntryTypeWanted();
00642     }
00643     if(isDuplicateEvent()) {
00644       ++indexIntoFileIter_;
00645       return getNextEntryTypeWanted();
00646     }
00647     return IndexIntoFile::kEvent;
00648   }
00649 
00650   bool
00651   RootFile::wasLastEventJustRead() const {
00652     IndexIntoFile::IndexIntoFileItr itr(indexIntoFileIter_);
00653     itr.advanceToEvent();
00654     return itr.getEntryType() == IndexIntoFile::kEnd;
00655   }
00656 
00657   bool
00658   RootFile::wasFirstEventJustRead() const {
00659     IndexIntoFile::IndexIntoFileItr itr(indexIntoFileIter_);
00660     int phIndex;
00661     RunNumber_t run;
00662     LuminosityBlockNumber_t lumi;
00663     IndexIntoFile::EntryNumber_t eventEntry;
00664     itr.skipEventBackward(phIndex,
00665                           run,
00666                           lumi,
00667                           eventEntry);
00668     itr.skipEventBackward(phIndex,
00669                           run,
00670                           lumi,
00671                           eventEntry);
00672     return eventEntry == IndexIntoFile::invalidEntry;
00673   }
00674 
00675   namespace {
00676     typedef IndexIntoFile::EntryNumber_t  EntryNumber_t;
00677     struct RunItem {
00678       RunItem(ProcessHistoryID const& phid, RunNumber_t const& run) :
00679         phid_(phid), run_(run) {}
00680       ProcessHistoryID phid_;
00681       RunNumber_t run_;
00682     };
00683     struct RunItemSortByRun {
00684       bool operator()(RunItem const& a, RunItem const& b) const {
00685         return a.run_ < b.run_;
00686       }
00687     };
00688     struct RunItemSortByRunPhid {
00689       bool operator()(RunItem const& a, RunItem const& b) const {
00690         return a.run_ < b.run_ || (!(b.run_ < a.run_) && a.phid_ < b.phid_);
00691       }
00692     };
00693     struct LumiItem {
00694       LumiItem(ProcessHistoryID const& phid, RunNumber_t const& run,
00695                  LuminosityBlockNumber_t const& lumi, EntryNumber_t const& entry) :
00696         phid_(phid), run_(run), lumi_(lumi), firstEventEntry_(entry),
00697         lastEventEntry_(entry == -1LL ? -1LL : entry + 1) {}
00698       ProcessHistoryID phid_;
00699       RunNumber_t run_;
00700       LuminosityBlockNumber_t lumi_;
00701       EntryNumber_t firstEventEntry_;
00702       EntryNumber_t lastEventEntry_;
00703     };
00704     struct LumiItemSortByRunLumi {
00705       bool operator()(LumiItem const& a, LumiItem const& b) const {
00706         return a.run_ < b.run_ || (!(b.run_ < a.run_) && a.lumi_ < b.lumi_);
00707       }
00708     };
00709     struct LumiItemSortByRunLumiPhid {
00710       bool operator()(LumiItem const& a, LumiItem const& b) const {
00711         if(a.run_ < b.run_) return true;
00712         if(b.run_ < a.run_) return false;
00713         if(a.lumi_ < b.lumi_) return true;
00714         if(b.lumi_ < a.lumi_) return false;
00715         return a.phid_ < b.phid_;
00716       }
00717     };
00718   }
00719 
00720   void
00721   RootFile::fillIndexIntoFile() {
00722     // This function is for backward compatibility.
00723     // If reading a current format file, indexIntoFile_ is read from the input
00724     // file and should always be there. Note that the algorithm below will work
00725     // sometimes but often fail with the new format introduced in release 3_8_0.
00726     // If it ever becomes necessary to rebuild IndexIntoFile from the new format,
00727     // probably a separate function should be written to deal with the task.
00728     // This is possible just not implemented yet.
00729     assert(!fileFormatVersion().hasIndexIntoFile());
00730 
00731     typedef std::list<LumiItem> LumiList;
00732     LumiList lumis; // (declare 1)
00733 
00734     typedef std::set<LuminosityBlockID> RunLumiSet;
00735     RunLumiSet runLumiSet; // (declare 2)
00736 
00737     typedef std::list<RunItem> RunList;
00738     RunList runs; // (declare 5)
00739 
00740     typedef std::set<RunNumber_t> RunSet;
00741     RunSet runSet; // (declare 4)
00742 
00743     typedef std::set<RunItem, RunItemSortByRunPhid> RunItemSet;
00744     RunItemSet runItemSet; // (declare 3)
00745 
00746     typedef std::map<RunNumber_t, ProcessHistoryID> PHIDMap;
00747     PHIDMap phidMap;
00748 
00749     RunNumber_t prevRun = 0;
00750     LuminosityBlockNumber_t prevLumi = 0;
00751     ProcessHistoryID prevPhid;
00752 
00753     indexIntoFile_.unsortedEventNumbers().clear(); // should already be empty, just being careful
00754     indexIntoFile_.unsortedEventNumbers().reserve(eventTree_.entries());
00755 
00756     // First, loop through the event tree.
00757     while(eventTree_.next()) {
00758       bool newRun = false;
00759       bool newLumi = false;
00760       fillThisEventAuxiliary();
00761       fillHistory();
00762 
00763       // Save the event numbers as we loop through the event auxiliary to avoid
00764       // having to read through the event auxiliary again later. These event numbers
00765       // are not actually used in this function, but could be needed elsewhere.
00766       indexIntoFile_.unsortedEventNumbers().push_back(eventAux().event());
00767 
00768       if(prevPhid != eventAux().processHistoryID() || prevRun != eventAux().run()) {
00769         newRun = newLumi = true;
00770       } else if(prevLumi != eventAux().luminosityBlock()) {
00771         newLumi = true;
00772       }
00773       prevPhid = eventAux().processHistoryID();
00774       prevRun = eventAux().run();
00775       prevLumi = eventAux().luminosityBlock();
00776       if(newLumi) {
00777         lumis.push_back(LumiItem(eventAux().processHistoryID(),
00778           eventAux().run(), eventAux().luminosityBlock(), eventTree_.entryNumber())); // (insert 1)
00779         runLumiSet.insert(LuminosityBlockID(eventAux().run(), eventAux().luminosityBlock())); // (insert 2)
00780       } else {
00781         LumiItem& currentLumi = lumis.back();
00782         assert(currentLumi.lastEventEntry_ == eventTree_.entryNumber());
00783         ++currentLumi.lastEventEntry_;
00784       }
00785       if(newRun) {
00786         // Insert run in list if it is not already there.
00787         RunItem item(eventAux().processHistoryID(), eventAux().run());
00788         if(runItemSet.insert(item).second) { // (check 3, insert 3)
00789           runs.push_back(item); // (insert 5)
00790           runSet.insert(eventAux().run()); // (insert 4)
00791           phidMap.insert(std::make_pair(eventAux().run(), eventAux().processHistoryID()));
00792         }
00793       }
00794     }
00795     // now clean up.
00796     eventTree_.setEntryNumber(-1);
00797     eventAux_ = EventAuxiliary();
00798     lastEventEntryNumberRead_ = -1LL;
00799 
00800     // Loop over run entries and fill information.
00801 
00802     typedef std::map<RunNumber_t, EntryNumber_t> RunMap;
00803     RunMap runMap; // (declare 11)
00804 
00805     typedef std::vector<RunItem> RunVector;
00806     RunVector emptyRuns; // (declare 12)
00807 
00808     if(runTree_.isValid()) {
00809       while(runTree_.next()) {
00810         // Note: adjacent duplicates will be skipped without an explicit check.
00811         boost::shared_ptr<RunAuxiliary> runAux = fillRunAuxiliary();
00812         if(runSet.insert(runAux->run()).second) { // (check 4, insert 4)
00813           // This run was not assciated with any events or lumis.
00814           emptyRuns.push_back(RunItem(runAux->processHistoryID(), runAux->run())); // (insert 12)
00815         }
00816         runMap.insert(std::make_pair(runAux->run(), runTree_.entryNumber())); // (insert 11)
00817         phidMap.insert(std::make_pair(runAux->run(), runAux->processHistoryID()));
00818       }
00819       // now clean up.
00820       runTree_.setEntryNumber(-1);
00821     }
00822 
00823     // Insert the ordered empty runs into the run list.
00824     RunItemSortByRun runItemSortByRun;
00825     stable_sort_all(emptyRuns, runItemSortByRun);
00826 
00827     RunList::iterator itRuns = runs.begin(), endRuns = runs.end();
00828     for (RunVector::const_iterator i = emptyRuns.begin(), iEnd = emptyRuns.end(); i != iEnd; ++i) {
00829       for (; itRuns != endRuns; ++itRuns) {
00830         if(runItemSortByRun(*i, *itRuns)) {
00831           break;
00832         }
00833       }
00834       runs.insert(itRuns, *i);
00835     }
00836 
00837     // Loop over luminosity block entries and fill information.
00838 
00839     typedef std::vector<LumiItem> LumiVector;
00840     LumiVector emptyLumis; // (declare 7)
00841 
00842     typedef std::map<LuminosityBlockID, EntryNumber_t> RunLumiMap;
00843     RunLumiMap runLumiMap; // (declare 6)
00844 
00845     if(lumiTree_.isValid()) {
00846       while(lumiTree_.next()) {
00847         // Note: adjacent duplicates will be skipped without an explicit check.
00848         boost::shared_ptr<LuminosityBlockAuxiliary> lumiAux = fillLumiAuxiliary();
00849         LuminosityBlockID lumiID = LuminosityBlockID(lumiAux->run(), lumiAux->luminosityBlock());
00850         if(runLumiSet.insert(lumiID).second) { // (check 2, insert 2)
00851           // This lumi was not associated with any events.
00852           // Use the process history ID from the corresponding run.  In cases of practical
00853           // importance, this should be the correct process history ID,  but it is possible
00854           // to construct files where this is not the correct process history ID ...
00855           PHIDMap::const_iterator iPhidMap = phidMap.find(lumiAux->run());
00856           assert(iPhidMap != phidMap.end());
00857           emptyLumis.push_back(LumiItem(iPhidMap->second, lumiAux->run(), lumiAux->luminosityBlock(), -1LL)); // (insert 7)
00858         }
00859         runLumiMap.insert(std::make_pair(lumiID, lumiTree_.entryNumber()));
00860       }
00861       // now clean up.
00862       lumiTree_.setEntryNumber(-1);
00863     }
00864 
00865     // Insert the ordered empty lumis into the lumi list.
00866     LumiItemSortByRunLumi lumiItemSortByRunLumi;
00867     stable_sort_all(emptyLumis, lumiItemSortByRunLumi);
00868 
00869     LumiList::iterator itLumis = lumis.begin(), endLumis = lumis.end();
00870     for (LumiVector::const_iterator i = emptyLumis.begin(), iEnd = emptyLumis.end(); i != iEnd; ++i) {
00871       for (; itLumis != endLumis; ++itLumis) {
00872         if(lumiItemSortByRunLumi(*i, *itLumis)) {
00873           break;
00874         }
00875       }
00876       lumis.insert(itLumis, *i);
00877     }
00878 
00879     // Create a map of RunItems that gives the order of first appearance in the list.
00880     // Also fill in the vector of process history IDs
00881     typedef std::map<RunItem, int, RunItemSortByRunPhid> RunCountMap;
00882     RunCountMap runCountMap; // Declare (17)
00883     std::vector<ProcessHistoryID>& phids = indexIntoFile_.setProcessHistoryIDs();
00884     assert(phids.empty());
00885     std::vector<IndexIntoFile::RunOrLumiEntry>& entries = indexIntoFile_.setRunOrLumiEntries();
00886     assert(entries.empty());
00887     int rcount = 0;
00888     for (RunList::iterator it = runs.begin(), itEnd = runs.end(); it != itEnd; ++it) {
00889       RunCountMap::const_iterator countMapItem = runCountMap.find(*it);
00890       if(countMapItem == runCountMap.end()) {
00891         countMapItem = runCountMap.insert(std::make_pair(*it, rcount)).first; // Insert (17)
00892         assert(countMapItem != runCountMap.end());
00893         ++rcount;
00894       }
00895       std::vector<ProcessHistoryID>::const_iterator phidItem = find_in_all(phids, it->phid_);
00896       if(phidItem == phids.end()) {
00897         phids.push_back(it->phid_);
00898         phidItem = phids.end() - 1;
00899       }
00900       entries.push_back(IndexIntoFile::RunOrLumiEntry(
00901         countMapItem->second, // use (17)
00902         -1LL,
00903         runMap[it->run_], // use (11)
00904         phidItem - phids.begin(),
00905         it->run_,
00906         0U,
00907         -1LL,
00908         -1LL));
00909     }
00910 
00911     // Create a map of LumiItems that gives the order of first appearance in the list.
00912     typedef std::map<LumiItem, int, LumiItemSortByRunLumiPhid> LumiCountMap;
00913     LumiCountMap lumiCountMap; // Declare (19)
00914     int lcount = 0;
00915     for (LumiList::iterator it = lumis.begin(), itEnd = lumis.end(); it != itEnd; ++it) {
00916       RunCountMap::const_iterator runCountMapItem = runCountMap.find(RunItem(it->phid_, it->run_));
00917       assert(runCountMapItem != runCountMap.end());
00918       LumiCountMap::const_iterator countMapItem = lumiCountMap.find(*it);
00919       if(countMapItem == lumiCountMap.end()) {
00920         countMapItem = lumiCountMap.insert(std::make_pair(*it, lcount)).first; // Insert (17)
00921         assert(countMapItem != lumiCountMap.end());
00922         ++lcount;
00923       }
00924       std::vector<ProcessHistoryID>::const_iterator phidItem = find_in_all(phids, it->phid_);
00925       assert(phidItem != phids.end());
00926       entries.push_back(IndexIntoFile::RunOrLumiEntry(
00927         runCountMapItem->second,
00928         countMapItem->second,
00929         runLumiMap[LuminosityBlockID(it->run_, it->lumi_)],
00930         phidItem - phids.begin(),
00931         it->run_,
00932         it->lumi_,
00933         it->firstEventEntry_,
00934         it->lastEventEntry_));
00935     }
00936     stable_sort_all(entries);
00937   }
00938 
00939   void
00940   RootFile::validateFile(bool secondaryFile, bool usingGoToEvent) {
00941     if(!fid_.isValid()) {
00942       fid_ = FileID(createGlobalIdentifier());
00943     }
00944     if(!eventTree_.isValid()) {
00945       throw Exception(errors::EventCorruption) <<
00946          "'Events' tree is corrupted or not present\n" << "in the input file.\n";
00947     }
00948 
00949     if(fileFormatVersion().hasIndexIntoFile()) {
00950       if(runTree().entries() > 0) {
00951         assert(!indexIntoFile_.empty());
00952       }
00953     }
00954     else {
00955       assert(indexIntoFile_.empty());
00956       fillIndexIntoFile();
00957     }
00958 
00959     indexIntoFile_.fixIndexes(orderedProcessHistoryIDs_);
00960     indexIntoFile_.setNumberOfEvents(eventTree_.entries());
00961     indexIntoFile_.setEventFinder(boost::shared_ptr<IndexIntoFile::EventFinder>(new RootFileEventFinder(eventTree_)));
00962     // We fill the event numbers explicitly if we need to find events in closed files,
00963     // such as for secondary files (or secondary sources) or if duplicate checking across files.
00964     bool needEventNumbers = false;
00965     bool needIndexesForDuplicateChecker = duplicateChecker_ && duplicateChecker_->checkingAllFiles() && !duplicateChecker_->checkDisabled();
00966     if(secondaryFile || needIndexesForDuplicateChecker || usingGoToEvent) {
00967       needEventNumbers = true;
00968     }
00969     bool needEventEntries = false;
00970     if(secondaryFile || !noEventSort_) {
00971       // We need event entries for sorting or for secondary files or sources.
00972       needEventEntries = true;
00973     }
00974     indexIntoFile_.fillEventNumbersOrEntries(needEventNumbers, needEventEntries);
00975   }
00976 
00977   void
00978   RootFile::reportOpened(std::string const& inputType) {
00979     // Report file opened.
00980     std::string const label = "source";
00981     std::string moduleName = "PoolSource";
00982     filePtr_->inputFileOpened(
00983               logicalFile_,
00984               inputType,
00985               moduleName,
00986               label,
00987               fid_.fid(),
00988               eventTree_.branchNames());
00989   }
00990 
00991   void
00992   RootFile::close() {
00993     // Just to play it safe, zero all pointers to objects in the InputFile to be closed.
00994     eventHistoryTree_ = 0;
00995     for(RootTreePtrArray::iterator it = treePointers_.begin(), itEnd = treePointers_.end(); it != itEnd; ++it) {
00996       (*it)->close();
00997       (*it) = 0;
00998     }
00999     filePtr_->Close();
01000     filePtr_.reset();
01001   }
01002 
01003   void
01004   RootFile::fillThisEventAuxiliary() {
01005     if(lastEventEntryNumberRead_ == eventTree_.entryNumber()) {
01006       // Already read.
01007       return;
01008     }
01009     if(fileFormatVersion().newAuxiliary()) {
01010       EventAuxiliary *pEvAux = &eventAux_;
01011       eventTree_.fillAux<EventAuxiliary>(pEvAux);
01012     } else {
01013       // for backward compatibility.
01014       EventAux eventAux;
01015       EventAux *pEvAux = &eventAux;
01016       eventTree_.fillAux<EventAux>(pEvAux);
01017       conversion(eventAux, eventAux_);
01018     }
01019     lastEventEntryNumberRead_ = eventTree_.entryNumber();
01020   }
01021 
01022   void
01023   RootFile::fillEventAuxiliary() {
01024     eventTree_.setEntryNumber(indexIntoFileIter_.entry());
01025     fillThisEventAuxiliary();
01026   }
01027 
01028   void
01029   RootFile::fillHistory() {
01030     // We could consider doing delayed reading, but because we have to
01031     // store this History object in a different tree than the event
01032     // data tree, this is too hard to do in this first version.
01033 
01034     if(fileFormatVersion().eventHistoryBranch()) {
01035       // Lumi block number was not in EventID for the relevant releases.
01036       EventID id(eventAux().id().run(), 0, eventAux().id().event());
01037       if(eventProcessHistoryIter_->eventID() != id) {
01038         EventProcessHistoryID target(id, ProcessHistoryID());
01039         eventProcessHistoryIter_ = lower_bound_all(eventProcessHistoryIDs_, target);
01040         assert(eventProcessHistoryIter_->eventID() == id);
01041       }
01042       eventAux_.setProcessHistoryID(eventProcessHistoryIter_->processHistoryID());
01043       ++eventProcessHistoryIter_;
01044     } else if(fileFormatVersion().eventHistoryTree()) {
01045       // for backward compatibility.
01046       History* pHistory = history_.get();
01047       TBranch* eventHistoryBranch = eventHistoryTree_->GetBranch(poolNames::eventHistoryBranchName().c_str());
01048       if(!eventHistoryBranch) {
01049         throw Exception(errors::EventCorruption)
01050           << "Failed to find history branch in event history tree.\n";
01051       }
01052       eventHistoryBranch->SetAddress(&pHistory);
01053       roottree::getEntry(eventHistoryTree_, eventTree_.entryNumber());
01054       eventAux_.setProcessHistoryID(history_->processHistoryID());
01055       eventSelectionIDs_.reset(&history_->eventSelectionIDs(), do_nothing_deleter());
01056       branchListIndexes_.reset(&history_->branchListIndexes(), do_nothing_deleter());
01057     } else if(fileFormatVersion().noMetaDataTrees()) {
01058       // Current format
01059       EventSelectionIDVector* pESV = eventSelectionIDs_.get();
01060       TBranch* eventSelectionIDBranch = eventTree_.tree()->GetBranch(poolNames::eventSelectionsBranchName().c_str());
01061       assert(eventSelectionIDBranch != 0);
01062       eventTree_.fillBranchEntry(eventSelectionIDBranch, pESV);
01063       BranchListIndexes* pBLI = branchListIndexes_.get();
01064       TBranch* branchListIndexesBranch = eventTree_.tree()->GetBranch(poolNames::branchListIndexesBranchName().c_str());
01065       assert(branchListIndexesBranch != 0);
01066       eventTree_.fillBranchEntry(branchListIndexesBranch, pBLI);
01067     }
01068     if(provenanceAdaptor_) {
01069       eventAux_.setProcessHistoryID(provenanceAdaptor_->convertID(eventAux().processHistoryID()));
01070       for(EventSelectionIDVector::iterator i = eventSelectionIDs_->begin(), e = eventSelectionIDs_->end(); i != e; ++i) {
01071         (*i) = provenanceAdaptor_->convertID(*i);
01072       }
01073     }
01074     if(!fileFormatVersion().splitProductIDs()) {
01075       // old format.  branchListIndexes_ must be filled in from the ProvenanceAdaptor.
01076       provenanceAdaptor_->branchListIndexes(*branchListIndexes_);
01077     }
01078   }
01079 
01080   boost::shared_ptr<LuminosityBlockAuxiliary>
01081   RootFile::fillLumiAuxiliary() {
01082     boost::shared_ptr<LuminosityBlockAuxiliary> lumiAuxiliary(new LuminosityBlockAuxiliary);
01083     if(fileFormatVersion().newAuxiliary()) {
01084       LuminosityBlockAuxiliary *pLumiAux = lumiAuxiliary.get();
01085       lumiTree_.fillAux<LuminosityBlockAuxiliary>(pLumiAux);
01086     } else {
01087       LuminosityBlockAux lumiAux;
01088       LuminosityBlockAux *pLumiAux = &lumiAux;
01089       lumiTree_.fillAux<LuminosityBlockAux>(pLumiAux);
01090       conversion(lumiAux, *lumiAuxiliary);
01091     }
01092     if(provenanceAdaptor_) {
01093       lumiAuxiliary->setProcessHistoryID(provenanceAdaptor_->convertID(lumiAuxiliary->processHistoryID()));
01094     }
01095     if(lumiAuxiliary->luminosityBlock() == 0 && !fileFormatVersion().runsAndLumis()) {
01096       lumiAuxiliary->id() = LuminosityBlockID(RunNumber_t(1), LuminosityBlockNumber_t(1));
01097     }
01098     return lumiAuxiliary;
01099   }
01100 
01101   boost::shared_ptr<RunAuxiliary>
01102   RootFile::fillRunAuxiliary() {
01103     boost::shared_ptr<RunAuxiliary> runAuxiliary(new RunAuxiliary);
01104     if(fileFormatVersion().newAuxiliary()) {
01105       RunAuxiliary *pRunAux = runAuxiliary.get();
01106       runTree_.fillAux<RunAuxiliary>(pRunAux);
01107     } else {
01108       RunAux runAux;
01109       RunAux *pRunAux = &runAux;
01110       runTree_.fillAux<RunAux>(pRunAux);
01111       conversion(runAux, *runAuxiliary);
01112     }
01113     if(provenanceAdaptor_) {
01114       runAuxiliary->setProcessHistoryID(provenanceAdaptor_->convertID(runAuxiliary->processHistoryID()));
01115     }
01116     return runAuxiliary;
01117   }
01118 
01119   bool
01120   RootFile::skipEvents(int& offset) {
01121     while (offset > 0 && indexIntoFileIter_ != indexIntoFileEnd_) {
01122 
01123       int phIndexOfSkippedEvent = IndexIntoFile::invalidIndex;
01124       RunNumber_t runOfSkippedEvent = IndexIntoFile::invalidRun;
01125       LuminosityBlockNumber_t lumiOfSkippedEvent = IndexIntoFile::invalidLumi;
01126       IndexIntoFile::EntryNumber_t skippedEventEntry = IndexIntoFile::invalidEntry;
01127 
01128       indexIntoFileIter_.skipEventForward(phIndexOfSkippedEvent,
01129                                           runOfSkippedEvent,
01130                                           lumiOfSkippedEvent,
01131                                           skippedEventEntry);
01132 
01133       // At the end of the file and there were no more events to skip
01134       if(skippedEventEntry == IndexIntoFile::invalidEntry) break;
01135 
01136       if(eventSkipperByID_ && eventSkipperByID_->somethingToSkip()) {
01137         eventTree_.setEntryNumber(skippedEventEntry);
01138         fillThisEventAuxiliary();
01139         if(eventSkipperByID_->skipIt(runOfSkippedEvent, lumiOfSkippedEvent, eventAux_.id().event())) {
01140             continue;
01141         }
01142       }
01143       if(duplicateChecker_ &&
01144          !duplicateChecker_->checkDisabled() &&
01145          !duplicateChecker_->noDuplicatesInFile()) {
01146 
01147         eventTree_.setEntryNumber(skippedEventEntry);
01148         fillThisEventAuxiliary();
01149         if(duplicateChecker_->isDuplicateAndCheckActive(phIndexOfSkippedEvent,
01150                                                          runOfSkippedEvent,
01151                                                          lumiOfSkippedEvent,
01152                                                          eventAux_.id().event(),
01153                                                          file_)) {
01154           continue;
01155         }
01156       }
01157       --offset;
01158     }
01159 
01160     while(offset < 0) {
01161 
01162       if(duplicateChecker_) {
01163         duplicateChecker_->disable();
01164       }
01165 
01166       int phIndexOfEvent = IndexIntoFile::invalidIndex;
01167       RunNumber_t runOfEvent =  IndexIntoFile::invalidRun;
01168       LuminosityBlockNumber_t lumiOfEvent = IndexIntoFile::invalidLumi;
01169       EntryNumber_t eventEntry = IndexIntoFile::invalidEntry;
01170 
01171       indexIntoFileIter_.skipEventBackward(phIndexOfEvent,
01172                                            runOfEvent,
01173                                            lumiOfEvent,
01174                                            eventEntry);
01175 
01176       if(eventEntry == IndexIntoFile::invalidEntry) break;
01177 
01178       if(eventSkipperByID_ && eventSkipperByID_->somethingToSkip()) {
01179         eventTree_.setEntryNumber(eventEntry);
01180         fillEventAuxiliary();
01181         if(eventSkipperByID_->skipIt(runOfEvent, lumiOfEvent, eventAux_.id().event())) {
01182           continue;
01183         }
01184       }
01185       ++offset;
01186     }
01187     return (indexIntoFileIter_ == indexIntoFileEnd_);
01188   }
01189 
01190   bool
01191   RootFile::goToEvent(EventID const& eventID) {
01192 
01193     indexIntoFile_.fillEventNumbers();
01194 
01195     if(duplicateChecker_) {
01196       duplicateChecker_->disable();
01197     }
01198 
01199     IndexIntoFile::SortOrder sortOrder = IndexIntoFile::numericalOrder;
01200     if(noEventSort_) sortOrder = IndexIntoFile::firstAppearanceOrder;
01201 
01202     IndexIntoFile::IndexIntoFileItr iter =
01203       indexIntoFile_.findPosition(sortOrder, eventID.run(), eventID.luminosityBlock(), eventID.event());
01204 
01205     if(iter == indexIntoFile_.end(sortOrder)) {
01206       return false;
01207     }
01208     indexIntoFileIter_ = iter;
01209     return true;
01210   }
01211 
01212   // readEvent() is responsible for creating, and setting up, the
01213   // EventPrincipal.
01214   //
01215   //   1. create an EventPrincipal with a unique EventID
01216   //   2. For each entry in the provenance, put in one Group,
01217   //      holding the Provenance for the corresponding EDProduct.
01218   //   3. set up the caches in the EventPrincipal to know about this
01219   //      Group.
01220   //
01221   // We do *not* create the EDProduct instance (the equivalent of reading
01222   // the branch containing this EDProduct. That will be done by the Delayed Reader,
01223   //  when it is asked to do so.
01224   //
01225   EventPrincipal*
01226   RootFile::readEvent(EventPrincipal& cache, boost::shared_ptr<RootFile> rootFilePtr, boost::shared_ptr<LuminosityBlockPrincipal> lb) {
01227     assert(indexIntoFileIter_ != indexIntoFileEnd_);
01228     assert(indexIntoFileIter_.getEntryType() == IndexIntoFile::kEvent);
01229     // Set the entry in the tree, and read the event at that entry.
01230     eventTree_.setEntryNumber(indexIntoFileIter_.entry());
01231     EventPrincipal* ep = readCurrentEvent(cache, rootFilePtr, lb);
01232 
01233     assert(ep != 0);
01234     assert(eventAux().run() == indexIntoFileIter_.run() + forcedRunOffset_);
01235     assert(eventAux().luminosityBlock() == indexIntoFileIter_.lumi());
01236 
01237     ++indexIntoFileIter_;
01238     return ep;
01239   }
01240 
01241   // Reads event at the current entry in the event tree
01242   EventPrincipal*
01243   RootFile::readCurrentEvent(EventPrincipal& cache,
01244                              boost::shared_ptr<RootFile> rootFilePtr,
01245                              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(), rootFilePtr));
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 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 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           roottree::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         roottree::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         roottree::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));
01631       mapper->setDelayedRead(true);
01632       return mapper;
01633     }
01634   }
01635 
01636   boost::shared_ptr<BranchMapper>
01637   RootFile::makeBranchMapper(RootTree& rootTree, BranchType const& type) const {
01638     if(fileFormatVersion().splitProductIDs()) {
01639       return makeBranchMapperInRelease300(rootTree);
01640     } else if(fileFormatVersion().perEventProductIDs()) {
01641       return makeBranchMapperInRelease210(rootTree, type);
01642     } else if(fileFormatVersion().eventHistoryTree()) {
01643       return makeBranchMapperInRelease200(rootTree, type, *productRegistry_);
01644     } else {
01645       return makeBranchMapperInRelease180(rootTree, type, *productRegistry_);
01646     }
01647   }
01648   // end backward compatibility
01649 }