16 #include "TBranchElement.h"
17 #include "TCollection.h"
19 #include "TTreeCloner.h"
25 #include "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,
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.";
207 if (readBranch->GetEntries() != expectedNumberOfEntries) {
215 if (
in->GetEntries() != 0) {
216 TObjArray* branches =
tree_->GetListOfBranches();
219 std::map<Int_t, TBranch*> auxIndexes;
220 bool mustRemoveSomeAuxs =
false;
223 int auxIndex = branches->IndexOf(auxBranch);
225 auxIndexes.insert(std::make_pair(auxIndex, auxBranch));
226 branches->RemoveAt(auxIndex);
228 mustRemoveSomeAuxs =
true;
233 int auxIndex = branches->IndexOf(auxBranch);
235 auxIndexes.insert(std::make_pair(auxIndex, auxBranch));
236 branches->RemoveAt(auxIndex);
237 mustRemoveSomeAuxs =
true;
240 if (mustRemoveSomeAuxs) {
241 branches->Compress();
246 dupTree.
tree(),
tree_,
option.c_str(), TTreeCloner::kNoWarnings | TTreeCloner::kIgnoreMissingTopLevel);
248 if (!cloner.IsValid()) {
250 static const char* okerror =
"One of the export branch";
251 if (strncmp(cloner.GetWarning(), okerror, strlen(okerror)) == 0) {
257 tree_->SetEntries(
tree_->GetEntries() +
in->GetEntries());
259 rootHandler->ignoreWarningsWhileDoing([&cloner] { cloner.Exec(); });
261 if (mustRemoveSomeAuxs) {
262 for (
auto const& auxIndex : auxIndexes) {
264 Int_t
last = branches->GetLast();
266 branches->AddAtAndExpand(branches->At(
last),
last + 1);
267 for (Int_t ind =
last - 1; ind >= auxIndex.first; --ind) {
268 branches->AddAt(branches->At(ind), ind + 1);
270 branches->AddAt(auxIndex.second, auxIndex.first);
272 branches->Add(auxIndex.second);
280 if (
tree->GetNbranches() != 0) {
283 tree->SetEntries(-1);
286 tree->AutoSave(
"FlushBaskets");
296 bool canFastCloneAux,
327 tbb::this_task_arena::isolate([&] {
tree_->Fill(); });