16 #include "TBranchElement.h" 17 #include "TCollection.h" 19 #include "TTreeCloner.h" 25 #include "tbb/task_arena.h" 63 edm::LogWarning(
"DuplicateTreeSentry") <<
"Re-opening file for fast-cloning";
66 const TUrl *
url = file->GetEndpointUrl();
71 file_.reset(TFile::Open(url->GetUrl(),
"READWRAP"));
84 std::unique_ptr<TFile, CloseBeforeDelete>
file_;
90 std::shared_ptr<TFile> filePtr,
93 int treeMaxVirtualSize) :
99 unclonedReadBranches_(),
100 clonedReadBranchNames_(),
101 currentlyFastCloning_(),
102 fastCloneAuxBranches_(
false) {
104 if(treeMaxVirtualSize >= 0)
tree_->SetMaxVirtualSize(treeMaxVirtualSize);
109 tree->SetDirectory(filePtr);
120 <<
"Failed to create the tree: " << name <<
"\n";
123 <<
"Tree: " << name <<
" is a zombie." <<
"\n";
131 assert(inputTree !=
nullptr);
135 if(outputBranch !=
nullptr) {
136 TBranch* inputBranch = inputTree->GetBranch(outputBranch->GetName());
138 if(inputBranch !=
nullptr) {
139 if(inputBranch->GetSplitLevel() != outputBranch->GetSplitLevel() ||
140 inputBranch->GetBasketSize() != outputBranch->GetBasketSize()) {
150 bool checkMatchingBranches(TBranchElement* inputBranch, TBranchElement* outputBranch) {
151 if(inputBranch->GetStreamerType() != outputBranch->GetStreamerType()) {
154 TObjArray* inputArray = inputBranch->GetListOfBranches();
155 TObjArray* outputArray = outputBranch->GetListOfBranches();
157 if(outputArray->GetSize() < inputArray->GetSize()) {
160 TIter iter(outputArray);
161 TObject*
obj =
nullptr;
162 while((obj = iter.Next()) !=
nullptr) {
163 TBranchElement* outBranch =
dynamic_cast<TBranchElement*
>(
obj);
165 TBranchElement* inBranch =
dynamic_cast<TBranchElement*
>(inputArray->FindObject(outBranch->GetName()));
169 if(!checkMatchingBranches(inBranch, outBranch)) {
180 if(inputTree ==
nullptr)
return false;
184 TBranchElement* outputBranch =
dynamic_cast<TBranchElement*
>(outputBr);
185 if(outputBranch !=
nullptr) {
186 TBranchElement* inputBranch =
dynamic_cast<TBranchElement*
>(inputTree->GetBranch(outputBranch->GetName()));
187 if(inputBranch !=
nullptr) {
189 if(!checkMatchingBranches(inputBranch, outputBranch)) {
191 <<
"Fast Cloning disabled because a data member has been added to split branch: " << inputBranch->GetName() <<
"\n.";
202 if(readBranch->GetEntries() != expectedNumberOfEntries) {
211 if(in->GetEntries() != 0) {
212 TObjArray* branches =
tree_->GetListOfBranches();
215 std::map<Int_t, TBranch *> auxIndexes;
216 bool mustRemoveSomeAuxs =
false;
219 int auxIndex = branches->IndexOf(auxBranch);
220 assert (auxIndex >= 0);
221 auxIndexes.insert(std::make_pair(auxIndex, auxBranch));
222 branches->RemoveAt(auxIndex);
224 mustRemoveSomeAuxs =
true;
229 int auxIndex = branches->IndexOf(auxBranch);
230 assert (auxIndex >= 0);
231 auxIndexes.insert(std::make_pair(auxIndex, auxBranch));
232 branches->RemoveAt(auxIndex);
233 mustRemoveSomeAuxs =
true;
236 if(mustRemoveSomeAuxs) {
237 branches->Compress();
241 TTreeCloner cloner(dupTree.
tree(),
tree_, option.c_str(), TTreeCloner::kNoWarnings|TTreeCloner::kIgnoreMissingTopLevel);
243 if(!cloner.IsValid()) {
245 static const char* okerror =
"One of the export branch";
246 if(strncmp(cloner.GetWarning(), okerror, strlen(okerror)) == 0) {
250 <<
"invalid TTreeCloner (" << cloner.GetWarning() <<
")\n";
253 tree_->SetEntries(
tree_->GetEntries() + in->GetEntries());
255 rootHandler->ignoreWarningsWhileDoing([&cloner] { cloner.Exec(); });
257 if(mustRemoveSomeAuxs) {
258 for(
auto const& auxIndex : auxIndexes) {
260 Int_t
last = branches->GetLast();
262 branches->AddAtAndExpand(branches->At(last), last+1);
263 for(Int_t ind = last-1; ind >= auxIndex.first; --ind) {
264 branches->AddAt(branches->At(ind), ind+1);
266 branches->AddAt(auxIndex.second, auxIndex.first);
268 branches->Add(auxIndex.second);
277 if(tree->GetNbranches() != 0) {
280 tree->SetEntries(-1);
283 tree->AutoSave(
"FlushBaskets");
326 tbb::this_task_arena::isolate( [&]{
tree_->Fill(); } );
339 TBranch*
branch =
tree_->Branch(branchName.c_str(),
344 assert(branch !=
nullptr);
virtual std::string const * sourceCacheHint() const =0
std::set< std::string > clonedReadBranchNames_
edm::propagate_const< TTree * > tree_
static int const invalidSplitLevel
DuplicateTreeSentry(TTree *tree)
static int const invalidBasketSize
static void fillTTree(std::vector< TBranch * > const &branches)
bool checkSplitLevelsAndBasketSizes(TTree *inputTree) const
TTree const * tree() const
void setRefCoreStreamer(bool resetAll=false)
std::vector< TBranch * > unclonedAuxBranches_
edm::propagate_const< std::shared_ptr< TFile > > filePtr_
bool checkIfFastClonable(TTree *inputTree) const
std::vector< TBranch * > producedBranches_
std::vector< TBranch * > auxBranches_
Func for_all(ForwardSequence &s, Func f)
wrapper for std::for_each
std::unique_ptr< TTree > mytree_
RootOutputTree(std::shared_ptr< TFile > filePtr, BranchType const &branchType, int splitLevel, int treeMaxVirtualSize)
static TTree * assignTTree(TFile *file, TTree *tree)
void addBranch(std::string const &branchName, std::string const &className, void const *&pProd, int splitLevel, int basketSize, bool produced)
void Fill(HcalDetId &id, double val, std::vector< TH2F > &depth)
void operator()(TFile *iFile) const
T const & get(Event const &event, InputTag const &tag)
bool currentlyFastCloning_
virtual std::string const * sourceCloneCacheHint() const =0
std::vector< TBranch * > unclonedReadBranches_
bool checkEntriesInReadBranches(Long64_t expectedNumberOfEntries) const
std::string const & BranchTypeToProductTreeName(BranchType const &branchType)
static TTree * makeTTree(TFile *filePtr, std::string const &name, int splitLevel)
DuplicateTreeSentry & operator=(DuplicateTreeSentry const &)=delete
static void writeTTree(TTree *tree)
std::vector< TBranch * > readBranches_
void maybeFastCloneTree(bool canFastClone, bool canFastCloneAux, TTree *tree, std::string const &option)
bool fastCloneAuxBranches_
const eventsetup::produce::Produce produced
def branchType(schema, name)
std::string className(const T &t)
void fastCloneTTree(TTree *in, std::string const &option)
std::unique_ptr< TFile, CloseBeforeDelete > file_