59 Int_t TBranch::fgCount = 0;
89 , fEntryOffsetLen(1000)
92 , fExtraBasket(nullptr)
100 , fFirstBasketEntry(-1)
101 , fNextBasketEntry(-1)
109 , fBaskets(fMaxBaskets)
120 , fTransientBuffer(0)
124 , fReadLeaves(&TBranch::ReadLeavesImpl)
125 , fFillLeaves(&TBranch::FillLeavesImpl)
127 SetBit(TBranch::kDoNotUseBufferMap);
194 TBranch::TBranch(TTree *tree,
const char *name,
void *address,
const char *leaflist, Int_t basketsize, Int_t compress)
195 : TNamed(name, leaflist)
197 , fCompress(compress)
198 , fBasketSize((basketsize < 100) ? 100 : basketsize)
202 , fExtraBasket(nullptr)
203 , fIOFeatures(tree ? tree->GetIOFeatures().GetFeatures() : 0)
211 , fFirstBasketEntry(-1)
212 , fNextBasketEntry(-1)
220 , fBaskets(fMaxBaskets)
227 , fAddress((char *)address)
228 , fDirectory(fTree->GetDirectory())
231 , fTransientBuffer(0)
235 , fReadLeaves(&TBranch::ReadLeavesImpl)
236 , fFillLeaves(&TBranch::FillLeavesImpl)
238 Init(name,leaflist,compress);
247 TBranch::TBranch(TBranch *parent,
const char *name,
void *address,
const char *leaflist, Int_t basketsize,
249 : TNamed(name, leaflist)
251 , fCompress(compress)
252 , fBasketSize((basketsize < 100) ? 100 : basketsize)
256 , fExtraBasket(nullptr)
257 , fIOFeatures(parent->fIOFeatures)
265 , fFirstBasketEntry(-1)
266 , fNextBasketEntry(-1)
274 , fBaskets(fMaxBaskets)
278 , fTree(parent ? parent->GetTree() : 0)
279 , fMother(parent ? parent->GetMother() : 0)
281 , fAddress((char *)address)
282 , fDirectory(fTree ? fTree->GetDirectory() : 0)
285 , fTransientBuffer(0)
289 , fReadLeaves(&TBranch::ReadLeavesImpl)
290 , fFillLeaves(&TBranch::FillLeavesImpl)
292 Init(name,leaflist,compress);
295 void TBranch::Init(
const char* name,
const char* leaflist, Int_t compress)
299 SetBit(TBranch::kDoNotUseBufferMap);
300 if ((compress == -1) && fTree->GetDirectory()) {
301 TFile* bfile = fTree->GetDirectory()->GetFile();
303 fCompress = bfile->GetCompressionSettings();
307 fBasketBytes =
new Int_t[fMaxBaskets];
308 fBasketEntry =
new Long64_t[fMaxBaskets];
309 fBasketSeek =
new Long64_t[fMaxBaskets];
311 for (Int_t i = 0; i < fMaxBaskets; ++i) {
321 char* nameBegin =
const_cast<char*
>(leaflist);
323 auto len = strlen(leaflist);
325 char* leafname =
new char[len + 1];
326 char* leaftype =
new char[320];
328 strlcpy(leaftype,
"F",320);
329 char* pos =
const_cast<char*
>(leaflist);
330 const char* leaflistEnd = leaflist + len;
331 for (; pos <= leaflistEnd; ++pos) {
333 if ((*pos ==
':') || (*pos == 0)) {
335 Int_t lenName = pos - nameBegin;
338 strncpy(leafname, nameBegin, lenName);
339 leafname[lenName] = 0;
340 ctype = strstr(leafname,
"/");
343 strlcpy(leaftype, ctype + 1,320);
346 if (lenName == 0 || ctype == leafname) {
347 Warning(
"TBranch",
"No name was given to the leaf number '%d' in the leaflist of the branch '%s'.",fNleaves,name);
348 snprintf(leafname,640,
"__noname%d",fNleaves);
351 if (leaftype[1] ==
'[' && !strchr(leaftype,
',')) {
352 Warning(
"TBranch",
"Array size for branch '%s' must be specified after leaf name, not after the type name!", name);
354 }
else if (leaftype[1] && !strchr(leaftype,
',')) {
355 Warning(
"TBranch",
"Extra characters after type tag '%s' for branch '%s'; must be one character.", leaftype, name);
358 if (*leaftype ==
'C') {
359 leaf =
new TLeafC(
this, leafname, leaftype);
360 }
else if (*leaftype ==
'O') {
361 leaf =
new TLeafO(
this, leafname, leaftype);
362 }
else if (*leaftype ==
'B') {
363 leaf =
new TLeafB(
this, leafname, leaftype);
364 }
else if (*leaftype ==
'b') {
365 leaf =
new TLeafB(
this, leafname, leaftype);
367 }
else if (*leaftype ==
'S') {
368 leaf =
new TLeafS(
this, leafname, leaftype);
369 }
else if (*leaftype ==
's') {
370 leaf =
new TLeafS(
this, leafname, leaftype);
372 }
else if (*leaftype ==
'I') {
373 leaf =
new TLeafI(
this, leafname, leaftype);
374 }
else if (*leaftype ==
'i') {
375 leaf =
new TLeafI(
this, leafname, leaftype);
377 }
else if (*leaftype ==
'F') {
378 leaf =
new TLeafF(
this, leafname, leaftype);
379 }
else if (*leaftype ==
'f') {
380 leaf =
new TLeafF16(
this, leafname, leaftype);
381 }
else if (*leaftype ==
'L') {
382 leaf =
new TLeafL(
this, leafname, leaftype);
383 }
else if (*leaftype ==
'l') {
384 leaf =
new TLeafL(
this, leafname, leaftype);
386 }
else if (*leaftype ==
'D') {
387 leaf =
new TLeafD(
this, leafname, leaftype);
388 }
else if (*leaftype ==
'd') {
389 leaf =
new TLeafD32(
this, leafname, leaftype);
392 Error(
"TLeaf",
"Illegal data type for %s/%s", name, leaflist);
398 if (leaf->IsZombie()) {
401 auto msg =
"Illegal leaf: %s/%s. If this is a variable size C array it's possible that the branch holding the size is not available.";
402 Error(
"TBranch", msg, name, leaflist);
408 leaf->SetBranch(
this);
409 leaf->SetAddress((
char*) (fAddress + offset));
410 leaf->SetOffset(offset);
411 if (leaf->GetLeafCount()) {
413 fEntryOffsetLen = 1000;
415 if (leaf->InheritsFrom(TLeafC::Class())) {
417 fEntryOffsetLen = 1000;
421 fTree->GetListOfLeaves()->Add(leaf);
427 offset += leaf->GetLenType() * leaf->GetLen();
448 delete [] fBasketSeek;
451 delete [] fBasketEntry;
454 delete [] fBasketBytes;
460 fFirstBasketEntry = -1;
461 fNextBasketEntry = -1;
465 TObjArray* lst = fTree->GetListOfLeaves();
466 if (lst && lst->GetLast()!=-1) {
467 lst->RemoveAll(&fLeaves);
487 if (fDirectory && (!fTree || fDirectory != fTree->GetDirectory())) {
488 TString bFileName( GetRealFileName() );
490 R__LOCKGUARD(gROOTMutex);
491 TFile* file = (TFile*)gROOT->GetListOfFiles()->FindObject(bFileName);
502 if (fTransientBuffer) {
503 delete fTransientBuffer;
504 fTransientBuffer = 0;
511 TBuffer* TBranch::GetTransientBuffer(Int_t size)
513 if (fTransientBuffer) {
514 if (fTransientBuffer->BufferSize() < size) {
515 fTransientBuffer->Expand(size);
517 return fTransientBuffer;
519 fTransientBuffer =
new TBufferFile(TBuffer::kRead, size);
520 return fTransientBuffer;
533 void TBranch::AddBasket(TBasket& b, Bool_t ondisk, Long64_t startEntry)
535 TBasket *basket = &b;
537 basket->SetBranch(
this);
539 if (fWriteBasket >= fMaxBaskets) {
540 ExpandBasketArrays();
542 Int_t where = fWriteBasket;
544 if (where && startEntry < fBasketEntry[where-1]) {
548 Warning(
"AddBasket",
"The assumption that out-of-order basket only comes from disk based ntuple is false.");
551 if (startEntry < fBasketEntry[0]) {
554 for(Int_t i=fWriteBasket-1; i>=0; --i) {
555 if (fBasketEntry[i] < startEntry) {
558 }
else if (fBasketEntry[i] == startEntry) {
559 Error(
"AddBasket",
"An out-of-order basket matches the entry number of an existing basket.");
564 if (where < fWriteBasket) {
566 for (Int_t j=fWriteBasket; j > where; --j) {
567 fBasketEntry[j] = fBasketEntry[j-1];
568 fBasketBytes[j] = fBasketBytes[j-1];
569 fBasketSeek[j] = fBasketSeek[j-1];
573 fBasketEntry[where] = startEntry;
576 fBasketBytes[where] = basket->GetNbytes();
577 fBasketSeek[where] = basket->GetSeekKey();
578 fBaskets.AddAtAndExpand(0,fWriteBasket);
582 fBaskets.AddAtAndExpand(basket,fWriteBasket);
583 fTree->IncrementTotalBuffers(basket->GetBufferSize());
586 fEntries += basket->GetNevBuf();
587 fEntryNumber += basket->GetNevBuf();
589 fTotBytes += basket->GetObjlen() + basket->GetKeylen() ;
590 fZipBytes += basket->GetNbytes();
591 fTree->AddTotBytes(basket->GetObjlen() + basket->GetKeylen());
592 fTree->AddZipBytes(basket->GetNbytes());
599 void TBranch::AddLastBasket(Long64_t startEntry)
601 if (fWriteBasket >= fMaxBaskets) {
602 ExpandBasketArrays();
604 Int_t where = fWriteBasket;
606 if (where && startEntry < fBasketEntry[where-1]) {
609 Fatal(
"AddBasket",
"The last basket must have the highest entry number (%s/%lld/%d).",GetName(),startEntry,fWriteBasket);
612 fBasketEntry[where] = startEntry;
613 fBaskets.AddAtAndExpand(0,fWriteBasket);
657 Int_t TBranch::BackFill() {
660 auto cluster = GetTree()->GetClusterIterator( GetEntries() );
662 auto endCluster = cluster.GetNextEntry();
664 auto result = FillImpl(
nullptr);
666 if ( result && GetEntries() >= endCluster ) {
676 void TBranch::Browse(TBrowser* b)
683 TString name = GetName();
684 Int_t pos = name.First(
'[');
685 if (pos!=kNPOS) name.Remove(pos);
687 GetTree()->Draw(name,
"", b ? b->GetDrawOption() :
"");
688 if (gPad) gPad->Update();
703 void TBranch::DeleteBaskets(Option_t* option)
705 TString opt = option;
707 TFile *file = GetFile(0);
709 if(fDirectory && (fDirectory != gROOT) && fDirectory->IsWritable()) {
710 for(Int_t i=0; i<fWriteBasket; i++) {
711 if (fBasketSeek[i]) file->MakeFree(fBasketSeek[i],fBasketSeek[i]+fBasketBytes[i]-1);
716 if (opt.Contains(
"all")) {
717 TObjArray *lb = GetListOfBranches();
718 Int_t nb = lb->GetEntriesFast();
719 for (Int_t j = 0; j < nb; j++) {
720 TBranch* branch = (TBranch*) lb->UncheckedAt(j);
721 if (branch) branch->DeleteBaskets(
"all");
734 void TBranch::DropBaskets(Option_t* options)
737 if (options && options[0]) {
738 TString opt = options;
740 if (opt.Contains(
"all")) all = kTRUE;
744 Int_t nbaskets = fBaskets.GetEntriesFast();
746 if ( (fNBaskets>1) || all ) {
748 for (Int_t i=0;i<nbaskets;i++) {
749 basket = (TBasket*)fBaskets.UncheckedAt(i);
750 if (!basket)
continue;
751 if ((i == fReadBasket || i == fWriteBasket) && !all)
continue;
754 if (fBasketBytes[i]==0 && basket->GetNevBuf() > 0)
continue;
755 basket->DropBuffers();
757 fBaskets.RemoveAt(i);
758 if (basket == fCurrentBasket) {
760 fFirstBasketEntry = -1;
761 fNextBasketEntry = -1;
768 TObjArray *lb = GetListOfBranches();
769 Int_t nb = lb->GetEntriesFast();
770 for (Int_t j = 0; j < nb; j++) {
771 TBranch* branch = (TBranch*) lb->UncheckedAt(j);
772 if (!branch)
continue;
773 branch->DropBaskets(
"all");
779 Int_t i = fBaskets.GetLast();
780 basket = (TBasket*)fBaskets.UncheckedAt(i);
781 if (basket && fBasketBytes[i]!=0) {
782 basket->DropBuffers();
783 if (basket == fCurrentBasket) {
785 fFirstBasketEntry = -1;
786 fNextBasketEntry = -1;
790 fBaskets.SetLast(-1);
802 void TBranch::ExpandBasketArrays()
804 Int_t newsize = TMath::Max(10,Int_t(1.5*fMaxBaskets));
805 fBasketBytes = TStorage::ReAllocInt(fBasketBytes, newsize, fMaxBaskets);
806 fBasketEntry = (Long64_t*)TStorage::ReAlloc(fBasketEntry,
807 newsize*
sizeof(Long64_t),fMaxBaskets*
sizeof(Long64_t));
808 fBasketSeek = (Long64_t*)TStorage::ReAlloc(fBasketSeek,
809 newsize*
sizeof(Long64_t),fMaxBaskets*
sizeof(Long64_t));
811 fMaxBaskets = newsize;
813 fBaskets.Expand(newsize);
815 for (Int_t i=fWriteBasket;i<fMaxBaskets;i++) {
833 Int_t TBranch::FillImpl(ROOT::Internal::TBranchIMTHelper *imtHelper)
835 if (TestBit(kDoNotProcess)) {
839 TBasket* basket = (TBasket*)fBaskets.UncheckedAt(fWriteBasket);
841 basket = fTree->CreateBasket(
this);
842 if (!basket)
return 0;
844 fBaskets.AddAtAndExpand(basket,fWriteBasket);
846 TBuffer* buf = basket->GetBufferRef();
852 if (buf->IsReading()) {
853 basket->SetWriteMode();
856 if (!TestBit(kDoNotUseBufferMap)) {
864 nbytes = FillEntryBuffer(basket,buf,lnew);
866 Int_t lold = buf->Length();
867 basket->Update(lold);
870 (this->*fFillLeaves)(*buf);
871 if (buf->GetMapCount()) {
873 ResetBit(TBranch::kDoNotUseBufferMap);
875 lnew = buf->Length();
876 nbytes = lnew - lold;
879 if (fEntryOffsetLen) {
880 Int_t nevbuf = basket->GetNevBuf();
882 nsize = nevbuf *
sizeof(Int_t);
884 if (!basket->GetNevBufSize()) {
885 basket->SetNevBufSize(nbytes);
897 bool noFlushAtCluster = !fTree->TestBit(TTree::kOnlyFlushAtCluster) || (fTree->GetAutoFlush() < 0);
899 if (noFlushAtCluster && !fTree->TestBit(TTree::kCircular) &&
900 ((fSkipZip && (lnew >= TBuffer::kMinimalSize)) || (buf->TestBit(TBufferFile::kNotDecompressed)) ||
901 ((lnew + (2 * nsize) + nbytes) >= fBasketSize))) {
902 Int_t nout = WriteBasketImpl(basket, fWriteBasket, imtHelper);
903 if (nout < 0) Error(
"TBranch::Fill",
"Failed to write out basket.\n");
904 return (nout >= 0) ? nbytes : -1;
912 Int_t TBranch::FillEntryBuffer(TBasket* basket, TBuffer* buf, Int_t& lnew)
915 Int_t objectStart = 0;
917 Int_t lold = buf->Length();
920 if (fEntryBuffer->IsA() == TMessage::Class()) {
923 if (fEntryBuffer->TestBit(TBufferFile::kNotDecompressed)) {
925 if (basket->GetNevBuf()) {
929 WriteBasket(basket,fWriteBasket);
933 Int_t startpos = fEntryBuffer->Length();
934 fEntryBuffer->SetBufferOffset(0);
935 static TBasket toread_fLast;
936 fEntryBuffer->SetReadMode();
937 toread_fLast.Streamer(*fEntryBuffer);
938 fEntryBuffer->SetWriteMode();
939 last = toread_fLast.GetLast();
941 fEntryBuffer->SetBufferOffset(startpos);
942 buf->SetBufferOffset(0);
943 buf->SetBit(TBufferFile::kNotDecompressed);
944 basket->Update(lold);
949 const UInt_t kNewClassTag = 0xFFFFFFFF;
950 const UInt_t kByteCountMask = 0x40000000;
952 UInt_t startpos = fEntryBuffer->Length();
953 fEntryBuffer->SetBufferOffset(objectStart);
954 *fEntryBuffer >> tag;
955 if (tag & kByteCountMask) {
956 *fEntryBuffer >> tag;
958 if (tag == kNewClassTag) {
959 UInt_t maxsize = 256;
960 char* s =
new char[maxsize];
961 Int_t name_start = fEntryBuffer->Length();
962 fEntryBuffer->ReadString(s, maxsize);
963 while (strlen(s) == (maxsize - 1)) {
965 fEntryBuffer->SetBufferOffset(name_start);
968 s =
new char[maxsize];
969 fEntryBuffer->ReadString(s, maxsize);
972 fEntryBuffer->SetBufferOffset(objectStart);
974 objectStart = fEntryBuffer->Length();
975 fEntryBuffer->SetBufferOffset(startpos);
976 basket->Update(lold, objectStart - fEntryBuffer->GetBufferDisplacement());
981 UInt_t startpos = fEntryBuffer->Length();
982 if (startpos > UInt_t(objectStart)) {
985 len = fEntryBuffer->Length() - objectStart;
991 len = fEntryBuffer->BufferSize() - objectStart;
993 buf->WriteBuf(fEntryBuffer->Buffer() + objectStart, len);
994 if (fEntryBuffer->TestBit(TBufferFile::kNotDecompressed)) {
1001 lnew = buf->Length();
1002 nbytes = lnew - lold;
1011 TBranch* TBranch::FindBranch(
const char* name)
1015 longnm.reserve(fName.Length()+strlen(name)+3);
1016 longnm = fName.Data();
1017 if (longnm[longnm.length()-1]==
']') {
1018 std::size_t dim = longnm.find_first_of(
"[");
1019 if (dim != std::string::npos) {
1023 if (longnm[longnm.length()-1] !=
'.') {
1027 UInt_t namelen = strlen(name);
1029 Int_t nbranches = fBranches.GetEntries();
1030 TBranch* branch = 0;
1031 for(Int_t i = 0; i < nbranches; ++i) {
1032 branch = (TBranch*) fBranches.UncheckedAt(i);
1034 const char *brname = branch->fName.Data();
1035 UInt_t brlen = branch->fName.Length();
1036 if (brname[brlen-1]==
']') {
1037 const char *dim = strchr(brname,
'[');
1039 brlen = dim - brname;
1042 if (namelen == brlen
1043 && strncmp(name,brname,brlen) == 0) {
1046 if (brlen == (
size_t)longnm.length()
1047 && strncmp(longnm.c_str(),brname,brlen) == 0) {
1057 TLeaf* TBranch::FindLeaf(
const char* searchname)
1065 TIter next(GetListOfLeaves());
1067 while ((leaf = (TLeaf*) next())) {
1068 leafname = leaf->GetName();
1069 Ssiz_t dim = leafname.First(
'[');
1070 if (dim >= 0) leafname.Remove(dim);
1072 if (leafname == searchname)
return leaf;
1075 leaftitle = leaf->GetTitle();
1076 dim = leaftitle.First(
'[');
1077 if (dim >= 0) leaftitle.Remove(dim);
1079 if (leaftitle == searchname)
return leaf;
1081 TBranch* branch = leaf->GetBranch();
1083 longname.Form(
"%s.%s",branch->GetName(),leafname.Data());
1084 dim = longname.First(
'[');
1085 if (dim>=0) longname.Remove(dim);
1086 if (longname == searchname)
return leaf;
1089 longname.Form(
"%s.%s",branch->GetName(),searchname);
1090 if (longname==leafname)
return leaf;
1092 longtitle.Form(
"%s.%s",branch->GetName(),leaftitle.Data());
1093 dim = longtitle.First(
'[');
1094 if (dim>=0) longtitle.Remove(dim);
1095 if (longtitle == searchname)
return leaf;
1102 if (strstr(searchname,
".") && !strcmp(searchname, branch->GetName()))
return leaf;
1112 Int_t TBranch::FlushBaskets()
1117 Int_t maxbasket = fWriteBasket + 1;
1123 for(Int_t i=0; i != maxbasket; ++i) {
1124 if (fBaskets.UncheckedAt(i)) {
1125 Int_t nwrite = FlushOneBasket(i);
1133 Int_t len = fBranches.GetEntriesFast();
1134 for (Int_t i = 0; i < len; ++i) {
1135 TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
1139 Int_t nwrite = branch->FlushBaskets();
1158 Int_t TBranch::FlushOneBasket(UInt_t ibasket)
1161 if (fDirectory && fBaskets.GetEntries()) {
1162 TBasket *basket = (TBasket*)fBaskets.UncheckedAt(ibasket);
1165 if (basket->GetNevBuf()
1166 && fBasketSeek[ibasket]==0) {
1170 if (basket->GetBufferRef()->IsReading()) {
1171 basket->SetWriteMode();
1173 nbytes = WriteBasket(basket,ibasket);
1177 if ((Int_t)ibasket==fWriteBasket) {
1180 basket->DropBuffers();
1181 if (basket == fCurrentBasket) {
1183 fFirstBasketEntry = -1;
1184 fNextBasketEntry = -1;
1188 fBaskets[ibasket] = 0;
1202 TBasket* TBranch::GetBasketImpl(Int_t basketnumber, TBuffer *user_buffer)
1208 static std::atomic<Int_t> nerrors(0);
1211 if (basketnumber <0 || basketnumber > fWriteBasket)
return 0;
1212 TBasket *basket = (TBasket*)fBaskets.UncheckedAt(basketnumber);
1213 if (basket)
return basket;
1214 if (basketnumber == fWriteBasket)
return 0;
1217 TFile *file = GetFile(0);
1223 if (fTree->GetMaxVirtualSize() < 0 || fTree->GetClusterPrefetch())
1224 basket = GetFreshCluster();
1226 basket = GetFreshBasket(user_buffer);
1229 if (fSkipZip) basket->SetBit(TBufferFile::kNotDecompressed);
1230 if (fBasketBytes[basketnumber] == 0) {
1231 fBasketBytes[basketnumber] = basket->ReadBasketBytes(fBasketSeek[basketnumber],file);
1235 R__LOCKGUARD_IMT(gROOTMutex);
1236 TFileCacheRead *pf = fTree->GetReadCache(file);
1238 if (pf->IsLearning()) pf->LearnBranch(
this, kFALSE);
1239 if (fSkipZip) pf->SetSkipZip();
1244 Int_t badread = basket->ReadBasketBuffers(fBasketSeek[basketnumber],fBasketBytes[basketnumber],file);
1245 if (R__unlikely(badread || basket->GetSeekKey() != fBasketSeek[basketnumber] || basket->IsZombie())) {
1247 if (nerrors > 10)
return 0;
1248 if (nerrors == 10) {
1249 printf(
" file probably overwritten: stopping reporting error messages\n");
1250 if (fBasketSeek[basketnumber] > 2000000000) {
1251 printf(
"===>File is more than 2 Gigabytes\n");
1254 if (fBasketSeek[basketnumber] > 1000000000) {
1255 printf(
"===>Your file is may be bigger than the maximum file size allowed on your system\n");
1256 printf(
" Check your AFS maximum file size limit for example\n");
1260 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.load(),basketnumber);
1266 fCacheInfo.SetUsed(basketnumber);
1267 auto perfStats = GetTree()->GetPerfStats();
1269 perfStats->SetUsed(
this, basketnumber);
1271 fBaskets.AddAt(basket,basketnumber);
1278 Long64_t TBranch::GetBasketSeek(Int_t basketnumber)
const
1280 if (basketnumber <0 || basketnumber > fWriteBasket)
return 0;
1281 return fBasketSeek[basketnumber];
1288 TList* TBranch::GetBrowsables() {
1289 if (fBrowsables)
return fBrowsables;
1290 fBrowsables=
new TList();
1291 TVirtualBranchBrowsable::FillListOfBrowsables(*fBrowsables,
this);
1300 const char * TBranch::GetClassName()
const
1308 const char* TBranch::GetIconName()
const
1311 return "TBranchElement-folder";
1313 return "TBranchElement-leaf";
1325 Int_t TBranch::GetBasketAndFirst(TBasket *&basket, Long64_t &first,
1326 TBuffer *user_buffer)
1328 Long64_t updatedNext = fNextBasketEntry;
1329 Long64_t entry = fReadEntry;
1330 if (R__likely(fCurrentBasket && fFirstBasketEntry <= entry && entry < fNextBasketEntry)) {
1333 basket = fCurrentBasket;
1334 first = fFirstBasketEntry;
1336 if ((entry < fFirstEntry) || (entry >= fEntryNumber)) {
1339 first = fFirstBasketEntry;
1340 Long64_t last = fNextBasketEntry - 1;
1342 if ((entry < first) || (entry > last)) {
1343 fReadBasket = TMath::BinarySearch(fWriteBasket + 1, fBasketEntry, entry);
1344 if (fReadBasket < 0) {
1345 fNextBasketEntry = -1;
1346 Error(
"GetBasketAndFirst",
"In the branch %s, no basket contains the entry %lld\n", GetName(), entry);
1349 if (fReadBasket == fWriteBasket) {
1350 fNextBasketEntry = fEntryNumber;
1352 fNextBasketEntry = fBasketEntry[fReadBasket+1];
1354 updatedNext = fNextBasketEntry;
1355 first = fFirstBasketEntry = fBasketEntry[fReadBasket];
1359 basket = (TBasket*) fBaskets.UncheckedAt(fReadBasket);
1361 basket = GetBasketImpl(fReadBasket, user_buffer);
1364 fFirstBasketEntry = -1;
1365 fNextBasketEntry = -1;
1368 if (fTree->GetClusterPrefetch()) {
1369 TTree::TClusterIterator clusterIterator = fTree->GetClusterIterator(entry);
1370 clusterIterator.Next();
1371 Int_t nextClusterEntry = clusterIterator.GetNextEntry();
1372 for (Int_t i = fReadBasket + 1; i < fMaxBaskets && fBasketEntry[i] < nextClusterEntry; i++) {
1378 fFirstBasketEntry = first;
1379 fNextBasketEntry = updatedNext;
1385 fCurrentBasket =
nullptr;
1386 fBaskets[fReadBasket] =
nullptr;
1388 fCurrentBasket = basket;
1400 Bool_t TBranch::SupportsBulkRead()
const {
1401 return (fNleaves == 1) &&
1402 (
static_cast<TLeaf*
>(fLeaves.UncheckedAt(0))->GetDeserializeType() != TLeaf::DeserializeType::kDestructive);
1425 Int_t TBranch::GetBulkEntries(Long64_t entry, TBuffer &user_buf)
1428 if (R__unlikely(fNleaves != 1))
return -1;
1429 TLeaf *leaf =
static_cast<TLeaf*
>(fLeaves.UncheckedAt(0));
1430 if (R__unlikely(leaf->GetDeserializeType() == TLeaf::DeserializeType::kDestructive)) {
return -1;}
1435 Bool_t enabled = !TestBit(kDoNotProcess);
1436 if (R__unlikely(!enabled))
return -1;
1437 TBasket *basket =
nullptr;
1439 Int_t result = GetBasketAndFirst(basket, first, &user_buf);
1440 if (R__unlikely(result <= 0))
return -1;
1442 if (R__unlikely(entry != first)) {
1447 basket->PrepareBasket(entry);
1448 TBuffer* buf = basket->GetBufferRef();
1451 if (R__unlikely(!buf)) {
1452 Error(
"GetBulkEntries",
"Failed to get a new buffer.\n");
1456 if (R__unlikely(basket->GetDisplacement())) {
1457 Error(
"GetBulkEntries",
"Basket has displacement.\n");
1461 Int_t bufbegin = basket->GetKeylen();
1462 buf->SetBufferOffset(bufbegin);
1464 Int_t N = ((fNextBasketEntry < 0) ? fEntryNumber : fNextBasketEntry) - first;
1466 if (R__unlikely(!leaf->ReadBasketFast(*buf, N))) {
1467 Error(
"GetBulkEntries",
"Leaf failed to read.\n");
1470 user_buf.SetBufferOffset(bufbegin);
1472 fCurrentBasket =
nullptr;
1473 fBaskets[fReadBasket] =
nullptr;
1474 R__ASSERT(fExtraBasket ==
nullptr &&
"fExtraBasket should have been set to nullptr by GetFreshBasket");
1475 fExtraBasket = basket;
1476 basket->DisownBuffer();
1483 Int_t TBranch::GetEntriesSerialized(Long64_t entry, TBuffer &user_buf, TBuffer *count_buf)
1486 if (R__unlikely(fNleaves != 1)) {
return -1; }
1487 TLeaf *leaf =
static_cast<TLeaf*
>(fLeaves.UncheckedAt(0));
1488 if (R__unlikely(leaf->GetDeserializeType() == TLeaf::DeserializeType::kDestructive)) {
1489 Error(
"GetEntriesSerialized",
"Encountered a branch with destructive deserialization; failing.\n");
1496 Bool_t enabled = !TestBit(kDoNotProcess);
1497 if (R__unlikely(!enabled)) {
return -1; }
1498 TBasket *basket =
nullptr;
1500 Int_t result = GetBasketAndFirst(basket, first, &user_buf);
1501 if (R__unlikely(result <= 0)) {
return -1; }
1503 if (R__unlikely(entry != first)) {
1504 Error(
"GetEntriesSerialized",
"Failed to read from full cluster; first entry is %lld; requested entry is %lld.\n", first, entry);
1508 basket->PrepareBasket(entry);
1509 TBuffer* buf = basket->GetBufferRef();
1512 if (R__unlikely(!buf)) {
1513 Error(
"GetEntriesSerialized",
"Failed to get a new buffer.\n");
1517 if (R__unlikely(basket->GetDisplacement())) {
1518 Error(
"GetEntriesSerialized",
"Basket has displacement.\n");
1522 Int_t bufbegin = basket->GetKeylen();
1523 buf->SetBufferOffset(bufbegin);
1525 Int_t N = ((fNextBasketEntry < 0) ? fEntryNumber : fNextBasketEntry) - first;
1528 if (R__unlikely(!leaf->ReadBasketSerialized(*buf, N))) {
1529 Error(
"GetEntriesSerialized",
"Leaf failed to read.\n");
1532 user_buf.SetBufferOffset(bufbegin);
1535 TLeaf *count_leaf = leaf->GetLeafCount();
1538 TBranch *count_branch = count_leaf->GetBranch();
1539 if (R__unlikely(count_branch->GetEntriesSerialized(entry, *count_buf) < 0)) {
1540 Error(
"GetEntriesSerialized",
"Failed to read count leaf.\n");
1546 Int_t entry_count_serialized;
1547 char *tmp_ptr =
reinterpret_cast<char*
>(&entry_count_serialized);
1548 tobuf(tmp_ptr, leaf->GetLenType() * leaf->GetNdata());
1549 Int_t cur_offset = count_buf->GetCurrent() - count_buf->Buffer();
1550 for (
int idx=0; idx<N; idx++) {
1551 *count_buf << entry_count_serialized;
1553 count_buf->SetBufferOffset(cur_offset);
1579 Int_t TBranch::GetEntry(Long64_t entry, Int_t getall)
1584 if (R__unlikely(TestBit(kDoNotProcess) && !getall)) {
return 0; }
1589 Int_t result = GetBasketAndFirst(basket, first,
nullptr);
1590 if (R__unlikely(result <= 0)) {
return result; }
1592 basket->PrepareBasket(entry);
1593 TBuffer* buf = basket->GetBufferRef();
1596 if (R__unlikely(!buf)) {
1597 TFile* file = GetFile(0);
1598 if (!file)
return -1;
1599 basket->ReadBasketBuffers(fBasketSeek[fReadBasket], fBasketBytes[fReadBasket], file);
1600 buf = basket->GetBufferRef();
1604 if (!TestBit(kDoNotUseBufferMap)) {
1607 if (R__unlikely(!buf->IsReading())) {
1608 basket->SetReadMode();
1611 Int_t* entryOffset = basket->GetEntryOffset();
1614 bufbegin = entryOffset[entry-first];
1615 buf->SetBufferOffset(bufbegin);
1616 Int_t* displacement = basket->GetDisplacement();
1617 if (R__unlikely(displacement)) {
1618 buf->SetBufferDisplacement(displacement[entry-first]);
1621 bufbegin = basket->GetKeylen() + ((entry-first) * basket->GetNevBufSize());
1622 buf->SetBufferOffset(bufbegin);
1626 (this->*fReadLeaves)(*buf);
1627 return buf->Length() - bufbegin;
1635 Int_t TBranch::GetEntryExport(Long64_t entry, Int_t , TClonesArray* li, Int_t nentries)
1640 if (TestBit(kDoNotProcess)) {
1643 if ((entry < 0) || (entry >= fEntryNumber)) {
1647 Long64_t first = fFirstBasketEntry;
1648 Long64_t last = fNextBasketEntry - 1;
1650 if ((entry < first) || (entry > last)) {
1651 fReadBasket = TMath::BinarySearch(fWriteBasket + 1, fBasketEntry, entry);
1652 if (fReadBasket < 0) {
1653 fNextBasketEntry = -1;
1654 Error(
"In the branch %s, no basket contains the entry %d\n", GetName(), entry);
1657 if (fReadBasket == fWriteBasket) {
1658 fNextBasketEntry = fEntryNumber;
1660 fNextBasketEntry = fBasketEntry[fReadBasket+1];
1662 fFirstBasketEntry = first = fBasketEntry[fReadBasket];
1667 TBasket* basket = GetBasketImpl(fReadBasket,
nullptr);
1668 fCurrentBasket = basket;
1670 fFirstBasketEntry = -1;
1671 fNextBasketEntry = -1;
1674 TBuffer* buf = basket->GetBufferRef();
1676 if (!TestBit(kDoNotUseBufferMap)) {
1679 if (R__unlikely(!buf->IsReading())) {
1680 basket->SetReadMode();
1682 Int_t* entryOffset = basket->GetEntryOffset();
1685 bufbegin = entryOffset[entry-first];
1686 buf->SetBufferOffset(bufbegin);
1687 Int_t* displacement = basket->GetDisplacement();
1688 if (R__unlikely(displacement)) {
1689 buf->SetBufferDisplacement(displacement[entry-first]);
1692 bufbegin = basket->GetKeylen() + ((entry-first) * basket->GetNevBufSize());
1693 buf->SetBufferOffset(bufbegin);
1695 TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(0);
1696 leaf->ReadBasketExport(*buf, li, nentries);
1697 nbytes = buf->Length() - bufbegin;
1707 Int_t TBranch::GetExpectedType(TClass *&expectedClass,EDataType &expectedType)
1710 expectedType = kOther_t;
1711 TLeaf* l = (TLeaf*) GetListOfLeaves()->At(0);
1713 expectedType = (EDataType) gROOT->GetType(l->GetTypeName())->GetType();
1716 Error(
"GetExpectedType",
"Did not find any leaves in %s",GetName());
1726 TFile* TBranch::GetFile(Int_t mode)
1728 if (fDirectory)
return fDirectory->GetFile();
1733 R__LOCKGUARD(gROOTMutex);
1734 file = (TFile*)gROOT->GetListOfFiles()->FindObject(fFileName.Data());
1741 if (fFileName.Length() == 0)
return 0;
1743 TString bFileName( GetRealFileName() );
1747 TDirectory::TContext ctxt;
1748 if (mode) file = TFile::Open(bFileName,
"recreate");
1749 else file = TFile::Open(bFileName);
1751 if (!file)
return 0;
1752 if (file->IsZombie()) {
delete file;
return 0;}
1753 fDirectory = (TDirectory*)file;
1764 TBasket* TBranch::GetFreshBasket(TBuffer* user_buffer)
1766 TBasket *basket = 0;
1767 if (user_buffer && fExtraBasket) {
1768 basket = fExtraBasket;
1769 fExtraBasket =
nullptr;
1770 basket->AdoptBuffer(user_buffer);
1772 if (GetTree()->MemoryFull(0)) {
1775 Int_t oldindex = fBaskets.GetLast();
1776 basket = (TBasket*)fBaskets.UncheckedAt(oldindex);
1778 fBaskets.SetLast(-2);
1779 oldindex = fBaskets.GetLast();
1780 if (oldindex != fBaskets.LowerBound()-1) {
1781 basket = (TBasket*)fBaskets.UncheckedAt(oldindex);
1784 if (basket && fBasketBytes[oldindex]!=0) {
1785 if (basket == fCurrentBasket) {
1787 fFirstBasketEntry = -1;
1788 fNextBasketEntry = -1;
1790 fBaskets.AddAt(0,oldindex);
1791 fBaskets.SetLast(-1);
1794 basket = fTree->CreateBasket(
this);
1796 }
else if (fNBaskets == 0) {
1798 basket = fTree->CreateBasket(
this);
1803 basket = fTree->CreateBasket(
this);
1806 basket = fTree->CreateBasket(
this);
1809 basket->AdoptBuffer(user_buffer);
1818 TBasket *TBranch::GetFreshCluster()
1820 TBasket *basket = 0;
1825 TTree::TClusterIterator iter = fTree->GetClusterIterator(fBasketEntry[fReadBasket]);
1826 if (iter.GetStartEntry() == 0) {
1827 return fTree->CreateBasket(
this);
1832 for (Int_t j = 0; j < -fTree->GetMaxVirtualSize(); j++) {
1833 if (iter.Previous() == 0) {
1834 return fTree->CreateBasket(
this);
1838 Int_t entryToUnload = iter.Previous();
1842 Int_t basketToUnload = fReadBasket;
1843 while (fBasketEntry[basketToUnload] != entryToUnload) {
1845 if (basketToUnload < 0) {
1846 return fTree->CreateBasket(
this);
1852 basket = (TBasket *)fBaskets.UncheckedAt(basketToUnload);
1854 fBaskets.AddAt(0, basketToUnload);
1857 basket = fTree->CreateBasket(
this);
1866 while (fBasketEntry[basketToUnload] < iter.GetStartEntry()) {
1867 TBasket *oldbasket = (TBasket *)fBaskets.UncheckedAt(basketToUnload);
1869 oldbasket->DropBuffers();
1871 fBaskets.AddAt(0, basketToUnload);
1876 fBaskets.SetLast(-1);
1883 TLeaf* TBranch::GetLeaf(
const char* name)
const
1886 for (i=0;i<fNleaves;i++) {
1887 TLeaf *leaf = (TLeaf*)fLeaves.UncheckedAt(i);
1888 if (!strcmp(leaf->GetName(),name))
return leaf;
1896 TString TBranch::GetRealFileName()
const
1898 if (fFileName.Length()==0) {
1901 TString bFileName = fFileName;
1904 char *bname = gSystem->ExpandPathName(fFileName.Data());
1905 if (!gSystem->IsAbsoluteFileName(bname) && !strstr(bname,
":/") && fTree && fTree->GetCurrentFile()) {
1908 const char *tfn = fTree->GetCurrentFile()->GetName();
1912 if (strlen(arc.GetAnchor()) > 0) {
1913 arc.SetAnchor(gSystem->BaseName(fFileName));
1914 bFileName = arc.GetUrl();
1918 char *tname = gSystem->ExpandPathName(tfn);
1919 if (gSystem->IsAbsoluteFileName(tname) || strstr(tname,
":/")) {
1920 bFileName = gSystem->DirName(tname);
1922 bFileName += fFileName;
1936 Int_t TBranch::GetRow(Int_t)
1945 Bool_t TBranch::GetMakeClass()
const
1955 TBranch* TBranch::GetMother()
const
1957 if (fMother)
return fMother;
1959 const TObjArray* array = fTree->GetListOfBranches();
1960 Int_t n = array->GetEntriesFast();
1961 for (Int_t i = 0; i < n; ++i) {
1962 TBranch* branch = (TBranch*) array->UncheckedAt(i);
1963 TBranch* parent = branch->GetSubBranch(
this);
1965 const_cast<TBranch*
>(
this)->fMother = branch;
1976 TBranch* TBranch::GetSubBranch(
const TBranch* child)
const
1979 if (
this == child) {
1981 return (TBranch*)
this;
1984 if (child->fParent) {
1985 return child->fParent;
1988 Int_t len = fBranches.GetEntriesFast();
1989 for (Int_t i = 0; i < len; ++i) {
1990 TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
1994 if (branch == child) {
1996 const_cast<TBranch*
>(child)->fParent = (TBranch*)
this;
1998 const_cast<TBranch*
>(child)->fParent = (TBranch*)
this;
1999 return (TBranch*)
this;
2002 TBranch* parent = branch->GetSubBranch(child);
2014 Long64_t TBranch::GetTotalSize(Option_t * )
const
2016 TBufferFile b(TBuffer::kWrite, 10000);
2022 const_cast<TBranch *
>(
this)->TBranch::Streamer(b);
2024 Long64_t totbytes = 0;
2025 if (fZipBytes > 0) totbytes = fTotBytes;
2026 return totbytes + b.Length();
2033 Long64_t TBranch::GetTotBytes(Option_t *option)
const
2035 Long64_t totbytes = fTotBytes;
2036 if (!option)
return totbytes;
2037 if (option[0] !=
'*')
return totbytes;
2039 Int_t len = fBranches.GetEntriesFast();
2040 for (Int_t i = 0; i < len; ++i) {
2041 TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
2042 if (branch) totbytes += branch->GetTotBytes(option);
2051 Long64_t TBranch::GetZipBytes(Option_t *option)
const
2053 Long64_t zipbytes = fZipBytes;
2054 if (!option)
return zipbytes;
2055 if (option[0] !=
'*')
return zipbytes;
2057 Int_t len = fBranches.GetEntriesFast();
2058 for (Int_t i = 0; i < len; ++i) {
2059 TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
2060 if (branch) zipbytes += branch->GetZipBytes(option);
2068 ROOT::TIOFeatures TBranch::GetIOFeatures()
const
2076 Bool_t TBranch::IsAutoDelete()
const
2078 return TestBit(kAutoDelete);
2084 Bool_t TBranch::IsFolder()
const
2089 TList* browsables =
const_cast<TBranch*
>(
this)->GetBrowsables();
2090 return browsables && browsables->GetSize();
2096 void TBranch::KeepCircular(Long64_t maxEntries)
2098 Int_t dentries = (Int_t) (fEntries - maxEntries);
2099 TBasket* basket = (TBasket*) fBaskets.UncheckedAt(0);
2100 if (basket) basket->MoveEntries(dentries);
2101 fEntries = maxEntries;
2102 fEntryNumber = maxEntries;
2104 Int_t nb = fBranches.GetEntriesFast();
2105 for (Int_t i = 0; i < nb; ++i) {
2106 TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
2107 branch->KeepCircular(maxEntries);
2122 Int_t TBranch::LoadBaskets()
2124 Int_t nimported = 0;
2125 Int_t nbaskets = fWriteBasket;
2126 TFile *file = GetFile(0);
2127 if (!file)
return 0;
2129 for (Int_t i=0;i<nbaskets;i++) {
2130 basket = (TBasket*)fBaskets.UncheckedAt(i);
2131 if (basket)
continue;
2132 basket = GetFreshBasket(
nullptr);
2133 if (fBasketBytes[i] == 0) {
2134 fBasketBytes[i] = basket->ReadBasketBytes(fBasketSeek[i],file);
2136 Int_t badread = basket->ReadBasketBuffers(fBasketSeek[i],fBasketBytes[i],file);
2138 Error(
"Loadbaskets",
"Error while reading basket buffer %d of branch %s",i,GetName());
2142 fBaskets.AddAt(basket,i);
2154 void TBranch::Print(Option_t *option)
const
2156 const int kLINEND = 77;
2159 TString titleContent(GetTitle());
2160 if ( titleContent == GetName() ) {
2161 titleContent.Clear();
2164 if (fLeaves.GetEntries() == 1) {
2165 if (titleContent.Length()>=2 && titleContent[titleContent.Length()-2]==
'/' && isalpha(titleContent[titleContent.Length()-1])) {
2168 TLeaf *leaf = (TLeaf*)fLeaves.UncheckedAt(0);
2169 if (titleContent.Length()) {
2170 titleContent.Prepend(
" ");
2173 titleContent.Prepend(leaf->GetTypeName());
2176 Int_t titleLength = titleContent.Length();
2178 Int_t aLength = titleLength + strlen(GetName());
2179 aLength += (aLength / 54 + 1) * 80 + 100;
2180 if (aLength < 200) aLength = 200;
2181 char *bline =
new char[aLength];
2183 Long64_t totBytes = GetTotalSize();
2184 if (fZipBytes) cx = (fTotBytes+0.00001)/fZipBytes;
2185 if (titleLength) snprintf(bline,aLength,
"*Br%5d :%-9s : %-54s *",fgCount,GetName(),titleContent.Data());
2186 else snprintf(bline,aLength,
"*Br%5d :%-9s : %-54s *",fgCount,GetName(),
" ");
2187 if (strlen(bline) > UInt_t(kLINEND)) {
2188 char *tmp =
new char[strlen(bline)+1];
2189 if (titleLength) strlcpy(tmp, titleContent.Data(),strlen(bline)+1);
2190 snprintf(bline,aLength,
"*Br%5d :%-9s : ",fgCount,GetName());
2191 int pos = strlen (bline);
2194 while (beg < titleLength) {
2195 for (end=beg+1; end < titleLength-1; end ++)
2196 if (tmp[end] ==
':')
break;
2197 if (npos + end-beg+1 >= 78) {
2198 while (npos < kLINEND) {
2199 bline[pos ++] =
' ';
2202 bline[pos ++] =
'*';
2203 bline[pos ++] =
'\n';
2204 bline[pos ++] =
'*';
2206 for (; npos < 12; npos ++)
2207 bline[pos ++] =
' ';
2210 for (
int n = beg; n <= end; n ++)
2211 bline[pos+n-beg] = tmp[n];
2216 while (npos < kLINEND) {
2217 bline[pos ++] =
' ';
2220 bline[pos ++] =
'*';
2224 Printf(
"%s", bline);
2226 if (fTotBytes > 2000000000) {
2227 Printf(
"*Entries :%lld : Total Size=%11lld bytes File Size = %lld *",fEntries,totBytes,fZipBytes);
2229 if (fZipBytes > 0) {
2230 Printf(
"*Entries :%9lld : Total Size=%11lld bytes File Size = %10lld *",fEntries,totBytes,fZipBytes);
2232 if (fWriteBasket > 0) {
2233 Printf(
"*Entries :%9lld : Total Size=%11lld bytes All baskets in memory *",fEntries,totBytes);
2235 Printf(
"*Entries :%9lld : Total Size=%11lld bytes One basket in memory *",fEntries,totBytes);
2239 Printf(
"*Baskets :%9d : Basket Size=%11d bytes Compression= %6.2f *",fWriteBasket,fBasketSize,cx);
2241 if (strncmp(option,
"basketsInfo",strlen(
"basketsInfo"))==0) {
2242 Int_t nbaskets = fWriteBasket;
2243 for (Int_t i=0;i<nbaskets;i++) {
2244 Printf(
"*Basket #%4d entry=%6lld pos=%6lld size=%5d",
2245 i, fBasketEntry[i], fBasketSeek[i], fBasketBytes[i]);
2249 Printf(
"*............................................................................*");
2258 void TBranch::PrintCacheInfo()
const
2260 fCacheInfo.Print(GetName(), fBasketEntry);
2266 void TBranch::ReadBasket(TBuffer&)
2274 void TBranch::ReadLeavesImpl(TBuffer& b)
2276 for (Int_t i = 0; i < fNleaves; ++i) {
2277 TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
2278 leaf->ReadBasket(b);
2285 void TBranch::ReadLeaves0Impl(TBuffer&)
2292 void TBranch::ReadLeaves1Impl(TBuffer& b)
2294 ((TLeaf*) fLeaves.UncheckedAt(0))->ReadBasket(b);
2300 void TBranch::ReadLeaves2Impl(TBuffer& b)
2302 ((TLeaf*) fLeaves.UncheckedAt(0))->ReadBasket(b);
2303 ((TLeaf*) fLeaves.UncheckedAt(1))->ReadBasket(b);
2309 void TBranch::FillLeavesImpl(TBuffer& b)
2311 for (Int_t i = 0; i < fNleaves; ++i) {
2312 TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
2313 leaf->FillBasket(b);
2321 void TBranch::Refresh(TBranch* b)
2325 fEntryOffsetLen = b->fEntryOffsetLen;
2326 fWriteBasket = b->fWriteBasket;
2327 fEntryNumber = b->fEntryNumber;
2328 fMaxBaskets = b->fMaxBaskets;
2329 fEntries = b->fEntries;
2330 fTotBytes = b->fTotBytes;
2331 fZipBytes = b->fZipBytes;
2334 fFirstBasketEntry = -1;
2335 fNextBasketEntry = -1;
2337 delete [] fBasketBytes;
2338 delete [] fBasketEntry;
2339 delete [] fBasketSeek;
2340 fBasketBytes =
new Int_t[fMaxBaskets];
2341 fBasketEntry =
new Long64_t[fMaxBaskets];
2342 fBasketSeek =
new Long64_t[fMaxBaskets];
2344 for (i=0;i<fMaxBaskets;i++) {
2345 fBasketBytes[i] = b->fBasketBytes[i];
2346 fBasketEntry[i] = b->fBasketEntry[i];
2347 fBasketSeek[i] = b->fBasketSeek[i];
2350 Int_t nbaskets = b->fBaskets.GetSize();
2351 fBaskets.Expand(nbaskets);
2354 TBasket *basket = (TBasket*)b->fBaskets.UncheckedAt(fWriteBasket);
2355 fBaskets.AddAt(basket,fWriteBasket);
2359 b->fBaskets.RemoveAt(fWriteBasket);
2360 basket->SetBranch(
this);
2370 void TBranch::Reset(Option_t*)
2374 fFirstBasketEntry = -1;
2375 fNextBasketEntry = -1;
2384 for (Int_t i = 0; i < fMaxBaskets; ++i) {
2385 fBasketBytes[i] = 0;
2390 for (Int_t i = 0; i < fMaxBaskets; ++i) {
2391 fBasketEntry[i] = 0;
2396 for (Int_t i = 0; i < fMaxBaskets; ++i) {
2411 void TBranch::ResetAfterMerge(TFileMergeInfo *)
2415 fFirstBasketEntry = -1;
2416 fNextBasketEntry = -1;
2425 for (Int_t i = 0; i < fMaxBaskets; ++i) {
2426 fBasketBytes[i] = 0;
2431 for (Int_t i = 0; i < fMaxBaskets; ++i) {
2432 fBasketEntry[i] = 0;
2437 for (Int_t i = 0; i < fMaxBaskets; ++i) {
2442 TBasket *reusebasket = (TBasket*)fBaskets[fWriteBasket];
2444 fBaskets[fWriteBasket] = 0;
2446 reusebasket = (TBasket*)fBaskets[fReadBasket];
2448 fBaskets[fReadBasket] = 0;
2454 reusebasket->Reset();
2455 fBaskets[0] = reusebasket;
2464 void TBranch::ResetAddress()
2471 for (Int_t i = 0; i < fNleaves; ++i) {
2472 TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
2473 leaf->SetAddress(0);
2476 Int_t nbranches = fBranches.GetEntriesFast();
2477 for (Int_t i = 0; i < nbranches; ++i) {
2478 TBranch* abranch = (TBranch*) fBranches[i];
2480 abranch->ResetAddress();
2487 void TBranch::ResetCount()
2495 void TBranch::SetAddress(
void* addr)
2497 if (TestBit(kDoNotProcess)) {
2501 fFirstBasketEntry = -1;
2502 fNextBasketEntry = -1;
2503 fAddress = (
char*) addr;
2504 for (Int_t i = 0; i < fNleaves; ++i) {
2505 TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
2506 Int_t offset = leaf->GetOffset();
2507 if (TestBit(kIsClone)) {
2510 if (fAddress) leaf->SetAddress(fAddress + offset);
2511 else leaf->SetAddress(0);
2529 void TBranch::SetAutoDelete(Bool_t autodel)
2532 SetBit(kAutoDelete, 1);
2534 SetBit(kAutoDelete, 0);
2542 void TBranch::SetBasketSize(Int_t buffsize)
2544 Int_t minsize = 100 + fName.Length();
2545 if (buffsize < minsize+fEntryOffsetLen) buffsize = minsize+fEntryOffsetLen;
2546 fBasketSize = buffsize;
2547 TBasket *basket = (TBasket*)fBaskets[fWriteBasket];
2549 basket->AdjustSize(fBasketSize);
2558 void TBranch::SetBufferAddress(TBuffer* buf)
2561 if ( (fNleaves != 1)
2562 || (strcmp(
"TLeafObject",fLeaves.UncheckedAt(0)->ClassName())!=0) ) {
2563 Error(
"TBranch::SetAddress",
"Filling from a TBuffer can only be done with a not split object branch. Request ignored.");
2566 fNextBasketEntry = -1;
2567 fFirstBasketEntry = -1;
2576 void TBranch::SetCompressionAlgorithm(Int_t algorithm)
2578 if (algorithm < 0 || algorithm >= ROOT::RCompressionSetting::EAlgorithm::kUndefined) algorithm = 0;
2579 if (fCompress < 0) {
2580 fCompress = 100 * algorithm + ROOT::RCompressionSetting::ELevel::kUseMin;
2582 int level = fCompress % 100;
2583 fCompress = 100 * algorithm + level;
2586 Int_t nb = fBranches.GetEntriesFast();
2587 for (Int_t i=0;i<nb;i++) {
2588 TBranch *branch = (TBranch*)fBranches.UncheckedAt(i);
2589 branch->SetCompressionAlgorithm(algorithm);
2596 void TBranch::SetCompressionLevel(Int_t level)
2598 if (level < 0) level = 0;
2599 if (level > 99) level = 99;
2600 if (fCompress < 0) {
2603 int algorithm = fCompress / 100;
2604 if (algorithm >= ROOT::RCompressionSetting::EAlgorithm::kUndefined) algorithm = 0;
2605 fCompress = 100 * algorithm + level;
2608 Int_t nb = fBranches.GetEntriesFast();
2609 for (Int_t i=0;i<nb;i++) {
2610 TBranch *branch = (TBranch*)fBranches.UncheckedAt(i);
2611 branch->SetCompressionLevel(level);
2618 void TBranch::SetCompressionSettings(Int_t settings)
2620 fCompress = settings;
2622 Int_t nb = fBranches.GetEntriesFast();
2623 for (Int_t i=0;i<nb;i++) {
2624 TBranch *branch = (TBranch*)fBranches.UncheckedAt(i);
2625 branch->SetCompressionSettings(settings);
2634 void TBranch::SetEntryOffsetLen(Int_t newdefault, Bool_t updateExisting)
2636 if (fEntryOffsetLen && newdefault) {
2637 fEntryOffsetLen = newdefault;
2639 if (updateExisting) {
2640 TIter next( GetListOfBranches() );
2642 while ( ( b = (TBranch*)next() ) ) {
2643 b->SetEntryOffsetLen( newdefault, kTRUE );
2651 void TBranch::SetEntries(Long64_t entries)
2654 fEntryNumber = entries;
2676 void TBranch::SetFile(TFile* file)
2678 if (file == 0) file = fTree->GetCurrentFile();
2679 fDirectory = (TDirectory*)file;
2680 if (file == fTree->GetCurrentFile()) fFileName =
"";
2681 else fFileName = file->GetName();
2683 if (file && fCompress == -1) {
2684 fCompress = file->GetCompressionLevel();
2688 TIter nextb(GetListOfBaskets());
2690 while ((basket = (TBasket*)nextb())) {
2691 basket->SetParent(file);
2695 TIter next(GetListOfBranches());
2697 while ((branch = (TBranch*)next())) {
2698 branch->SetFile(file);
2721 void TBranch::SetFile(
const char* fname)
2727 TIter next(GetListOfBranches());
2729 while ((branch = (TBranch*)next())) {
2730 branch->SetFile(fname);
2740 Bool_t TBranch::SetMakeClass(Bool_t )
2749 void TBranch::SetObject(
void * )
2751 if (TestBit(kDoNotProcess)) {
2754 Warning(
"SetObject",
"is not supported in TBranch objects");
2760 void TBranch::SetStatus(Bool_t status)
2762 if (status) ResetBit(kDoNotProcess);
2763 else SetBit(kDoNotProcess);
2769 void TBranch::Streamer(TBuffer& b)
2771 if (b.IsReading()) {
2775 gROOT->SetReadingObject(kTRUE);
2778 SetBit(TBranch::kDoNotUseBufferMap);
2780 fFirstBasketEntry = -1;
2781 fNextBasketEntry = -1;
2783 Version_t v = b.ReadVersion(&R__s, &R__c);
2785 b.ReadClassBuffer(TBranch::Class(),
this, v, R__s, R__c);
2787 if (fWriteBasket>=fBaskets.GetSize()) {
2788 fBaskets.Expand(fWriteBasket+1);
2791 fNleaves = fLeaves.GetEntriesFast();
2792 for (Int_t i=0;i<fNleaves;i++) {
2793 TLeaf *leaf = (TLeaf*)fLeaves.UncheckedAt(i);
2794 leaf->SetBranch(
this);
2797 fNBaskets = fBaskets.GetEntries();
2798 for (Int_t j=fWriteBasket,n=0;j>=0 && n<fNBaskets;--j) {
2799 TBasket *bk = (TBasket*)fBaskets.UncheckedAt(j);
2801 bk->SetBranch(
this);
2806 if (fWriteBasket >= fMaxBaskets) {
2808 ExpandBasketArrays();
2809 fBasketBytes[fWriteBasket] = fBasketBytes[fWriteBasket-1];
2810 fBasketEntry[fWriteBasket] = fEntries;
2811 fBasketSeek [fWriteBasket] = fBasketSeek [fWriteBasket-1];
2814 if (!fSplitLevel && fBranches.GetEntriesFast()) fSplitLevel = 1;
2815 gROOT->SetReadingObject(kFALSE);
2816 if (IsA() == TBranch::Class()) {
2817 if (fNleaves == 0) {
2818 fReadLeaves = &TBranch::ReadLeaves0Impl;
2819 }
else if (fNleaves == 1) {
2820 fReadLeaves = &TBranch::ReadLeaves1Impl;
2821 }
else if (fNleaves == 2) {
2822 fReadLeaves = &TBranch::ReadLeaves2Impl;
2824 fReadLeaves = &TBranch::ReadLeavesImpl;
2833 TNamed::Streamer(b);
2834 if (v > 7) TAttFill::Streamer(b);
2837 b >> fEntryOffsetLen;
2839 b >> ijunk; fEntryNumber = (Long64_t)ijunk;
2842 if (v > 6) b >> fSplitLevel;
2843 b >> djunk; fEntries = (Long64_t)djunk;
2844 b >> djunk; fTotBytes = (Long64_t)djunk;
2845 b >> djunk; fZipBytes = (Long64_t)djunk;
2847 fBranches.Streamer(b);
2848 fLeaves.Streamer(b);
2849 fBaskets.Streamer(b);
2850 fBasketBytes =
new Int_t[fMaxBaskets];
2851 fBasketEntry =
new Long64_t[fMaxBaskets];
2852 fBasketSeek =
new Long64_t[fMaxBaskets];
2855 b.ReadFastArray(fBasketBytes,fMaxBaskets);
2857 for (i=0;i<fMaxBaskets;i++) {b >> ijunk; fBasketEntry[i] = ijunk;}
2859 for (i=0;i<fMaxBaskets;i++) {
2860 if (isArray == 2) b >> fBasketSeek[i];
2861 else {Int_t bsize; b >> bsize; fBasketSeek[i] = (Long64_t)bsize;};
2863 fFileName.Streamer(b);
2864 b.CheckByteCount(R__s, R__c, TBranch::IsA());
2866 fNleaves = fLeaves.GetEntriesFast();
2867 for (i=0;i<fNleaves;i++) {
2868 TLeaf *leaf = (TLeaf*)fLeaves.UncheckedAt(i);
2869 leaf->SetBranch(
this);
2871 fNBaskets = fBaskets.GetEntries();
2872 for (j=fWriteBasket,n=0;j>=0 && n<fNBaskets;--j) {
2873 TBasket *bk = (TBasket*)fBaskets.UncheckedAt(j);
2875 bk->SetBranch(
this);
2880 if (fWriteBasket >= fMaxBaskets) {
2882 ExpandBasketArrays();
2883 fBasketBytes[fWriteBasket] = fBasketBytes[fWriteBasket-1];
2884 fBasketEntry[fWriteBasket] = fEntries;
2885 fBasketSeek [fWriteBasket] = fBasketSeek [fWriteBasket-1];
2889 if (!fSplitLevel && fBranches.GetEntriesFast()) fSplitLevel = 1;
2890 gROOT->SetReadingObject(kFALSE);
2891 b.CheckByteCount(R__s, R__c, TBranch::IsA());
2892 if (IsA() == TBranch::Class()) {
2893 if (fNleaves == 0) {
2894 fReadLeaves = &TBranch::ReadLeaves0Impl;
2895 }
else if (fNleaves == 1) {
2896 fReadLeaves = &TBranch::ReadLeaves1Impl;
2897 }
else if (fNleaves == 2) {
2898 fReadLeaves = &TBranch::ReadLeaves2Impl;
2900 fReadLeaves = &TBranch::ReadLeavesImpl;
2907 TNamed::Streamer(b);
2910 b >> fEntryOffsetLen;
2913 b >> ijunk; fEntryNumber = (Long64_t)ijunk;
2914 b >> djunk; fEntries = (Long64_t)djunk;
2915 b >> djunk; fTotBytes = (Long64_t)djunk;
2916 b >> djunk; fZipBytes = (Long64_t)djunk;
2918 fBranches.Streamer(b);
2919 fLeaves.Streamer(b);
2920 fNleaves = fLeaves.GetEntriesFast();
2921 for (i=0;i<fNleaves;i++) {
2922 TLeaf *leaf = (TLeaf*)fLeaves.UncheckedAt(i);
2923 leaf->SetBranch(
this);
2925 fBaskets.Streamer(b);
2926 Int_t nbaskets = fBaskets.GetEntries();
2927 for (j=fWriteBasket,n=0;j>0 && n<nbaskets;--j) {
2928 TBasket *bk = (TBasket*)fBaskets.UncheckedAt(j);
2930 bk->SetBranch(
this);
2935 fBasketEntry =
new Long64_t[fMaxBaskets];
2937 for (i=0;i<n;i++) {b >> ijunk; fBasketEntry[i] = ijunk;}
2938 fBasketBytes =
new Int_t[fMaxBaskets];
2940 n = b.ReadArray(fBasketBytes);
2942 for (n=0;n<fMaxBaskets;n++) fBasketBytes[n] = 0;
2945 fBasketSeek =
new Long64_t[fMaxBaskets];
2946 for (n=0;n<fWriteBasket;n++) {
2947 TBasket *basket = GetBasketImpl(n,
nullptr);
2948 fBasketSeek[n] = basket ? basket->GetSeekKey() : 0;
2951 fBasketSeek =
new Long64_t[fMaxBaskets];
2953 for (n=0;n<fMaxBaskets;n++) {
2956 fBasketSeek[n] = Long64_t(aseek);
2960 fFileName.Streamer(b);
2963 if (v < 4) SetAutoDelete(kTRUE);
2964 if (!fSplitLevel && fBranches.GetEntriesFast()) fSplitLevel = 1;
2965 gROOT->SetReadingObject(kFALSE);
2966 b.CheckByteCount(R__s, R__c, TBranch::IsA());
2968 if (IsA() == TBranch::Class()) {
2969 if (fNleaves == 0) {
2970 fReadLeaves = &TBranch::ReadLeaves0Impl;
2971 }
else if (fNleaves == 1) {
2972 fReadLeaves = &TBranch::ReadLeaves1Impl;
2973 }
else if (fNleaves == 2) {
2974 fReadLeaves = &TBranch::ReadLeaves2Impl;
2976 fReadLeaves = &TBranch::ReadLeavesImpl;
2980 Int_t maxBaskets = fMaxBaskets;
2981 fMaxBaskets = fWriteBasket+1;
2982 Int_t lastBasket = fMaxBaskets;
2983 if (fMaxBaskets < 10) fMaxBaskets = 10;
2985 TBasket **stash =
new TBasket *[lastBasket];
2986 for (Int_t i = 0; i < lastBasket; ++i) {
2987 TBasket *ba = (TBasket *)fBaskets.UncheckedAt(i);
2988 if (ba && (fBasketBytes[i] || ba->GetNevBuf()==0)) {
2991 fBaskets[i] =
nullptr;
2997 b.WriteClassBuffer(TBranch::Class(),
this);
2999 for (Int_t i = 0; i < lastBasket; ++i) {
3000 if (stash[i]) fBaskets[i] = stash[i];
3004 fMaxBaskets = maxBaskets;
3012 Int_t TBranch::WriteBasketImpl(TBasket* basket, Int_t where, ROOT::Internal::TBranchIMTHelper *imtHelper)
3014 Int_t nevbuf = basket->GetNevBuf();
3015 if (fEntryOffsetLen > 10 && (4*nevbuf) < fEntryOffsetLen ) {
3017 fEntryOffsetLen = nevbuf < 3 ? 10 : 4*nevbuf;
3018 }
else if (fEntryOffsetLen && nevbuf > fEntryOffsetLen) {
3020 fEntryOffsetLen = 2*nevbuf;
3026 auto doUpdates = [=]() {
3027 Int_t nout = basket->WriteBuffer();
3028 if (nout < 0) Error(
"TBranch::WriteBasketImpl",
"basket's WriteBuffer failed.\n");
3029 fBasketBytes[where] = basket->GetNbytes();
3030 fBasketSeek[where] = basket->GetSeekKey();
3031 Int_t addbytes = basket->GetObjlen() + basket->GetKeylen();
3032 TBasket *reusebasket = 0;
3035 fBaskets[where] = 0;
3037 reusebasket = basket;
3038 reusebasket->Reset();
3041 fTotBytes += addbytes;
3042 fTree->AddTotBytes(addbytes);
3043 fTree->AddZipBytes(nout);
3044 #ifdef R__TRACK_BASKET_ALLOC_TIME
3045 fTree->AddAllocationTime(reusebasket->GetResetAllocationTime());
3047 fTree->AddAllocationCount(reusebasket->GetResetAllocationCount());
3050 if (where==fWriteBasket) {
3052 if (fWriteBasket >= fMaxBaskets) {
3053 ExpandBasketArrays();
3055 if (reusebasket && reusebasket == fCurrentBasket) {
3059 fFirstBasketEntry = -1;
3060 fNextBasketEntry = -1;
3062 fBaskets.AddAtAndExpand(reusebasket,fWriteBasket);
3063 fBasketEntry[fWriteBasket] = fEntryNumber;
3066 fBaskets[where] = 0;
3067 basket->DropBuffers();
3068 if (basket == fCurrentBasket) {
3070 fFirstBasketEntry = -1;
3071 fNextBasketEntry = -1;
3078 imtHelper->Run(doUpdates);
3088 void TBranch::SetFirstEntry(Long64_t entry)
3090 fFirstEntry = entry;
3092 fEntryNumber = entry;
3094 fBasketEntry[0] = entry;
3095 for( Int_t i = 0; i < fBranches.GetEntriesFast(); ++i )
3096 ((TBranch*)fBranches[i])->SetFirstEntry( entry );
3103 void TBranch::SetupAddresses()
3113 void TBranch::UpdateFile()
3115 TFile *file = fTree->GetCurrentFile();
3116 if (fFileName.Length() == 0) {
3120 TIter nextb(GetListOfBaskets());
3122 while ((basket = (TBasket*)nextb())) {
3123 basket->SetParent(file);
3128 TIter next(GetListOfBranches());
3130 while ((branch = (TBranch*)next())) {
3131 branch->UpdateFile();