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