// @(#)root/tree:$Name: $:$Id: TTreeFilePrefetch.cxx,v 1.12 2006/06/19 09:35:45 brun Exp $
// Author: Rene Brun 04/06/2006
/*************************************************************************
* Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
* All rights reserved. *
* *
* For the licensing terms see $ROOTSYS/LICENSE. *
* For the list of contributors see $ROOTSYS/README/CREDITS. *
*************************************************************************/
//////////////////////////////////////////////////////////////////////////
// //
// TTreeFilePrefetch //
// //
// A specialized TFilePrefetch object for a TTree //
// This class acts as a file cache, registering automatically the //
// baskets from the branches being processed (TTree::Draw or //
// TTree::Process and TSelectors) when in the learning phase. //
// The learning phase is by default 100 entries. //
// It can be changed via TTreeFileFrefetch::SetLearnEntries. //
// //
// This cache speeds-up considerably the performance, in particular //
// when the Tree is accessed remotely via a high latency network. //
// //
// The default cache size (10 Mbytes) may be changed via the function //
// TTreeFilePrefetch::SetCacheSize //
// //
// Only the baskets for the requested entry range are put in the cache //
// //
// For each Tree being processed a TTreeFilePrefetch object is created.//
// This object is automatically deleted when the Tree is deleted or //
// when the file is deleted. //
// //
// -Special case of a TChain //
// Once the training is done on the first Tree, the list of branches //
// in the cache is kept for the following files. //
// //
// -Special case of a TEventlist //
// if the Tree or TChain has a TEventlist, only the buffers //
// referenced by the list are put in the cache. //
// //
//////////////////////////////////////////////////////////////////////////
#include "TTreeFilePrefetch.h"
#include "TChain.h"
#include "TBranch.h"
#include "TEventList.h"
#include "TObjString.h"
Int_t TTreeFilePrefetch::fgLearnEntries = 100;
ClassImp(TTreeFilePrefetch)
//______________________________________________________________________________
TTreeFilePrefetch::TTreeFilePrefetch() : TFilePrefetch(),
fEntryMin(0),
fEntryMax(1),
fEntryNext(1),
fZipBytes(0),
fNbranches(0),
fBranches(0),
fBrNames(0),
fOwner(0),
fTree(0),
fIsLearning(kTRUE)
{
// Default Constructor.
}
//______________________________________________________________________________
TTreeFilePrefetch::TTreeFilePrefetch(TTree *tree, Int_t buffersize) : TFilePrefetch(tree->GetCurrentFile(),buffersize),
fEntryMin(0),
fEntryMax(tree->GetEntriesFast()),
fEntryNext(0),
fZipBytes(0),
fNbranches(0),
fBranches(0),
fBrNames(new TList),
fOwner(tree),
fTree(0),
fIsLearning(kTRUE)
{
// Constructor.
fEntryNext = fEntryMin + fgLearnEntries;
Int_t nleaves = tree->GetListOfLeaves()->GetEntries();
fBranches = new TBranch*[nleaves+10]; //add a margin just in case in a TChain?
}
//______________________________________________________________________________
TTreeFilePrefetch::TTreeFilePrefetch(const TTreeFilePrefetch &pf) : TFilePrefetch(pf)
{
// Copy Constructor.
}
//______________________________________________________________________________
TTreeFilePrefetch::~TTreeFilePrefetch()
{
// destructor. (in general called by the TFile destructor
delete [] fBranches;
if (fBrNames) {fBrNames->Delete(); delete fBrNames;}
}
//______________________________________________________________________________
TTreeFilePrefetch& TTreeFilePrefetch::operator=(const TTreeFilePrefetch& pf)
{
// Assignment.
if (this != &pf) TFilePrefetch::operator=(pf);
return *this;
}
//_____________________________________________________________________________
void TTreeFilePrefetch::AddBranch(TBranch *b)
{
//add a branch to the list of branches to be stored in the cache
//this function is called by TBranch::GetBasket
if (!fIsLearning) return;
//Is branch already in the cache?
Bool_t isNew = kTRUE;
for (int i=0;i<fNbranches;i++) {
if (fBranches[i] == b) {isNew = kFALSE; break;}
}
if (isNew) {
fTree = b->GetTree();
fBranches[fNbranches] = b;
fBrNames->Add(new TObjString(b->GetName()));
fZipBytes += b->GetZipBytes();
fNbranches++;
if (gDebug > 0) printf("Entry: %lld, registering branch: %s\n",b->GetTree()->GetReadEntry(),b->GetName());
}
}
//_____________________________________________________________________________
Bool_t TTreeFilePrefetch::FillBuffer()
{
//Fill the cache buffer with the branchse in the cache
if (fNbranches <= 0) return kFALSE;
TTree *tree = fBranches[0]->GetTree();
Long64_t entry = tree->GetReadEntry();
if (entry < fEntryNext) return kFALSE;
//estimate number of entries that can fit in the cache
fEntryNext = entry + tree->GetEntries()*fBufferSize/fZipBytes;
if (fEntryNext > fEntryMax) fEntryNext = fEntryMax+1;
//check if owner has a TEventList set. If yes we optimize for this special case
//reading only the baskets containing entries in the list
TEventList *elist = fOwner->GetEventList();
Long64_t chainOffset = 0;
if (elist) {
fEntryNext = fTree->GetEntries();
if (fOwner->IsA() ==TChain::Class()) {
TChain *chain = (TChain*)fOwner;
Int_t t = chain->GetTreeNumber();
chainOffset = chain->GetTreeOffset()[t];
}
}
//clear cache buffer
TFilePrefetch::Prefetch(0,0);
//store baskets
for (Int_t i=0;i<fNbranches;i++) {
TBranch *b = fBranches[i];
Int_t nb = b->GetMaxBaskets();
Int_t *lbaskets = b->GetBasketBytes();
Long64_t *entries = b->GetBasketEntry();
if (!lbaskets || !entries) continue;
//we have found the branch. We now register all its baskets
//from the requested offset to the basket below fEntrymax
for (Int_t j=0;j<nb;j++) {
Long64_t pos = b->GetBasketSeek(j);
Int_t len = lbaskets[j];
if (pos <= 0 || len <= 0) continue;
if (entries[j] > fEntryNext) continue;
if (entries[j] < entry && (j<nb-1 && entries[j+1] < entry)) continue;
if (elist) {
Long64_t emax = fEntryMax;
if (j<nb-1) emax = entries[j+1]-1;
if (!elist->ContainsRange(entries[j]+chainOffset,emax+chainOffset)) continue;
}
TFilePrefetch::Prefetch(pos,len);
}
if (gDebug > 0) printf("Entry: %lld, registering baskets branch %s, fEntryNext=%lld, fNseek=%d, fNtot=%d\n",entry,fBranches[i]->GetName(),fEntryNext,fNseek,fNtot);
}
fIsLearning = kFALSE;
return kTRUE;
}
//_____________________________________________________________________________
Int_t TTreeFilePrefetch::GetLearnEntries()
{
//static function returning the number of entries used to train the cache
//see SetLearnEntries
return fgLearnEntries;
}
//_____________________________________________________________________________
TTree *TTreeFilePrefetch::GetTree() const
{
//return Tree in the cache
if (fNbranches <= 0) return 0;
return fBranches[0]->GetTree();
}
//_____________________________________________________________________________
Bool_t TTreeFilePrefetch::ReadBuffer(char *buf, Long64_t pos, Int_t len)
{
// Read buffer at position pos.
// If pos is in the list of prefetched blocks read from fBuffer,
// then try to fill the cache from the list of selected branches,
// otherwise normal read from file. Returns kTRUE in case of failure.
// This function overloads TFilePrefetch::ReadBuffer.
// It returns kFALSE if the requested block is in the cache
//Is request already in the cache?
Bool_t inCache = !TFilePrefetch::ReadBuffer(buf,pos,len);
if (inCache) return kFALSE;
//not found in cache. Do we need to fill the cache?
Bool_t bufferFilled = FillBuffer();
if (bufferFilled) return TFilePrefetch::ReadBuffer(buf,pos,len);
return kTRUE;
}
//_____________________________________________________________________________
void TTreeFilePrefetch::SetEntryRange(Long64_t emin, Long64_t emax)
{
// Set the minimum and maximum entry number to be processed
// this information helps to optimize the number of baskets to read
// when prefetching the branch buffers.
fEntryMin = emin;
fEntryMax = emax;
fEntryNext = fEntryMin + fgLearnEntries;
fIsLearning = kTRUE;
fNbranches = 0;
fZipBytes = 0;
if (fBrNames) fBrNames->Delete();
if (gDebug > 0) printf("SetEntryRange: fEntryMin=%lld, fEntryMax=%lld, fEntryNext=%lld\n",fEntryMin,fEntryMax,fEntryNext);
}
//_____________________________________________________________________________
void TTreeFilePrefetch::SetLearnEntries(Int_t n)
{
// Static function to set the number of entries to be used in learning mode
// The default value for n is 10. n must be >= 1
if (n < 1) n = 1;
fgLearnEntries = n;
}
//_____________________________________________________________________________
void TTreeFilePrefetch::UpdateBranches(TTree *tree)
{
//update pointer to current Tree and recompute pointers to the branches in the cache
fTree = tree;
Prefetch(0,0);
fEntryMin = 0;
fEntryMax = fTree->GetEntries();
fEntryNext = fEntryMin + fgLearnEntries;
fZipBytes = 0;
fNbranches = 0;
TIter next(fBrNames);
TObjString *os;
while ((os = (TObjString*)next())) {
TBranch *b = fTree->GetBranch(os->GetName());
if (!b) continue;
fBranches[fNbranches] = b;
fZipBytes += b->GetZipBytes();
fNbranches++;
}
}
ROOT page - Class index - Class Hierarchy - Top of the page
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.