CMS 3D CMS Logo

/data/doxygen/doxygen-1.7.3/gen/CMSSW_4_2_8/src/IOPool/Input/src/RootTree.cc

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