CMS 3D CMS Logo

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