diff --git a/tree/tree/inc/TBranch.h b/tree/tree/inc/TBranch.h index 3ec84bd36f17f..75d73e5624bb8 100644 --- a/tree/tree/inc/TBranch.h +++ b/tree/tree/inc/TBranch.h @@ -169,7 +169,7 @@ class TBranch : public TNamed , public TAttFill { void Init(const char *name, const char *leaflist, Int_t compress); TBasket *GetFreshBasket(Int_t basketnumber, TBuffer *user_buffer); - TBasket *GetFreshCluster(); + TBasket *GetFreshCluster(TBuffer *user_buffer); Int_t WriteBasket(TBasket* basket, Int_t where) { return WriteBasketImpl(basket, where, nullptr); } TString GetRealFileName() const; diff --git a/tree/tree/src/TBranch.cxx b/tree/tree/src/TBranch.cxx index fa71e647bfc12..35c3a3442c107 100644 --- a/tree/tree/src/TBranch.cxx +++ b/tree/tree/src/TBranch.cxx @@ -1233,7 +1233,7 @@ TBasket* TBranch::GetBasketImpl(Int_t basketnumber, TBuffer *user_buffer) // if cluster pre-fetching or retaining is on, do not re-use existing baskets // unless a new cluster is used. if (fTree->GetMaxVirtualSize() < 0 || fTree->GetClusterPrefetch()) - basket = GetFreshCluster(); + basket = GetFreshCluster(user_buffer); else basket = GetFreshBasket(basketnumber, user_buffer); @@ -1835,23 +1835,36 @@ TBasket* TBranch::GetFreshBasket(Int_t basketnumber, TBuffer* user_buffer) /// Drops the cluster two behind the current cluster and returns a fresh basket /// by either reusing or creating a new one -TBasket *TBranch::GetFreshCluster() +TBasket *TBranch::GetFreshCluster(TBuffer* user_buffer) { TBasket *basket = 0; + auto CreateOrReuseBasket = [this, user_buffer]() -> TBasket* { + TBasket *newbasket = nullptr; + if (fExtraBasket) { + newbasket = fExtraBasket; + fExtraBasket = nullptr; + } else { + newbasket = fTree->CreateBasket(this); + } + if (user_buffer) + newbasket->AdoptBuffer(user_buffer); + return newbasket; + }; + // If GetClusterIterator is called with a negative entry then GetStartEntry will be 0 // So we need to check if we reach the zero before we have gone back (1-VirtualSize) clusters // if this is the case, we want to keep everything in memory so we return a new basket TTree::TClusterIterator iter = fTree->GetClusterIterator(fBasketEntry[fReadBasket]); if (iter.GetStartEntry() == 0) { - return fTree->CreateBasket(this); + return CreateOrReuseBasket(); } // Iterate backwards (1-VirtualSize) clusters to reach cluster to be unloaded from memory, // skipped if VirtualSize > 0. for (Int_t j = 0; j < -fTree->GetMaxVirtualSize(); j++) { if (iter.Previous() == 0) { - return fTree->CreateBasket(this); + return CreateOrReuseBasket(); } } @@ -1863,7 +1876,7 @@ TBasket *TBranch::GetFreshCluster() while (fBasketEntry[basketToUnload] != entryToUnload) { basketToUnload--; if (basketToUnload < 0) { - return fTree->CreateBasket(this); + return CreateOrReuseBasket(); } } @@ -1874,7 +1887,7 @@ TBasket *TBranch::GetFreshCluster() fBaskets.AddAt(0, basketToUnload); --fNBaskets; } else { - basket = fTree->CreateBasket(this); + basket = CreateOrReuseBasket(); } ++basketToUnload;