#include "TBranch.h"
#include "Compression.h"
#include "TBasket.h"
#include "TBranchBrowsable.h"
#include "TBrowser.h"
#include "TClass.h"
#include "TBufferFile.h"
#include "TClonesArray.h"
#include "TFile.h"
#include "TLeaf.h"
#include "TLeafB.h"
#include "TLeafC.h"
#include "TLeafD.h"
#include "TLeafF.h"
#include "TLeafI.h"
#include "TLeafL.h"
#include "TLeafO.h"
#include "TLeafObject.h"
#include "TLeafS.h"
#include "TMessage.h"
#include "TROOT.h"
#include "TSystem.h"
#include "TMath.h"
#include "TTree.h"
#include "TTreeCache.h"
#include "TTreeCacheUnzip.h"
#include "TVirtualMutex.h"
#include "TVirtualPad.h"
#include <cstddef>
#include <string.h>
#include <stdio.h>
Int_t TBranch::fgCount = 0;
#if (__GNUC__ >= 3) || defined(__INTEL_COMPILER)
#if !defined(R__unlikely)
#define R__unlikely(expr) __builtin_expect(!!(expr), 0)
#endif
#if !defined(R__likely)
#define R__likely(expr) __builtin_expect(!!(expr), 1)
#endif
#else
#define R__unlikely(expr) expr
#define R__likely(expr) expr
#endif
ClassImp(TBranch)
TBranch::TBranch()
: TNamed()
, TAttFill(0, 1001)
, fCompress(0)
, fBasketSize(32000)
, fEntryOffsetLen(1000)
, fWriteBasket(0)
, fEntryNumber(0)
, fOffset(0)
, fMaxBaskets(10)
, fNBaskets(0)
, fSplitLevel(0)
, fNleaves(0)
, fReadBasket(0)
, fReadEntry(-1)
, fFirstBasketEntry(-1)
, fNextBasketEntry(-1)
, fCurrentBasket(0)
, fEntries(0)
, fFirstEntry(0)
, fTotBytes(0)
, fZipBytes(0)
, fBranches()
, fLeaves()
, fBaskets(fMaxBaskets)
, fBasketBytes(0)
, fBasketEntry(0)
, fBasketSeek(0)
, fTree(0)
, fMother(0)
, fParent(0)
, fAddress(0)
, fDirectory(0)
, fFileName("")
, fEntryBuffer(0)
, fBrowsables(0)
, fSkipZip(kFALSE)
, fReadLeaves(&TBranch::ReadLeavesImpl)
, fFillLeaves(&TBranch::FillLeavesImpl)
{
SetBit(TBranch::kDoNotUseBufferMap);
}
TBranch::TBranch(TTree *tree, const char* name, void* address, const char* leaflist, Int_t basketsize, Int_t compress)
: TNamed(name, leaflist)
, TAttFill(0, 1001)
, fCompress(compress)
, fBasketSize((basketsize < 100) ? 100 : basketsize)
, fEntryOffsetLen(0)
, fWriteBasket(0)
, fEntryNumber(0)
, fOffset(0)
, fMaxBaskets(10)
, fNBaskets(0)
, fSplitLevel(0)
, fNleaves(0)
, fReadBasket(0)
, fReadEntry(-1)
, fFirstBasketEntry(-1)
, fNextBasketEntry(-1)
, fCurrentBasket(0)
, fEntries(0)
, fFirstEntry(0)
, fTotBytes(0)
, fZipBytes(0)
, fBranches()
, fLeaves()
, fBaskets(fMaxBaskets)
, fBasketBytes(0)
, fBasketEntry(0)
, fBasketSeek(0)
, fTree(tree)
, fMother(0)
, fParent(0)
, fAddress((char*) address)
, fDirectory(fTree->GetDirectory())
, fFileName("")
, fEntryBuffer(0)
, fBrowsables(0)
, fSkipZip(kFALSE)
, fReadLeaves(&TBranch::ReadLeavesImpl)
, fFillLeaves(&TBranch::FillLeavesImpl)
{
Init(name,leaflist,compress);
}
TBranch::TBranch(TBranch *parent, const char* name, void* address, const char* leaflist, Int_t basketsize, Int_t compress)
: TNamed(name, leaflist)
, TAttFill(0, 1001)
, fCompress(compress)
, fBasketSize((basketsize < 100) ? 100 : basketsize)
, fEntryOffsetLen(0)
, fWriteBasket(0)
, fEntryNumber(0)
, fOffset(0)
, fMaxBaskets(10)
, fNBaskets(0)
, fSplitLevel(0)
, fNleaves(0)
, fReadBasket(0)
, fReadEntry(-1)
, fFirstBasketEntry(-1)
, fNextBasketEntry(-1)
, fCurrentBasket(0)
, fEntries(0)
, fFirstEntry(0)
, fTotBytes(0)
, fZipBytes(0)
, fBranches()
, fLeaves()
, fBaskets(fMaxBaskets)
, fBasketBytes(0)
, fBasketEntry(0)
, fBasketSeek(0)
, fTree(parent ? parent->GetTree() : 0)
, fMother(parent ? parent->GetMother() : 0)
, fParent(parent)
, fAddress((char*) address)
, fDirectory(fTree ? fTree->GetDirectory() : 0)
, fFileName("")
, fEntryBuffer(0)
, fBrowsables(0)
, fSkipZip(kFALSE)
, fReadLeaves(&TBranch::ReadLeavesImpl)
, fFillLeaves(&TBranch::FillLeavesImpl)
{
Init(name,leaflist,compress);
}
void TBranch::Init(const char* name, const char* leaflist, Int_t compress)
{
SetBit(TBranch::kDoNotUseBufferMap);
if ((compress == -1) && fTree->GetDirectory()) {
TFile* bfile = fTree->GetDirectory()->GetFile();
if (bfile) {
fCompress = bfile->GetCompressionSettings();
}
}
fBasketBytes = new Int_t[fMaxBaskets];
fBasketEntry = new Long64_t[fMaxBaskets];
fBasketSeek = new Long64_t[fMaxBaskets];
for (Int_t i = 0; i < fMaxBaskets; ++i) {
fBasketBytes[i] = 0;
fBasketEntry[i] = 0;
fBasketSeek[i] = 0;
}
char* nameBegin = const_cast<char*>(leaflist);
Int_t offset = 0;
char* leafname = new char[640];
char* leaftype = new char[320];
strlcpy(leaftype, "F",320);
char* pos = const_cast<char*>(leaflist);
const char* leaflistEnd = leaflist + strlen(leaflist);
for (; pos <= leaflistEnd; ++pos) {
if ((*pos == ':') || (*pos == 0)) {
Int_t lenName = pos - nameBegin;
char* ctype = 0;
if (lenName) {
strncpy(leafname, nameBegin, lenName);
leafname[lenName] = 0;
ctype = strstr(leafname, "/");
if (ctype) {
*ctype = 0;
strlcpy(leaftype, ctype + 1,320);
}
}
if (lenName == 0 || ctype == leafname) {
Warning("TBranch","No name was given to the leaf number '%d' in the leaflist of the branch '%s'.",fNleaves,name);
snprintf(leafname,640,"__noname%d",fNleaves);
}
TLeaf* leaf = 0;
if (*leaftype == 'C') {
leaf = new TLeafC(this, leafname, leaftype);
} else if (*leaftype == 'O') {
leaf = new TLeafO(this, leafname, leaftype);
} else if (*leaftype == 'B') {
leaf = new TLeafB(this, leafname, leaftype);
} else if (*leaftype == 'b') {
leaf = new TLeafB(this, leafname, leaftype);
leaf->SetUnsigned();
} else if (*leaftype == 'S') {
leaf = new TLeafS(this, leafname, leaftype);
} else if (*leaftype == 's') {
leaf = new TLeafS(this, leafname, leaftype);
leaf->SetUnsigned();
} else if (*leaftype == 'I') {
leaf = new TLeafI(this, leafname, leaftype);
} else if (*leaftype == 'i') {
leaf = new TLeafI(this, leafname, leaftype);
leaf->SetUnsigned();
} else if (*leaftype == 'F') {
leaf = new TLeafF(this, leafname, leaftype);
} else if (*leaftype == 'f') {
leaf = new TLeafF(this, leafname, leaftype);
} else if (*leaftype == 'L') {
leaf = new TLeafL(this, leafname, leaftype);
} else if (*leaftype == 'l') {
leaf = new TLeafL(this, leafname, leaftype);
leaf->SetUnsigned();
} else if (*leaftype == 'D') {
leaf = new TLeafD(this, leafname, leaftype);
} else if (*leaftype == 'd') {
leaf = new TLeafD(this, leafname, leaftype);
}
if (!leaf) {
Error("TLeaf", "Illegal data type for %s/%s", name, leaflist);
delete[] leaftype;
delete [] leafname;
MakeZombie();
return;
}
if (leaf->IsZombie()) {
delete leaf;
leaf = 0;
Error("TBranch", "Illegal leaf: %s/%s", name, leaflist);
delete [] leafname;
delete[] leaftype;
MakeZombie();
return;
}
leaf->SetBranch(this);
leaf->SetAddress((char*) (fAddress + offset));
leaf->SetOffset(offset);
if (leaf->GetLeafCount()) {
fEntryOffsetLen = 1000;
}
if (leaf->InheritsFrom(TLeafC::Class())) {
fEntryOffsetLen = 1000;
}
++fNleaves;
fLeaves.Add(leaf);
fTree->GetListOfLeaves()->Add(leaf);
if (*pos == 0) {
break;
}
nameBegin = pos + 1;
offset += leaf->GetLenType() * leaf->GetLen();
}
}
delete[] leafname;
leafname = 0;
delete[] leaftype;
leaftype = 0;
}
TBranch::~TBranch()
{
delete fBrowsables;
fBrowsables = 0;
fEntryBuffer = 0;
delete [] fBasketSeek;
fBasketSeek = 0;
delete [] fBasketEntry;
fBasketEntry = 0;
delete [] fBasketBytes;
fBasketBytes = 0;
fBaskets.Delete();
fNBaskets = 0;
fCurrentBasket = 0;
fFirstBasketEntry = -1;
fNextBasketEntry = -1;
if (fTree) {
TObjArray* lst = fTree->GetListOfLeaves();
if (lst && lst->GetLast()!=-1) {
lst->RemoveAll(&fLeaves);
}
}
fLeaves.Delete();
fBranches.Delete();
if (fDirectory && (!fTree || fDirectory != fTree->GetDirectory())) {
TString bFileName( GetRealFileName() );
R__LOCKGUARD2(gROOTMutex);
TFile* file = (TFile*)gROOT->GetListOfFiles()->FindObject(bFileName);
if (file){
file->Close();
delete file;
file = 0;
}
}
fTree = 0;
fDirectory = 0;
}
void TBranch::AddBasket(TBasket& b, Bool_t ondisk, Long64_t startEntry)
{
TBasket *basket = &b;
basket->SetBranch(this);
if (fWriteBasket >= fMaxBaskets) {
ExpandBasketArrays();
}
Int_t where = fWriteBasket;
if (where && startEntry < fBasketEntry[where-1]) {
if (!ondisk) {
Warning("AddBasket","The assumption that out-of-order basket only comes from disk based ntuple is false.");
}
if (startEntry < fBasketEntry[0]) {
where = 0;
} else {
for(Int_t i=fWriteBasket-1; i>=0; --i) {
if (fBasketEntry[i] < startEntry) {
where = i+1;
break;
} else if (fBasketEntry[i] == startEntry) {
Error("AddBasket","An out-of-order basket matches the entry number of an existing basket.");
}
}
}
if (where < fWriteBasket) {
for (Int_t j=fWriteBasket; j > where; --j) {
fBasketEntry[j] = fBasketEntry[j-1];
fBasketBytes[j] = fBasketBytes[j-1];
fBasketSeek[j] = fBasketSeek[j-1];
}
}
}
fBasketEntry[where] = startEntry;
if (ondisk) {
fBasketBytes[where] = basket->GetNbytes();
fBasketSeek[where] = basket->GetSeekKey();
fBaskets.AddAtAndExpand(0,fWriteBasket);
++fWriteBasket;
} else {
++fNBaskets;
fBaskets.AddAtAndExpand(basket,fWriteBasket);
fTree->IncrementTotalBuffers(basket->GetBufferSize());
}
fEntries += basket->GetNevBuf();
fEntryNumber += basket->GetNevBuf();
if (ondisk) {
fTotBytes += basket->GetObjlen() + basket->GetKeylen() ;
fZipBytes += basket->GetNbytes();
fTree->AddTotBytes(basket->GetObjlen() + basket->GetKeylen());
fTree->AddZipBytes(basket->GetNbytes());
}
}
void TBranch::AddLastBasket(Long64_t startEntry)
{
if (fWriteBasket >= fMaxBaskets) {
ExpandBasketArrays();
}
Int_t where = fWriteBasket;
if (where && startEntry < fBasketEntry[where-1]) {
Fatal("AddBasket","The last basket must have the highest entry number (%s/%lld/%d).",GetName(),startEntry,fWriteBasket);
}
fBasketEntry[where] = startEntry;
fBaskets.AddAtAndExpand(0,fWriteBasket);
}
void TBranch::Browse(TBrowser* b)
{
if (fNleaves > 1) {
fLeaves.Browse(b);
} else {
TString name = GetName();
Int_t pos = name.First('[');
if (pos!=kNPOS) name.Remove(pos);
GetTree()->Draw(name, "", b ? b->GetDrawOption() : "");
if (gPad) gPad->Update();
}
}
void TBranch::DeleteBaskets(Option_t* option)
{
TString opt = option;
opt.ToLower();
TFile *file = GetFile(0);
if(fDirectory && (fDirectory != gROOT) && fDirectory->IsWritable()) {
for(Int_t i=0; i<fWriteBasket; i++) {
if (fBasketSeek[i]) file->MakeFree(fBasketSeek[i],fBasketSeek[i]+fBasketBytes[i]-1);
}
}
if (opt.Contains("all")) {
TObjArray *lb = GetListOfBranches();
Int_t nb = lb->GetEntriesFast();
for (Int_t j = 0; j < nb; j++) {
TBranch* branch = (TBranch*) lb->UncheckedAt(j);
if (branch) branch->DeleteBaskets("all");
}
}
DropBaskets("all");
Reset();
}
void TBranch::DropBaskets(Option_t* options)
{
Bool_t all = kFALSE;
if (options && options[0]) {
TString opt = options;
opt.ToLower();
if (opt.Contains("all")) all = kTRUE;
}
TBasket *basket;
Int_t nbaskets = fBaskets.GetEntriesFast();
if ( (fNBaskets>1) || all ) {
for (Int_t i=0;i<nbaskets;i++) {
basket = (TBasket*)fBaskets.UncheckedAt(i);
if (!basket) continue;
if ((i == fReadBasket || i == fWriteBasket) && !all) continue;
if (fBasketBytes[i]==0 && basket->GetNevBuf() > 0) continue;
basket->DropBuffers();
--fNBaskets;
fBaskets.RemoveAt(i);
if (basket == fCurrentBasket) {
fCurrentBasket = 0;
fFirstBasketEntry = -1;
fNextBasketEntry = -1;
}
delete basket;
}
if (all) {
TObjArray *lb = GetListOfBranches();
Int_t nb = lb->GetEntriesFast();
for (Int_t j = 0; j < nb; j++) {
TBranch* branch = (TBranch*) lb->UncheckedAt(j);
if (!branch) continue;
branch->DropBaskets("all");
}
}
} else {
if (nbaskets > 0) {
Int_t i = fBaskets.GetLast();
basket = (TBasket*)fBaskets.UncheckedAt(i);
if (basket && fBasketBytes[i]!=0) {
basket->DropBuffers();
if (basket == fCurrentBasket) {
fCurrentBasket = 0;
fFirstBasketEntry = -1;
fNextBasketEntry = -1;
}
delete basket;
fBaskets.AddAt(0,i);
fBaskets.SetLast(-1);
fNBaskets = 0;
}
}
}
}
void TBranch::ExpandBasketArrays()
{
Int_t newsize = TMath::Max(10,Int_t(1.5*fMaxBaskets));
fBasketBytes = TStorage::ReAllocInt(fBasketBytes, newsize, fMaxBaskets);
fBasketEntry = (Long64_t*)TStorage::ReAlloc(fBasketEntry,
newsize*sizeof(Long64_t),fMaxBaskets*sizeof(Long64_t));
fBasketSeek = (Long64_t*)TStorage::ReAlloc(fBasketSeek,
newsize*sizeof(Long64_t),fMaxBaskets*sizeof(Long64_t));
fMaxBaskets = newsize;
fBaskets.Expand(newsize);
for (Int_t i=fWriteBasket;i<fMaxBaskets;i++) {
fBasketBytes[i] = 0;
fBasketEntry[i] = 0;
fBasketSeek[i] = 0;
}
}
Int_t TBranch::Fill()
{
if (TestBit(kDoNotProcess)) {
return 0;
}
TBasket* basket = GetBasket(fWriteBasket);
if (!basket) {
basket = fTree->CreateBasket(this);
if (!basket) return 0;
++fNBaskets;
fBaskets.AddAtAndExpand(basket,fWriteBasket);
}
TBuffer* buf = basket->GetBufferRef();
Int_t nsize = 0;
if (buf->IsReading()) {
basket->SetWriteMode();
}
buf->ResetMap();
Int_t lnew = 0;
Int_t nbytes = 0;
if (fEntryBuffer) {
nbytes = FillEntryBuffer(basket,buf,lnew);
} else {
Int_t lold = buf->Length();
basket->Update(lold);
++fEntries;
++fEntryNumber;
(this->*fFillLeaves)(*buf);
if (buf->GetMapCount()) {
ResetBit(TBranch::kDoNotUseBufferMap);
}
lnew = buf->Length();
nbytes = lnew - lold;
}
if (fEntryOffsetLen) {
Int_t nevbuf = basket->GetNevBuf();
nsize = nevbuf * sizeof(Int_t);
} else {
if (!basket->GetNevBufSize()) {
basket->SetNevBufSize(nbytes);
}
}
if ((fSkipZip && (lnew >= TBuffer::kMinimalSize)) || (buf->TestBit(TBufferFile::kNotDecompressed)) || ((lnew + (2 * nsize) + nbytes) >= fBasketSize)) {
if (fTree->TestBit(TTree::kCircular)) {
return nbytes;
}
Int_t nout = WriteBasket(basket,fWriteBasket);
return (nout >= 0) ? nbytes : -1;
}
return nbytes;
}
Int_t TBranch::FillEntryBuffer(TBasket* basket, TBuffer* buf, Int_t& lnew)
{
Int_t nbytes = 0;
Int_t objectStart = 0;
Int_t last = 0;
Int_t lold = buf->Length();
if (fEntryBuffer->IsA() == TMessage::Class()) {
objectStart = 8;
}
if (fEntryBuffer->TestBit(TBufferFile::kNotDecompressed)) {
if (basket->GetNevBuf()) {
WriteBasket(basket,fWriteBasket);
return Fill();
}
Int_t startpos = fEntryBuffer->Length();
fEntryBuffer->SetBufferOffset(0);
static TBasket toread_fLast;
fEntryBuffer->SetReadMode();
toread_fLast.Streamer(*fEntryBuffer);
fEntryBuffer->SetWriteMode();
last = toread_fLast.GetLast();
fEntryBuffer->SetBufferOffset(startpos);
buf->SetBufferOffset(0);
buf->SetBit(TBufferFile::kNotDecompressed);
basket->Update(lold);
} else {
const UInt_t kNewClassTag = 0xFFFFFFFF;
const UInt_t kByteCountMask = 0x40000000;
UInt_t tag = 0;
UInt_t startpos = fEntryBuffer->Length();
fEntryBuffer->SetBufferOffset(objectStart);
*fEntryBuffer >> tag;
if (tag & kByteCountMask) {
*fEntryBuffer >> tag;
}
if (tag == kNewClassTag) {
UInt_t maxsize = 256;
char* s = new char[maxsize];
Int_t name_start = fEntryBuffer->Length();
fEntryBuffer->ReadString(s, maxsize);
while (strlen(s) == (maxsize - 1)) {
fEntryBuffer->SetBufferOffset(name_start);
maxsize *= 2;
delete[] s;
s = new char[maxsize];
fEntryBuffer->ReadString(s, maxsize);
}
} else {
fEntryBuffer->SetBufferOffset(objectStart);
}
objectStart = fEntryBuffer->Length();
fEntryBuffer->SetBufferOffset(startpos);
basket->Update(lold, objectStart - fEntryBuffer->GetBufferDisplacement());
}
fEntries++;
fEntryNumber++;
UInt_t len = 0;
UInt_t startpos = fEntryBuffer->Length();
if (startpos > UInt_t(objectStart)) {
len = fEntryBuffer->Length() - objectStart;
} else {
len = fEntryBuffer->BufferSize() - objectStart;
}
buf->WriteBuf(fEntryBuffer->Buffer() + objectStart, len);
if (fEntryBuffer->TestBit(TBufferFile::kNotDecompressed)) {
nbytes = last;
lnew = last;
} else {
lnew = buf->Length();
nbytes = lnew - lold;
}
return nbytes;
}
TBranch* TBranch::FindBranch(const char* name)
{
std::string longnm;
longnm.reserve(fName.Length()+strlen(name)+3);
longnm = fName.Data();
if (longnm[longnm.length()-1]==']') {
std::size_t dim = longnm.find_first_of("[");
if (dim != std::string::npos) {
longnm.erase(dim);
}
}
if (longnm[longnm.length()-1] != '.') {
longnm += '.';
}
longnm += name;
UInt_t namelen = strlen(name);
Int_t nbranches = fBranches.GetEntries();
TBranch* branch = 0;
for(Int_t i = 0; i < nbranches; ++i) {
branch = (TBranch*) fBranches.UncheckedAt(i);
const char *brname = branch->fName.Data();
UInt_t brlen = branch->fName.Length();
if (brname[brlen-1]==']') {
const char *dim = strchr(brname,'[');
if (dim) {
brlen = dim - brname;
}
}
if (namelen == brlen
&& strncmp(name,brname,brlen) == 0) {
return branch;
}
if (brlen == (size_t)longnm.length()
&& strncmp(longnm.c_str(),brname,brlen) == 0) {
return branch;
}
}
return 0;
}
TLeaf* TBranch::FindLeaf(const char* searchname)
{
TString leafname;
TString leaftitle;
TString longname;
TString longtitle;
TIter next(GetListOfLeaves());
TLeaf* leaf = 0;
while ((leaf = (TLeaf*) next())) {
leafname = leaf->GetName();
Ssiz_t dim = leafname.First('[');
if (dim >= 0) leafname.Remove(dim);
if (leafname == searchname) return leaf;
leaftitle = leaf->GetTitle();
dim = leaftitle.First('[');
if (dim >= 0) leaftitle.Remove(dim);
if (leaftitle == searchname) return leaf;
TBranch* branch = leaf->GetBranch();
if (branch) {
longname.Form("%s.%s",branch->GetName(),leafname.Data());
dim = longname.First('[');
if (dim>=0) longname.Remove(dim);
if (longname == searchname) return leaf;
longname.Form("%s.%s",branch->GetName(),searchname);
if (longname==leafname) return leaf;
longtitle.Form("%s.%s",branch->GetName(),leaftitle.Data());
dim = longtitle.First('[');
if (dim>=0) longtitle.Remove(dim);
if (longtitle == searchname) return leaf;
if (strstr(searchname, ".") && !strcmp(searchname, branch->GetName())) return leaf;
}
}
return 0;
}
Int_t TBranch::FlushBaskets()
{
UInt_t nerror = 0;
Int_t nbytes = 0;
Int_t maxbasket = fWriteBasket + 1;
for(Int_t i=0; i != maxbasket; ++i) {
if (fBaskets.UncheckedAt(i)) {
Int_t nwrite = FlushOneBasket(i);
if (nwrite<0) {
++nerror;
} else {
nbytes += nwrite;
}
}
}
Int_t len = fBranches.GetEntriesFast();
for (Int_t i = 0; i < len; ++i) {
TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
if (!branch) {
continue;
}
Int_t nwrite = branch->FlushBaskets();
if (nwrite<0) {
++nerror;
} else {
nbytes += nwrite;
}
}
if (nerror) {
return -1;
} else {
return nbytes;
}
}
Int_t TBranch::FlushOneBasket(UInt_t ibasket)
{
Int_t nbytes = 0;
if (fDirectory && fBaskets.GetEntries()) {
TBasket *basket = (TBasket*)fBaskets.UncheckedAt(ibasket);
if (basket) {
if (basket->GetNevBuf()
&& fBasketSeek[ibasket]==0) {
if (basket->GetBufferRef()->IsReading()) {
basket->SetWriteMode();
}
nbytes = WriteBasket(basket,ibasket);
} else {
if ((Int_t)ibasket==fWriteBasket) {
} else {
basket->DropBuffers();
if (basket == fCurrentBasket) {
fCurrentBasket = 0;
fFirstBasketEntry = -1;
fNextBasketEntry = -1;
}
delete basket;
--fNBaskets;
fBaskets[ibasket] = 0;
}
}
}
}
return nbytes;
}
TBasket* TBranch::GetBasket(Int_t basketnumber)
{
static Int_t nerrors = 0;
if (basketnumber <0 || basketnumber > fWriteBasket) return 0;
TBasket *basket = (TBasket*)fBaskets.UncheckedAt(basketnumber);
if (basket) return basket;
if (basketnumber == fWriteBasket) return 0;
TFile *file = GetFile(0);
if (file == 0) {
return 0;
}
basket = GetFreshBasket();
if (fSkipZip) basket->SetBit(TBufferFile::kNotDecompressed);
if (fBasketBytes[basketnumber] == 0) {
fBasketBytes[basketnumber] = basket->ReadBasketBytes(fBasketSeek[basketnumber],file);
}
TFileCacheRead *pf = file->GetCacheRead(fTree);
if (pf){
if (pf->IsLearning()) pf->AddBranch(this);
if (fSkipZip) pf->SetSkipZip();
}
Int_t badread = basket->ReadBasketBuffers(fBasketSeek[basketnumber],fBasketBytes[basketnumber],file);
if (badread || basket->GetSeekKey() != fBasketSeek[basketnumber]) {
nerrors++;
if (nerrors > 10) return 0;
if (nerrors == 10) {
printf(" file probably overwritten: stopping reporting error messages\n");
if (fBasketSeek[basketnumber] > 2000000000) {
printf("===>File is more than 2 Gigabytes\n");
return 0;
}
if (fBasketSeek[basketnumber] > 1000000000) {
printf("===>Your file is may be bigger than the maximum file size allowed on your system\n");
printf(" Check your AFS maximum file size limit for example\n");
return 0;
}
}
Error("GetBasket","File: %s at byte:%lld, branch:%s, entry:%lld, badread=%d, nerrors=%d, basketnumber=%d",file->GetName(),basket->GetSeekKey(),GetName(),fReadEntry,badread,nerrors,basketnumber);
return 0;
}
++fNBaskets;
fBaskets.AddAt(basket,basketnumber);
return basket;
}
Long64_t TBranch::GetBasketSeek(Int_t basketnumber) const
{
if (basketnumber <0 || basketnumber > fWriteBasket) return 0;
return fBasketSeek[basketnumber];
}
TList* TBranch::GetBrowsables() {
if (fBrowsables) return fBrowsables;
fBrowsables=new TList();
TVirtualBranchBrowsable::FillListOfBrowsables(*fBrowsables, this);
return fBrowsables;
}
const char * TBranch::GetClassName() const
{
return "";
}
const char* TBranch::GetIconName() const
{
if (IsFolder())
return "TBranchElement-folder";
else
return "TBranchElement-leaf";
}
Int_t TBranch::GetEntry(Long64_t entry, Int_t getall)
{
fReadEntry = entry;
Bool_t enabled = !TestBit(kDoNotProcess) || getall;
TBasket *basket;
Long64_t first;
if (R__likely(enabled && fFirstBasketEntry <= entry && entry < fNextBasketEntry)) {
basket = fCurrentBasket;
first = fFirstBasketEntry;
} else {
if (!enabled) {
return 0;
}
if ((entry < fFirstEntry) || (entry >= fEntryNumber)) {
return 0;
}
first = fFirstBasketEntry;
Long64_t last = fNextBasketEntry - 1;
if ((entry < first) || (entry > last)) {
fReadBasket = TMath::BinarySearch(fWriteBasket + 1, fBasketEntry, entry);
if (fReadBasket < 0) {
fNextBasketEntry = -1;
Error("In the branch %s, no basket contains the entry %d\n", GetName(), entry);
return -1;
}
if (fReadBasket == fWriteBasket) {
fNextBasketEntry = fEntryNumber;
} else {
fNextBasketEntry = fBasketEntry[fReadBasket+1];
}
first = fFirstBasketEntry = fBasketEntry[fReadBasket];
}
basket = (TBasket*) fBaskets.UncheckedAt(fReadBasket);
if (!basket) {
basket = GetBasket(fReadBasket);
if (!basket) {
fCurrentBasket = 0;
fFirstBasketEntry = -1;
fNextBasketEntry = -1;
return -1;
}
}
fCurrentBasket = basket;
}
basket->PrepareBasket(entry);
TBuffer* buf = basket->GetBufferRef();
if (R__unlikely(!buf)) {
TFile* file = GetFile(0);
if (!file) return -1;
basket->ReadBasketBuffers(fBasketSeek[fReadBasket], fBasketBytes[fReadBasket], file);
buf = basket->GetBufferRef();
}
if (!TestBit(kDoNotUseBufferMap)) {
buf->ResetMap();
}
if (R__unlikely(!buf->IsReading())) {
basket->SetReadMode();
}
Int_t* entryOffset = basket->GetEntryOffset();
Int_t bufbegin = 0;
if (entryOffset) {
bufbegin = entryOffset[entry-first];
buf->SetBufferOffset(bufbegin);
Int_t* displacement = basket->GetDisplacement();
if (R__unlikely(displacement)) {
buf->SetBufferDisplacement(displacement[entry-first]);
}
} else {
bufbegin = basket->GetKeylen() + ((entry-first) * basket->GetNevBufSize());
buf->SetBufferOffset(bufbegin);
}
(this->*fReadLeaves)(*buf);
return buf->Length() - bufbegin;
}
Int_t TBranch::GetEntryExport(Long64_t entry, Int_t , TClonesArray* li, Int_t nentries)
{
fReadEntry = entry;
if (TestBit(kDoNotProcess)) {
return 0;
}
if ((entry < 0) || (entry >= fEntryNumber)) {
return 0;
}
Int_t nbytes = 0;
Long64_t first = fFirstBasketEntry;
Long64_t last = fNextBasketEntry - 1;
if ((entry < first) || (entry > last)) {
fReadBasket = TMath::BinarySearch(fWriteBasket + 1, fBasketEntry, entry);
if (fReadBasket < 0) {
fNextBasketEntry = -1;
Error("In the branch %s, no basket contains the entry %d\n", GetName(), entry);
return -1;
}
if (fReadBasket == fWriteBasket) {
fNextBasketEntry = fEntryNumber;
} else {
fNextBasketEntry = fBasketEntry[fReadBasket+1];
}
fFirstBasketEntry = first = fBasketEntry[fReadBasket];
}
TBasket* basket = GetBasket(fReadBasket);
fCurrentBasket = basket;
if (!basket) {
fFirstBasketEntry = -1;
fNextBasketEntry = -1;
return 0;
}
TBuffer* buf = basket->GetBufferRef();
if (!TestBit(kDoNotUseBufferMap)) {
buf->ResetMap();
}
if (R__unlikely(!buf->IsReading())) {
basket->SetReadMode();
}
Int_t* entryOffset = basket->GetEntryOffset();
Int_t bufbegin = 0;
if (entryOffset) {
bufbegin = entryOffset[entry-first];
buf->SetBufferOffset(bufbegin);
Int_t* displacement = basket->GetDisplacement();
if (R__unlikely(displacement)) {
buf->SetBufferDisplacement(displacement[entry-first]);
}
} else {
bufbegin = basket->GetKeylen() + ((entry-first) * basket->GetNevBufSize());
buf->SetBufferOffset(bufbegin);
}
TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(0);
leaf->ReadBasketExport(*buf, li, nentries);
nbytes = buf->Length() - bufbegin;
return nbytes;
}
Int_t TBranch::GetExpectedType(TClass *&expectedClass,EDataType &expectedType)
{
expectedClass = 0;
expectedType = kOther_t;
TLeaf* l = (TLeaf*) GetListOfLeaves()->At(0);
if (l) {
expectedType = (EDataType) gROOT->GetType(l->GetTypeName())->GetType();
return 0;
} else {
Error("GetExpectedType", "Did not find any leaves in %s",GetName());
return 1;
}
}
TFile* TBranch::GetFile(Int_t mode)
{
if (fDirectory) return fDirectory->GetFile();
TFile *file = 0;
{
R__LOCKGUARD2(gROOTMutex);
file = (TFile*)gROOT->GetListOfFiles()->FindObject(fFileName.Data());
if (file) {
fDirectory = file;
return file;
}
}
if (fFileName.Length() == 0) return 0;
TString bFileName( GetRealFileName() );
{
TDirectory::TContext ctxt(0);
if (mode) file = TFile::Open(bFileName, "recreate");
else file = TFile::Open(bFileName);
}
if (!file) return 0;
if (file->IsZombie()) {delete file; return 0;}
fDirectory = (TDirectory*)file;
return file;
}
TBasket* TBranch::GetFreshBasket()
{
TBasket *basket = 0;
if (GetTree()->MemoryFull(0)) {
if (fNBaskets==1) {
Int_t oldindex = fBaskets.GetLast();
basket = (TBasket*)fBaskets.UncheckedAt(oldindex);
if (!basket) {
fBaskets.SetLast(-2);
oldindex = fBaskets.GetLast();
basket = (TBasket*)fBaskets.UncheckedAt(oldindex);
}
if (basket && fBasketBytes[oldindex]!=0) {
if (basket == fCurrentBasket) {
fCurrentBasket = 0;
fFirstBasketEntry = -1;
fNextBasketEntry = -1;
}
fBaskets.AddAt(0,oldindex);
fBaskets.SetLast(-1);
fNBaskets = 0;
} else {
basket = fTree->CreateBasket(this);
}
} else if (fNBaskets == 0) {
basket = fTree->CreateBasket(this);
} else {
DropBaskets();
basket = fTree->CreateBasket(this);
}
} else {
basket = fTree->CreateBasket(this);
}
return basket;
}
TLeaf* TBranch::GetLeaf(const char* name) const
{
Int_t i;
for (i=0;i<fNleaves;i++) {
TLeaf *leaf = (TLeaf*)fLeaves.UncheckedAt(i);
if (!strcmp(leaf->GetName(),name)) return leaf;
}
return 0;
}
TString TBranch::GetRealFileName() const
{
if (fFileName.Length()==0) {
return fFileName;
}
TString bFileName = fFileName;
char *bname = gSystem->ExpandPathName(fFileName.Data());
if (!gSystem->IsAbsoluteFileName(bname) && !strstr(bname, ":/") && fTree && fTree->GetCurrentFile()) {
const char *tfn = fTree->GetCurrentFile()->GetName();
TUrl arc(tfn);
if (strlen(arc.GetAnchor()) > 0) {
arc.SetAnchor(gSystem->BaseName(fFileName));
bFileName = arc.GetUrl();
} else {
char *tname = gSystem->ExpandPathName(tfn);
if (gSystem->IsAbsoluteFileName(tname) || strstr(tname, ":/")) {
bFileName = gSystem->DirName(tname);
bFileName += "/";
bFileName += fFileName;
}
delete [] tname;
}
}
delete [] bname;
return bFileName;
}
Int_t TBranch::GetRow(Int_t)
{
return 1;
}
Bool_t TBranch::GetMakeClass() const
{
return kFALSE;
}
TBranch* TBranch::GetMother() const
{
if (fMother) return fMother;
const TObjArray* array = fTree->GetListOfBranches();
Int_t n = array->GetEntriesFast();
for (Int_t i = 0; i < n; ++i) {
TBranch* branch = (TBranch*) array->UncheckedAt(i);
TBranch* parent = branch->GetSubBranch(this);
if (parent) {
const_cast<TBranch*>(this)->fMother = branch;
return branch;
}
}
return 0;
}
TBranch* TBranch::GetSubBranch(const TBranch* child) const
{
if (this == child) {
return (TBranch*) this;
}
if (child->fParent) {
return child->fParent;
}
Int_t len = fBranches.GetEntriesFast();
for (Int_t i = 0; i < len; ++i) {
TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
if (!branch) {
continue;
}
if (branch == child) {
const_cast<TBranch*>(child)->fParent = (TBranch*)this;
const_cast<TBranch*>(child)->fParent = (TBranch*)this;
return (TBranch*) this;
}
TBranch* parent = branch->GetSubBranch(child);
if (parent) {
return parent;
}
}
return 0;
}
Long64_t TBranch::GetTotalSize(Option_t * ) const
{
TObjArray &baskets( const_cast<TObjArray&>(fBaskets) );
TBasket *writebasket = 0;
if (fNBaskets == 1) {
writebasket = (TBasket*)fBaskets.UncheckedAt(fWriteBasket);
if (writebasket && writebasket->GetNevBuf()==0) {
baskets[fWriteBasket] = 0;
} else {
writebasket = 0;
}
}
TBufferFile b(TBuffer::kWrite,10000);
TBranch::Class()->WriteBuffer(b,(TBranch*)this);
if (writebasket) {
baskets[fWriteBasket] = writebasket;
}
Long64_t totbytes = 0;
if (fZipBytes > 0) totbytes = fTotBytes;
return totbytes + b.Length();
}
Long64_t TBranch::GetTotBytes(Option_t *option) const
{
Long64_t totbytes = fTotBytes;
if (!option) return totbytes;
if (option[0] != '*') return totbytes;
Int_t len = fBranches.GetEntriesFast();
for (Int_t i = 0; i < len; ++i) {
TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
if (branch) totbytes += branch->GetTotBytes();
}
return totbytes;
}
Long64_t TBranch::GetZipBytes(Option_t *option) const
{
Long64_t zipbytes = fZipBytes;
if (!option) return zipbytes;
if (option[0] != '*') return zipbytes;
Int_t len = fBranches.GetEntriesFast();
for (Int_t i = 0; i < len; ++i) {
TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
if (branch) zipbytes += branch->GetZipBytes();
}
return zipbytes;
}
Bool_t TBranch::IsAutoDelete() const
{
return TestBit(kAutoDelete);
}
Bool_t TBranch::IsFolder() const
{
if (fNleaves > 1) {
return kTRUE;
}
TList* browsables = const_cast<TBranch*>(this)->GetBrowsables();
return browsables && browsables->GetSize();
}
void TBranch::KeepCircular(Long64_t maxEntries)
{
Int_t dentries = (Int_t) (fEntries - maxEntries);
TBasket* basket = (TBasket*) fBaskets.UncheckedAt(0);
if (basket) basket->MoveEntries(dentries);
fEntries = maxEntries;
fEntryNumber = maxEntries;
Int_t nb = fBranches.GetEntriesFast();
for (Int_t i = 0; i < nb; ++i) {
TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
branch->KeepCircular(maxEntries);
}
}
Int_t TBranch::LoadBaskets()
{
Int_t nimported = 0;
Int_t nbaskets = fWriteBasket;
TFile *file = GetFile(0);
if (!file) return 0;
TBasket *basket;
for (Int_t i=0;i<nbaskets;i++) {
basket = (TBasket*)fBaskets.UncheckedAt(i);
if (basket) continue;
basket = GetFreshBasket();
if (fBasketBytes[i] == 0) {
fBasketBytes[i] = basket->ReadBasketBytes(fBasketSeek[i],file);
}
Int_t badread = basket->ReadBasketBuffers(fBasketSeek[i],fBasketBytes[i],file);
if (badread) {
Error("Loadbaskets","Error while reading basket buffer %d of branch %s",i,GetName());
return -1;
}
++fNBaskets;
fBaskets.AddAt(basket,i);
nimported++;
}
return nimported;
}
void TBranch::Print(Option_t*) const
{
const int kLINEND = 77;
Float_t cx = 1;
TString titleContent(GetTitle());
if ( titleContent == GetName() ) {
titleContent.Clear();
}
if (fLeaves.GetEntries() == 1) {
if (titleContent.Length()>=2 && titleContent[titleContent.Length()-2]=='/' && isalpha(titleContent[titleContent.Length()-1])) {
} else {
TLeaf *leaf = (TLeaf*)fLeaves.UncheckedAt(0);
if (titleContent.Length()) {
titleContent.Prepend(" ");
}
titleContent.Prepend(leaf->GetTypeName());
}
}
Int_t titleLength = titleContent.Length();
Int_t aLength = titleLength + strlen(GetName());
aLength += (aLength / 54 + 1) * 80 + 100;
if (aLength < 200) aLength = 200;
char *bline = new char[aLength];
Long64_t totBytes = GetTotalSize();
if (fZipBytes) cx = (fTotBytes+0.00001)/fZipBytes;
if (titleLength) snprintf(bline,aLength,"*Br%5d :%-9s : %-54s *",fgCount,GetName(),titleContent.Data());
else snprintf(bline,aLength,"*Br%5d :%-9s : %-54s *",fgCount,GetName()," ");
if (strlen(bline) > UInt_t(kLINEND)) {
char *tmp = new char[strlen(bline)+1];
if (titleLength) strlcpy(tmp, titleContent.Data(),strlen(bline)+1);
snprintf(bline,aLength,"*Br%5d :%-9s : ",fgCount,GetName());
int pos = strlen (bline);
int npos = pos;
int beg=0, end;
while (beg < titleLength) {
for (end=beg+1; end < titleLength-1; end ++)
if (tmp[end] == ':') break;
if (npos + end-beg+1 >= 78) {
while (npos < kLINEND) {
bline[pos ++] = ' ';
npos ++;
}
bline[pos ++] = '*';
bline[pos ++] = '\n';
bline[pos ++] = '*';
npos = 1;
for (; npos < 12; npos ++)
bline[pos ++] = ' ';
bline[pos-2] = '|';
}
for (int n = beg; n <= end; n ++)
bline[pos+n-beg] = tmp[n];
pos += end-beg+1;
npos += end-beg+1;
beg = end+1;
}
while (npos < kLINEND) {
bline[pos ++] = ' ';
npos ++;
}
bline[pos ++] = '*';
bline[pos] = '\0';
delete[] tmp;
}
Printf("%s", bline);
if (fTotBytes > 2000000000) {
Printf("*Entries :%lld : Total Size=%11lld bytes File Size = %lld *",fEntries,totBytes,fZipBytes);
} else {
if (fZipBytes > 0) {
Printf("*Entries :%9lld : Total Size=%11lld bytes File Size = %10lld *",fEntries,totBytes,fZipBytes);
} else {
if (fWriteBasket > 0) {
Printf("*Entries :%9lld : Total Size=%11lld bytes All baskets in memory *",fEntries,totBytes);
} else {
Printf("*Entries :%9lld : Total Size=%11lld bytes One basket in memory *",fEntries,totBytes);
}
}
}
Printf("*Baskets :%9d : Basket Size=%11d bytes Compression= %6.2f *",fWriteBasket,fBasketSize,cx);
Printf("*............................................................................*");
delete [] bline;
fgCount++;
}
void TBranch::ReadBasket(TBuffer&)
{
}
void TBranch::ReadLeavesImpl(TBuffer& b)
{
for (Int_t i = 0; i < fNleaves; ++i) {
TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
leaf->ReadBasket(b);
}
}
void TBranch::ReadLeaves0Impl(TBuffer&)
{
}
void TBranch::ReadLeaves1Impl(TBuffer& b)
{
((TLeaf*) fLeaves.UncheckedAt(0))->ReadBasket(b);
}
void TBranch::ReadLeaves2Impl(TBuffer& b)
{
((TLeaf*) fLeaves.UncheckedAt(0))->ReadBasket(b);
((TLeaf*) fLeaves.UncheckedAt(1))->ReadBasket(b);
}
void TBranch::FillLeavesImpl(TBuffer& b)
{
for (Int_t i = 0; i < fNleaves; ++i) {
TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
leaf->FillBasket(b);
}
}
void TBranch::Refresh(TBranch* b)
{
if (b==0) return;
fEntryOffsetLen = b->fEntryOffsetLen;
fWriteBasket = b->fWriteBasket;
fEntryNumber = b->fEntryNumber;
fMaxBaskets = b->fMaxBaskets;
fEntries = b->fEntries;
fTotBytes = b->fTotBytes;
fZipBytes = b->fZipBytes;
fReadBasket = 0;
fReadEntry = -1;
fFirstBasketEntry = -1;
fNextBasketEntry = -1;
fCurrentBasket = 0;
delete [] fBasketBytes;
delete [] fBasketEntry;
delete [] fBasketSeek;
fBasketBytes = new Int_t[fMaxBaskets];
fBasketEntry = new Long64_t[fMaxBaskets];
fBasketSeek = new Long64_t[fMaxBaskets];
Int_t i;
for (i=0;i<fMaxBaskets;i++) {
fBasketBytes[i] = b->fBasketBytes[i];
fBasketEntry[i] = b->fBasketEntry[i];
fBasketSeek[i] = b->fBasketSeek[i];
}
fBaskets.Delete();
Int_t nbaskets = b->fBaskets.GetSize();
fBaskets.Expand(nbaskets);
TBasket *basket = (TBasket*)b->fBaskets.UncheckedAt(fWriteBasket);
fBaskets.AddAt(basket,fWriteBasket);
if (basket) {
fNBaskets = 1;
--(b->fNBaskets);
b->fBaskets.RemoveAt(fWriteBasket);
basket->SetBranch(this);
}
}
void TBranch::Reset(Option_t*)
{
fReadBasket = 0;
fReadEntry = -1;
fFirstBasketEntry = -1;
fNextBasketEntry = -1;
fCurrentBasket = 0;
fWriteBasket = 0;
fEntries = 0;
fTotBytes = 0;
fZipBytes = 0;
fEntryNumber = 0;
if (fBasketBytes) {
for (Int_t i = 0; i < fMaxBaskets; ++i) {
fBasketBytes[i] = 0;
}
}
if (fBasketEntry) {
for (Int_t i = 0; i < fMaxBaskets; ++i) {
fBasketEntry[i] = 0;
}
}
if (fBasketSeek) {
for (Int_t i = 0; i < fMaxBaskets; ++i) {
fBasketSeek[i] = 0;
}
}
fBaskets.Delete();
fNBaskets = 0;
}
void TBranch::ResetAfterMerge(TFileMergeInfo *)
{
fReadBasket = 0;
fReadEntry = -1;
fFirstBasketEntry = -1;
fNextBasketEntry = -1;
fCurrentBasket = 0;
fWriteBasket = 0;
fEntries = 0;
fTotBytes = 0;
fZipBytes = 0;
fEntryNumber = 0;
if (fBasketBytes) {
for (Int_t i = 0; i < fMaxBaskets; ++i) {
fBasketBytes[i] = 0;
}
}
if (fBasketEntry) {
for (Int_t i = 0; i < fMaxBaskets; ++i) {
fBasketEntry[i] = 0;
}
}
if (fBasketSeek) {
for (Int_t i = 0; i < fMaxBaskets; ++i) {
fBasketSeek[i] = 0;
}
}
TBasket *reusebasket = (TBasket*)fBaskets[fWriteBasket];
if (reusebasket) {
fBaskets[fWriteBasket] = 0;
} else {
reusebasket = (TBasket*)fBaskets[fReadBasket];
if (reusebasket) {
fBaskets[fReadBasket] = 0;
}
}
fBaskets.Delete();
if (reusebasket) {
fNBaskets = 1;
reusebasket->Reset();
fBaskets[0] = reusebasket;
} else {
fNBaskets = 0;
}
}
void TBranch::ResetAddress()
{
fAddress = 0;
fReadEntry = -1;
fFirstBasketEntry = -1;
fNextBasketEntry = -1;
for (Int_t i = 0; i < fNleaves; ++i) {
TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
leaf->SetAddress(0);
}
Int_t nbranches = fBranches.GetEntriesFast();
for (Int_t i = 0; i < nbranches; ++i) {
TBranch* abranch = (TBranch*) fBranches[i];
abranch->ResetAddress();
}
}
void TBranch::ResetCount()
{
fgCount = 0;
}
void TBranch::SetAddress(void* addr)
{
if (TestBit(kDoNotProcess)) {
return;
}
fReadEntry = -1;
fFirstBasketEntry = -1;
fNextBasketEntry = -1;
fAddress = (char*) addr;
for (Int_t i = 0; i < fNleaves; ++i) {
TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
Int_t offset = leaf->GetOffset();
if (TestBit(kIsClone)) {
offset = 0;
}
if (fAddress) leaf->SetAddress(fAddress + offset);
else leaf->SetAddress(0);
}
}
void TBranch::SetAutoDelete(Bool_t autodel)
{
if (autodel) {
SetBit(kAutoDelete, 1);
} else {
SetBit(kAutoDelete, 0);
}
}
void TBranch::SetBasketSize(Int_t buffsize)
{
Int_t minsize = 100 + fName.Length();
if (buffsize < minsize+fEntryOffsetLen) buffsize = minsize+fEntryOffsetLen;
fBasketSize = buffsize;
TBasket *basket = (TBasket*)fBaskets[fWriteBasket];
if (basket) {
basket->AdjustSize(fBasketSize);
}
}
void TBranch::SetBufferAddress(TBuffer* buf)
{
if ( (fNleaves != 1)
|| (strcmp("TLeafObject",fLeaves.UncheckedAt(0)->ClassName())!=0) ) {
Error("TBranch::SetAddress","Filling from a TBuffer can only be done with a not split object branch. Request ignored.");
} else {
fReadEntry = -1;
fNextBasketEntry = -1;
fFirstBasketEntry = -1;
fEntryBuffer = buf;
}
}
void TBranch::SetCompressionAlgorithm(Int_t algorithm)
{
if (algorithm < 0 || algorithm >= ROOT::kUndefinedCompressionAlgorithm) algorithm = 0;
if (fCompress < 0) {
fCompress = 100 * algorithm + 1;
} else {
int level = fCompress % 100;
fCompress = 100 * algorithm + level;
}
Int_t nb = fBranches.GetEntriesFast();
for (Int_t i=0;i<nb;i++) {
TBranch *branch = (TBranch*)fBranches.UncheckedAt(i);
branch->SetCompressionAlgorithm(algorithm);
}
}
void TBranch::SetCompressionLevel(Int_t level)
{
if (level < 0) level = 0;
if (level > 99) level = 99;
if (fCompress < 0) {
fCompress = level;
} else {
int algorithm = fCompress / 100;
if (algorithm >= ROOT::kUndefinedCompressionAlgorithm) algorithm = 0;
fCompress = 100 * algorithm + level;
}
Int_t nb = fBranches.GetEntriesFast();
for (Int_t i=0;i<nb;i++) {
TBranch *branch = (TBranch*)fBranches.UncheckedAt(i);
branch->SetCompressionLevel(level);
}
}
void TBranch::SetCompressionSettings(Int_t settings)
{
fCompress = settings;
Int_t nb = fBranches.GetEntriesFast();
for (Int_t i=0;i<nb;i++) {
TBranch *branch = (TBranch*)fBranches.UncheckedAt(i);
branch->SetCompressionSettings(settings);
}
}
void TBranch::SetEntryOffsetLen(Int_t newdefault, Bool_t updateExisting)
{
if (fEntryOffsetLen && newdefault) {
fEntryOffsetLen = newdefault;
}
if (updateExisting) {
TIter next( GetListOfBranches() );
TBranch *b;
while ( ( b = (TBranch*)next() ) ) {
b->SetEntryOffsetLen( newdefault, kTRUE );
}
}
}
void TBranch::SetEntries(Long64_t entries)
{
fEntries = entries;
fEntryNumber = entries;
}
void TBranch::SetFile(TFile* file)
{
if (file == 0) file = fTree->GetCurrentFile();
fDirectory = (TDirectory*)file;
if (file == fTree->GetCurrentFile()) fFileName = "";
else fFileName = file->GetName();
if (file && fCompress == -1) {
fCompress = file->GetCompressionLevel();
}
TIter nextb(GetListOfBaskets());
TBasket *basket;
while ((basket = (TBasket*)nextb())) {
basket->SetParent(file);
}
TIter next(GetListOfBranches());
TBranch *branch;
while ((branch = (TBranch*)next())) {
branch->SetFile(file);
}
}
void TBranch::SetFile(const char* fname)
{
fFileName = fname;
fDirectory = 0;
TIter next(GetListOfBranches());
TBranch *branch;
while ((branch = (TBranch*)next())) {
branch->SetFile(fname);
}
}
Bool_t TBranch::SetMakeClass(Bool_t )
{
return kFALSE;
}
void TBranch::SetObject(void * )
{
if (TestBit(kDoNotProcess)) {
return;
}
Warning("SetObject","is not supported in TBranch objects");
}
void TBranch::SetStatus(Bool_t status)
{
if (status) ResetBit(kDoNotProcess);
else SetBit(kDoNotProcess);
}
void TBranch::Streamer(TBuffer& b)
{
if (b.IsReading()) {
UInt_t R__s, R__c;
fTree = 0;
fAddress = 0;
gROOT->SetReadingObject(kTRUE);
SetBit(TBranch::kDoNotUseBufferMap);
fCurrentBasket = 0;
fFirstBasketEntry = -1;
fNextBasketEntry = -1;
Version_t v = b.ReadVersion(&R__s, &R__c);
if (v > 9) {
b.ReadClassBuffer(TBranch::Class(), this, v, R__s, R__c);
if (fWriteBasket>=fBaskets.GetSize()) {
fBaskets.Expand(fWriteBasket+1);
}
fDirectory = 0;
fNleaves = fLeaves.GetEntriesFast();
for (Int_t i=0;i<fNleaves;i++) {
TLeaf *leaf = (TLeaf*)fLeaves.UncheckedAt(i);
leaf->SetBranch(this);
}
fNBaskets = fBaskets.GetEntries();
for (Int_t j=fWriteBasket,n=0;j>=0 && n<fNBaskets;--j) {
TBasket *bk = (TBasket*)fBaskets.UncheckedAt(j);
if (bk) {
bk->SetBranch(this);
++n;
}
}
if (fWriteBasket >= fMaxBaskets) {
ExpandBasketArrays();
fBasketBytes[fWriteBasket] = fBasketBytes[fWriteBasket-1];
fBasketEntry[fWriteBasket] = fEntries;
fBasketSeek [fWriteBasket] = fBasketSeek [fWriteBasket-1];
}
if (!fSplitLevel && fBranches.GetEntriesFast()) fSplitLevel = 1;
gROOT->SetReadingObject(kFALSE);
if (IsA() == TBranch::Class()) {
if (fNleaves == 0) {
fReadLeaves = &TBranch::ReadLeaves0Impl;
} else if (fNleaves == 1) {
fReadLeaves = &TBranch::ReadLeaves1Impl;
} else if (fNleaves == 2) {
fReadLeaves = &TBranch::ReadLeaves2Impl;
} else {
fReadLeaves = &TBranch::ReadLeavesImpl;
}
}
return;
}
Int_t n,i,j,ijunk;
if (v > 5) {
Stat_t djunk;
TNamed::Streamer(b);
if (v > 7) TAttFill::Streamer(b);
b >> fCompress;
b >> fBasketSize;
b >> fEntryOffsetLen;
b >> fWriteBasket;
b >> ijunk; fEntryNumber = (Long64_t)ijunk;
b >> fOffset;
b >> fMaxBaskets;
if (v > 6) b >> fSplitLevel;
b >> djunk; fEntries = (Long64_t)djunk;
b >> djunk; fTotBytes = (Long64_t)djunk;
b >> djunk; fZipBytes = (Long64_t)djunk;
fBranches.Streamer(b);
fLeaves.Streamer(b);
fBaskets.Streamer(b);
fBasketBytes = new Int_t[fMaxBaskets];
fBasketEntry = new Long64_t[fMaxBaskets];
fBasketSeek = new Long64_t[fMaxBaskets];
Char_t isArray;
b >> isArray;
b.ReadFastArray(fBasketBytes,fMaxBaskets);
b >> isArray;
for (i=0;i<fMaxBaskets;i++) {b >> ijunk; fBasketEntry[i] = ijunk;}
b >> isArray;
for (i=0;i<fMaxBaskets;i++) {
if (isArray == 2) b >> fBasketSeek[i];
else {Int_t bsize; b >> bsize; fBasketSeek[i] = (Long64_t)bsize;};
}
fFileName.Streamer(b);
b.CheckByteCount(R__s, R__c, TBranch::IsA());
fDirectory = 0;
fNleaves = fLeaves.GetEntriesFast();
for (i=0;i<fNleaves;i++) {
TLeaf *leaf = (TLeaf*)fLeaves.UncheckedAt(i);
leaf->SetBranch(this);
}
fNBaskets = fBaskets.GetEntries();
for (j=fWriteBasket,n=0;j>=0 && n<fNBaskets;--j) {
TBasket *bk = (TBasket*)fBaskets.UncheckedAt(j);
if (bk) {
bk->SetBranch(this);
++n;
}
}
if (fWriteBasket >= fMaxBaskets) {
ExpandBasketArrays();
fBasketBytes[fWriteBasket] = fBasketBytes[fWriteBasket-1];
fBasketEntry[fWriteBasket] = fEntries;
fBasketSeek [fWriteBasket] = fBasketSeek [fWriteBasket-1];
}
if (!fSplitLevel && fBranches.GetEntriesFast()) fSplitLevel = 1;
gROOT->SetReadingObject(kFALSE);
b.CheckByteCount(R__s, R__c, TBranch::IsA());
if (IsA() == TBranch::Class()) {
if (fNleaves == 0) {
fReadLeaves = &TBranch::ReadLeaves0Impl;
} else if (fNleaves == 1) {
fReadLeaves = &TBranch::ReadLeaves1Impl;
} else if (fNleaves == 2) {
fReadLeaves = &TBranch::ReadLeaves2Impl;
} else {
fReadLeaves = &TBranch::ReadLeavesImpl;
}
}
return;
}
Stat_t djunk;
TNamed::Streamer(b);
b >> fCompress;
b >> fBasketSize;
b >> fEntryOffsetLen;
b >> fMaxBaskets;
b >> fWriteBasket;
b >> ijunk; fEntryNumber = (Long64_t)ijunk;
b >> djunk; fEntries = (Long64_t)djunk;
b >> djunk; fTotBytes = (Long64_t)djunk;
b >> djunk; fZipBytes = (Long64_t)djunk;
b >> fOffset;
fBranches.Streamer(b);
fLeaves.Streamer(b);
fNleaves = fLeaves.GetEntriesFast();
for (i=0;i<fNleaves;i++) {
TLeaf *leaf = (TLeaf*)fLeaves.UncheckedAt(i);
leaf->SetBranch(this);
}
fBaskets.Streamer(b);
Int_t nbaskets = fBaskets.GetEntries();
for (j=fWriteBasket,n=0;j>0 && n<nbaskets;--j) {
TBasket *bk = (TBasket*)fBaskets.UncheckedAt(j);
if (bk) {
bk->SetBranch(this);
++n;
}
}
fBasketEntry = new Long64_t[fMaxBaskets];
b >> n;
for (i=0;i<n;i++) {b >> ijunk; fBasketEntry[i] = ijunk;}
fBasketBytes = new Int_t[fMaxBaskets];
if (v > 4) {
n = b.ReadArray(fBasketBytes);
} else {
for (n=0;n<fMaxBaskets;n++) fBasketBytes[n] = 0;
}
if (v < 2) {
fBasketSeek = new Long64_t[fMaxBaskets];
for (n=0;n<fWriteBasket;n++) {
TBasket *basket = GetBasket(n);
fBasketSeek[n] = basket ? basket->GetSeekKey() : 0;
}
} else {
fBasketSeek = new Long64_t[fMaxBaskets];
b >> n;
for (n=0;n<fMaxBaskets;n++) {
Int_t aseek;
b >> aseek;
fBasketSeek[n] = Long64_t(aseek);
}
}
if (v > 2) {
fFileName.Streamer(b);
}
fDirectory = 0;
if (v < 4) SetAutoDelete(kTRUE);
if (!fSplitLevel && fBranches.GetEntriesFast()) fSplitLevel = 1;
gROOT->SetReadingObject(kFALSE);
b.CheckByteCount(R__s, R__c, TBranch::IsA());
if (IsA() == TBranch::Class()) {
if (fNleaves == 0) {
fReadLeaves = &TBranch::ReadLeaves0Impl;
} else if (fNleaves == 1) {
fReadLeaves = &TBranch::ReadLeaves1Impl;
} else if (fNleaves == 2) {
fReadLeaves = &TBranch::ReadLeaves2Impl;
} else {
fReadLeaves = &TBranch::ReadLeavesImpl;
}
}
} else {
Int_t maxBaskets = fMaxBaskets;
fMaxBaskets = fWriteBasket+1;
if (fMaxBaskets < 10) fMaxBaskets=10;
TBasket *writebasket = 0;
if (fNBaskets == 1) {
writebasket = (TBasket*)fBaskets.UncheckedAt(fWriteBasket);
if (writebasket && writebasket->GetNevBuf()==0) {
fBaskets[fWriteBasket] = 0;
} else {
writebasket = 0;
}
}
b.WriteClassBuffer(TBranch::Class(),this);
if (writebasket) {
fBaskets[fWriteBasket] = writebasket;
}
fMaxBaskets = maxBaskets;
}
}
Int_t TBranch::WriteBasket(TBasket* basket, Int_t where)
{
Int_t nevbuf = basket->GetNevBuf();
if (fEntryOffsetLen > 10 && (4*nevbuf) < fEntryOffsetLen ) {
fEntryOffsetLen = nevbuf < 3 ? 10 : 4*nevbuf;
} else if (fEntryOffsetLen && nevbuf > fEntryOffsetLen) {
fEntryOffsetLen = 2*nevbuf;
}
Int_t nout = basket->WriteBuffer();
fBasketBytes[where] = basket->GetNbytes();
fBasketSeek[where] = basket->GetSeekKey();
Int_t addbytes = basket->GetObjlen() + basket->GetKeylen();
TBasket *reusebasket = 0;
if (nout>0) {
fBaskets[where] = 0;
reusebasket = basket;
reusebasket->Reset();
fZipBytes += nout;
fTotBytes += addbytes;
fTree->AddTotBytes(addbytes);
fTree->AddZipBytes(nout);
}
if (where==fWriteBasket) {
++fWriteBasket;
if (fWriteBasket >= fMaxBaskets) {
ExpandBasketArrays();
}
fBaskets.AddAtAndExpand(reusebasket,fWriteBasket);
fBasketEntry[fWriteBasket] = fEntryNumber;
} else {
--fNBaskets;
fBaskets[where] = 0;
basket->DropBuffers();
if (basket == fCurrentBasket) {
fCurrentBasket = 0;
fFirstBasketEntry = -1;
fNextBasketEntry = -1;
}
delete basket;
}
return nout;
}
void TBranch::SetFirstEntry(Long64_t entry)
{
fFirstEntry = entry;
fEntries = 0;
fEntryNumber = entry;
if( fBasketEntry )
fBasketEntry[0] = entry;
for( Int_t i = 0; i < fBranches.GetEntriesFast(); ++i )
((TBranch*)fBranches[i])->SetFirstEntry( entry );
}
void TBranch::SetupAddresses()
{
}
void TBranch::UpdateFile()
{
TFile *file = fTree->GetCurrentFile();
if (fFileName.Length() == 0) {
fDirectory = file;
TIter nextb(GetListOfBaskets());
TBasket *basket;
while ((basket = (TBasket*)nextb())) {
basket->SetParent(file);
}
}
TIter next(GetListOfBranches());
TBranch *branch;
while ((branch = (TBranch*)next())) {
branch->UpdateFile();
}
}