00001 #include "RootTree.h"
00002 #include "RootDelayedReader.h"
00003 #include "FWCore/Framework/interface/Principal.h"
00004 #include "FWCore/Utilities/interface/WrappedClassName.h"
00005 #include "DataFormats/Provenance/interface/BranchDescription.h"
00006 #include "DataFormats/Provenance/interface/ConstBranchDescription.h"
00007 #include "DataFormats/Provenance/interface/Provenance.h"
00008 #include "Rtypes.h"
00009 #include "TFile.h"
00010 #include "TVirtualIndex.h"
00011 #include "TTreeIndex.h"
00012 #include "TTreeCache.h"
00013
00014 #include <iostream>
00015
00016 namespace edm {
00017 namespace {
00018 TBranch * getAuxiliaryBranch(TTree * tree, BranchType const& branchType) {
00019 TBranch *branch = tree->GetBranch(BranchTypeToAuxiliaryBranchName(branchType).c_str());
00020 if (branch == 0) {
00021 branch = tree->GetBranch(BranchTypeToAuxBranchName(branchType).c_str());
00022 }
00023 return branch;
00024 }
00025 TBranch * getEventEntryInfoBranch(TTree * tree, BranchType const& branchType) {
00026 TBranch *branch = tree->GetBranch(BranchTypeToBranchEntryInfoBranchName(branchType).c_str());
00027 return branch;
00028 }
00029 TBranch * getStatusBranch(TTree * tree, BranchType const& branchType) {
00030 TBranch *branch = tree->GetBranch(BranchTypeToProductStatusBranchName(branchType).c_str());
00031 return branch;
00032 }
00033 }
00034 RootTree::RootTree(boost::shared_ptr<TFile> filePtr, BranchType const& branchType) :
00035 filePtr_(filePtr),
00036 tree_(dynamic_cast<TTree *>(filePtr_.get() != 0 ? filePtr->Get(BranchTypeToProductTreeName(branchType).c_str()) : 0)),
00037 metaTree_(dynamic_cast<TTree *>(filePtr_.get() != 0 ? filePtr->Get(BranchTypeToMetaDataTreeName(branchType).c_str()) : 0)),
00038 branchType_(branchType),
00039 auxBranch_(tree_ ? getAuxiliaryBranch(tree_, branchType_) : 0),
00040 branchEntryInfoBranch_(metaTree_ ? getEventEntryInfoBranch(metaTree_, branchType_) : 0),
00041 entries_(tree_ ? tree_->GetEntries() : 0),
00042 entryNumber_(-1),
00043 branchNames_(),
00044 branches_(new BranchMap),
00045 productStatuses_(),
00046 pProductStatuses_(&productStatuses_),
00047 infoTree_(dynamic_cast<TTree *>(filePtr_.get() != 0 ? filePtr->Get(BranchTypeToInfoTreeName(branchType).c_str()) : 0)),
00048 statusBranch_(infoTree_ ? getStatusBranch(infoTree_, branchType_) : 0)
00049 { }
00050
00051 bool
00052 RootTree::isValid() const {
00053 if (metaTree_ == 0 || metaTree_->GetNbranches() == 0) {
00054 return tree_ != 0 && auxBranch_ != 0 && tree_->GetNbranches() == 1;
00055 }
00056 if (tree_ != 0 && auxBranch_ != 0 && metaTree_ != 0) {
00057 if (branchEntryInfoBranch_ != 0 || statusBranch_ != 0) return true;
00058 return (entries_ == metaTree_->GetEntries() && tree_->GetNbranches() <= metaTree_->GetNbranches() + 1);
00059 }
00060 return false;
00061 }
00062
00063 void
00064 RootTree::setPresence(BranchDescription const& prod) {
00065 assert(isValid());
00066 prod.init();
00067 prod.setPresent(tree_->GetBranch(prod.branchName().c_str()) != 0);
00068 }
00069
00070 void
00071 RootTree::addBranch(BranchKey const& key,
00072 BranchDescription const& prod,
00073 std::string const& oldBranchName) {
00074 assert(isValid());
00075 prod.init();
00076
00077 TBranch * branch = tree_->GetBranch(oldBranchName.c_str());
00078 assert (prod.present() == (branch != 0));
00079 input::BranchInfo info = input::BranchInfo(ConstBranchDescription(prod));
00080 info.productBranch_ = 0;
00081 if (prod.present()) {
00082 info.productBranch_ = branch;
00083
00084 branchNames_.push_back(prod.branchName());
00085 }
00086 info.provenanceBranch_ = metaTree_->GetBranch(oldBranchName.c_str());
00087 branches_->insert(std::make_pair(key, info));
00088 }
00089
00090 void
00091 RootTree::dropBranch(std::string const& oldBranchName) {
00092
00093 TBranch * branch = tree_->GetBranch(oldBranchName.c_str());
00094 if (branch != 0) {
00095 TObjArray * leaves = tree_->GetListOfLeaves();
00096 int entries = leaves->GetEntries();
00097 for (int i = 0; i < entries; ++i) {
00098 TLeaf *leaf = (TLeaf *)(*leaves)[i];
00099 if (leaf == 0) continue;
00100 TBranch* br = leaf->GetBranch();
00101 if (br == 0) continue;
00102 if (br->GetMother() == branch) {
00103 leaves->Remove(leaf);
00104 }
00105 }
00106 leaves->Compress();
00107 tree_->GetListOfBranches()->Remove(branch);
00108 tree_->GetListOfBranches()->Compress();
00109 delete branch;
00110 }
00111 }
00112
00113 boost::shared_ptr<DelayedReader>
00114 RootTree::makeDelayedReader() const {
00115 boost::shared_ptr<DelayedReader> store(new RootDelayedReader(entryNumber_, branches_, filePtr_));
00116 return store;
00117 }
00118
00119 void
00120 RootTree::setCacheSize(unsigned int cacheSize) const {
00121 tree_->SetCacheSize(static_cast<Long64_t>(cacheSize));
00122 }
00123
00124 void
00125 RootTree::setTreeMaxVirtualSize(int treeMaxVirtualSize) {
00126 if (treeMaxVirtualSize >= 0) tree_->SetMaxVirtualSize(static_cast<Long64_t>(treeMaxVirtualSize));
00127 }
00128
00129 void
00130 RootTree::setEntryNumber(EntryNumber theEntryNumber) {
00131 if (TTreeCache *tc = dynamic_cast<TTreeCache *>(filePtr_->GetCacheRead())) {
00132 if (theEntryNumber >= 0 && tc->GetOwner() == tree_ && tc->IsLearning()) {
00133 tc->SetLearnEntries(1);
00134 tc->SetEntryRange(0, tree_->GetEntries());
00135 for (BranchMap::const_iterator i = branches_->begin(), e = branches_->end(); i != e; ++i) {
00136 if (i->second.productBranch_) {
00137 tc->AddBranch(i->second.productBranch_, kTRUE);
00138 }
00139 }
00140 tc->StopLearningPhase();
00141 }
00142 }
00143
00144 entryNumber_ = theEntryNumber;
00145 tree_->LoadTree(theEntryNumber);
00146 }
00147
00148 namespace input {
00149 Int_t
00150 getEntry(TBranch* branch, EntryNumber entryNumber) {
00151 Int_t n = 0;
00152 try {
00153 n = branch->GetEntry(entryNumber);
00154 }
00155 catch(cms::Exception e) {
00156 throw edm::Exception(edm::errors::FileReadError) << e.explainSelf() << "\n";
00157 }
00158 return n;
00159 }
00160
00161 Int_t
00162 getEntry(TTree* tree, EntryNumber entryNumber) {
00163 Int_t n = 0;
00164 try {
00165 n = tree->GetEntry(entryNumber);
00166 }
00167 catch(cms::Exception e) {
00168 throw edm::Exception(edm::errors::FileReadError) << e.explainSelf() << "\n";
00169 }
00170 return n;
00171 }
00172 }
00173 }