16 #include "TBranchElement.h"
17 #include "TCollection.h"
19 #include "TTreeCloner.h"
25 #include "oneapi/tbb/task_arena.h"
70 edm::LogWarning(
"DuplicateTreeSentry") <<
"Re-opening file for fast-cloning";
73 const TUrl*
url = file->GetEndpointUrl();
77 file_.reset(TFile::Open(url->GetUrl(),
"READWRAP"));
91 std::unique_ptr<TFile, CloseBeforeDelete>
file_;
99 int treeMaxVirtualSize,
102 tree_(processName.
empty()
108 unclonedReadBranches_(),
109 clonedReadBranchNames_(),
110 currentlyFastCloning_(),
111 fastCloneAuxBranches_(
false) {
112 if (treeMaxVirtualSize >= 0)
113 tree_->SetMaxVirtualSize(treeMaxVirtualSize);
117 tree->SetDirectory(filePtr);
128 if (tree->IsZombie())
136 assert(inputTree !=
nullptr);
140 if (outputBranch !=
nullptr) {
141 TBranch* inputBranch = inputTree->GetBranch(outputBranch->GetName());
143 if (inputBranch !=
nullptr) {
144 if (inputBranch->GetSplitLevel() != outputBranch->GetSplitLevel() ||
145 inputBranch->GetBasketSize() != outputBranch->GetBasketSize()) {
155 bool checkMatchingBranches(TBranchElement* inputBranch, TBranchElement* outputBranch) {
156 if (inputBranch->GetStreamerType() != outputBranch->GetStreamerType()) {
159 TObjArray* inputArray = inputBranch->GetListOfBranches();
160 TObjArray* outputArray = outputBranch->GetListOfBranches();
162 if (outputArray->GetSize() < inputArray->GetSize()) {
165 TIter iter(outputArray);
166 TObject*
obj =
nullptr;
167 while ((obj = iter.Next()) !=
nullptr) {
168 TBranchElement* outBranch =
dynamic_cast<TBranchElement*
>(
obj);
170 TBranchElement* inBranch =
dynamic_cast<TBranchElement*
>(inputArray->FindObject(outBranch->GetName()));
174 if (!checkMatchingBranches(inBranch, outBranch)) {
184 if (inputTree ==
nullptr)
189 TBranchElement* outputBranch =
dynamic_cast<TBranchElement*
>(outputBr);
190 if (outputBranch !=
nullptr) {
191 TBranchElement* inputBranch =
dynamic_cast<TBranchElement*
>(inputTree->GetBranch(outputBranch->GetName()));
192 if (inputBranch !=
nullptr) {
194 if (!checkMatchingBranches(inputBranch, outputBranch)) {
195 LogInfo(
"FastCloning") <<
"Fast Cloning disabled because a data member has been added to split branch: "
196 << inputBranch->GetName() <<
"\n.";
206 void setMatchingBranchSizes(TBranchElement* inputBranch, TBranchElement* outputBranch) {
207 if (inputBranch->GetStreamerType() != outputBranch->GetStreamerType()) {
210 TObjArray* inputArray = inputBranch->GetListOfBranches();
211 TObjArray* outputArray = outputBranch->GetListOfBranches();
213 if (outputArray->GetSize() < inputArray->GetSize()) {
216 TIter iter(outputArray);
217 TObject* obj =
nullptr;
218 while ((obj = iter.Next()) !=
nullptr) {
219 TBranchElement* outBranch =
dynamic_cast<TBranchElement*
>(
obj);
221 TBranchElement* inBranch =
dynamic_cast<TBranchElement*
>(inputArray->FindObject(outBranch->GetName()));
223 outBranch->SetBasketSize(inBranch->GetBasketSize());
224 setMatchingBranchSizes(inBranch, outBranch);
232 if (inputTree ==
nullptr)
236 TBranchElement* outputBranch =
dynamic_cast<TBranchElement*
>(outputBr);
237 if (outputBranch !=
nullptr) {
238 TBranchElement* inputBranch =
dynamic_cast<TBranchElement*
>(inputTree->GetBranch(outputBranch->GetName()));
239 if (inputBranch !=
nullptr) {
241 setMatchingBranchSizes(inputBranch, outputBranch);
249 if (readBranch->GetEntries() != expectedNumberOfEntries) {
257 if (in->GetEntries() != 0) {
258 TObjArray* branches =
tree_->GetListOfBranches();
261 std::map<Int_t, TBranch*> auxIndexes;
262 bool mustRemoveSomeAuxs =
false;
265 int auxIndex = branches->IndexOf(auxBranch);
267 auxIndexes.insert(std::make_pair(auxIndex, auxBranch));
268 branches->RemoveAt(auxIndex);
270 mustRemoveSomeAuxs =
true;
275 int auxIndex = branches->IndexOf(auxBranch);
277 auxIndexes.insert(std::make_pair(auxIndex, auxBranch));
278 branches->RemoveAt(auxIndex);
279 mustRemoveSomeAuxs =
true;
282 if (mustRemoveSomeAuxs) {
283 branches->Compress();
288 dupTree.
tree(),
tree_, option.c_str(), TTreeCloner::kNoWarnings | TTreeCloner::kIgnoreMissingTopLevel);
290 if (!cloner.IsValid()) {
292 static const char* okerror =
"One of the export branch";
293 if (strncmp(cloner.GetWarning(), okerror, strlen(okerror)) == 0) {
299 tree_->SetEntries(
tree_->GetEntries() + in->GetEntries());
301 rootHandler->ignoreWarningsWhileDoing([&cloner] { cloner.Exec(); });
303 if (mustRemoveSomeAuxs) {
304 for (
auto const& auxIndex : auxIndexes) {
306 Int_t
last = branches->GetLast();
308 branches->AddAtAndExpand(branches->At(last), last + 1);
309 for (Int_t ind = last - 1; ind >= auxIndex.first; --ind) {
310 branches->AddAt(branches->At(ind), ind + 1);
312 branches->AddAt(auxIndex.second, auxIndex.first);
314 branches->Add(auxIndex.second);
322 if (tree->GetNbranches() != 0) {
325 tree->SetEntries(-1);
328 tree->AutoSave(
"FlushBaskets");
338 bool canFastCloneAux,
348 if (branch->GetEntries() ==
tree_->GetEntries()) {
369 oneapi::tbb::this_task_arena::isolate([&] {
tree_->Fill(); });
381 TBranch* branch =
tree_->Branch(branchName.c_str(), className.c_str(), &pProd, basketSize,
splitLevel);
382 assert(branch !=
nullptr);
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, std::string const &processName=std::string())
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
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)
void setSubBranchBasketSizes(TTree *inputTree) const
Log< level::Info, false > LogInfo
DuplicateTreeSentry & operator=(DuplicateTreeSentry const &)=delete
static void writeTTree(TTree *tree)
std::vector< TBranch * > readBranches_
T const & get(Event const &event, InputTag const &tag) noexcept(false)
virtual std::string const * sourceCacheHint() const =0
Log< level::Warning, false > LogWarning
void maybeFastCloneTree(bool canFastClone, bool canFastCloneAux, TTree *tree, std::string const &option)
bool fastCloneAuxBranches_
std::string className(const T &t)
void fastCloneTTree(TTree *in, std::string const &option)
std::unique_ptr< TFile, CloseBeforeDelete > file_