From 782caaca0ab99e2b9e501636638ee0af4b5af81d Mon Sep 17 00:00:00 2001
From: Philippe Canal <pcanal@fnal.gov>
Date: Thu, 4 Feb 2021 21:32:03 -0600
Subject: [PATCH] Do not call CopyAddresses during TTree::Merge fast cloning
 operation.

We do not apply the same to CloneTree as the addresses copying
is a side-effect (no reset at the end) that is relied upon by
user code.g
---
 tree/tree/inc/TTree.h   |  2 +-
 tree/tree/src/TTree.cxx | 47 +++++++++++++++++++++--------------------
 2 files changed, 25 insertions(+), 24 deletions(-)

diff --git a/tree/tree/inc/TTree.h b/tree/tree/inc/TTree.h
index dc9a014fb51..ffd08f1a567 100644
--- a/tree/tree/inc/TTree.h
+++ b/tree/tree/inc/TTree.h
@@ -417,7 +417,7 @@ public:
    virtual TFile          *ChangeFile(TFile* file);
    virtual TTree          *CloneTree(Long64_t nentries = -1, Option_t* option = "");
    virtual void            CopyAddresses(TTree*,Bool_t undo = kFALSE);
-   virtual Long64_t        CopyEntries(TTree* tree, Long64_t nentries = -1, Option_t *option = "");
+   virtual Long64_t        CopyEntries(TTree* tree, Long64_t nentries = -1, Option_t *option = "", Bool_t needCopyAddresses = false);
    virtual TTree          *CopyTree(const char* selection, Option_t* option = "", Long64_t nentries = kMaxEntries, Long64_t firstentry = 0);
    virtual TBasket        *CreateBasket(TBranch*);
    virtual void            DirectoryAutoAdd(TDirectory *);
diff --git a/tree/tree/src/TTree.cxx b/tree/tree/src/TTree.cxx
index b3f190502b2..e4c73667a54 100644
--- a/tree/tree/src/TTree.cxx
+++ b/tree/tree/src/TTree.cxx
@@ -3224,7 +3224,7 @@ TTree* TTree::CloneTree(Long64_t nentries /* = -1 */, Option_t* option /* = "" *
 
    if (nentries != 0) {
       if (fastClone && (nentries < 0)) {
-         if ( newtree->CopyEntries( this, -1, option ) < 0 ) {
+         if ( newtree->CopyEntries( this, -1, option, kFALSE ) < 0 ) {
             // There was a problem!
             Error("CloneTTree", "TTree has not been cloned\n");
             delete newtree;
@@ -3232,7 +3232,7 @@ TTree* TTree::CloneTree(Long64_t nentries /* = -1 */, Option_t* option /* = "" *
             return 0;
          }
       } else {
-         newtree->CopyEntries( this, nentries, option );
+         newtree->CopyEntries( this, nentries, option, kFALSE );
       }
    }
 
@@ -3472,7 +3472,7 @@ namespace {
 /// - BuildIndexOnError : If any of the underlying TTree objects do not have a TTreeIndex,
 ///                          all TTreeIndex are 'ignored' and the missing piece are rebuilt.
 
-Long64_t TTree::CopyEntries(TTree* tree, Long64_t nentries /* = -1 */, Option_t* option /* = "" */)
+Long64_t TTree::CopyEntries(TTree* tree, Long64_t nentries /* = -1 */, Option_t* option /* = "" */, Bool_t needCopyAddresses /* = false */)
 {
    if (!tree) {
       return 0;
@@ -3552,12 +3552,20 @@ Long64_t TTree::CopyEntries(TTree* tree, Long64_t nentries /* = -1 */, Option_t*
                if (cloner.NeedConversion()) {
                   TTree *localtree = tree->GetTree();
                   Long64_t tentries = localtree->GetEntries();
+                  if (needCopyAddresses) {
+                     // Copy MakeClass status.
+                     tree->SetMakeClass(fMakeClass);
+                     // Copy branch addresses.
+                     CopyAddresses(tree);
+                  }
                   for (Long64_t ii = 0; ii < tentries; ii++) {
                      if (localtree->GetEntry(ii) <= 0) {
                         break;
                      }
                      this->Fill();
                   }
+                  if (needCopyAddresses)
+                     tree->ResetBranchAddresses();
                   if (this->GetTreeIndex()) {
                      this->GetTreeIndex()->Append(tree->GetTree()->GetTreeIndex(), kTRUE);
                   }
@@ -3583,6 +3591,12 @@ Long64_t TTree::CopyEntries(TTree* tree, Long64_t nentries /* = -1 */, Option_t*
       } else if (nentries > treeEntries) {
          nentries = treeEntries;
       }
+      if (needCopyAddresses) {
+         // Copy MakeClass status.
+         tree->SetMakeClass(fMakeClass);
+         // Copy branch addresses.
+         CopyAddresses(tree);
+      }
       Int_t treenumber = -1;
       for (Long64_t i = 0; i < nentries; i++) {
          if (tree->LoadTree(i) < 0) {
@@ -3599,6 +3613,8 @@ Long64_t TTree::CopyEntries(TTree* tree, Long64_t nentries /* = -1 */, Option_t*
          }
          nbytes += this->Fill();
       }
+      if (needCopyAddresses)
+         tree->ResetBranchAddresses();
       if (this->GetTreeIndex()) {
          this->GetTreeIndex()->Append(0,kFALSE); // Force the sorting
       }
@@ -4489,8 +4505,8 @@ void TTree::DropBuffers(Int_t)
 /// Note that the user can decide to call FlushBaskets and AutoSave in her event loop
 /// base on the number of events written instead of the number of bytes written.
 ///
-/// \note Calling `TTree::FlushBaskets` too often increases the IO time. 
-/// 
+/// \note Calling `TTree::FlushBaskets` too often increases the IO time.
+///
 /// \note Calling `TTree::AutoSave` too often increases the IO time and also the
 ///       file size.
 ///
@@ -6754,11 +6770,7 @@ TTree* TTree::MergeTrees(TList* li, Option_t* options)
          continue;
       }
 
-      newtree->CopyAddresses(tree);
-
-      newtree->CopyEntries(tree,-1,options);
-
-      tree->ResetBranchAddresses(); // Disconnect from new tree.
+      newtree->CopyEntries(tree, -1, options, kTRUE);
    }
    if (newtree && newtree->GetTreeIndex()) {
       newtree->GetTreeIndex()->Append(0,kFALSE); // Force the sorting
@@ -6793,11 +6805,7 @@ Long64_t TTree::Merge(TCollection* li, Option_t *options)
       Long64_t nentries = tree->GetEntries();
       if (nentries == 0) continue;
 
-      CopyAddresses(tree);
-
-      CopyEntries(tree,-1,options);
-
-      tree->ResetBranchAddresses();
+      CopyEntries(tree, -1, options, kTRUE);
    }
    fAutoSave = storeAutoSave;
    return GetEntries();
@@ -6856,15 +6864,8 @@ Long64_t TTree::Merge(TCollection* li, TFileMergeInfo *info)
          fAutoSave = storeAutoSave;
          return -1;
       }
-      // Copy MakeClass status.
-      tree->SetMakeClass(fMakeClass);
 
-      // Copy branch addresses.
-      CopyAddresses(tree);
-
-      CopyEntries(tree,-1,options);
-
-      tree->ResetBranchAddresses();
+      CopyEntries(tree, -1, options, kTRUE);
    }
    fAutoSave = storeAutoSave;
    return GetEntries();
-- 
GitLab