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 treeAutoFlush_(tree_ ? tree_->GetAutoFlush() : 0),
00048 rootDelayedReader_(new RootDelayedReader(*this, 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))
00051 {
00052 assert(tree_);
00053
00054
00055 if (treeAutoFlush_ < 0) {
00056
00057 Long64_t averageEventSizeBytes = tree_->GetZipBytes() / (tree_->GetEntries()+1) + 1;
00058 treeAutoFlush_ = cacheSize_/averageEventSizeBytes+1;
00059 }
00060 setTreeMaxVirtualSize(maxVirtualSize);
00061 setCacheSize(cacheSize);
00062 }
00063
00064 RootTree::~RootTree() {
00065 }
00066
00067 bool
00068 RootTree::isValid() const {
00069 if (metaTree_ == 0 || metaTree_->GetNbranches() == 0) {
00070 return tree_ != 0 && auxBranch_ != 0;
00071 }
00072 if (tree_ != 0 && auxBranch_ != 0 && metaTree_ != 0) {
00073 if (branchEntryInfoBranch_ != 0 || infoTree_ != 0) return true;
00074 return (entries_ == metaTree_->GetEntries() && tree_->GetNbranches() <= metaTree_->GetNbranches() + 1);
00075 }
00076 return false;
00077 }
00078
00079 DelayedReader*
00080 RootTree::rootDelayedReader() const {
00081 rootDelayedReader_->reset();
00082 return rootDelayedReader_.get();
00083 }
00084
00085 void
00086 RootTree::setPresence(BranchDescription const& prod, std::string const& oldBranchName) {
00087 assert(isValid());
00088 prod.init();
00089 if(tree_->GetBranch(oldBranchName.c_str()) == 0){
00090 prod.setDropped();
00091 }
00092 }
00093
00094 void
00095 RootTree::addBranch(BranchKey const& key,
00096 BranchDescription const& prod,
00097 std::string const& oldBranchName) {
00098 assert(isValid());
00099 prod.init();
00100
00101 TBranch* branch = tree_->GetBranch(oldBranchName.c_str());
00102 roottree::BranchInfo info = roottree::BranchInfo(ConstBranchDescription(prod));
00103 info.productBranch_ = 0;
00104 if (prod.present()) {
00105 info.productBranch_ = branch;
00106
00107 branchNames_.push_back(prod.branchName());
00108 }
00109 TTree* provTree = (metaTree_ != 0 ? metaTree_ : tree_);
00110 info.provenanceBranch_ = provTree->GetBranch(oldBranchName.c_str());
00111 branches_->insert(std::make_pair(key, info));
00112 }
00113
00114 void
00115 RootTree::dropBranch(std::string const& oldBranchName) {
00116
00117 TBranch* branch = tree_->GetBranch(oldBranchName.c_str());
00118 if (branch != 0) {
00119 TObjArray* leaves = tree_->GetListOfLeaves();
00120 int entries = leaves->GetEntries();
00121 for (int i = 0; i < entries; ++i) {
00122 TLeaf* leaf = (TLeaf*)(*leaves)[i];
00123 if (leaf == 0) continue;
00124 TBranch* br = leaf->GetBranch();
00125 if (br == 0) continue;
00126 if (br->GetMother() == branch) {
00127 leaves->Remove(leaf);
00128 }
00129 }
00130 leaves->Compress();
00131 tree_->GetListOfBranches()->Remove(branch);
00132 tree_->GetListOfBranches()->Compress();
00133 delete branch;
00134 }
00135 }
00136
00137 roottree::BranchMap const&
00138 RootTree::branches() const {return *branches_;}
00139
00140 void
00141 RootTree::setCacheSize(unsigned int cacheSize) {
00142 cacheSize_ = cacheSize;
00143 tree_->SetCacheSize(static_cast<Long64_t>(cacheSize));
00144 treeCache_.reset(dynamic_cast<TTreeCache*>(filePtr_->GetCacheRead()));
00145 filePtr_->SetCacheRead(0);
00146 rawTreeCache_.reset();
00147 }
00148
00149 void
00150 RootTree::setTreeMaxVirtualSize(int treeMaxVirtualSize) {
00151 if (treeMaxVirtualSize >= 0) tree_->SetMaxVirtualSize(static_cast<Long64_t>(treeMaxVirtualSize));
00152 }
00153
00154 void
00155 RootTree::setEntryNumber(EntryNumber theEntryNumber) {
00156 filePtr_->SetCacheRead(treeCache_.get());
00157
00158
00159
00160
00161
00162
00163 if ((theEntryNumber < static_cast<EntryNumber>(entryNumber_-treeAutoFlush_)) &&
00164 (treeCache_) && (!treeCache_->IsLearning()) && (entries_ > 0) && (switchOverEntry_ >= 0)) {
00165 treeCache_->SetEntryRange(theEntryNumber, entries_);
00166 treeCache_->FillBuffer();
00167 }
00168
00169 entryNumber_ = theEntryNumber;
00170 tree_->LoadTree(entryNumber_);
00171 filePtr_->SetCacheRead(0);
00172 if(treeCache_ && trainNow_ && entryNumber_ >= 0) {
00173 startTraining();
00174 trainNow_ = false;
00175 }
00176 if (treeCache_ && treeCache_->IsLearning() && switchOverEntry_ >= 0 && entryNumber_ >= switchOverEntry_) {
00177 stopTraining();
00178 }
00179 }
00180
00181 void
00182 RootTree::getEntry(TBranch* branch, EntryNumber entryNumber) const {
00183 try {
00184 if (!treeCache_) {
00185 filePtr_->SetCacheRead(0);
00186 branch->GetEntry(entryNumber);
00187 } else if (treeCache_->IsLearning() && rawTreeCache_) {
00188 treeCache_->AddBranch(branch, kTRUE);
00189 filePtr_->SetCacheRead(rawTreeCache_.get());
00190 branch->GetEntry(entryNumber);
00191 filePtr_->SetCacheRead(0);
00192 } else {
00193 filePtr_->SetCacheRead(treeCache_.get());
00194 branch->GetEntry(entryNumber);
00195 filePtr_->SetCacheRead(0);
00196 }
00197 } catch(cms::Exception const& e) {
00198
00199
00200 filePtr_->SetCacheRead(0);
00201 Exception t(errors::FileReadError, "", e);
00202 t.addContext(std::string("Reading branch ")+branch->GetName());
00203 throw t;
00204 }
00205 }
00206
00207 void
00208 RootTree::startTraining() {
00209 if (cacheSize_ == 0) {
00210 return;
00211 }
00212 assert(treeCache_ && treeCache_->GetOwner() == tree_);
00213 assert(branchType_ == InEvent);
00214 assert(!rawTreeCache_);
00215 treeCache_->SetLearnEntries(learningEntries_);
00216 tree_->SetCacheSize(static_cast<Long64_t>(cacheSize_));
00217 rawTreeCache_.reset(dynamic_cast<TTreeCache *>(filePtr_->GetCacheRead()));
00218 filePtr_->SetCacheRead(0);
00219 rawTreeCache_->SetLearnEntries(0);
00220 switchOverEntry_ = entryNumber_ + learningEntries_;
00221 rawTreeCache_->StartLearningPhase();
00222 rawTreeCache_->SetEntryRange(entryNumber_, switchOverEntry_);
00223 rawTreeCache_->AddBranch("*", kTRUE);
00224 rawTreeCache_->StopLearningPhase();
00225 treeCache_->StartLearningPhase();
00226 treeCache_->SetEntryRange(switchOverEntry_, tree_->GetEntries());
00227 treeCache_->AddBranch(poolNames::branchListIndexesBranchName().c_str(), kTRUE);
00228 treeCache_->AddBranch(BranchTypeToAuxiliaryBranchName(branchType_).c_str(), kTRUE);
00229 }
00230
00231 void
00232 RootTree::stopTraining() {
00233 filePtr_->SetCacheRead(treeCache_.get());
00234 treeCache_->StopLearningPhase();
00235 rawTreeCache_.reset();
00236 }
00237
00238 void
00239 RootTree::close () {
00240
00241
00242 auxBranch_ = branchEntryInfoBranch_ = 0;
00243 tree_ = metaTree_ = infoTree_ = 0;
00244
00245
00246
00247 filePtr_->SetCacheRead(0);
00248
00249 filePtr_.reset();
00250 }
00251
00252 void
00253 RootTree::trainCache(char const* branchNames) {
00254 if (cacheSize_ == 0) {
00255 return;
00256 }
00257 tree_->LoadTree(0);
00258 assert(treeCache_);
00259 filePtr_->SetCacheRead(treeCache_.get());
00260 assert(treeCache_->GetOwner() == tree_);
00261 treeCache_->StartLearningPhase();
00262 treeCache_->SetEntryRange(0, tree_->GetEntries());
00263 treeCache_->AddBranch(branchNames, kTRUE);
00264 treeCache_->StopLearningPhase();
00265
00266
00267
00268 filePtr_->SetCacheRead(0);
00269 }
00270
00271 namespace roottree {
00272 Int_t
00273 getEntry(TBranch* branch, EntryNumber entryNumber) {
00274 Int_t n = 0;
00275 try {
00276 n = branch->GetEntry(entryNumber);
00277 }
00278 catch(cms::Exception const& e) {
00279 throw Exception(errors::FileReadError, "", e);
00280 }
00281 return n;
00282 }
00283
00284 Int_t
00285 getEntry(TTree* tree, EntryNumber entryNumber) {
00286 Int_t n = 0;
00287 try {
00288 n = tree->GetEntry(entryNumber);
00289 }
00290 catch(cms::Exception const& e) {
00291 throw Exception (errors::FileReadError, "", e);
00292 }
00293 return n;
00294 }
00295
00296 std::unique_ptr<TTreeCache>
00297 trainCache(TTree* tree, InputFile& file, unsigned int cacheSize, char const* branchNames) {
00298 tree->LoadTree(0);
00299 tree->SetCacheSize(cacheSize);
00300 std::unique_ptr<TTreeCache> treeCache(dynamic_cast<TTreeCache*>(file.GetCacheRead()));
00301 if (0 != treeCache.get()) {
00302 treeCache->StartLearningPhase();
00303 treeCache->SetEntryRange(0, tree->GetEntries());
00304 treeCache->AddBranch(branchNames, kTRUE);
00305 treeCache->StopLearningPhase();
00306 }
00307
00308
00309
00310 file.SetCacheRead(0);
00311 return treeCache;
00312 }
00313 }
00314 }