File indexing completed on 2025-06-06 01:33:27
0001 #include "DataFormats/Provenance/interface/BranchType.h"
0002 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0003 #include "FWCore/Utilities/interface/EDMException.h"
0004 #include "FWCore/Utilities/interface/Exception.h"
0005 #include "IOPool/Common/interface/getWrapperBasePtr.h"
0006
0007 #include "InputFile.h"
0008 #include "RootTree.h"
0009 #include "RootDelayedReader.h"
0010 #include "RootPromptReadDelayedReader.h"
0011
0012 #include "TTree.h"
0013 #include "TTreeCache.h"
0014 #include "TLeaf.h"
0015
0016 #include "oneapi/tbb/task_arena.h"
0017 #include <cassert>
0018
0019 namespace edm {
0020 namespace {
0021 TBranch* getAuxiliaryBranch(TTree* tree, BranchType const& branchType) {
0022 TBranch* branch = tree->GetBranch(BranchTypeToAuxiliaryBranchName(branchType).c_str());
0023 if (branch == nullptr) {
0024 branch = tree->GetBranch(BranchTypeToAuxBranchName(branchType).c_str());
0025 }
0026 return branch;
0027 }
0028 TBranch* getProductProvenanceBranch(TTree* tree, BranchType const& branchType) {
0029 TBranch* branch = tree->GetBranch(BranchTypeToBranchEntryInfoBranchName(branchType).c_str());
0030 return branch;
0031 }
0032
0033 std::unique_ptr<RootDelayedReaderBase> makeRootDelayedReader(RootTree const& tree,
0034 std::shared_ptr<InputFile> filePtr,
0035 InputType inputType,
0036 unsigned int nIndexes,
0037 bool promptRead) {
0038 if (promptRead) {
0039 return std::make_unique<RootPromptReadDelayedReader>(tree, filePtr, inputType, nIndexes);
0040 }
0041 return std::make_unique<RootDelayedReader>(tree, filePtr, inputType);
0042 }
0043 }
0044
0045
0046
0047 RootTree::RootTree(std::shared_ptr<InputFile> filePtr,
0048 BranchType const& branchType,
0049 unsigned int nIndexes,
0050 unsigned int learningEntries,
0051 bool enablePrefetching,
0052 bool promptRead,
0053 InputType inputType)
0054 : filePtr_(filePtr),
0055 branchType_(branchType),
0056 entryNumberForIndex_(std::make_unique<std::vector<EntryNumber>>(nIndexes, IndexIntoFile::invalidEntry)),
0057 learningEntries_(learningEntries),
0058 enablePrefetching_(enablePrefetching),
0059 enableTriggerCache_(branchType_ == InEvent),
0060 promptRead_(promptRead),
0061 rootDelayedReader_(makeRootDelayedReader(*this, filePtr, inputType, nIndexes, promptRead)) {}
0062
0063
0064 RootTree::RootTree(std::shared_ptr<InputFile> filePtr,
0065 BranchType const& branchType,
0066 unsigned int nIndexes,
0067 Options const& options,
0068 unsigned int learningEntries,
0069 InputType inputType)
0070 : RootTree(
0071 filePtr, branchType, nIndexes, learningEntries, options.enablePrefetching, options.promptReading, inputType) {
0072 init(BranchTypeToProductTreeName(branchType), options.treeMaxVirtualSize, options.treeCacheSize);
0073 metaTree_ = dynamic_cast<TTree*>(filePtr_->Get(BranchTypeToMetaDataTreeName(branchType).c_str()));
0074 auxBranch_ = getAuxiliaryBranch(tree_, branchType_);
0075 branchEntryInfoBranch_ =
0076 metaTree_ ? getProductProvenanceBranch(metaTree_, branchType_) : getProductProvenanceBranch(tree_, branchType_);
0077 infoTree_ =
0078 dynamic_cast<TTree*>(filePtr->Get(BranchTypeToInfoTreeName(branchType).c_str()));
0079 }
0080
0081
0082 RootTree::RootTree(std::shared_ptr<InputFile> filePtr,
0083 BranchType const& branchType,
0084 std::string const& processName,
0085 unsigned int nIndexes,
0086 Options const& options,
0087 unsigned int learningEntries,
0088 InputType inputType)
0089 : RootTree(
0090 filePtr, branchType, nIndexes, learningEntries, options.enablePrefetching, options.promptReading, inputType) {
0091 processName_ = processName;
0092 init(BranchTypeToProductTreeName(branchType, processName), options.treeMaxVirtualSize, options.treeCacheSize);
0093 }
0094
0095 void RootTree::init(std::string const& productTreeName, unsigned int maxVirtualSize, unsigned int cacheSize) {
0096 if (filePtr_.get() != nullptr) {
0097 tree_ = dynamic_cast<TTree*>(filePtr_->Get(productTreeName.c_str()));
0098 }
0099 if (not tree_) {
0100 throw cms::Exception("WrongFileFormat")
0101 << "The ROOT file does not contain a TTree named " << productTreeName
0102 << "\n This is either not an edm ROOT file or is one that has been corrupted.";
0103 }
0104 entries_ = tree_->GetEntries();
0105
0106
0107
0108 long treeAutoFlush = tree_->GetAutoFlush();
0109 if (treeAutoFlush < 0) {
0110
0111 Long64_t averageEventSizeBytes = tree_->GetZipBytes() / (tree_->GetEntries() + 1) + 1;
0112 treeAutoFlush_ = cacheSize / averageEventSizeBytes + 1;
0113 } else {
0114 treeAutoFlush_ = treeAutoFlush;
0115 }
0116 if (treeAutoFlush_ < learningEntries_) {
0117 learningEntries_ = treeAutoFlush_;
0118 }
0119 setTreeMaxVirtualSize(maxVirtualSize);
0120 setCacheSize(cacheSize);
0121 if (branchType_ == InEvent) {
0122 Int_t branchCount = tree_->GetListOfBranches()->GetEntriesFast();
0123 trainedSet_.reserve(branchCount);
0124 triggerSet_.reserve(branchCount);
0125 }
0126 }
0127
0128 RootTree::~RootTree() {}
0129
0130 RootTree::EntryNumber const& RootTree::entryNumberForIndex(unsigned int index) const {
0131 assert(index < entryNumberForIndex_->size());
0132 return (*entryNumberForIndex_)[index];
0133 }
0134
0135 void RootTree::insertEntryForIndex(unsigned int index) {
0136 assert(index < entryNumberForIndex_->size());
0137 (*entryNumberForIndex_)[index] = entryNumber();
0138 }
0139
0140 bool RootTree::isValid() const {
0141
0142 if (branchType_ == InProcess) {
0143 return tree_ != nullptr;
0144 }
0145
0146 if (metaTree_ == nullptr || metaTree_->GetNbranches() == 0) {
0147 return tree_ != nullptr && auxBranch_ != nullptr;
0148 }
0149
0150 if (tree_ != nullptr && auxBranch_ != nullptr && metaTree_ != nullptr) {
0151 if (branchEntryInfoBranch_ != nullptr || infoTree_ != nullptr)
0152 return true;
0153 return (entries_ == metaTree_->GetEntries() &&
0154 tree_->GetNbranches() <= metaTree_->GetNbranches() + 1);
0155 }
0156 return false;
0157 }
0158
0159 DelayedReader* RootTree::resetAndGetRootDelayedReader() const {
0160 rootDelayedReader_->reset();
0161 return rootDelayedReader_.get();
0162 }
0163
0164 RootDelayedReaderBase* RootTree::rootDelayedReader() const { return rootDelayedReader_.get(); }
0165
0166 void RootTree::setPresence(ProductDescription& prod, std::string const& oldBranchName) {
0167 assert(isValid());
0168 if (tree_->GetBranch(oldBranchName.c_str()) == nullptr) {
0169 prod.setDropped(true);
0170 }
0171 }
0172
0173 void roottree::BranchInfo::setBranch(TBranch* branch, TClass const* wrapperBaseTClass) {
0174 productBranch_ = branch;
0175 if (branch) {
0176 classCache_ = TClass::GetClass(productDescription_.wrappedName().c_str());
0177 offsetToWrapperBase_ = classCache_->GetBaseClassOffset(wrapperBaseTClass);
0178 }
0179 }
0180 std::unique_ptr<WrapperBase> roottree::BranchInfo::newWrapper() const {
0181 assert(nullptr != classCache_);
0182 void* p = classCache_->New();
0183 return getWrapperBasePtr(p, offsetToWrapperBase_);
0184 }
0185
0186 void RootTree::addBranch(ProductDescription const& prod, std::string const& oldBranchName) {
0187 assert(isValid());
0188 static TClass const* const wrapperBaseTClass = TClass::GetClass("edm::WrapperBase");
0189
0190 TBranch* branch = tree_->GetBranch(oldBranchName.c_str());
0191 roottree::BranchInfo info = roottree::BranchInfo(prod);
0192 info.productBranch_ = nullptr;
0193 if (prod.present()) {
0194 info.setBranch(branch, wrapperBaseTClass);
0195
0196 branchNames_.push_back(prod.branchName());
0197 }
0198 branches_.insert(prod.branchID(), info);
0199 }
0200
0201 void RootTree::dropBranch(std::string const& oldBranchName) {
0202
0203 TBranch* branch = tree_->GetBranch(oldBranchName.c_str());
0204 if (branch != nullptr) {
0205 TObjArray* leaves = tree_->GetListOfLeaves();
0206 int entries = leaves->GetEntries();
0207 for (int i = 0; i < entries; ++i) {
0208 TLeaf* leaf = (TLeaf*)(*leaves)[i];
0209 if (leaf == nullptr)
0210 continue;
0211 TBranch* br = leaf->GetBranch();
0212 if (br == nullptr)
0213 continue;
0214 if (br->GetMother() == branch) {
0215 leaves->Remove(leaf);
0216 }
0217 }
0218 leaves->Compress();
0219 tree_->GetListOfBranches()->Remove(branch);
0220 tree_->GetListOfBranches()->Compress();
0221 delete branch;
0222 }
0223 }
0224
0225 roottree::BranchMap const& RootTree::branches() const { return branches_; }
0226
0227 std::shared_ptr<TTreeCache> RootTree::createCacheWithSize(unsigned int cacheSize) const {
0228 return filePtr_->createCacheWithSize(*tree_, cacheSize);
0229 }
0230
0231 void RootTree::setCacheSize(unsigned int cacheSize) {
0232 cacheSize_ = cacheSize;
0233 treeCache_ = createCacheWithSize(cacheSize);
0234 if (treeCache_)
0235 treeCache_->SetEnablePrefetching(enablePrefetching_);
0236 rawTreeCache_.reset();
0237 }
0238
0239 void RootTree::setTreeMaxVirtualSize(int treeMaxVirtualSize) {
0240 if (treeMaxVirtualSize >= 0)
0241 tree_->SetMaxVirtualSize(static_cast<Long64_t>(treeMaxVirtualSize));
0242 }
0243
0244 bool RootTree::nextWithCache() {
0245 bool returnValue = ++entryNumber_ < entries_;
0246 if (returnValue) {
0247 setEntryNumber(entryNumber_);
0248 }
0249 return returnValue;
0250 }
0251
0252 void RootTree::setEntryNumber(EntryNumber theEntryNumber) {
0253 {
0254 auto guard = filePtr_->setCacheReadTemporarily(treeCache_.get(), tree_);
0255
0256
0257
0258
0259
0260
0261 if (theEntryNumber < entryNumber_ and theEntryNumber >= 0) {
0262
0263 if (switchOverEntry_ > tree_->GetEntries()) {
0264 switchOverEntry_ = switchOverEntry_ - tree_->GetEntries();
0265 if (rawTreeCache_) {
0266 rawTreeCache_->SetEntryRange(theEntryNumber, switchOverEntry_);
0267 rawTreeCache_->FillBuffer();
0268 }
0269 }
0270 if (performedSwitchOver_ and triggerTreeCache_) {
0271
0272
0273 triggerTreeCache_->SetEntryRange(theEntryNumber, tree_->GetEntries());
0274 } else if (rawTriggerTreeCache_) {
0275
0276 rawTriggerSwitchOverEntry_ = -1;
0277 TTree::TClusterIterator clusterIter = tree_->GetClusterIterator(theEntryNumber);
0278 while ((rawTriggerSwitchOverEntry_ < theEntryNumber) || (rawTriggerSwitchOverEntry_ <= 0)) {
0279 rawTriggerSwitchOverEntry_ = clusterIter();
0280 }
0281 rawTriggerTreeCache_->SetEntryRange(theEntryNumber, rawTriggerSwitchOverEntry_);
0282 }
0283 }
0284 if ((theEntryNumber < static_cast<EntryNumber>(entryNumber_ - treeAutoFlush_)) && (treeCache_) &&
0285 (!treeCache_->IsLearning()) && (entries_ > 0) && (switchOverEntry_ >= 0)) {
0286 treeCache_->SetEntryRange(theEntryNumber, entries_);
0287 treeCache_->FillBuffer();
0288 }
0289
0290 entryNumber_ = theEntryNumber;
0291 tree_->LoadTree(entryNumber_);
0292
0293 }
0294 if (treeCache_ && trainNow_ && entryNumber_ >= 0) {
0295 startTraining();
0296 trainNow_ = false;
0297 trainedSet_.clear();
0298 triggerSet_.clear();
0299 rawTriggerSwitchOverEntry_ = -1;
0300 }
0301 if (not promptRead_ && treeCache_ && treeCache_->IsLearning() && switchOverEntry_ >= 0 &&
0302 entryNumber_ >= switchOverEntry_) {
0303 stopTraining();
0304 }
0305 }
0306
0307
0308
0309 inline TTreeCache* RootTree::checkTriggerCache(TBranch* branch, EntryNumber entryNumber) const {
0310 if (!treeCache_->IsAsyncReading() && enableTriggerCache_ && (trainedSet_.find(branch) == trainedSet_.end())) {
0311 return checkTriggerCacheImpl(branch, entryNumber);
0312 } else {
0313 return nullptr;
0314 }
0315 }
0316
0317
0318
0319 TTreeCache* RootTree::checkTriggerCacheImpl(TBranch* branch, EntryNumber entryNumber) const {
0320
0321
0322
0323 if (triggerSet_.find(branch) == triggerSet_.end()) {
0324 triggerSet_.insert(branch);
0325 if (triggerTreeCache_.get()) {
0326 triggerTreeCache_->AddBranch(branch, kTRUE);
0327 }
0328 }
0329
0330 if (rawTriggerSwitchOverEntry_ < 0) {
0331
0332
0333
0334
0335
0336
0337
0338
0339 TTree::TClusterIterator clusterIter = tree_->GetClusterIterator(entryNumber);
0340 while ((rawTriggerSwitchOverEntry_ < entryNumber) || (rawTriggerSwitchOverEntry_ <= 0)) {
0341 rawTriggerSwitchOverEntry_ = clusterIter();
0342 }
0343
0344
0345
0346 rawTriggerTreeCache_ = createCacheWithSize(5 * 1024 * 1024);
0347 if (rawTriggerTreeCache_)
0348 rawTriggerTreeCache_->SetEnablePrefetching(false);
0349 TObjArray* branches = tree_->GetListOfBranches();
0350 int branchCount = branches->GetEntriesFast();
0351
0352
0353 rawTriggerTreeCache_->SetLearnEntries(0);
0354 rawTriggerTreeCache_->SetEntryRange(entryNumber, rawTriggerSwitchOverEntry_);
0355 for (int i = 0; i < branchCount; i++) {
0356 TBranch* tmp_branch = (TBranch*)branches->UncheckedAt(i);
0357 if (trainedSet_.find(tmp_branch) != trainedSet_.end()) {
0358 continue;
0359 }
0360 rawTriggerTreeCache_->AddBranch(tmp_branch, kTRUE);
0361 }
0362 performedSwitchOver_ = false;
0363 rawTriggerTreeCache_->StopLearningPhase();
0364
0365 return rawTriggerTreeCache_.get();
0366 } else if (!performedSwitchOver_ and entryNumber_ < rawTriggerSwitchOverEntry_) {
0367
0368 return rawTriggerTreeCache_.get();
0369 } else if (rawTriggerSwitchOverEntry_ > 0) {
0370
0371
0372 if (!performedSwitchOver_) {
0373 rawTriggerTreeCache_.reset();
0374 performedSwitchOver_ = true;
0375
0376
0377 triggerTreeCache_ = createCacheWithSize(5 * 1024 * 1024);
0378 triggerTreeCache_->SetEnablePrefetching(false);
0379 triggerTreeCache_->SetLearnEntries(0);
0380 triggerTreeCache_->SetEntryRange(entryNumber, tree_->GetEntries());
0381 for (std::unordered_set<TBranch*>::const_iterator it = triggerSet_.begin(), itEnd = triggerSet_.end();
0382 it != itEnd;
0383 it++) {
0384 triggerTreeCache_->AddBranch(*it, kTRUE);
0385 }
0386 triggerTreeCache_->StopLearningPhase();
0387 }
0388 return triggerTreeCache_.get();
0389 }
0390
0391
0392 assert(false);
0393 return nullptr;
0394 }
0395
0396 inline TTreeCache* RootTree::selectCache(TBranch* branch, EntryNumber entryNumber) const {
0397 TTreeCache* triggerCache = nullptr;
0398 if (promptRead_) {
0399 return rawTreeCache_.get();
0400 }
0401 if (!treeCache_) {
0402 return nullptr;
0403 } else if (treeCache_->IsLearning() && rawTreeCache_) {
0404 treeCache_->AddBranch(branch, kTRUE);
0405 trainedSet_.insert(branch);
0406 return rawTreeCache_.get();
0407 } else if ((triggerCache = checkTriggerCache(branch, entryNumber))) {
0408
0409
0410 return triggerCache;
0411 } else {
0412
0413 return treeCache_.get();
0414 }
0415 }
0416 TTreeCache* RootTree::getAuxCache(TBranch* auxBranch) const {
0417 if (not auxCache_ and cacheSize_ > 0) {
0418 auxCache_ = createCacheWithSize(1 * 1024 * 1024);
0419 if (auxCache_) {
0420 auxCache_->SetEnablePrefetching(enablePrefetching_);
0421 auxCache_->SetLearnEntries(0);
0422 auxCache_->StartLearningPhase();
0423 auxCache_->SetEntryRange(0, tree_->GetEntries());
0424 auxCache_->AddBranch(auxBranch->GetName(), kTRUE);
0425 auxCache_->StopLearningPhase();
0426 }
0427 }
0428 return auxCache_.get();
0429 }
0430
0431 void RootTree::getEntryForAllBranches() const {
0432 oneapi::tbb::this_task_arena::isolate([&]() {
0433 auto guard = filePtr_->setCacheReadTemporarily(treeCache_.get(), tree_);
0434 tree_->GetEntry(entryNumber_);
0435 });
0436 }
0437
0438 void RootTree::getEntry(TBranch* branch, EntryNumber entryNumber) const {
0439 getEntryUsingCache(branch, entryNumber, selectCache(branch, entryNumber));
0440 }
0441
0442 inline void RootTree::getEntryUsingCache(TBranch* branch, EntryNumber entryNumber, TTreeCache* cache) const {
0443 LogTrace("IOTrace").format(
0444 "RootTree::getEntryUsingCache() begin for branch {} entry {}", branch->GetName(), entryNumber);
0445 try {
0446 auto guard = filePtr_->setCacheReadTemporarily(cache, tree_);
0447 branch->GetEntry(entryNumber);
0448 } catch (cms::Exception const& e) {
0449
0450
0451 Exception t(errors::FileReadError, "", e);
0452 t.addContext(std::string("Reading branch ") + branch->GetName());
0453 throw t;
0454 } catch (std::exception const& e) {
0455 Exception t(errors::FileReadError);
0456 t << e.what();
0457 t.addContext(std::string("Reading branch ") + branch->GetName());
0458 throw t;
0459 } catch (...) {
0460 Exception t(errors::FileReadError);
0461 t << "An exception of unknown type was thrown.";
0462 t.addContext(std::string("Reading branch ") + branch->GetName());
0463 throw t;
0464 }
0465 LogTrace("IOTrace").format(
0466 "RootTree::getEntryUsingCache() end for branch {} entry {}", branch->GetName(), entryNumber);
0467 }
0468
0469 bool RootTree::skipEntries(unsigned int& offset) {
0470 entryNumber_ += offset;
0471 bool retval = (entryNumber_ < entries_);
0472 if (retval) {
0473 offset = 0;
0474 } else {
0475
0476
0477 long long overshoot = entryNumber_ + 1 - entries_;
0478 entryNumber_ = entries_;
0479 offset = overshoot;
0480 }
0481 return retval;
0482 }
0483
0484 void RootTree::startTraining() {
0485 if (cacheSize_ == 0) {
0486 return;
0487 }
0488 assert(treeCache_);
0489 assert(branchType_ == InEvent);
0490 assert(!rawTreeCache_);
0491 treeCache_->SetLearnEntries(learningEntries_);
0492 rawTreeCache_ = createCacheWithSize(cacheSize_);
0493 rawTreeCache_->SetEnablePrefetching(false);
0494 rawTreeCache_->SetLearnEntries(0);
0495 if (promptRead_) {
0496 switchOverEntry_ = entries_;
0497 } else {
0498 switchOverEntry_ = entryNumber_ + learningEntries_;
0499 }
0500 auto rawStart = entryNumber_;
0501 auto rawEnd = switchOverEntry_;
0502 auto treeStart = switchOverEntry_;
0503 if (switchOverEntry_ >= tree_->GetEntries()) {
0504 treeStart = switchOverEntry_ - tree_->GetEntries();
0505 rawEnd = tree_->GetEntries();
0506 }
0507 rawTreeCache_->StartLearningPhase();
0508 rawTreeCache_->SetEntryRange(rawStart, rawEnd);
0509 rawTreeCache_->AddBranch("*", kTRUE);
0510 rawTreeCache_->StopLearningPhase();
0511
0512 treeCache_->StartLearningPhase();
0513 treeCache_->SetEntryRange(treeStart, tree_->GetEntries());
0514
0515 if (filePtr_->Get(poolNames::branchListIndexesBranchName().c_str()) != nullptr) {
0516 treeCache_->AddBranch(poolNames::branchListIndexesBranchName().c_str(), kTRUE);
0517 }
0518 treeCache_->AddBranch(BranchTypeToAuxiliaryBranchName(branchType_).c_str(), kTRUE);
0519 trainedSet_.clear();
0520 triggerSet_.clear();
0521 assert(treeCache_->GetTree() == tree_);
0522 }
0523
0524 void RootTree::stopTraining() {
0525 auto guard = filePtr_->setCacheReadTemporarily(treeCache_.get(), tree_);
0526 treeCache_->StopLearningPhase();
0527 rawTreeCache_.reset();
0528 }
0529
0530 void RootTree::close() {
0531
0532
0533 auxBranch_ = branchEntryInfoBranch_ = nullptr;
0534 tree_ = metaTree_ = infoTree_ = nullptr;
0535
0536
0537
0538 filePtr_->clearCacheRead(tree_);
0539
0540
0541
0542
0543 treeCache_.reset();
0544 rawTreeCache_.reset();
0545 triggerTreeCache_.reset();
0546 rawTriggerTreeCache_.reset();
0547 auxCache_.reset();
0548
0549 filePtr_.reset();
0550 }
0551
0552 void RootTree::trainCache(char const* branchNames) {
0553 if (cacheSize_ == 0) {
0554 return;
0555 }
0556 tree_->LoadTree(0);
0557 assert(treeCache_);
0558 {
0559 auto guard = filePtr_->setCacheReadTemporarily(treeCache_.get(), tree_);
0560 treeCache_->StartLearningPhase();
0561 treeCache_->SetEntryRange(0, tree_->GetEntries());
0562 treeCache_->AddBranch(branchNames, kTRUE);
0563 treeCache_->StopLearningPhase();
0564 assert(treeCache_->GetTree() == tree_);
0565
0566
0567
0568
0569
0570 }
0571
0572 if (branchType_ == InEvent) {
0573
0574 TObjArray* branches = tree_->GetListOfBranches();
0575 int branchCount = branches->GetEntriesFast();
0576 for (int i = 0; i < branchCount; i++) {
0577 TBranch* branch = (TBranch*)branches->UncheckedAt(i);
0578 if ((branchNames[0] == '*') || (strcmp(branchNames, branch->GetName()) == 0)) {
0579 trainedSet_.insert(branch);
0580 }
0581 }
0582 }
0583 }
0584
0585 void RootTree::setSignals(
0586 signalslot::Signal<void(StreamContext const&, ModuleCallingContext const&)> const* preEventReadSource,
0587 signalslot::Signal<void(StreamContext const&, ModuleCallingContext const&)> const* postEventReadSource) {
0588 rootDelayedReader_->setSignals(preEventReadSource, postEventReadSource);
0589 }
0590
0591 namespace roottree {
0592 Int_t getEntry(TBranch* branch, EntryNumber entryNumber) {
0593 Int_t n = 0;
0594 try {
0595 n = branch->GetEntry(entryNumber);
0596 } catch (cms::Exception const& e) {
0597 throw Exception(errors::FileReadError, "", e);
0598 }
0599 return n;
0600 }
0601
0602 Int_t getEntry(TTree* tree, EntryNumber entryNumber) {
0603 Int_t n = 0;
0604 try {
0605 n = tree->GetEntry(entryNumber);
0606 } catch (cms::Exception const& e) {
0607 throw Exception(errors::FileReadError, "", e);
0608 }
0609 return n;
0610 }
0611
0612 std::unique_ptr<TTreeCache> trainCache(TTree* tree,
0613 InputFile& file,
0614 unsigned int cacheSize,
0615 char const* branchNames) {
0616 tree->LoadTree(0);
0617 std::unique_ptr<TTreeCache> treeCache = file.createCacheWithSize(*tree, cacheSize);
0618 if (nullptr != treeCache.get()) {
0619 treeCache->StartLearningPhase();
0620 treeCache->SetEntryRange(0, tree->GetEntries());
0621 treeCache->AddBranch(branchNames, kTRUE);
0622 treeCache->StopLearningPhase();
0623 }
0624 return treeCache;
0625 }
0626 }
0627 }