CMS 3D CMS Logo

CMSSW_4_4_3_patch1/src/IOPool/Input/src/RootTree.cc

Go to the documentation of this file.
00001 #include "RootTree.h"
00002 #include "RootDelayedReader.h"
00003 #include "FWCore/Utilities/interface/EDMException.h"
00004 #include "FWCore/Utilities/interface/Exception.h"
00005 #include "DataFormats/Provenance/interface/BranchDescription.h"
00006 #include "InputFile.h"
00007 #include "TTree.h"
00008 #include "TTreeIndex.h"
00009 #include "TTreeCache.h"
00010 
00011 #include <iostream>
00012 
00013 namespace edm {
00014   namespace {
00015     TBranch* getAuxiliaryBranch(TTree* tree, BranchType const& branchType) {
00016       TBranch* branch = tree->GetBranch(BranchTypeToAuxiliaryBranchName(branchType).c_str());
00017       if (branch == 0) {
00018         branch = tree->GetBranch(BranchTypeToAuxBranchName(branchType).c_str());
00019       }
00020       return branch;
00021     }
00022     TBranch* getProductProvenanceBranch(TTree* tree, BranchType const& branchType) {
00023       TBranch* branch = tree->GetBranch(BranchTypeToBranchEntryInfoBranchName(branchType).c_str());
00024       return branch;
00025     }
00026   }
00027   RootTree::RootTree(boost::shared_ptr<InputFile> filePtr,
00028                      FileFormatVersion const& fileFormatVersion,
00029                      BranchType const& branchType,
00030                      unsigned int maxVirtualSize,
00031                      unsigned int cacheSize,
00032                      unsigned int learningEntries) :
00033     filePtr_(filePtr),
00034     tree_(dynamic_cast<TTree*>(filePtr_.get() != 0 ? filePtr_->Get(BranchTypeToProductTreeName(branchType).c_str()) : 0)),
00035     metaTree_(dynamic_cast<TTree*>(filePtr_.get() != 0 ? filePtr_->Get(BranchTypeToMetaDataTreeName(branchType).c_str()) : 0)),
00036     branchType_(branchType),
00037     auxBranch_(tree_ ? getAuxiliaryBranch(tree_, branchType_) : 0),
00038     treeCache_(),
00039     rawTreeCache_(),
00040     entries_(tree_ ? tree_->GetEntries() : 0),
00041     entryNumber_(-1),
00042     branchNames_(),
00043     branches_(new BranchMap),
00044     trainNow_(false),
00045     switchOverEntry_(-1),
00046     learningEntries_(learningEntries),
00047     cacheSize_(cacheSize),
00048     rootDelayedReader_(new RootDelayedReader(*this, fileFormatVersion, filePtr)),
00049     branchEntryInfoBranch_(metaTree_ ? getProductProvenanceBranch(metaTree_, branchType_) : (tree_ ? getProductProvenanceBranch(tree_, branchType_) : 0)),
00050     infoTree_(dynamic_cast<TTree*>(filePtr_.get() != 0 ? filePtr->Get(BranchTypeToInfoTreeName(branchType).c_str()) : 0)) // backward compatibility
00051     {
00052       assert(tree_);
00053       setTreeMaxVirtualSize(maxVirtualSize);
00054       setCacheSize(cacheSize);
00055   }
00056 
00057   RootTree::~RootTree() {
00058   }
00059 
00060   bool
00061   RootTree::isValid() const {
00062     if (metaTree_ == 0 || metaTree_->GetNbranches() == 0) {
00063       return tree_ != 0 && auxBranch_ != 0;
00064     }
00065     if (tree_ != 0 && auxBranch_ != 0 && metaTree_ != 0) { // backward compatibility
00066       if (branchEntryInfoBranch_ != 0 || infoTree_ != 0) return true; // backward compatibility
00067       return (entries_ == metaTree_->GetEntries() && tree_->GetNbranches() <= metaTree_->GetNbranches() + 1);  // backward compatibility
00068     } // backward compatibility
00069     return false;
00070   }
00071 
00072   DelayedReader*
00073   RootTree::rootDelayedReader() const {
00074     rootDelayedReader_->reset();
00075     return rootDelayedReader_.get();
00076   }  
00077 
00078   void
00079   RootTree::setPresence(BranchDescription const& prod) {
00080       assert(isValid());
00081       prod.init();
00082       if(tree_->GetBranch(prod.branchName().c_str()) == 0){
00083         prod.setDropped();
00084       }
00085   }
00086 
00087   void
00088   RootTree::addBranch(BranchKey const& key,
00089                       BranchDescription const& prod,
00090                       std::string const& oldBranchName) {
00091       assert(isValid());
00092       prod.init();
00093       //use the translated branch name
00094       TBranch* branch = tree_->GetBranch(oldBranchName.c_str());
00095       roottree::BranchInfo info = roottree::BranchInfo(ConstBranchDescription(prod));
00096       info.productBranch_ = 0;
00097       if (prod.present()) {
00098         info.productBranch_ = branch;
00099         //we want the new branch name for the JobReport
00100         branchNames_.push_back(prod.branchName());
00101       }
00102       TTree* provTree = (metaTree_ != 0 ? metaTree_ : tree_);
00103       info.provenanceBranch_ = provTree->GetBranch(oldBranchName.c_str());
00104       branches_->insert(std::make_pair(key, info));
00105   }
00106 
00107   void
00108   RootTree::dropBranch(std::string const& oldBranchName) {
00109       //use the translated branch name
00110       TBranch* branch = tree_->GetBranch(oldBranchName.c_str());
00111       if (branch != 0) {
00112         TObjArray* leaves = tree_->GetListOfLeaves();
00113         int entries = leaves->GetEntries();
00114         for (int i = 0; i < entries; ++i) {
00115           TLeaf* leaf = (TLeaf*)(*leaves)[i];
00116           if (leaf == 0) continue;
00117           TBranch* br = leaf->GetBranch();
00118           if (br == 0) continue;
00119           if (br->GetMother() == branch) {
00120             leaves->Remove(leaf);
00121           }
00122         }
00123         leaves->Compress();
00124         tree_->GetListOfBranches()->Remove(branch);
00125         tree_->GetListOfBranches()->Compress();
00126         delete branch;
00127       }
00128   }
00129 
00130   roottree::BranchMap const&
00131   RootTree::branches() const {return *branches_;}
00132 
00133   void
00134   RootTree::setCacheSize(unsigned int cacheSize) {
00135     cacheSize_ = cacheSize;
00136     tree_->SetCacheSize(static_cast<Long64_t>(cacheSize));
00137     treeCache_.reset(dynamic_cast<TTreeCache*>(filePtr_->GetCacheRead()));
00138     filePtr_->SetCacheRead(0);
00139     rawTreeCache_.reset();
00140   }
00141 
00142   void
00143   RootTree::setTreeMaxVirtualSize(int treeMaxVirtualSize) {
00144     if (treeMaxVirtualSize >= 0) tree_->SetMaxVirtualSize(static_cast<Long64_t>(treeMaxVirtualSize));
00145   }
00146 
00147   void
00148   RootTree::setEntryNumber(EntryNumber theEntryNumber) {
00149     filePtr_->SetCacheRead(treeCache_.get());
00150     entryNumber_ = theEntryNumber;
00151     tree_->LoadTree(entryNumber_);
00152     filePtr_->SetCacheRead(0);
00153     if(treeCache_ && trainNow_ && entryNumber_ >= 0) {
00154       startTraining();
00155       trainNow_ = false;
00156     }
00157     if (treeCache_ && treeCache_->IsLearning() && switchOverEntry_ >= 0 && entryNumber_ >= switchOverEntry_) {
00158       stopTraining();
00159     }
00160   }
00161 
00162   void
00163   RootTree::getEntry(TBranch* branch, EntryNumber entryNumber) const {
00164     try {
00165       if (!treeCache_) {
00166         filePtr_->SetCacheRead(0);
00167         branch->GetEntry(entryNumber);
00168       } else if (treeCache_->IsLearning() && rawTreeCache_) {
00169         treeCache_->AddBranch(branch, kTRUE);
00170         filePtr_->SetCacheRead(rawTreeCache_.get());
00171         branch->GetEntry(entryNumber);
00172         filePtr_->SetCacheRead(0);
00173       } else {
00174         filePtr_->SetCacheRead(treeCache_.get());
00175         branch->GetEntry(entryNumber);
00176         filePtr_->SetCacheRead(0);
00177       }
00178     } catch(cms::Exception const& e) {
00179       // We make sure the treeCache_ is detached from the file,
00180       // so that ROOT does not also delete it.
00181       filePtr_->SetCacheRead(0);
00182       throw Exception(errors::FileReadError, "", e);
00183     }
00184   }
00185 
00186   void
00187   RootTree::startTraining() {
00188     if (cacheSize_ == 0) {
00189       return;
00190     }
00191     assert(treeCache_ && treeCache_->GetOwner() == tree_);
00192     assert(branchType_ == InEvent);
00193     assert(!rawTreeCache_);
00194     treeCache_->SetLearnEntries(learningEntries_);
00195     tree_->SetCacheSize(static_cast<Long64_t>(cacheSize_));
00196     rawTreeCache_.reset(dynamic_cast<TTreeCache *>(filePtr_->GetCacheRead()));
00197     filePtr_->SetCacheRead(0);
00198     rawTreeCache_->SetLearnEntries(0);
00199     switchOverEntry_ = entryNumber_ + learningEntries_;
00200     rawTreeCache_->StartLearningPhase();
00201     rawTreeCache_->SetEntryRange(entryNumber_, switchOverEntry_);
00202     rawTreeCache_->AddBranch("*", kTRUE);
00203     rawTreeCache_->StopLearningPhase();
00204     treeCache_->StartLearningPhase();
00205     treeCache_->SetEntryRange(switchOverEntry_, tree_->GetEntries());
00206     treeCache_->AddBranch(poolNames::branchListIndexesBranchName().c_str(), kTRUE);
00207     treeCache_->AddBranch(BranchTypeToAuxiliaryBranchName(branchType_).c_str(), kTRUE);
00208   }
00209 
00210   void
00211   RootTree::stopTraining() {
00212     filePtr_->SetCacheRead(treeCache_.get());
00213     treeCache_->StopLearningPhase();
00214     rawTreeCache_.reset();
00215   }
00216 
00217   void
00218   RootTree::close () {
00219     // The TFile is about to be closed, and destructed.
00220     // Just to play it safe, zero all pointers to quantities that are owned by the TFile.
00221     auxBranch_  = branchEntryInfoBranch_ = 0;
00222     tree_ = metaTree_ = infoTree_ = 0;
00223     // We own the treeCache_.
00224     // We make sure the treeCache_ is detached from the file,
00225     // so that ROOT does not also delete it.
00226     filePtr_->SetCacheRead(0);
00227     // We give up our shared ownership of the TFile itself.
00228     filePtr_.reset();
00229   }
00230 
00231   void
00232   RootTree::trainCache(char const* branchNames) {
00233     if (cacheSize_ == 0) {
00234       return;
00235     }
00236     tree_->LoadTree(0);
00237     assert(treeCache_);
00238     filePtr_->SetCacheRead(treeCache_.get());
00239     assert(treeCache_->GetOwner() == tree_);
00240     treeCache_->StartLearningPhase();
00241     treeCache_->SetEntryRange(0, tree_->GetEntries());
00242     treeCache_->AddBranch(branchNames, kTRUE);
00243     treeCache_->StopLearningPhase();
00244     // We own the treeCache_.
00245     // We make sure the treeCache_ is detached from the file,
00246     // so that ROOT does not also delete it.
00247     filePtr_->SetCacheRead(0);
00248   }
00249 
00250   namespace roottree {
00251     Int_t
00252     getEntry(TBranch* branch, EntryNumber entryNumber) {
00253       Int_t n = 0;
00254       try {
00255         n = branch->GetEntry(entryNumber);
00256       }
00257       catch(cms::Exception const& e) {
00258         throw Exception(errors::FileReadError, "", e);
00259       }
00260       return n;
00261     }
00262 
00263     Int_t
00264     getEntry(TTree* tree, EntryNumber entryNumber) {
00265       Int_t n = 0;
00266       try {
00267         n = tree->GetEntry(entryNumber);
00268       }
00269       catch(cms::Exception const& e) {
00270         throw Exception (errors::FileReadError, "", e);
00271       }
00272       return n;
00273     }
00274 
00275     std::auto_ptr<TTreeCache>
00276     trainCache(TTree* tree, InputFile& file, unsigned int cacheSize, char const* branchNames) {
00277       tree->LoadTree(0);
00278       tree->SetCacheSize(cacheSize);
00279       std::auto_ptr<TTreeCache> treeCache(dynamic_cast<TTreeCache*>(file.GetCacheRead()));
00280       if (0 != treeCache.get()) {
00281         treeCache->StartLearningPhase();
00282         treeCache->SetEntryRange(0, tree->GetEntries());
00283         treeCache->AddBranch(branchNames, kTRUE);
00284         treeCache->StopLearningPhase();
00285       }
00286       // We own the treeCache_.
00287       // We make sure the treeCache_ is detached from the file,
00288       // so that ROOT does not also delete it.
00289       file.SetCacheRead(0);
00290       return treeCache;
00291     }
00292   }
00293 }