Logo ROOT   6.16/01
Reference Guide
TBranch.cxx
Go to the documentation of this file.
1// @(#)root/tree:$Id$
2// Author: Rene Brun 12/01/96
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12#include "TBranchCacheInfo.h"
13
14#include "TBranch.h"
15
16#include "Compression.h"
17#include "TBasket.h"
18#include "TBranchBrowsable.h"
19#include "TBrowser.h"
20#include "TBuffer.h"
21#include "TClass.h"
22#include "TBufferFile.h"
23#include "TClonesArray.h"
24#include "TFile.h"
25#include "TLeaf.h"
26#include "TLeafB.h"
27#include "TLeafC.h"
28#include "TLeafD.h"
29#include "TLeafF.h"
30#include "TLeafI.h"
31#include "TLeafL.h"
32#include "TLeafO.h"
33#include "TLeafObject.h"
34#include "TLeafS.h"
35#include "TMessage.h"
36#include "TROOT.h"
37#include "TSystem.h"
38#include "TMath.h"
39#include "TTree.h"
40#include "TTreeCache.h"
41#include "TTreeCacheUnzip.h"
42#include "TVirtualMutex.h"
43#include "TVirtualPad.h"
44#include "TVirtualPerfStats.h"
45
46#include "TBranchIMTHelper.h"
47
48#include "ROOT/TIOFeatures.hxx"
49
50#include <atomic>
51#include <cstddef>
52#include <string.h>
53#include <stdio.h>
54
55
57
58/** \class TBranch
59\ingroup tree
60
61A TTree is a list of TBranches
62
63A TBranch supports:
64 - The list of TLeaf describing this branch.
65 - The list of TBasket (branch buffers).
66
67See TBranch structure in TTree.
68
69See also specialized branches:
70 - TBranchObject in case the branch is one object
71 - TBranchClones in case the branch is an array of clone objects
72*/
73
75
76
77
78////////////////////////////////////////////////////////////////////////////////
79/// Default constructor. Used for I/O by default.
80
82: TNamed()
83, TAttFill(0, 1001)
84, fCompress(0)
85, fBasketSize(32000)
86, fEntryOffsetLen(1000)
87, fWriteBasket(0)
88, fEntryNumber(0)
89, fOffset(0)
90, fMaxBaskets(10)
91, fNBaskets(0)
92, fSplitLevel(0)
93, fNleaves(0)
94, fReadBasket(0)
95, fReadEntry(-1)
96, fFirstBasketEntry(-1)
97, fNextBasketEntry(-1)
98, fCurrentBasket(0)
99, fEntries(0)
100, fFirstEntry(0)
101, fTotBytes(0)
102, fZipBytes(0)
103, fBranches()
104, fLeaves()
105, fBaskets(fMaxBaskets)
106, fBasketBytes(0)
107, fBasketEntry(0)
108, fBasketSeek(0)
109, fTree(0)
110, fMother(0)
111, fParent(0)
112, fAddress(0)
113, fDirectory(0)
114, fFileName("")
115, fEntryBuffer(0)
116, fTransientBuffer(0)
117, fBrowsables(0)
118, fSkipZip(kFALSE)
119, fReadLeaves(&TBranch::ReadLeavesImpl)
120, fFillLeaves(&TBranch::FillLeavesImpl)
121{
123}
124
125////////////////////////////////////////////////////////////////////////////////
126/// Create a Branch as a child of a Tree
127///
128/// * address is the address of the first item of a structure
129/// or the address of a pointer to an object (see example in TTree.cxx).
130/// * leaflist is the concatenation of all the variable names and types
131/// separated by a colon character :
132/// The variable name and the variable type are separated by a
133/// slash (/). The variable type must be 1 character. (Characters
134/// after the first are legal and will be appended to the visible
135/// name of the leaf, but have no effect.) If no type is given, the
136/// type of the variable is assumed to be the same as the previous
137/// variable. If the first variable does not have a type, it is
138/// assumed of type F by default. The list of currently supported
139/// types is given below:
140/// - `C` : a character string terminated by the 0 character
141/// - `B` : an 8 bit signed integer (`Char_t`)
142/// - `b` : an 8 bit unsigned integer (`UChar_t`)
143/// - `S` : a 16 bit signed integer (`Short_t`)
144/// - `s` : a 16 bit unsigned integer (`UShort_t`)
145/// - `I` : a 32 bit signed integer (`Int_t`)
146/// - `i` : a 32 bit unsigned integer (`UInt_t`)
147/// - `F` : a 32 bit floating point (`Float_t`)
148/// - `D` : a 64 bit floating point (`Double_t`)
149/// - `L` : a 64 bit signed integer (`Long64_t`)
150/// - `l` : a 64 bit unsigned integer (`ULong64_t`)
151/// - `O` : [the letter `o`, not a zero] a boolean (`Bool_t`)
152///
153/// Arrays of values are supported with the following syntax:
154/// - If leaf name has the form var[nelem], where nelem is alphanumeric, then
155/// if nelem is a leaf name, it is used as the variable size of the array,
156/// otherwise return 0.
157/// The leaf referred to by nelem **MUST** be an int (/I),
158/// - If leaf name has the form var[nelem], where nelem is a non-negative integers, then
159/// it is used as the fixed size of the array.
160/// - If leaf name has the form of a multi dimension array (e.g. var[nelem][nelem2])
161/// where nelem and nelem2 are non-negative integers) then
162/// it is used as a 2 dimensional array of fixed size.
163/// - Any of other form is not supported.
164///
165/// Note that the TTree will assume that all the item are contiguous in memory.
166/// On some platform, this is not always true of the member of a struct or a class,
167/// due to padding and alignment. Sorting your data member in order of decreasing
168/// sizeof usually leads to their being contiguous in memory.
169///
170/// * bufsize is the buffer size in bytes for this branch
171/// The default value is 32000 bytes and should be ok for most cases.
172/// You can specify a larger value (e.g. 256000) if your Tree is not split
173/// and each entry is large (Megabytes)
174/// A small value for bufsize is optimum if you intend to access
175/// the entries in the Tree randomly and your Tree is in split mode.
176///
177/// See an example of a Branch definition in the TTree constructor.
178///
179/// Note that in case the data type is an object, this branch can contain
180/// only this object.
181///
182/// Note that this function is invoked by TTree::Branch
183
184TBranch::TBranch(TTree *tree, const char *name, void *address, const char *leaflist, Int_t basketsize, Int_t compress)
185 : TNamed(name, leaflist)
186, TAttFill(0, 1001)
187, fCompress(compress)
188, fBasketSize((basketsize < 100) ? 100 : basketsize)
189, fEntryOffsetLen(0)
190, fWriteBasket(0)
191, fEntryNumber(0)
192, fIOFeatures(tree ? tree->GetIOFeatures().GetFeatures() : 0)
193, fOffset(0)
194, fMaxBaskets(10)
195, fNBaskets(0)
196, fSplitLevel(0)
197, fNleaves(0)
198, fReadBasket(0)
199, fReadEntry(-1)
200, fFirstBasketEntry(-1)
201, fNextBasketEntry(-1)
202, fCurrentBasket(0)
203, fEntries(0)
204, fFirstEntry(0)
205, fTotBytes(0)
206, fZipBytes(0)
207, fBranches()
208, fLeaves()
209, fBaskets(fMaxBaskets)
210, fBasketBytes(0)
211, fBasketEntry(0)
212, fBasketSeek(0)
213, fTree(tree)
214, fMother(0)
215, fParent(0)
216, fAddress((char *)address)
217, fDirectory(fTree->GetDirectory())
218, fFileName("")
219, fEntryBuffer(0)
220, fTransientBuffer(0)
221, fBrowsables(0)
222, fSkipZip(kFALSE)
223, fReadLeaves(&TBranch::ReadLeavesImpl)
224, fFillLeaves(&TBranch::FillLeavesImpl)
225{
226 Init(name,leaflist,compress);
227}
228
229////////////////////////////////////////////////////////////////////////////////
230/// Create a Branch as a child of another Branch
231///
232/// See documentation for
233/// TBranch::TBranch(TTree *, const char *, void *, const char *, Int_t, Int_t)
234
235TBranch::TBranch(TBranch *parent, const char *name, void *address, const char *leaflist, Int_t basketsize,
236 Int_t compress)
237: TNamed(name, leaflist)
238, TAttFill(0, 1001)
239, fCompress(compress)
240, fBasketSize((basketsize < 100) ? 100 : basketsize)
241, fEntryOffsetLen(0)
242, fWriteBasket(0)
243, fEntryNumber(0)
244, fIOFeatures(parent->fIOFeatures)
245, fOffset(0)
246, fMaxBaskets(10)
247, fNBaskets(0)
248, fSplitLevel(0)
249, fNleaves(0)
250, fReadBasket(0)
251, fReadEntry(-1)
252, fFirstBasketEntry(-1)
253, fNextBasketEntry(-1)
254, fCurrentBasket(0)
255, fEntries(0)
256, fFirstEntry(0)
257, fTotBytes(0)
258, fZipBytes(0)
259, fBranches()
260, fLeaves()
261, fBaskets(fMaxBaskets)
262, fBasketBytes(0)
263, fBasketEntry(0)
264, fBasketSeek(0)
265, fTree(parent ? parent->GetTree() : 0)
266, fMother(parent ? parent->GetMother() : 0)
267, fParent(parent)
268, fAddress((char *)address)
269, fDirectory(fTree ? fTree->GetDirectory() : 0)
270, fFileName("")
271, fEntryBuffer(0)
272, fTransientBuffer(0)
273, fBrowsables(0)
274, fSkipZip(kFALSE)
275, fReadLeaves(&TBranch::ReadLeavesImpl)
276, fFillLeaves(&TBranch::FillLeavesImpl)
277{
278 Init(name,leaflist,compress);
279}
280
281void TBranch::Init(const char* name, const char* leaflist, Int_t compress)
282{
283 // Initialization routine called from the constructor. This should NOT be made virtual.
284
286 if ((compress == -1) && fTree->GetDirectory()) {
287 TFile* bfile = fTree->GetDirectory()->GetFile();
288 if (bfile) {
290 }
291 }
292
296
297 for (Int_t i = 0; i < fMaxBaskets; ++i) {
298 fBasketBytes[i] = 0;
299 fBasketEntry[i] = 0;
300 fBasketSeek[i] = 0;
301 }
302
303 //
304 // Decode the leaflist (search for : as separator).
305 //
306
307 char* nameBegin = const_cast<char*>(leaflist);
308 Int_t offset = 0;
309 auto len = strlen(leaflist);
310 // FIXME: Make these string streams instead.
311 char* leafname = new char[len + 1];
312 char* leaftype = new char[320];
313 // Note: The default leaf type is a float.
314 strlcpy(leaftype, "F",320);
315 char* pos = const_cast<char*>(leaflist);
316 const char* leaflistEnd = leaflist + len;
317 for (; pos <= leaflistEnd; ++pos) {
318 // -- Scan leaf specification and create leaves.
319 if ((*pos == ':') || (*pos == 0)) {
320 // -- Reached end of a leaf spec, create a leaf.
321 Int_t lenName = pos - nameBegin;
322 char* ctype = 0;
323 if (lenName) {
324 strncpy(leafname, nameBegin, lenName);
325 leafname[lenName] = 0;
326 ctype = strstr(leafname, "/");
327 if (ctype) {
328 *ctype = 0;
329 strlcpy(leaftype, ctype + 1,320);
330 }
331 }
332 if (lenName == 0 || ctype == leafname) {
333 Warning("TBranch","No name was given to the leaf number '%d' in the leaflist of the branch '%s'.",fNleaves,name);
334 snprintf(leafname,640,"__noname%d",fNleaves);
335 }
336 TLeaf* leaf = 0;
337 if (leaftype[1] == '[') {
338 Warning("TBranch", "Array size for branch '%s' must be specified after leaf name, not after the type name!", name);
339 // and continue for backward compatibility?
340 } else if (leaftype[1]) {
341 Warning("TBranch", "Extra characters after type tag '%s' for branch '%s'; must be one character.", leaftype, name);
342 // and continue for backward compatibility?
343 }
344 if (*leaftype == 'C') {
345 leaf = new TLeafC(this, leafname, leaftype);
346 } else if (*leaftype == 'O') {
347 leaf = new TLeafO(this, leafname, leaftype);
348 } else if (*leaftype == 'B') {
349 leaf = new TLeafB(this, leafname, leaftype);
350 } else if (*leaftype == 'b') {
351 leaf = new TLeafB(this, leafname, leaftype);
352 leaf->SetUnsigned();
353 } else if (*leaftype == 'S') {
354 leaf = new TLeafS(this, leafname, leaftype);
355 } else if (*leaftype == 's') {
356 leaf = new TLeafS(this, leafname, leaftype);
357 leaf->SetUnsigned();
358 } else if (*leaftype == 'I') {
359 leaf = new TLeafI(this, leafname, leaftype);
360 } else if (*leaftype == 'i') {
361 leaf = new TLeafI(this, leafname, leaftype);
362 leaf->SetUnsigned();
363 } else if (*leaftype == 'F') {
364 leaf = new TLeafF(this, leafname, leaftype);
365 } else if (*leaftype == 'f') {
366 leaf = new TLeafF(this, leafname, leaftype);
367 } else if (*leaftype == 'L') {
368 leaf = new TLeafL(this, leafname, leaftype);
369 } else if (*leaftype == 'l') {
370 leaf = new TLeafL(this, leafname, leaftype);
371 leaf->SetUnsigned();
372 } else if (*leaftype == 'D') {
373 leaf = new TLeafD(this, leafname, leaftype);
374 } else if (*leaftype == 'd') {
375 leaf = new TLeafD(this, leafname, leaftype);
376 }
377 if (!leaf) {
378 Error("TLeaf", "Illegal data type for %s/%s", name, leaflist);
379 delete[] leaftype;
380 delete [] leafname;
381 MakeZombie();
382 return;
383 }
384 if (leaf->IsZombie()) {
385 delete leaf;
386 leaf = 0;
387 Error("TBranch", "Illegal leaf: %s/%s", name, leaflist);
388 delete [] leafname;
389 delete[] leaftype;
390 MakeZombie();
391 return;
392 }
393 leaf->SetBranch(this);
394 leaf->SetAddress((char*) (fAddress + offset));
395 leaf->SetOffset(offset);
396 if (leaf->GetLeafCount()) {
397 // -- Leaf is a varying length array, we need an offset array.
398 fEntryOffsetLen = 1000;
399 }
400 if (leaf->InheritsFrom(TLeafC::Class())) {
401 // -- Leaf is a character string, we need an offset array.
402 fEntryOffsetLen = 1000;
403 }
404 ++fNleaves;
405 fLeaves.Add(leaf);
406 fTree->GetListOfLeaves()->Add(leaf);
407 if (*pos == 0) {
408 // -- We reached the end of the leaf specification.
409 break;
410 }
411 nameBegin = pos + 1;
412 offset += leaf->GetLenType() * leaf->GetLen();
413 }
414 }
415 delete[] leafname;
416 leafname = 0;
417 delete[] leaftype;
418 leaftype = 0;
419
420}
421
422////////////////////////////////////////////////////////////////////////////////
423/// Destructor.
424
426{
427 delete fBrowsables;
428 fBrowsables = 0;
429
430 // Note: We do *not* have ownership of the buffer.
431 fEntryBuffer = 0;
432
433 delete [] fBasketSeek;
434 fBasketSeek = 0;
435
436 delete [] fBasketEntry;
437 fBasketEntry = 0;
438
439 delete [] fBasketBytes;
440 fBasketBytes = 0;
441
443 fNBaskets = 0;
444 fCurrentBasket = 0;
446 fNextBasketEntry = -1;
447
448 // Remove our leaves from our tree's list of leaves.
449 if (fTree) {
451 if (lst && lst->GetLast()!=-1) {
452 lst->RemoveAll(&fLeaves);
453 }
454 }
455 // And delete our leaves.
456 fLeaves.Delete();
457
459
460 // If we are in a directory and that directory is not the same
461 // directory that our tree is in, then try to find an open file
462 // with the name fFileName. If we find one, delete that file.
463 // We are attempting to close any alternate file which we have
464 // been directed to write our baskets to.
465 // FIXME: We make no attempt to check if someone else might be
466 // using this file. This is very user hostile. A violation
467 // of the principle of least surprises.
468 //
469 // Warning. Must use FindObject by name instead of fDirectory->GetFile()
470 // because two branches may point to the same file and the file
471 // may have already been deleted in the previous branch.
472 if (fDirectory && (!fTree || fDirectory != fTree->GetDirectory())) {
473 TString bFileName( GetRealFileName() );
474
476 TFile* file = (TFile*)gROOT->GetListOfFiles()->FindObject(bFileName);
477 if (file){
478 file->Close();
479 delete file;
480 file = 0;
481 }
482 }
483
484 fTree = 0;
485 fDirectory = 0;
486
487 if (fTransientBuffer) {
488 delete fTransientBuffer;
490 }
491}
492
493////////////////////////////////////////////////////////////////////////////////
494/// Returns the transient buffer currently used by this TBranch for reading/writing baskets.
495
497{
498 if (fTransientBuffer) {
499 if (fTransientBuffer->BufferSize() < size) {
501 }
502 return fTransientBuffer;
503 }
505 return fTransientBuffer;
506}
507
508////////////////////////////////////////////////////////////////////////////////
509/// Add the basket to this branch.
510///
511/// Warning: if the basket are not 'flushed/copied' in the same
512/// order as they were created, this will induce a slow down in
513/// the insert (since we'll need to move all the record that are
514/// entere 'too early').
515/// Warning we also assume that the __current__ write basket is
516/// not present (aka has been removed).
517
518void TBranch::AddBasket(TBasket& b, Bool_t ondisk, Long64_t startEntry)
519{
520 TBasket *basket = &b;
521
522 basket->SetBranch(this);
523
524 if (fWriteBasket >= fMaxBaskets) {
526 }
527 Int_t where = fWriteBasket;
528
529 if (where && startEntry < fBasketEntry[where-1]) {
530 // Need to find the right location and move the possible baskets
531
532 if (!ondisk) {
533 Warning("AddBasket","The assumption that out-of-order basket only comes from disk based ntuple is false.");
534 }
535
536 if (startEntry < fBasketEntry[0]) {
537 where = 0;
538 } else {
539 for(Int_t i=fWriteBasket-1; i>=0; --i) {
540 if (fBasketEntry[i] < startEntry) {
541 where = i+1;
542 break;
543 } else if (fBasketEntry[i] == startEntry) {
544 Error("AddBasket","An out-of-order basket matches the entry number of an existing basket.");
545 }
546 }
547 }
548
549 if (where < fWriteBasket) {
550 // We shall move the content of the array
551 for (Int_t j=fWriteBasket; j > where; --j) {
552 fBasketEntry[j] = fBasketEntry[j-1];
553 fBasketBytes[j] = fBasketBytes[j-1];
554 fBasketSeek[j] = fBasketSeek[j-1];
555 }
556 }
557 }
558 fBasketEntry[where] = startEntry;
559
560 if (ondisk) {
561 fBasketBytes[where] = basket->GetNbytes(); // not for in mem
562 fBasketSeek[where] = basket->GetSeekKey(); // not for in mem
564 ++fWriteBasket;
565 } else {
566 ++fNBaskets;
569 }
570
571 fEntries += basket->GetNevBuf();
572 fEntryNumber += basket->GetNevBuf();
573 if (ondisk) {
574 fTotBytes += basket->GetObjlen() + basket->GetKeylen() ;
575 fZipBytes += basket->GetNbytes();
576 fTree->AddTotBytes(basket->GetObjlen() + basket->GetKeylen());
577 fTree->AddZipBytes(basket->GetNbytes());
578 }
579}
580
581////////////////////////////////////////////////////////////////////////////////
582/// Add the start entry of the write basket (not yet created)
583
585{
586 if (fWriteBasket >= fMaxBaskets) {
588 }
589 Int_t where = fWriteBasket;
590
591 if (where && startEntry < fBasketEntry[where-1]) {
592 // Need to find the right location and move the possible baskets
593
594 Fatal("AddBasket","The last basket must have the highest entry number (%s/%lld/%d).",GetName(),startEntry,fWriteBasket);
595
596 }
597 fBasketEntry[where] = startEntry;
599}
600
601////////////////////////////////////////////////////////////////////////////////
602/// Loop on all leaves of this branch to back fill Basket buffer.
603///
604/// Use this routine instead of TBranch::Fill when filling a branch individually
605/// to catch up with the number of entries already in the TTree.
606///
607/// First it calls TBranch::Fill and then if the number of entries of the branch
608/// reach one of TTree cluster's boundary, the basket is flushed.
609///
610/// The function returns the number of bytes committed to the memory basket.
611/// If a write error occurs, the number of bytes returned is -1.
612/// If no data are written, because e.g. the branch is disabled,
613/// the number of bytes returned is 0.
614///
615/// To insure that the baskets of each cluster are located close by in the
616/// file, when back-filling multiple branches make sure to call BackFill
617/// for the same entry for all the branches consecutively
618/// ~~~ {.cpp}
619/// for( auto e = 0; e < tree->GetEntries(); ++e ) { // loop over entries.
620/// for( auto branch : branchCollection) {
621/// ... Make change to the data associated with the branch ...
622/// branch->BackFill();
623/// }
624/// }
625/// // Since we loop over all the branches for each new entry
626/// // all the baskets for a cluster are consecutive in the file.
627/// ~~~
628/// rather than doing all the entries of one branch at a time.
629/// ~~~ {.cpp}
630/// // Do NOT do things in the following order, it will lead to
631/// // poorly clustered files.
632/// for(auto branch : branchCollection) {
633/// for( auto e = 0; e < tree->GetEntries(); ++e ) { // loop over entries.
634/// ... Make change to the data associated with the branch ...
635/// branch->BackFill();
636/// }
637/// }
638/// // Since we loop over all the entries for one branch
639/// // all the baskets for that branch are consecutive.
640/// ~~~
641
643
644 // Get the end of the next cluster.
645 auto cluster = GetTree()->GetClusterIterator( GetEntries() );
646 cluster.Next();
647 auto endCluster = cluster.GetNextEntry();
648
649 auto result = FillImpl(nullptr);
650
651 if ( result && GetEntries() >= endCluster ) {
652 FlushBaskets();
653 }
654
655 return result;
656}
657
658////////////////////////////////////////////////////////////////////////////////
659/// Browser interface.
660
662{
663 if (fNleaves > 1) {
665 } else {
666 // Get the name and strip any extra brackets
667 // in order to get the full arrays.
668 TString name = GetName();
669 Int_t pos = name.First('[');
670 if (pos!=kNPOS) name.Remove(pos);
671
672 GetTree()->Draw(name, "", b ? b->GetDrawOption() : "");
673 if (gPad) gPad->Update();
674 }
675}
676
677 ///////////////////////////////////////////////////////////////////////////////
678 /// Loop on all branch baskets. If the file where branch buffers reside is
679 /// writable, free the disk space associated to the baskets of the branch,
680 /// then call Reset(). If the option contains "all", delete also the baskets
681 /// for the subbranches.
682 /// The branch is reset.
683 ///
684 /// NOTE that this function must be used with extreme care. Deleting branch baskets
685 /// fragments the file and may introduce inefficiencies when adding new entries
686 /// in the Tree or later on when reading the Tree.
687
689{
690 TString opt = option;
691 opt.ToLower();
692 TFile *file = GetFile(0);
693
695 for(Int_t i=0; i<fWriteBasket; i++) {
696 if (fBasketSeek[i]) file->MakeFree(fBasketSeek[i],fBasketSeek[i]+fBasketBytes[i]-1);
697 }
698 }
699
700 // process subbranches
701 if (opt.Contains("all")) {
703 Int_t nb = lb->GetEntriesFast();
704 for (Int_t j = 0; j < nb; j++) {
705 TBranch* branch = (TBranch*) lb->UncheckedAt(j);
706 if (branch) branch->DeleteBaskets("all");
707 }
708 }
709 DropBaskets("all");
710 Reset();
711}
712
713////////////////////////////////////////////////////////////////////////////////
714/// Loop on all branch baskets. Drop all baskets from memory except readbasket.
715/// If the option contains "all", drop all baskets including
716/// read- and write-baskets (unless they are not stored individually on disk).
717/// The option "all" also lead to DropBaskets being called on the sub-branches.
718
720{
721 Bool_t all = kFALSE;
722 if (options && options[0]) {
723 TString opt = options;
724 opt.ToLower();
725 if (opt.Contains("all")) all = kTRUE;
726 }
727
728 TBasket *basket;
729 Int_t nbaskets = fBaskets.GetEntriesFast();
730
731 if ( (fNBaskets>1) || all ) {
732 //slow case
733 for (Int_t i=0;i<nbaskets;i++) {
734 basket = (TBasket*)fBaskets.UncheckedAt(i);
735 if (!basket) continue;
736 if ((i == fReadBasket || i == fWriteBasket) && !all) continue;
737 // if the basket is not yet on file but already has event in it
738 // we must continue to avoid dropping the basket (and thus losing data)
739 if (fBasketBytes[i]==0 && basket->GetNevBuf() > 0) continue;
740 basket->DropBuffers();
741 --fNBaskets;
743 if (basket == fCurrentBasket) {
744 fCurrentBasket = 0;
746 fNextBasketEntry = -1;
747 }
748 delete basket;
749 }
750
751 // process subbranches
752 if (all) {
754 Int_t nb = lb->GetEntriesFast();
755 for (Int_t j = 0; j < nb; j++) {
756 TBranch* branch = (TBranch*) lb->UncheckedAt(j);
757 if (!branch) continue;
758 branch->DropBaskets("all");
759 }
760 }
761 } else {
762 //fast case
763 if (nbaskets > 0) {
764 Int_t i = fBaskets.GetLast();
765 basket = (TBasket*)fBaskets.UncheckedAt(i);
766 if (basket && fBasketBytes[i]!=0) {
767 basket->DropBuffers();
768 if (basket == fCurrentBasket) {
769 fCurrentBasket = 0;
771 fNextBasketEntry = -1;
772 }
773 delete basket;
774 fBaskets.AddAt(0,i);
775 fBaskets.SetLast(-1);
776 fNBaskets = 0;
777 }
778 }
779 }
780
781}
782
783////////////////////////////////////////////////////////////////////////////////
784/// Increase BasketEntry buffer of a minimum of 10 locations
785/// and a maximum of 50 per cent of current size.
786
788{
789 Int_t newsize = TMath::Max(10,Int_t(1.5*fMaxBaskets));
792 newsize*sizeof(Long64_t),fMaxBaskets*sizeof(Long64_t));
794 newsize*sizeof(Long64_t),fMaxBaskets*sizeof(Long64_t));
795
796 fMaxBaskets = newsize;
797
798 fBaskets.Expand(newsize);
799
800 for (Int_t i=fWriteBasket;i<fMaxBaskets;i++) {
801 fBasketBytes[i] = 0;
802 fBasketEntry[i] = 0;
803 fBasketSeek[i] = 0;
804 }
805}
806
807////////////////////////////////////////////////////////////////////////////////
808/// Loop on all leaves of this branch to fill Basket buffer.
809///
810/// If TBranchIMTHelper is non-null and it is time to WriteBasket, then we will
811/// use TBB to compress in parallel.
812///
813/// The function returns the number of bytes committed to the memory basket.
814/// If a write error occurs, the number of bytes returned is -1.
815/// If no data are written, because e.g. the branch is disabled,
816/// the number of bytes returned is 0.
817
819{
820 if (TestBit(kDoNotProcess)) {
821 return 0;
822 }
823
825 if (!basket) {
826 basket = fTree->CreateBasket(this); // create a new basket
827 if (!basket) return 0;
828 ++fNBaskets;
830 }
831 TBuffer* buf = basket->GetBufferRef();
832
833 // Fill basket buffer.
834
835 Int_t nsize = 0;
836
837 if (buf->IsReading()) {
838 basket->SetWriteMode();
839 }
840
842 buf->ResetMap();
843 }
844
845 Int_t lnew = 0;
846 Int_t nbytes = 0;
847
848 if (fEntryBuffer) {
849 nbytes = FillEntryBuffer(basket,buf,lnew);
850 } else {
851 Int_t lold = buf->Length();
852 basket->Update(lold);
853 ++fEntries;
854 ++fEntryNumber;
855 (this->*fFillLeaves)(*buf);
856 if (buf->GetMapCount()) {
857 // The map is used.
859 }
860 lnew = buf->Length();
861 nbytes = lnew - lold;
862 }
863
864 if (fEntryOffsetLen) {
865 Int_t nevbuf = basket->GetNevBuf();
866 // Total size in bytes of EntryOffset table.
867 nsize = nevbuf * sizeof(Int_t);
868 } else {
869 if (!basket->GetNevBufSize()) {
870 basket->SetNevBufSize(nbytes);
871 }
872 }
873
874 // Should we create a new basket?
875 // fSkipZip force one entry per buffer (old stuff still maintained for CDF)
876 // Transfer full compressed buffer only
877
878 // If GetAutoFlush() is less than zero, then we are determining the end of the autocluster
879 // based upon the number of bytes already flushed. This is incompatible with one-basket-per-cluster
880 // (since we will grow the basket indefinitely and never flush!). Hence, we wait until the
881 // first event cluster is written out and *then* enable one-basket-per-cluster mode.
882 bool noFlushAtCluster = !fTree->TestBit(TTree::kOnlyFlushAtCluster) || (fTree->GetAutoFlush() < 0);
883
884 if (noFlushAtCluster && !fTree->TestBit(TTree::kCircular) &&
886 ((lnew + (2 * nsize) + nbytes) >= fBasketSize))) {
887 Int_t nout = WriteBasketImpl(basket, fWriteBasket, imtHelper);
888 if (nout < 0) Error("TBranch::Fill", "Failed to write out basket.\n");
889 return (nout >= 0) ? nbytes : -1;
890 }
891 return nbytes;
892}
893
894////////////////////////////////////////////////////////////////////////////////
895/// Copy the data from fEntryBuffer into the current basket.
896
898{
899 Int_t nbytes = 0;
900 Int_t objectStart = 0;
901 Int_t last = 0;
902 Int_t lold = buf->Length();
903
904 // Handle the special case of fEntryBuffer != 0
905 if (fEntryBuffer->IsA() == TMessage::Class()) {
906 objectStart = 8;
907 }
909 // The buffer given as input has not been decompressed.
910 if (basket->GetNevBuf()) {
911 // If the basket already contains entry we need to close it
912 // out. (This is because we can only transfer full compressed
913 // buffer)
915 // And restart from scratch
916 return Fill();
917 }
918 Int_t startpos = fEntryBuffer->Length();
920 static TBasket toread_fLast;
922 toread_fLast.Streamer(*fEntryBuffer);
924 last = toread_fLast.GetLast();
925 // last now contains the decompressed number of bytes.
926 fEntryBuffer->SetBufferOffset(startpos);
927 buf->SetBufferOffset(0);
929 basket->Update(lold);
930 } else {
931 // We are required to copy starting at the version number (so not
932 // including the class name.
933 // See if byte count is here, if not it class still be a newClass
934 const UInt_t kNewClassTag = 0xFFFFFFFF;
935 const UInt_t kByteCountMask = 0x40000000; // OR the byte count with this
936 UInt_t tag = 0;
937 UInt_t startpos = fEntryBuffer->Length();
938 fEntryBuffer->SetBufferOffset(objectStart);
939 *fEntryBuffer >> tag;
940 if (tag & kByteCountMask) {
941 *fEntryBuffer >> tag;
942 }
943 if (tag == kNewClassTag) {
944 UInt_t maxsize = 256;
945 char* s = new char[maxsize];
946 Int_t name_start = fEntryBuffer->Length();
947 fEntryBuffer->ReadString(s, maxsize); // Reads at most maxsize - 1 characters, plus null at end.
948 while (strlen(s) == (maxsize - 1)) {
949 // The classname is too large, try again with a large buffer.
950 fEntryBuffer->SetBufferOffset(name_start);
951 maxsize *= 2;
952 delete[] s;
953 s = new char[maxsize];
954 fEntryBuffer->ReadString(s, maxsize); // Reads at most maxsize - 1 characters, plus null at end
955 }
956 } else {
957 fEntryBuffer->SetBufferOffset(objectStart);
958 }
959 objectStart = fEntryBuffer->Length();
960 fEntryBuffer->SetBufferOffset(startpos);
961 basket->Update(lold, objectStart - fEntryBuffer->GetBufferDisplacement());
962 }
963 fEntries++;
964 fEntryNumber++;
965 UInt_t len = 0;
966 UInt_t startpos = fEntryBuffer->Length();
967 if (startpos > UInt_t(objectStart)) {
968 // We assume this buffer have just been directly filled
969 // the current position in the buffer indicates the end of the object!
970 len = fEntryBuffer->Length() - objectStart;
971 } else {
972 // The buffer have been acquired either via TSocket or via
973 // TBuffer::SetBuffer(newloc,newsize)
974 // Only the actual size of the memory buffer gives us an hint about where
975 // the object ends.
976 len = fEntryBuffer->BufferSize() - objectStart;
977 }
978 buf->WriteBuf(fEntryBuffer->Buffer() + objectStart, len);
980 // The original buffer came pre-compressed and thus the buffer Length
981 // does not really show the really object size
982 // lnew = nbytes = basket->GetLast();
983 nbytes = last;
984 lnew = last;
985 } else {
986 lnew = buf->Length();
987 nbytes = lnew - lold;
988 }
989
990 return nbytes;
991}
992
993////////////////////////////////////////////////////////////////////////////////
994/// Find the immediate sub-branch with passed name.
995
997{
998 // We allow the user to pass only the last dotted component of the name.
999 std::string longnm;
1000 longnm.reserve(fName.Length()+strlen(name)+3);
1001 longnm = fName.Data();
1002 if (longnm[longnm.length()-1]==']') {
1003 std::size_t dim = longnm.find_first_of("[");
1004 if (dim != std::string::npos) {
1005 longnm.erase(dim);
1006 }
1007 }
1008 if (longnm[longnm.length()-1] != '.') {
1009 longnm += '.';
1010 }
1011 longnm += name;
1012 UInt_t namelen = strlen(name);
1013
1014 Int_t nbranches = fBranches.GetEntries();
1015 TBranch* branch = 0;
1016 for(Int_t i = 0; i < nbranches; ++i) {
1017 branch = (TBranch*) fBranches.UncheckedAt(i);
1018
1019 const char *brname = branch->fName.Data();
1020 UInt_t brlen = branch->fName.Length();
1021 if (brname[brlen-1]==']') {
1022 const char *dim = strchr(brname,'[');
1023 if (dim) {
1024 brlen = dim - brname;
1025 }
1026 }
1027 if (namelen == brlen /* same effective size */
1028 && strncmp(name,brname,brlen) == 0) {
1029 return branch;
1030 }
1031 if (brlen == (size_t)longnm.length()
1032 && strncmp(longnm.c_str(),brname,brlen) == 0) {
1033 return branch;
1034 }
1035 }
1036 return 0;
1037}
1038
1039////////////////////////////////////////////////////////////////////////////////
1040/// Find the leaf corresponding to the name 'searchname'.
1041
1042TLeaf* TBranch::FindLeaf(const char* searchname)
1043{
1044 TString leafname;
1045 TString leaftitle;
1046 TString longname;
1047 TString longtitle;
1048
1049 // We allow the user to pass only the last dotted component of the name.
1050 TIter next(GetListOfLeaves());
1051 TLeaf* leaf = 0;
1052 while ((leaf = (TLeaf*) next())) {
1053 leafname = leaf->GetName();
1054 Ssiz_t dim = leafname.First('[');
1055 if (dim >= 0) leafname.Remove(dim);
1056
1057 if (leafname == searchname) return leaf;
1058
1059 // The leaf element contains the branch name in its name, let's use the title.
1060 leaftitle = leaf->GetTitle();
1061 dim = leaftitle.First('[');
1062 if (dim >= 0) leaftitle.Remove(dim);
1063
1064 if (leaftitle == searchname) return leaf;
1065
1066 TBranch* branch = leaf->GetBranch();
1067 if (branch) {
1068 longname.Form("%s.%s",branch->GetName(),leafname.Data());
1069 dim = longname.First('[');
1070 if (dim>=0) longname.Remove(dim);
1071 if (longname == searchname) return leaf;
1072
1073 // The leaf element contains the branch name in its name.
1074 longname.Form("%s.%s",branch->GetName(),searchname);
1075 if (longname==leafname) return leaf;
1076
1077 longtitle.Form("%s.%s",branch->GetName(),leaftitle.Data());
1078 dim = longtitle.First('[');
1079 if (dim>=0) longtitle.Remove(dim);
1080 if (longtitle == searchname) return leaf;
1081
1082 // The following is for the case where the branch is only
1083 // a sub-branch. Since we do not see it through
1084 // TTree::GetListOfBranches, we need to see it indirectly.
1085 // This is the less sturdy part of this search ... it may
1086 // need refining ...
1087 if (strstr(searchname, ".") && !strcmp(searchname, branch->GetName())) return leaf;
1088 }
1089 }
1090 return 0;
1091}
1092
1093////////////////////////////////////////////////////////////////////////////////
1094/// Flush to disk all the baskets of this branch and any of subbranches.
1095/// Return the number of bytes written or -1 in case of write error.
1096
1098{
1099 UInt_t nerror = 0;
1100 Int_t nbytes = 0;
1101
1102 Int_t maxbasket = fWriteBasket + 1;
1103 // The following protection is not necessary since we should always
1104 // have fWriteBasket < fBasket.GetSize()
1105 //if (fBaskets.GetSize() < maxbasket) {
1106 // maxbasket = fBaskets.GetSize();
1107 //}
1108 for(Int_t i=0; i != maxbasket; ++i) {
1109 if (fBaskets.UncheckedAt(i)) {
1110 Int_t nwrite = FlushOneBasket(i);
1111 if (nwrite<0) {
1112 ++nerror;
1113 } else {
1114 nbytes += nwrite;
1115 }
1116 }
1117 }
1119 for (Int_t i = 0; i < len; ++i) {
1120 TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
1121 if (!branch) {
1122 continue;
1123 }
1124 Int_t nwrite = branch->FlushBaskets();
1125 if (nwrite<0) {
1126 ++nerror;
1127 } else {
1128 nbytes += nwrite;
1129 }
1130 }
1131 if (nerror) {
1132 return -1;
1133 } else {
1134 return nbytes;
1135 }
1136}
1137
1138////////////////////////////////////////////////////////////////////////////////
1139/// If we have a write basket in memory and it contains some entries and
1140/// has not yet been written to disk, we write it and delete it from memory.
1141/// Return the number of bytes written;
1142
1144{
1145 Int_t nbytes = 0;
1146 if (fDirectory && fBaskets.GetEntries()) {
1147 TBasket *basket = (TBasket*)fBaskets.UncheckedAt(ibasket);
1148
1149 if (basket) {
1150 if (basket->GetNevBuf()
1151 && fBasketSeek[ibasket]==0) {
1152 // If the basket already contains entry we need to close it out.
1153 // (This is because we can only transfer full compressed buffer)
1154
1155 if (basket->GetBufferRef()->IsReading()) {
1156 basket->SetWriteMode();
1157 }
1158 nbytes = WriteBasket(basket,ibasket);
1159
1160 } else {
1161 // If the basket is empty or has already been written.
1162 if ((Int_t)ibasket==fWriteBasket) {
1163 // Nothing to do.
1164 } else {
1165 basket->DropBuffers();
1166 if (basket == fCurrentBasket) {
1167 fCurrentBasket = 0;
1168 fFirstBasketEntry = -1;
1169 fNextBasketEntry = -1;
1170 }
1171 delete basket;
1172 --fNBaskets;
1173 fBaskets[ibasket] = 0;
1174 }
1175 }
1176 }
1177 }
1178 return nbytes;
1179}
1180
1181////////////////////////////////////////////////////////////////////////////////
1182/// Return pointer to basket basketnumber in this Branch
1183
1185{
1186 // This counter in the sequential case collects errors coming also from
1187 // different files (suppose to have a program reading f1.root, f2.root ...)
1188 // In the mt case, it is made atomic: it safely collects errors from
1189 // different files processed simultaneously.
1190 static std::atomic<Int_t> nerrors(0);
1191
1192 // reference to an existing basket in memory ?
1193 if (basketnumber <0 || basketnumber > fWriteBasket) return 0;
1194 TBasket *basket = (TBasket*)fBaskets.UncheckedAt(basketnumber);
1195 if (basket) return basket;
1196 if (basketnumber == fWriteBasket) return 0;
1197
1198 // create/decode basket parameters from buffer
1199 TFile *file = GetFile(0);
1200 if (file == 0) {
1201 return 0;
1202 }
1203 // if cluster pre-fetching or retaining is on, do not re-use existing baskets
1204 // unless a new cluster is used.
1206 basket = GetFreshCluster();
1207 else
1208 basket = GetFreshBasket();
1209
1210 // fSkipZip is old stuff still maintained for CDF
1212 if (fBasketBytes[basketnumber] == 0) {
1213 fBasketBytes[basketnumber] = basket->ReadBasketBytes(fBasketSeek[basketnumber],file);
1214 }
1215 //add branch to cache (if any)
1216 {
1217 R__LOCKGUARD_IMT(gROOTMutex); // Lock for parallel TTree I/O
1219 if (pf){
1220 if (pf->IsLearning()) pf->LearnBranch(this, kFALSE);
1221 if (fSkipZip) pf->SetSkipZip();
1222 }
1223 }
1224
1225 //now read basket
1226 Int_t badread = basket->ReadBasketBuffers(fBasketSeek[basketnumber],fBasketBytes[basketnumber],file);
1227 if (R__unlikely(badread || basket->GetSeekKey() != fBasketSeek[basketnumber] || basket->IsZombie())) {
1228 nerrors++;
1229 if (nerrors > 10) return 0;
1230 if (nerrors == 10) {
1231 printf(" file probably overwritten: stopping reporting error messages\n");
1232 if (fBasketSeek[basketnumber] > 2000000000) {
1233 printf("===>File is more than 2 Gigabytes\n");
1234 return 0;
1235 }
1236 if (fBasketSeek[basketnumber] > 1000000000) {
1237 printf("===>Your file is may be bigger than the maximum file size allowed on your system\n");
1238 printf(" Check your AFS maximum file size limit for example\n");
1239 return 0;
1240 }
1241 }
1242 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);
1243 return 0;
1244 }
1245
1246 ++fNBaskets;
1247
1248 fCacheInfo.SetUsed(basketnumber);
1249 auto perfStats = GetTree()->GetPerfStats();
1250 if (perfStats)
1251 perfStats->SetUsed(this, basketnumber);
1252
1253 fBaskets.AddAt(basket,basketnumber);
1254 return basket;
1255}
1256
1257////////////////////////////////////////////////////////////////////////////////
1258/// Return address of basket in the file
1259
1261{
1262 if (basketnumber <0 || basketnumber > fWriteBasket) return 0;
1263 return fBasketSeek[basketnumber];
1264}
1265
1266////////////////////////////////////////////////////////////////////////////////
1267/// Returns (and, if 0, creates) browsable objects for this branch
1268/// See TVirtualBranchBrowsable::FillListOfBrowsables.
1269
1271 if (fBrowsables) return fBrowsables;
1272 fBrowsables=new TList();
1274 return fBrowsables;
1275}
1276
1277////////////////////////////////////////////////////////////////////////////////
1278/// Return the name of the user class whose content is stored in this branch,
1279/// if any. If this branch was created using the 'leaflist' technique, this
1280/// function returns an empty string.
1281
1282const char * TBranch::GetClassName() const
1283{
1284 return "";
1285}
1286
1287////////////////////////////////////////////////////////////////////////////////
1288/// Return icon name depending on type of branch.
1289
1290const char* TBranch::GetIconName() const
1291{
1292 if (IsFolder())
1293 return "TBranchElement-folder";
1294 else
1295 return "TBranchElement-leaf";
1296}
1297
1298////////////////////////////////////////////////////////////////////////////////
1299/// Read all leaves of entry and return total number of bytes read.
1300///
1301/// The input argument "entry" is the entry number in the current tree.
1302/// In case of a TChain, the entry number in the current Tree must be found
1303/// before calling this function. For example:
1304///
1305///~~~ {.cpp}
1306/// TChain* chain = ...;
1307/// Long64_t localEntry = chain->LoadTree(entry);
1308/// branch->GetEntry(localEntry);
1309///~~~
1310///
1311/// The function returns the number of bytes read from the input buffer.
1312/// If entry does not exist, the function returns 0.
1313/// If an I/O error occurs, the function returns -1.
1314///
1315/// See IMPORTANT REMARKS in TTree::GetEntry.
1316
1318{
1319 // Remember which entry we are reading.
1320 fReadEntry = entry;
1321
1322 Bool_t enabled = !TestBit(kDoNotProcess) || getall;
1323 TBasket *basket; // will be initialized in the if/then clauses.
1325 if (R__likely(enabled && fFirstBasketEntry <= entry && entry < fNextBasketEntry)) {
1326 // We have found the basket containing this entry.
1327 // make sure basket buffers are in memory.
1328 basket = fCurrentBasket;
1330 } else {
1331 if (!enabled) {
1332 return 0;
1333 }
1334 if ((entry < fFirstEntry) || (entry >= fEntryNumber)) {
1335 return 0;
1336 }
1338 Long64_t last = fNextBasketEntry - 1;
1339 // Are we still in the same ReadBasket?
1340 if ((entry < first) || (entry > last)) {
1342 if (fReadBasket < 0) {
1343 fNextBasketEntry = -1;
1344 Error("In the branch %s, no basket contains the entry %d\n", GetName(), entry);
1345 return -1;
1346 }
1347 if (fReadBasket == fWriteBasket) {
1349 } else {
1351 }
1353 }
1354 // We have found the basket containing this entry.
1355 // make sure basket buffers are in memory.
1357 if (!basket) {
1358 basket = GetBasket(fReadBasket);
1359 if (!basket) {
1360 fCurrentBasket = 0;
1361 fFirstBasketEntry = -1;
1362 fNextBasketEntry = -1;
1363 return -1;
1364 }
1365 if (fTree->GetClusterPrefetch()) {
1366 TTree::TClusterIterator clusterIterator = fTree->GetClusterIterator(entry);
1367 clusterIterator.Next();
1368 Int_t nextClusterEntry = clusterIterator.GetNextEntry();
1369 for (Int_t i = fReadBasket + 1; i < fMaxBaskets && fBasketEntry[i] < nextClusterEntry; i++) {
1370 GetBasket(i);
1371 }
1372 }
1373 }
1374 fCurrentBasket = basket;
1375 }
1376 basket->PrepareBasket(entry);
1377 TBuffer* buf = basket->GetBufferRef();
1378
1379 // This test necessary to read very old Root files (NvE).
1380 if (R__unlikely(!buf)) {
1381 TFile* file = GetFile(0);
1382 if (!file) return -1;
1384 buf = basket->GetBufferRef();
1385 }
1386 // Set entry offset in buffer.
1388 buf->ResetMap();
1389 }
1390 if (R__unlikely(!buf->IsReading())) {
1391 basket->SetReadMode();
1392 }
1393 Int_t* entryOffset = basket->GetEntryOffset();
1394 Int_t bufbegin = 0;
1395 if (entryOffset) {
1396 bufbegin = entryOffset[entry-first];
1397 buf->SetBufferOffset(bufbegin);
1398 Int_t* displacement = basket->GetDisplacement();
1399 if (R__unlikely(displacement)) {
1400 buf->SetBufferDisplacement(displacement[entry-first]);
1401 }
1402 } else {
1403 bufbegin = basket->GetKeylen() + ((entry-first) * basket->GetNevBufSize());
1404 buf->SetBufferOffset(bufbegin);
1405 }
1406
1407 // Int_t bufbegin = buf->Length();
1408 (this->*fReadLeaves)(*buf);
1409 return buf->Length() - bufbegin;
1410}
1411
1412////////////////////////////////////////////////////////////////////////////////
1413/// Read all leaves of an entry and export buffers to real objects in a TClonesArray list.
1414///
1415/// Returns total number of bytes read.
1416
1418{
1419 // Remember which entry we are reading.
1420 fReadEntry = entry;
1421
1422 if (TestBit(kDoNotProcess)) {
1423 return 0;
1424 }
1425 if ((entry < 0) || (entry >= fEntryNumber)) {
1426 return 0;
1427 }
1428 Int_t nbytes = 0;
1430 Long64_t last = fNextBasketEntry - 1;
1431 // Are we still in the same ReadBasket?
1432 if ((entry < first) || (entry > last)) {
1434 if (fReadBasket < 0) {
1435 fNextBasketEntry = -1;
1436 Error("In the branch %s, no basket contains the entry %d\n", GetName(), entry);
1437 return -1;
1438 }
1439 if (fReadBasket == fWriteBasket) {
1441 } else {
1443 }
1445 }
1446
1447 // We have found the basket containing this entry.
1448 // Make sure basket buffers are in memory.
1449 TBasket* basket = GetBasket(fReadBasket);
1450 fCurrentBasket = basket;
1451 if (!basket) {
1452 fFirstBasketEntry = -1;
1453 fNextBasketEntry = -1;
1454 return 0;
1455 }
1456 TBuffer* buf = basket->GetBufferRef();
1457 // Set entry offset in buffer and read data from all leaves.
1459 buf->ResetMap();
1460 }
1461 if (R__unlikely(!buf->IsReading())) {
1462 basket->SetReadMode();
1463 }
1464 Int_t* entryOffset = basket->GetEntryOffset();
1465 Int_t bufbegin = 0;
1466 if (entryOffset) {
1467 bufbegin = entryOffset[entry-first];
1468 buf->SetBufferOffset(bufbegin);
1469 Int_t* displacement = basket->GetDisplacement();
1470 if (R__unlikely(displacement)) {
1471 buf->SetBufferDisplacement(displacement[entry-first]);
1472 }
1473 } else {
1474 bufbegin = basket->GetKeylen() + ((entry-first) * basket->GetNevBufSize());
1475 buf->SetBufferOffset(bufbegin);
1476 }
1477 TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(0);
1478 leaf->ReadBasketExport(*buf, li, nentries);
1479 nbytes = buf->Length() - bufbegin;
1480 return nbytes;
1481}
1482
1483////////////////////////////////////////////////////////////////////////////////
1484/// Fill expectedClass and expectedType with information on the data type of the
1485/// object/values contained in this branch (and thus the type of pointers
1486/// expected to be passed to Set[Branch]Address
1487/// return 0 in case of success and > 0 in case of failure.
1488
1489Int_t TBranch::GetExpectedType(TClass *&expectedClass,EDataType &expectedType)
1490{
1491 expectedClass = 0;
1492 expectedType = kOther_t;
1493 TLeaf* l = (TLeaf*) GetListOfLeaves()->At(0);
1494 if (l) {
1495 expectedType = (EDataType) gROOT->GetType(l->GetTypeName())->GetType();
1496 return 0;
1497 } else {
1498 Error("GetExpectedType", "Did not find any leaves in %s",GetName());
1499 return 1;
1500 }
1501}
1502
1503////////////////////////////////////////////////////////////////////////////////
1504/// Return pointer to the file where branch buffers reside, returns 0
1505/// in case branch buffers reside in the same file as tree header.
1506/// If mode is 1 the branch buffer file is recreated.
1507
1509{
1510 if (fDirectory) return fDirectory->GetFile();
1511
1512 // check if a file with this name is in the list of Root files
1513 TFile *file = 0;
1514 {
1516 file = (TFile*)gROOT->GetListOfFiles()->FindObject(fFileName.Data());
1517 if (file) {
1518 fDirectory = file;
1519 return file;
1520 }
1521 }
1522
1523 if (fFileName.Length() == 0) return 0;
1524
1525 TString bFileName( GetRealFileName() );
1526
1527 // Open file (new file if mode = 1)
1528 {
1530 if (mode) file = TFile::Open(bFileName, "recreate");
1531 else file = TFile::Open(bFileName);
1532 }
1533 if (!file) return 0;
1534 if (file->IsZombie()) {delete file; return 0;}
1536 return file;
1537}
1538
1539////////////////////////////////////////////////////////////////////////////////
1540/// Return a fresh basket by either resusing an existing basket that needs
1541/// to be drop (according to TTree::MemoryFull) or create a new one.
1542
1544{
1545 TBasket *basket = 0;
1546 if (GetTree()->MemoryFull(0)) {
1547 if (fNBaskets==1) {
1548 // Steal the existing basket
1549 Int_t oldindex = fBaskets.GetLast();
1550 basket = (TBasket*)fBaskets.UncheckedAt(oldindex);
1551 if (!basket) {
1552 fBaskets.SetLast(-2); // For recalculation of Last.
1553 oldindex = fBaskets.GetLast();
1554 basket = (TBasket*)fBaskets.UncheckedAt(oldindex);
1555 }
1556 if (basket && fBasketBytes[oldindex]!=0) {
1557 if (basket == fCurrentBasket) {
1558 fCurrentBasket = 0;
1559 fFirstBasketEntry = -1;
1560 fNextBasketEntry = -1;
1561 }
1562 fBaskets.AddAt(0,oldindex);
1563 fBaskets.SetLast(-1);
1564 fNBaskets = 0;
1565 } else {
1566 basket = fTree->CreateBasket(this);
1567 }
1568 } else if (fNBaskets == 0) {
1569 // There is nothing to drop!
1570 basket = fTree->CreateBasket(this);
1571 } else {
1572 // Memory is full and there is more than one basket,
1573 // Let DropBaskets do it job.
1574 DropBaskets();
1575 basket = fTree->CreateBasket(this);
1576 }
1577 } else {
1578 basket = fTree->CreateBasket(this);
1579 }
1580 return basket;
1581}
1582
1583////////////////////////////////////////////////////////////////////////////////
1584/// Drops the cluster two behind the current cluster and returns a fresh basket
1585/// by either reusing or creating a new one
1586
1588{
1589 TBasket *basket = 0;
1590
1591 // If GetClusterIterator is called with a negative entry then GetStartEntry will be 0
1592 // So we need to check if we reach the zero before we have gone back (1-VirtualSize) clusters
1593 // if this is the case, we want to keep everything in memory so we return a new basket
1595 if (iter.GetStartEntry() == 0) {
1596 return fTree->CreateBasket(this);
1597 }
1598
1599 // Iterate backwards (1-VirtualSize) clusters to reach cluster to be unloaded from memory,
1600 // skipped if VirtualSize > 0.
1601 for (Int_t j = 0; j < -fTree->GetMaxVirtualSize(); j++) {
1602 if (iter.Previous() == 0) {
1603 return fTree->CreateBasket(this);
1604 }
1605 }
1606
1607 Int_t entryToUnload = iter.Previous();
1608 // Finds the basket to unload from memory. Since the basket should be close to current
1609 // basket, just iterate backwards until the correct basket is reached. This should
1610 // be fast as long as the number of baskets per cluster is small
1611 Int_t basketToUnload = fReadBasket;
1612 while (fBasketEntry[basketToUnload] != entryToUnload) {
1613 basketToUnload--;
1614 if (basketToUnload < 0) {
1615 return fTree->CreateBasket(this);
1616 }
1617 }
1618
1619 // Retrieves the basket that is going to be unloaded from memory. If the basket did not
1620 // exist, create a new one
1621 basket = (TBasket *)fBaskets.UncheckedAt(basketToUnload);
1622 if (basket) {
1623 fBaskets.AddAt(0, basketToUnload);
1624 --fNBaskets;
1625 } else {
1626 basket = fTree->CreateBasket(this);
1627 }
1628 ++basketToUnload;
1629
1630 // Clear the rest of the baskets. While it would be ideal to reuse these baskets
1631 // for other baskets in the new cluster. It would require the function to go
1632 // beyond its current scope. In the ideal case when each cluster only has 1 basket
1633 // this will perform well
1634 iter.Next();
1635 while (fBasketEntry[basketToUnload] < iter.GetStartEntry()) {
1636 TBasket *oldbasket = (TBasket *)fBaskets.UncheckedAt(basketToUnload);
1637 if (oldbasket) {
1638 oldbasket->DropBuffers();
1639 delete oldbasket;
1640 fBaskets.AddAt(0, basketToUnload);
1641 --fNBaskets;
1642 }
1643 ++basketToUnload;
1644 }
1645 fBaskets.SetLast(-1);
1646 return basket;
1647}
1648
1649////////////////////////////////////////////////////////////////////////////////
1650/// Return pointer to the 1st Leaf named name in thisBranch
1651
1652TLeaf* TBranch::GetLeaf(const char* name) const
1653{
1654 Int_t i;
1655 for (i=0;i<fNleaves;i++) {
1656 TLeaf *leaf = (TLeaf*)fLeaves.UncheckedAt(i);
1657 if (!strcmp(leaf->GetName(),name)) return leaf;
1658 }
1659 return 0;
1660}
1661
1662////////////////////////////////////////////////////////////////////////////////
1663/// Get real file name
1664
1666{
1667 if (fFileName.Length()==0) {
1668 return fFileName;
1669 }
1670 TString bFileName = fFileName;
1671
1672 // check if branch file name is absolute or a URL (e.g. /castor/...,
1673 // root://host/..., rfio:/path/...)
1674 char *bname = gSystem->ExpandPathName(fFileName.Data());
1675 if (!gSystem->IsAbsoluteFileName(bname) && !strstr(bname, ":/") && fTree && fTree->GetCurrentFile()) {
1676
1677 // if not, get filename where tree header is stored
1678 const char *tfn = fTree->GetCurrentFile()->GetName();
1679
1680 // If it is an archive file we need a special treatment
1681 TUrl arc(tfn);
1682 if (strlen(arc.GetAnchor()) > 0) {
1684 bFileName = arc.GetUrl();
1685 } else {
1686 // if this is an absolute path or a URL then prepend this path
1687 // to the branch file name
1688 char *tname = gSystem->ExpandPathName(tfn);
1689 if (gSystem->IsAbsoluteFileName(tname) || strstr(tname, ":/")) {
1690 bFileName = gSystem->DirName(tname);
1691 bFileName += "/";
1692 bFileName += fFileName;
1693 }
1694 delete [] tname;
1695 }
1696 }
1697 delete [] bname;
1698
1699 return bFileName;
1700}
1701
1702////////////////////////////////////////////////////////////////////////////////
1703/// Return all elements of one row unpacked in internal array fValues
1704/// [Actually just returns 1 (?)]
1705
1707{
1708 return 1;
1709}
1710
1711////////////////////////////////////////////////////////////////////////////////
1712/// Return whether this branch is in a mode where the object are decomposed
1713/// or not (Also known as MakeClass mode).
1714
1716{
1717 // Regular TBranch and TBrancObject can not be in makeClass mode
1718
1719 return kFALSE;
1720}
1721
1722////////////////////////////////////////////////////////////////////////////////
1723/// Get our top-level parent branch in the tree.
1724
1726{
1727 if (fMother) return fMother;
1728
1729 const TObjArray* array = fTree->GetListOfBranches();
1730 Int_t n = array->GetEntriesFast();
1731 for (Int_t i = 0; i < n; ++i) {
1732 TBranch* branch = (TBranch*) array->UncheckedAt(i);
1733 TBranch* parent = branch->GetSubBranch(this);
1734 if (parent) {
1735 const_cast<TBranch*>(this)->fMother = branch; // We can not yet use the 'mutable' keyword
1736 return branch;
1737 }
1738 }
1739 return 0;
1740}
1741
1742////////////////////////////////////////////////////////////////////////////////
1743/// Find the parent branch of child.
1744/// Return 0 if child is not in this branch hierarchy.
1745
1747{
1748 // Handle error condition, if the parameter is us, we cannot find the parent.
1749 if (this == child) {
1750 // Note: We cast away any const-ness of "this".
1751 return (TBranch*) this;
1752 }
1753
1754 if (child->fParent) {
1755 return child->fParent;
1756 }
1757
1759 for (Int_t i = 0; i < len; ++i) {
1760 TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
1761 if (!branch) {
1762 continue;
1763 }
1764 if (branch == child) {
1765 // We are the direct parent of child.
1766 const_cast<TBranch*>(child)->fParent = (TBranch*)this; // We can not yet use the 'mutable' keyword
1767 // Note: We cast away any const-ness of "this".
1768 const_cast<TBranch*>(child)->fParent = (TBranch*)this; // We can not yet use the 'mutable' keyword
1769 return (TBranch*) this;
1770 }
1771 // FIXME: This is a tail-recursion!
1772 TBranch* parent = branch->GetSubBranch(child);
1773 if (parent) {
1774 return parent;
1775 }
1776 }
1777 // We failed to find the parent.
1778 return 0;
1779}
1780
1781////////////////////////////////////////////////////////////////////////////////
1782/// Return total number of bytes in the branch (including current buffer)
1783
1785{
1787 // This intentionally only store the TBranch part and thus slightly
1788 // under-estimate the space used.
1789 // Since the TBranchElement part contains pointers to other branches (branch count),
1790 // doing regular Streaming would end up including those and thus greatly over-estimate
1791 // the size used.
1792 const_cast<TBranch *>(this)->TBranch::Streamer(b);
1793
1794 Long64_t totbytes = 0;
1795 if (fZipBytes > 0) totbytes = fTotBytes;
1796 return totbytes + b.Length();
1797}
1798
1799////////////////////////////////////////////////////////////////////////////////
1800/// Return total number of bytes in the branch (excluding current buffer)
1801/// if option ="*" includes all sub-branches of this branch too
1802
1804{
1805 Long64_t totbytes = fTotBytes;
1806 if (!option) return totbytes;
1807 if (option[0] != '*') return totbytes;
1808 //scan sub-branches
1810 for (Int_t i = 0; i < len; ++i) {
1811 TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
1812 if (branch) totbytes += branch->GetTotBytes(option);
1813 }
1814 return totbytes;
1815}
1816
1817////////////////////////////////////////////////////////////////////////////////
1818/// Return total number of zip bytes in the branch
1819/// if option ="*" includes all sub-branches of this branch too
1820
1822{
1823 Long64_t zipbytes = fZipBytes;
1824 if (!option) return zipbytes;
1825 if (option[0] != '*') return zipbytes;
1826 //scan sub-branches
1828 for (Int_t i = 0; i < len; ++i) {
1829 TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
1830 if (branch) zipbytes += branch->GetZipBytes(option);
1831 }
1832 return zipbytes;
1833}
1834
1835////////////////////////////////////////////////////////////////////////////////
1836/// Returns the IO settings currently in use for this branch.
1837
1839{
1840 return fIOFeatures;
1841}
1842
1843////////////////////////////////////////////////////////////////////////////////
1844/// Return kTRUE if an existing object in a TBranchObject must be deleted.
1845
1847{
1848 return TestBit(kAutoDelete);
1849}
1850
1851////////////////////////////////////////////////////////////////////////////////
1852/// Return kTRUE if more than one leaf or browsables, kFALSE otherwise.
1853
1855{
1856 if (fNleaves > 1) {
1857 return kTRUE;
1858 }
1859 TList* browsables = const_cast<TBranch*>(this)->GetBrowsables();
1860 return browsables && browsables->GetSize();
1861}
1862
1863////////////////////////////////////////////////////////////////////////////////
1864/// keep a maximum of fMaxEntries in memory
1865
1867{
1868 Int_t dentries = (Int_t) (fEntries - maxEntries);
1869 TBasket* basket = (TBasket*) fBaskets.UncheckedAt(0);
1870 if (basket) basket->MoveEntries(dentries);
1871 fEntries = maxEntries;
1872 fEntryNumber = maxEntries;
1873 //loop on sub branches
1875 for (Int_t i = 0; i < nb; ++i) {
1876 TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
1877 branch->KeepCircular(maxEntries);
1878 }
1879}
1880
1881////////////////////////////////////////////////////////////////////////////////
1882/// Baskets associated to this branch are forced to be in memory.
1883/// You can call TTree::SetMaxVirtualSize(maxmemory) to instruct
1884/// the system that the total size of the imported baskets does not
1885/// exceed maxmemory bytes.
1886///
1887/// The function returns the number of baskets that have been put in memory.
1888/// This method may be called to force all baskets of one or more branches
1889/// in memory when random access to entries in this branch is required.
1890/// See also TTree::LoadBaskets to load all baskets of all branches in memory.
1891
1893{
1894 Int_t nimported = 0;
1895 Int_t nbaskets = fWriteBasket;
1896 TFile *file = GetFile(0);
1897 if (!file) return 0;
1898 TBasket *basket;
1899 for (Int_t i=0;i<nbaskets;i++) {
1900 basket = (TBasket*)fBaskets.UncheckedAt(i);
1901 if (basket) continue;
1902 basket = GetFreshBasket();
1903 if (fBasketBytes[i] == 0) {
1905 }
1906 Int_t badread = basket->ReadBasketBuffers(fBasketSeek[i],fBasketBytes[i],file);
1907 if (badread) {
1908 Error("Loadbaskets","Error while reading basket buffer %d of branch %s",i,GetName());
1909 return -1;
1910 }
1911 ++fNBaskets;
1912 fBaskets.AddAt(basket,i);
1913 nimported++;
1914 }
1915 return nimported;
1916}
1917
1918////////////////////////////////////////////////////////////////////////////////
1919/// Print TBranch parameters
1920///
1921/// If options contains "basketsInfo" print the entry number, location and size
1922/// of each baskets.
1923
1924void TBranch::Print(Option_t *option) const
1925{
1926 const int kLINEND = 77;
1927 Float_t cx = 1;
1928
1929 TString titleContent(GetTitle());
1930 if ( titleContent == GetName() ) {
1931 titleContent.Clear();
1932 }
1933
1934 if (fLeaves.GetEntries() == 1) {
1935 if (titleContent.Length()>=2 && titleContent[titleContent.Length()-2]=='/' && isalpha(titleContent[titleContent.Length()-1])) {
1936 // The type is already encoded. Nothing to do.
1937 } else {
1938 TLeaf *leaf = (TLeaf*)fLeaves.UncheckedAt(0);
1939 if (titleContent.Length()) {
1940 titleContent.Prepend(" ");
1941 }
1942 // titleContent.Append("type: ");
1943 titleContent.Prepend(leaf->GetTypeName());
1944 }
1945 }
1946 Int_t titleLength = titleContent.Length();
1947
1948 Int_t aLength = titleLength + strlen(GetName());
1949 aLength += (aLength / 54 + 1) * 80 + 100;
1950 if (aLength < 200) aLength = 200;
1951 char *bline = new char[aLength];
1952
1953 Long64_t totBytes = GetTotalSize();
1954 if (fZipBytes) cx = (fTotBytes+0.00001)/fZipBytes;
1955 if (titleLength) snprintf(bline,aLength,"*Br%5d :%-9s : %-54s *",fgCount,GetName(),titleContent.Data());
1956 else snprintf(bline,aLength,"*Br%5d :%-9s : %-54s *",fgCount,GetName()," ");
1957 if (strlen(bline) > UInt_t(kLINEND)) {
1958 char *tmp = new char[strlen(bline)+1];
1959 if (titleLength) strlcpy(tmp, titleContent.Data(),strlen(bline)+1);
1960 snprintf(bline,aLength,"*Br%5d :%-9s : ",fgCount,GetName());
1961 int pos = strlen (bline);
1962 int npos = pos;
1963 int beg=0, end;
1964 while (beg < titleLength) {
1965 for (end=beg+1; end < titleLength-1; end ++)
1966 if (tmp[end] == ':') break;
1967 if (npos + end-beg+1 >= 78) {
1968 while (npos < kLINEND) {
1969 bline[pos ++] = ' ';
1970 npos ++;
1971 }
1972 bline[pos ++] = '*';
1973 bline[pos ++] = '\n';
1974 bline[pos ++] = '*';
1975 npos = 1;
1976 for (; npos < 12; npos ++)
1977 bline[pos ++] = ' ';
1978 bline[pos-2] = '|';
1979 }
1980 for (int n = beg; n <= end; n ++)
1981 bline[pos+n-beg] = tmp[n];
1982 pos += end-beg+1;
1983 npos += end-beg+1;
1984 beg = end+1;
1985 }
1986 while (npos < kLINEND) {
1987 bline[pos ++] = ' ';
1988 npos ++;
1989 }
1990 bline[pos ++] = '*';
1991 bline[pos] = '\0';
1992 delete[] tmp;
1993 }
1994 Printf("%s", bline);
1995
1996 if (fTotBytes > 2000000000) {
1997 Printf("*Entries :%lld : Total Size=%11lld bytes File Size = %lld *",fEntries,totBytes,fZipBytes);
1998 } else {
1999 if (fZipBytes > 0) {
2000 Printf("*Entries :%9lld : Total Size=%11lld bytes File Size = %10lld *",fEntries,totBytes,fZipBytes);
2001 } else {
2002 if (fWriteBasket > 0) {
2003 Printf("*Entries :%9lld : Total Size=%11lld bytes All baskets in memory *",fEntries,totBytes);
2004 } else {
2005 Printf("*Entries :%9lld : Total Size=%11lld bytes One basket in memory *",fEntries,totBytes);
2006 }
2007 }
2008 }
2009 Printf("*Baskets :%9d : Basket Size=%11d bytes Compression= %6.2f *",fWriteBasket,fBasketSize,cx);
2010
2011 if (strncmp(option,"basketsInfo",strlen("basketsInfo"))==0) {
2012 Int_t nbaskets = fWriteBasket;
2013 for (Int_t i=0;i<nbaskets;i++) {
2014 Printf("*Basket #%4d entry=%6lld pos=%6lld size=%5d",
2015 i, fBasketEntry[i], fBasketSeek[i], fBasketBytes[i]);
2016 }
2017 }
2018
2019 Printf("*............................................................................*");
2020 delete [] bline;
2021 fgCount++;
2022}
2023
2024////////////////////////////////////////////////////////////////////////////////
2025/// Print the information we have about which basket is currently cached and
2026/// whether they have been 'used'/'read' from the cache.
2027
2029{
2031}
2032
2033////////////////////////////////////////////////////////////////////////////////
2034/// Loop on all leaves of this branch to read Basket buffer.
2035
2037{
2038 // fLeaves->ReadBasket(basket);
2039}
2040
2041////////////////////////////////////////////////////////////////////////////////
2042/// Loop on all leaves of this branch to read Basket buffer.
2043
2045{
2046 for (Int_t i = 0; i < fNleaves; ++i) {
2047 TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
2048 leaf->ReadBasket(b);
2049 }
2050}
2051
2052////////////////////////////////////////////////////////////////////////////////
2053/// Read zero leaves without the overhead of a loop.
2054
2056{
2057}
2058
2059////////////////////////////////////////////////////////////////////////////////
2060/// Read one leaf without the overhead of a loop.
2061
2063{
2065}
2066
2067////////////////////////////////////////////////////////////////////////////////
2068/// Read two leaves without the overhead of a loop.
2069
2071{
2074}
2075
2076////////////////////////////////////////////////////////////////////////////////
2077/// Loop on all leaves of this branch to fill Basket buffer.
2078
2080{
2081 for (Int_t i = 0; i < fNleaves; ++i) {
2082 TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
2083 leaf->FillBasket(b);
2084 }
2085}
2086
2087////////////////////////////////////////////////////////////////////////////////
2088/// Refresh this branch using new information in b
2089/// This function is called by TTree::Refresh
2090
2092{
2093 if (b==0) return;
2094
2095 fEntryOffsetLen = b->fEntryOffsetLen;
2096 fWriteBasket = b->fWriteBasket;
2097 fEntryNumber = b->fEntryNumber;
2098 fMaxBaskets = b->fMaxBaskets;
2099 fEntries = b->fEntries;
2100 fTotBytes = b->fTotBytes;
2101 fZipBytes = b->fZipBytes;
2102 fReadBasket = 0;
2103 fReadEntry = -1;
2104 fFirstBasketEntry = -1;
2105 fNextBasketEntry = -1;
2106 fCurrentBasket = 0;
2107 delete [] fBasketBytes;
2108 delete [] fBasketEntry;
2109 delete [] fBasketSeek;
2113 Int_t i;
2114 for (i=0;i<fMaxBaskets;i++) {
2115 fBasketBytes[i] = b->fBasketBytes[i];
2116 fBasketEntry[i] = b->fBasketEntry[i];
2117 fBasketSeek[i] = b->fBasketSeek[i];
2118 }
2119 fBaskets.Delete();
2120 Int_t nbaskets = b->fBaskets.GetSize();
2121 fBaskets.Expand(nbaskets);
2122 // If the current fWritebasket is in memory, take it (just swap)
2123 // from the Tree being read
2124 TBasket *basket = (TBasket*)b->fBaskets.UncheckedAt(fWriteBasket);
2125 fBaskets.AddAt(basket,fWriteBasket);
2126 if (basket) {
2127 fNBaskets = 1;
2128 --(b->fNBaskets);
2129 b->fBaskets.RemoveAt(fWriteBasket);
2130 basket->SetBranch(this);
2131 }
2132}
2133
2134////////////////////////////////////////////////////////////////////////////////
2135/// Reset a Branch.
2136///
2137/// - Existing buffers are deleted.
2138/// - Entries, max and min are reset.
2139
2141{
2142 fReadBasket = 0;
2143 fReadEntry = -1;
2144 fFirstBasketEntry = -1;
2145 fNextBasketEntry = -1;
2146 fCurrentBasket = 0;
2147 fWriteBasket = 0;
2148 fEntries = 0;
2149 fTotBytes = 0;
2150 fZipBytes = 0;
2151 fEntryNumber = 0;
2152
2153 if (fBasketBytes) {
2154 for (Int_t i = 0; i < fMaxBaskets; ++i) {
2155 fBasketBytes[i] = 0;
2156 }
2157 }
2158
2159 if (fBasketEntry) {
2160 for (Int_t i = 0; i < fMaxBaskets; ++i) {
2161 fBasketEntry[i] = 0;
2162 }
2163 }
2164
2165 if (fBasketSeek) {
2166 for (Int_t i = 0; i < fMaxBaskets; ++i) {
2167 fBasketSeek[i] = 0;
2168 }
2169 }
2170
2171 fBaskets.Delete();
2172 fNBaskets = 0;
2173}
2174
2175////////////////////////////////////////////////////////////////////////////////
2176/// Reset a Branch.
2177///
2178/// - Existing buffers are deleted.
2179/// - Entries, max and min are reset.
2180
2182{
2183 fReadBasket = 0;
2184 fReadEntry = -1;
2185 fFirstBasketEntry = -1;
2186 fNextBasketEntry = -1;
2187 fCurrentBasket = 0;
2188 fWriteBasket = 0;
2189 fEntries = 0;
2190 fTotBytes = 0;
2191 fZipBytes = 0;
2192 fEntryNumber = 0;
2193
2194 if (fBasketBytes) {
2195 for (Int_t i = 0; i < fMaxBaskets; ++i) {
2196 fBasketBytes[i] = 0;
2197 }
2198 }
2199
2200 if (fBasketEntry) {
2201 for (Int_t i = 0; i < fMaxBaskets; ++i) {
2202 fBasketEntry[i] = 0;
2203 }
2204 }
2205
2206 if (fBasketSeek) {
2207 for (Int_t i = 0; i < fMaxBaskets; ++i) {
2208 fBasketSeek[i] = 0;
2209 }
2210 }
2211
2212 TBasket *reusebasket = (TBasket*)fBaskets[fWriteBasket];
2213 if (reusebasket) {
2215 } else {
2216 reusebasket = (TBasket*)fBaskets[fReadBasket];
2217 if (reusebasket) {
2218 fBaskets[fReadBasket] = 0;
2219 }
2220 }
2221 fBaskets.Delete();
2222 if (reusebasket) {
2223 fNBaskets = 1;
2224 reusebasket->Reset();
2225 fBaskets[0] = reusebasket;
2226 } else {
2227 fNBaskets = 0;
2228 }
2229}
2230
2231////////////////////////////////////////////////////////////////////////////////
2232/// Reset the address of the branch.
2233
2235{
2236 fAddress = 0;
2237
2238 // Reset last read entry number, we have will had new user object now.
2239 fReadEntry = -1;
2240
2241 for (Int_t i = 0; i < fNleaves; ++i) {
2242 TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
2243 leaf->SetAddress(0);
2244 }
2245
2246 Int_t nbranches = fBranches.GetEntriesFast();
2247 for (Int_t i = 0; i < nbranches; ++i) {
2248 TBranch* abranch = (TBranch*) fBranches[i];
2249 // FIXME: This is a tail recursion.
2250 abranch->ResetAddress();
2251 }
2252}
2253
2254////////////////////////////////////////////////////////////////////////////////
2255/// Static function resetting fgCount
2256
2258{
2259 fgCount = 0;
2260}
2261
2262////////////////////////////////////////////////////////////////////////////////
2263/// Set address of this branch.
2264
2265void TBranch::SetAddress(void* addr)
2266{
2267 if (TestBit(kDoNotProcess)) {
2268 return;
2269 }
2270 fReadEntry = -1;
2271 fFirstBasketEntry = -1;
2272 fNextBasketEntry = -1;
2273 fAddress = (char*) addr;
2274 for (Int_t i = 0; i < fNleaves; ++i) {
2275 TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
2276 Int_t offset = leaf->GetOffset();
2277 if (TestBit(kIsClone)) {
2278 offset = 0;
2279 }
2280 if (fAddress) leaf->SetAddress(fAddress + offset);
2281 else leaf->SetAddress(0);
2282 }
2283}
2284
2285////////////////////////////////////////////////////////////////////////////////
2286/// Set the automatic delete bit.
2287///
2288/// This bit is used by TBranchObject::ReadBasket to decide if an object
2289/// referenced by a TBranchObject must be deleted or not before reading
2290/// a new entry.
2291///
2292/// If autodel is kTRUE, this existing object will be deleted, a new object
2293/// created by the default constructor, then read from disk by the streamer.
2294///
2295/// If autodel is kFALSE, the existing object is not deleted. Root assumes
2296/// that the user is taking care of deleting any internal object or array
2297/// (this can be done in the streamer).
2298
2300{
2301 if (autodel) {
2302 SetBit(kAutoDelete, 1);
2303 } else {
2304 SetBit(kAutoDelete, 0);
2305 }
2306}
2307
2308////////////////////////////////////////////////////////////////////////////////
2309/// Set the basket size
2310/// The function makes sure that the basket size is greater than fEntryOffsetlen
2311
2313{
2314 Int_t minsize = 100 + fName.Length();
2315 if (buffsize < minsize+fEntryOffsetLen) buffsize = minsize+fEntryOffsetLen;
2316 fBasketSize = buffsize;
2317 TBasket *basket = (TBasket*)fBaskets[fWriteBasket];
2318 if (basket) {
2319 basket->AdjustSize(fBasketSize);
2320 }
2321}
2322
2323////////////////////////////////////////////////////////////////////////////////
2324/// Set address of this branch directly from a TBuffer to avoid streaming.
2325///
2326/// Note: We do not take ownership of the buffer.
2327
2329{
2330 // Check this is possible
2331 if ( (fNleaves != 1)
2332 || (strcmp("TLeafObject",fLeaves.UncheckedAt(0)->ClassName())!=0) ) {
2333 Error("TBranch::SetAddress","Filling from a TBuffer can only be done with a not split object branch. Request ignored.");
2334 } else {
2335 fReadEntry = -1;
2336 fNextBasketEntry = -1;
2337 fFirstBasketEntry = -1;
2338 // Note: We do not take ownership of the buffer.
2339 fEntryBuffer = buf;
2340 }
2341}
2342
2343////////////////////////////////////////////////////////////////////////////////
2344/// Set compression algorithm.
2345
2347{
2348 if (algorithm < 0 || algorithm >= ROOT::RCompressionSetting::EAlgorithm::kUndefined) algorithm = 0;
2349 if (fCompress < 0) {
2351 } else {
2352 int level = fCompress % 100;
2353 fCompress = 100 * algorithm + level;
2354 }
2355
2357 for (Int_t i=0;i<nb;i++) {
2358 TBranch *branch = (TBranch*)fBranches.UncheckedAt(i);
2359 branch->SetCompressionAlgorithm(algorithm);
2360 }
2361}
2362
2363////////////////////////////////////////////////////////////////////////////////
2364/// Set compression level.
2365
2367{
2368 if (level < 0) level = 0;
2369 if (level > 99) level = 99;
2370 if (fCompress < 0) {
2371 fCompress = level;
2372 } else {
2373 int algorithm = fCompress / 100;
2374 if (algorithm >= ROOT::RCompressionSetting::EAlgorithm::kUndefined) algorithm = 0;
2375 fCompress = 100 * algorithm + level;
2376 }
2377
2379 for (Int_t i=0;i<nb;i++) {
2380 TBranch *branch = (TBranch*)fBranches.UncheckedAt(i);
2381 branch->SetCompressionLevel(level);
2382 }
2383}
2384
2385////////////////////////////////////////////////////////////////////////////////
2386/// Set compression settings.
2387
2389{
2390 fCompress = settings;
2391
2393 for (Int_t i=0;i<nb;i++) {
2394 TBranch *branch = (TBranch*)fBranches.UncheckedAt(i);
2395 branch->SetCompressionSettings(settings);
2396 }
2397}
2398
2399////////////////////////////////////////////////////////////////////////////////
2400/// Update the default value for the branch's fEntryOffsetLen if and only if
2401/// it was already non zero (and the new value is not zero)
2402/// If updateExisting is true, also update all the existing branches.
2403
2404void TBranch::SetEntryOffsetLen(Int_t newdefault, Bool_t updateExisting)
2405{
2406 if (fEntryOffsetLen && newdefault) {
2407 fEntryOffsetLen = newdefault;
2408 }
2409 if (updateExisting) {
2410 TIter next( GetListOfBranches() );
2411 TBranch *b;
2412 while ( ( b = (TBranch*)next() ) ) {
2413 b->SetEntryOffsetLen( newdefault, kTRUE );
2414 }
2415 }
2416}
2417
2418////////////////////////////////////////////////////////////////////////////////
2419/// Set the number of entries in this branch.
2420
2422{
2423 fEntries = entries;
2424 fEntryNumber = entries;
2425}
2426
2427////////////////////////////////////////////////////////////////////////////////
2428/// Set file where this branch writes/reads its buffers.
2429/// By default the branch buffers reside in the file where the
2430/// Tree was created.
2431/// If the file name where the tree was created is an absolute
2432/// path name or an URL (e.g. /castor/... or root://host/...)
2433/// and if the fname is not an absolute path name or an URL then
2434/// the path of the tree file is prepended to fname to make the
2435/// branch file relative to the tree file. In this case one can
2436/// move the tree + all branch files to a different location in
2437/// the file system and still access the branch files.
2438/// The ROOT file will be connected only when necessary.
2439/// If called by TBranch::Fill (via TBasket::WriteFile), the file
2440/// will be created with the option "recreate".
2441/// If called by TBranch::GetEntry (via TBranch::GetBasket), the file
2442/// will be opened in read mode.
2443/// To open a file in "update" mode or with a certain compression
2444/// level, use TBranch::SetFile(TFile *file).
2445
2447{
2448 if (file == 0) file = fTree->GetCurrentFile();
2450 if (file == fTree->GetCurrentFile()) fFileName = "";
2451 else fFileName = file->GetName();
2452
2453 if (file && fCompress == -1) {
2454 fCompress = file->GetCompressionLevel();
2455 }
2456
2457 // Apply to all existing baskets.
2458 TIter nextb(GetListOfBaskets());
2459 TBasket *basket;
2460 while ((basket = (TBasket*)nextb())) {
2461 basket->SetParent(file);
2462 }
2463
2464 // Apply to sub-branches as well.
2465 TIter next(GetListOfBranches());
2466 TBranch *branch;
2467 while ((branch = (TBranch*)next())) {
2468 branch->SetFile(file);
2469 }
2470}
2471
2472////////////////////////////////////////////////////////////////////////////////
2473/// Set file where this branch writes/reads its buffers.
2474/// By default the branch buffers reside in the file where the
2475/// Tree was created.
2476/// If the file name where the tree was created is an absolute
2477/// path name or an URL (e.g. /castor/... or root://host/...)
2478/// and if the fname is not an absolute path name or an URL then
2479/// the path of the tree file is prepended to fname to make the
2480/// branch file relative to the tree file. In this case one can
2481/// move the tree + all branch files to a different location in
2482/// the file system and still access the branch files.
2483/// The ROOT file will be connected only when necessary.
2484/// If called by TBranch::Fill (via TBasket::WriteFile), the file
2485/// will be created with the option "recreate".
2486/// If called by TBranch::GetEntry (via TBranch::GetBasket), the file
2487/// will be opened in read mode.
2488/// To open a file in "update" mode or with a certain compression
2489/// level, use TBranch::SetFile(TFile *file).
2490
2491void TBranch::SetFile(const char* fname)
2492{
2493 fFileName = fname;
2494 fDirectory = 0;
2495
2496 //apply to sub-branches as well
2497 TIter next(GetListOfBranches());
2498 TBranch *branch;
2499 while ((branch = (TBranch*)next())) {
2500 branch->SetFile(fname);
2501 }
2502}
2503
2504////////////////////////////////////////////////////////////////////////////////
2505/// Set the branch in a mode where the object are decomposed
2506/// (Also known as MakeClass mode).
2507/// Return whether the setting was possible (it is not possible for
2508/// TBranch and TBranchObject).
2509
2511{
2512 // Regular TBranch and TBrancObject can not be in makeClass mode
2513 return kFALSE;
2514}
2515
2516////////////////////////////////////////////////////////////////////////////////
2517/// Set object this branch is pointing to.
2518
2519void TBranch::SetObject(void * /* obj */)
2520{
2521 if (TestBit(kDoNotProcess)) {
2522 return;
2523 }
2524 Warning("SetObject","is not supported in TBranch objects");
2525}
2526
2527////////////////////////////////////////////////////////////////////////////////
2528/// Set branch status to Process or DoNotProcess.
2529
2531{
2532 if (status) ResetBit(kDoNotProcess);
2533 else SetBit(kDoNotProcess);
2534}
2535
2536////////////////////////////////////////////////////////////////////////////////
2537/// Stream a class object
2538
2539void TBranch::Streamer(TBuffer& b)
2540{
2541 if (b.IsReading()) {
2542 UInt_t R__s, R__c;
2543 fTree = 0; // Will be set by TTree::Streamer
2544 fAddress = 0;
2545 gROOT->SetReadingObject(kTRUE);
2546
2547 // Reset transients.
2549 fCurrentBasket = 0;
2550 fFirstBasketEntry = -1;
2551 fNextBasketEntry = -1;
2552
2553 Version_t v = b.ReadVersion(&R__s, &R__c);
2554 if (v > 9) {
2555 b.ReadClassBuffer(TBranch::Class(), this, v, R__s, R__c);
2556
2557 if (fWriteBasket>=fBaskets.GetSize()) {
2559 }
2560 fDirectory = 0;
2562 for (Int_t i=0;i<fNleaves;i++) {
2563 TLeaf *leaf = (TLeaf*)fLeaves.UncheckedAt(i);
2564 leaf->SetBranch(this);
2565 }
2566
2568 for (Int_t j=fWriteBasket,n=0;j>=0 && n<fNBaskets;--j) {
2570 if (bk) {
2571 bk->SetBranch(this);
2572 // GetTree()->IncrementTotalBuffers(bk->GetBufferSize());
2573 ++n;
2574 }
2575 }
2576 if (fWriteBasket >= fMaxBaskets) {
2577 //old versions may need this fix
2582
2583 }
2585 gROOT->SetReadingObject(kFALSE);
2586 if (IsA() == TBranch::Class()) {
2587 if (fNleaves == 0) {
2589 } else if (fNleaves == 1) {
2591 } else if (fNleaves == 2) {
2593 } else {
2595 }
2596 }
2597 return;
2598 }
2599 //====process old versions before automatic schema evolution
2600 Int_t n,i,j,ijunk;
2601 if (v > 5) {
2602 Stat_t djunk;
2603 TNamed::Streamer(b);
2604 if (v > 7) TAttFill::Streamer(b);
2605 b >> fCompress;
2606 b >> fBasketSize;
2607 b >> fEntryOffsetLen;
2608 b >> fWriteBasket;
2609 b >> ijunk; fEntryNumber = (Long64_t)ijunk;
2610 b >> fOffset;
2611 b >> fMaxBaskets;
2612 if (v > 6) b >> fSplitLevel;
2613 b >> djunk; fEntries = (Long64_t)djunk;
2614 b >> djunk; fTotBytes = (Long64_t)djunk;
2615 b >> djunk; fZipBytes = (Long64_t)djunk;
2616
2617 fBranches.Streamer(b);
2618 fLeaves.Streamer(b);
2619 fBaskets.Streamer(b);
2623 Char_t isArray;
2624 b >> isArray;
2625 b.ReadFastArray(fBasketBytes,fMaxBaskets);
2626 b >> isArray;
2627 for (i=0;i<fMaxBaskets;i++) {b >> ijunk; fBasketEntry[i] = ijunk;}
2628 b >> isArray;
2629 for (i=0;i<fMaxBaskets;i++) {
2630 if (isArray == 2) b >> fBasketSeek[i];
2631 else {Int_t bsize; b >> bsize; fBasketSeek[i] = (Long64_t)bsize;};
2632 }
2633 fFileName.Streamer(b);
2634 b.CheckByteCount(R__s, R__c, TBranch::IsA());
2635 fDirectory = 0;
2637 for (i=0;i<fNleaves;i++) {
2638 TLeaf *leaf = (TLeaf*)fLeaves.UncheckedAt(i);
2639 leaf->SetBranch(this);
2640 }
2642 for (j=fWriteBasket,n=0;j>=0 && n<fNBaskets;--j) {
2644 if (bk) {
2645 bk->SetBranch(this);
2646 //GetTree()->IncrementTotalBuffers(bk->GetBufferSize());
2647 ++n;
2648 }
2649 }
2650 if (fWriteBasket >= fMaxBaskets) {
2651 //old versions may need this fix
2656
2657 }
2658 // Check Byte Count is not needed since it was done in ReadBuffer
2660 gROOT->SetReadingObject(kFALSE);
2661 b.CheckByteCount(R__s, R__c, TBranch::IsA());
2662 if (IsA() == TBranch::Class()) {
2663 if (fNleaves == 0) {
2665 } else if (fNleaves == 1) {
2667 } else if (fNleaves == 2) {
2669 } else {
2671 }
2672 }
2673 return;
2674 }
2675 //====process very old versions
2676 Stat_t djunk;
2677 TNamed::Streamer(b);
2678 b >> fCompress;
2679 b >> fBasketSize;
2680 b >> fEntryOffsetLen;
2681 b >> fMaxBaskets;
2682 b >> fWriteBasket;
2683 b >> ijunk; fEntryNumber = (Long64_t)ijunk;
2684 b >> djunk; fEntries = (Long64_t)djunk;
2685 b >> djunk; fTotBytes = (Long64_t)djunk;
2686 b >> djunk; fZipBytes = (Long64_t)djunk;
2687 b >> fOffset;
2688 fBranches.Streamer(b);
2689 fLeaves.Streamer(b);
2691 for (i=0;i<fNleaves;i++) {
2692 TLeaf *leaf = (TLeaf*)fLeaves.UncheckedAt(i);
2693 leaf->SetBranch(this);
2694 }
2695 fBaskets.Streamer(b);
2696 Int_t nbaskets = fBaskets.GetEntries();
2697 for (j=fWriteBasket,n=0;j>0 && n<nbaskets;--j) {
2699 if (bk) {
2700 bk->SetBranch(this);
2701 //GetTree()->IncrementTotalBuffers(bk->GetBufferSize());
2702 ++n;
2703 }
2704 }
2706 b >> n;
2707 for (i=0;i<n;i++) {b >> ijunk; fBasketEntry[i] = ijunk;}
2709 if (v > 4) {
2710 n = b.ReadArray(fBasketBytes);
2711 } else {
2712 for (n=0;n<fMaxBaskets;n++) fBasketBytes[n] = 0;
2713 }
2714 if (v < 2) {
2716 for (n=0;n<fWriteBasket;n++) {
2717 TBasket *basket = GetBasket(n);
2718 fBasketSeek[n] = basket ? basket->GetSeekKey() : 0;
2719 }
2720 } else {
2722 b >> n;
2723 for (n=0;n<fMaxBaskets;n++) {
2724 Int_t aseek;
2725 b >> aseek;
2726 fBasketSeek[n] = Long64_t(aseek);
2727 }
2728 }
2729 if (v > 2) {
2730 fFileName.Streamer(b);
2731 }
2732 fDirectory = 0;
2733 if (v < 4) SetAutoDelete(kTRUE);
2735 gROOT->SetReadingObject(kFALSE);
2736 b.CheckByteCount(R__s, R__c, TBranch::IsA());
2737 //====end of old versions
2738 if (IsA() == TBranch::Class()) {
2739 if (fNleaves == 0) {
2741 } else if (fNleaves == 1) {
2743 } else if (fNleaves == 2) {
2745 } else {
2747 }
2748 }
2749 } else {
2750 Int_t maxBaskets = fMaxBaskets;
2752 Int_t lastBasket = fMaxBaskets;
2753 if (fMaxBaskets < 10) fMaxBaskets = 10;
2754
2755 TBasket **stash = new TBasket *[lastBasket];
2756 for (Int_t i = 0; i < lastBasket; ++i) {
2757 TBasket *ba = (TBasket *)fBaskets.UncheckedAt(i);
2758 if (ba && (fBasketBytes[i] || ba->GetNevBuf()==0)) {
2759 // Already on disk or empty.
2760 stash[i] = ba;
2761 fBaskets[i] = nullptr;
2762 } else {
2763 stash[i] = nullptr;
2764 }
2765 }
2766
2767 b.WriteClassBuffer(TBranch::Class(), this);
2768
2769 for (Int_t i = 0; i < lastBasket; ++i) {
2770 if (stash[i]) fBaskets[i] = stash[i];
2771 }
2772
2773 delete[] stash;
2774 fMaxBaskets = maxBaskets;
2775 }
2776}
2777
2778////////////////////////////////////////////////////////////////////////////////
2779/// Write the current basket to disk and return the number of bytes
2780/// written to the file.
2781
2783{
2784 Int_t nevbuf = basket->GetNevBuf();
2785 if (fEntryOffsetLen > 10 && (4*nevbuf) < fEntryOffsetLen ) {
2786 // Make sure that the fEntryOffset array does not stay large unnecessarily.
2787 fEntryOffsetLen = nevbuf < 3 ? 10 : 4*nevbuf; // assume some fluctuations.
2788 } else if (fEntryOffsetLen && nevbuf > fEntryOffsetLen) {
2789 // Increase the array ...
2790 fEntryOffsetLen = 2*nevbuf; // assume some fluctuations.
2791 }
2792
2793 // Note: captures `basket`, `where`, and `this` by value; modifies the TBranch and basket,
2794 // as we make a copy of the pointer. We cannot capture `basket` by reference as the pointer
2795 // itself might be modified after `WriteBasketImpl` exits.
2796 auto doUpdates = [=]() {
2797 Int_t nout = basket->WriteBuffer(); // Write buffer
2798 if (nout < 0) Error("TBranch::WriteBasketImpl", "basket's WriteBuffer failed.\n");
2799 fBasketBytes[where] = basket->GetNbytes();
2800 fBasketSeek[where] = basket->GetSeekKey();
2801 Int_t addbytes = basket->GetObjlen() + basket->GetKeylen();
2802 TBasket *reusebasket = 0;
2803 if (nout>0) {
2804 // The Basket was written so we can now safely reuse it.
2805 fBaskets[where] = 0;
2806
2807 reusebasket = basket;
2808 reusebasket->Reset();
2809
2810 fZipBytes += nout;
2811 fTotBytes += addbytes;
2812 fTree->AddTotBytes(addbytes);
2813 fTree->AddZipBytes(nout);
2814#ifdef R__TRACK_BASKET_ALLOC_TIME
2815 fTree->AddAllocationTime(reusebasket->GetResetAllocationTime());
2816#endif
2818 }
2819
2820 if (where==fWriteBasket) {
2821 ++fWriteBasket;
2822 if (fWriteBasket >= fMaxBaskets) {
2824 }
2825 if (reusebasket && reusebasket == fCurrentBasket) {
2826 // The 'current' basket has Reset, so if we need it we will need
2827 // to reload it.
2828 fCurrentBasket = 0;
2829 fFirstBasketEntry = -1;
2830 fNextBasketEntry = -1;
2831 }
2834 } else {
2835 --fNBaskets;
2836 fBaskets[where] = 0;
2837 basket->DropBuffers();
2838 if (basket == fCurrentBasket) {
2839 fCurrentBasket = 0;
2840 fFirstBasketEntry = -1;
2841 fNextBasketEntry = -1;
2842 }
2843 delete basket;
2844 }
2845 return nout;
2846 };
2847 if (imtHelper) {
2848 imtHelper->Run(doUpdates);
2849 return 0;
2850 } else {
2851 return doUpdates();
2852 }
2853}
2854
2855////////////////////////////////////////////////////////////////////////////////
2856///set the first entry number (case of TBranchSTL)
2857
2859{
2860 fFirstEntry = entry;
2861 fEntries = 0;
2862 fEntryNumber = entry;
2863 if( fBasketEntry )
2864 fBasketEntry[0] = entry;
2865 for( Int_t i = 0; i < fBranches.GetEntriesFast(); ++i )
2866 ((TBranch*)fBranches[i])->SetFirstEntry( entry );
2867}
2868
2869////////////////////////////////////////////////////////////////////////////////
2870/// If the branch address is not set, we set all addresses starting with
2871/// the top level parent branch.
2872
2874{
2875 // Nothing to do for regular branch, the TLeaf already did it.
2876}
2877
2878////////////////////////////////////////////////////////////////////////////////
2879/// Refresh the value of fDirectory (i.e. where this branch writes/reads its buffers)
2880/// with the current value of fTree->GetCurrentFile unless this branch has been
2881/// redirected to a different file. Also update the sub-branches.
2882
2884{
2886 if (fFileName.Length() == 0) {
2887 fDirectory = file;
2888
2889 // Apply to all existing baskets.
2890 TIter nextb(GetListOfBaskets());
2891 TBasket *basket;
2892 while ((basket = (TBasket*)nextb())) {
2893 basket->SetParent(file);
2894 }
2895 }
2896
2897 // Apply to sub-branches as well.
2898 TIter next(GetListOfBranches());
2899 TBranch *branch;
2900 while ((branch = (TBranch*)next())) {
2901 branch->UpdateFile();
2902 }
2903}
void Class()
Definition: Class.C:29
SVector< double, 2 > v
Definition: Dict.h:5
#define R__likely(expr)
Definition: RConfig.hxx:579
#define R__unlikely(expr)
Definition: RConfig.hxx:578
#define b(i)
Definition: RSha256.hxx:100
const Ssiz_t kNPOS
Definition: RtypesCore.h:111
int Int_t
Definition: RtypesCore.h:41
short Version_t
Definition: RtypesCore.h:61
int Ssiz_t
Definition: RtypesCore.h:63
char Char_t
Definition: RtypesCore.h:29
unsigned int UInt_t
Definition: RtypesCore.h:42
const Bool_t kFALSE
Definition: RtypesCore.h:88
bool Bool_t
Definition: RtypesCore.h:59
double Stat_t
Definition: RtypesCore.h:73
long long Long64_t
Definition: RtypesCore.h:69
float Float_t
Definition: RtypesCore.h:53
const Bool_t kTRUE
Definition: RtypesCore.h:87
const char Option_t
Definition: RtypesCore.h:62
#define ClassImp(name)
Definition: Rtypes.h:363
const UInt_t kNewClassTag
Definition: TBufferFile.cxx:49
const UInt_t kByteCountMask
Definition: TBufferFile.cxx:51
EDataType
Definition: TDataType.h:28
@ kOther_t
Definition: TDataType.h:32
#define Printf
Definition: TGeoToOCC.h:18
int nentries
Definition: THbookFile.cxx:89
R__EXTERN TVirtualMutex * gROOTMutex
Definition: TROOT.h:57
#define gROOT
Definition: TROOT.h:410
R__EXTERN TSystem * gSystem
Definition: TSystem.h:540
#define R__LOCKGUARD_IMT(mutex)
#define R__LOCKGUARD(mutex)
#define gPad
Definition: TVirtualPad.h:286
#define snprintf
Definition: civetweb.c:1540
void SetUsed(Int_t basketNumber)
void Print(const char *owner, Long64_t *entries) const
TIOFeatures provides the end-user with the ability to change the IO behavior of data written via a TT...
Definition: TIOFeatures.hxx:62
Fill Area Attributes class.
Definition: TAttFill.h:19
Manages buffers for branches of a Tree.
Definition: TBasket.h:34
virtual void Reset()
Reset the basket to the starting state.
Definition: TBasket.cxx:707
Int_t GetNevBufSize() const
Definition: TBasket.h:123
Int_t * GetEntryOffset()
Definition: TBasket.h:117
Int_t * GetDisplacement() const
Definition: TBasket.h:116
Int_t GetNevBuf() const
Definition: TBasket.h:122
void SetBranch(TBranch *branch)
Definition: TBasket.h:141
Int_t ReadBasketBuffers(Long64_t pos, Int_t len, TFile *file)
Read basket buffers in memory and cleanup.
Definition: TBasket.cxx:460
virtual Int_t DropBuffers()
Drop buffers of this basket if it is not the current basket.
Definition: TBasket.cxx:169
virtual void PrepareBasket(Long64_t)
Definition: TBasket.h:126
virtual void MoveEntries(Int_t dentries)
Remove the first dentries of this basket, moving entries at dentries to the start of the buffer.
Definition: TBasket.cxx:306
void SetNevBufSize(Int_t n)
Definition: TBasket.h:142
Int_t GetBufferSize() const
Definition: TBasket.h:115
virtual void AdjustSize(Int_t newsize)
Increase the size of the current fBuffer up to newsize.
Definition: TBasket.cxx:123
virtual void SetReadMode()
Set read mode of basket.
Definition: TBasket.cxx:826
virtual void SetWriteMode()
Set write mode of basket.
Definition: TBasket.cxx:835
Bool_t GetResetAllocationCount() const
Definition: TBasket.h:136
Int_t ReadBasketBytes(Long64_t pos, TFile *file)
Read basket buffers in memory and cleanup.
Definition: TBasket.cxx:692
virtual Int_t WriteBuffer()
Write buffer of this basket on the current file.
Definition: TBasket.cxx:1032
Int_t GetLast() const
Definition: TBasket.h:124
void Update(Int_t newlast)
Definition: TBasket.h:145
A TTree is a list of TBranches.
Definition: TBranch.h:64
virtual TLeaf * GetLeaf(const char *name) const
Return pointer to the 1st Leaf named name in thisBranch.
Definition: TBranch.cxx:1652
virtual void SetupAddresses()
If the branch address is not set, we set all addresses starting with the top level parent branch.
Definition: TBranch.cxx:2873
virtual void ResetAddress()
Reset the address of the branch.
Definition: TBranch.cxx:2234
virtual void SetAutoDelete(Bool_t autodel=kTRUE)
Set the automatic delete bit.
Definition: TBranch.cxx:2299
TString fFileName
Name of file where buffers are stored ("" if in same file as Tree header)
Definition: TBranch.h:116
virtual const char * GetClassName() const
Return the name of the user class whose content is stored in this branch, if any.
Definition: TBranch.cxx:1282
const char * GetIconName() const
Return icon name depending on type of branch.
Definition: TBranch.cxx:1290
Int_t fEntryOffsetLen
Initial Length of fEntryOffset table in the basket buffers.
Definition: TBranch.h:87
virtual void DeleteBaskets(Option_t *option="")
Loop on all branch baskets.
Definition: TBranch.cxx:688
virtual Long64_t GetBasketSeek(Int_t basket) const
Return address of basket in the file.
Definition: TBranch.cxx:1260
TBranch()
Default constructor. Used for I/O by default.
Definition: TBranch.cxx:81
Int_t BackFill()
Loop on all leaves of this branch to back fill Basket buffer.
Definition: TBranch.cxx:642
Int_t fMaxBaskets
Maximum number of Baskets so far.
Definition: TBranch.h:92
Long64_t fTotBytes
Total number of bytes in all leaves before compression.
Definition: TBranch.h:103
TBuffer * fTransientBuffer
! Pointer to the current transient buffer.
Definition: TBranch.h:118
virtual void ReadBasket(TBuffer &b)
Loop on all leaves of this branch to read Basket buffer.
Definition: TBranch.cxx:2036
TTree * GetTree() const
Definition: TBranch.h:209
FillLeaves_t fFillLeaves
! Pointer to the FillLeaves implementation to use.
Definition: TBranch.h:129
@ kAutoDelete
Definition: TBranch.h:79
@ kDoNotUseBufferMap
Definition: TBranch.h:81
@ kIsClone
Definition: TBranch.h:75
@ kDoNotProcess
Definition: TBranch.h:74
TObjArray fLeaves
-> List of leaves of this branch
Definition: TBranch.h:106
char * fAddress
! Address of 1st leaf (variable or object)
Definition: TBranch.h:114
virtual void DropBaskets(Option_t *option="")
Loop on all branch baskets.
Definition: TBranch.cxx:719
TObjArray * GetListOfBranches()
Definition: TBranch.h:203
virtual TList * GetBrowsables()
Returns (and, if 0, creates) browsable objects for this branch See TVirtualBranchBrowsable::FillListO...
Definition: TBranch.cxx:1270
TList * fBrowsables
! List of TVirtualBranchBrowsables used for Browse()
Definition: TBranch.h:119
void ReadLeavesImpl(TBuffer &b)
Loop on all leaves of this branch to read Basket buffer.
Definition: TBranch.cxx:2044
Int_t fOffset
Offset of this branch.
Definition: TBranch.h:91
Long64_t * fBasketEntry
[fMaxBaskets] Table of first entry in each basket
Definition: TBranch.h:109
virtual void SetEntryOffsetLen(Int_t len, Bool_t updateSubBranches=kFALSE)
Update the default value for the branch's fEntryOffsetLen if and only if it was already non zero (and...
Definition: TBranch.cxx:2404
void ExpandBasketArrays()
Increase BasketEntry buffer of a minimum of 10 locations and a maximum of 50 per cent of current size...
Definition: TBranch.cxx:787
void Init(const char *name, const char *leaflist, Int_t compress)
Definition: TBranch.cxx:281
virtual Int_t GetEntry(Long64_t entry=0, Int_t getall=0)
Read all leaves of entry and return total number of bytes read.
Definition: TBranch.cxx:1317
TIOFeatures GetIOFeatures() const
Returns the IO settings currently in use for this branch.
Definition: TBranch.cxx:1838
void FillLeavesImpl(TBuffer &b)
Loop on all leaves of this branch to fill Basket buffer.
Definition: TBranch.cxx:2079
Long64_t fReadEntry
! Current entry number when reading
Definition: TBranch.h:97
virtual void AddBasket(TBasket &b, Bool_t ondisk, Long64_t startEntry)
Add the basket to this branch.
Definition: TBranch.cxx:518
static void ResetCount()
Static function resetting fgCount.
Definition: TBranch.cxx:2257
TBranch * GetSubBranch(const TBranch *br) const
Find the parent branch of child.
Definition: TBranch.cxx:1746
ReadLeaves_t fReadLeaves
! Pointer to the ReadLeaves implementation to use.
Definition: TBranch.h:127
virtual void SetObject(void *objadd)
Set object this branch is pointing to.
Definition: TBranch.cxx:2519
Int_t FlushBaskets()
Flush to disk all the baskets of this branch and any of subbranches.
Definition: TBranch.cxx:1097
void ReadLeaves2Impl(TBuffer &b)
Read two leaves without the overhead of a loop.
Definition: TBranch.cxx:2070
TBasket * GetFreshCluster()
Drops the cluster two behind the current cluster and returns a fresh basket by either reusing or crea...
Definition: TBranch.cxx:1587
virtual void SetAddress(void *add)
Set address of this branch.
Definition: TBranch.cxx:2265
static Int_t fgCount
! branch counter
Definition: TBranch.h:84
virtual void AddLastBasket(Long64_t startEntry)
Add the start entry of the write basket (not yet created)
Definition: TBranch.cxx:584
TBasket * GetBasket(Int_t basket)
Return pointer to basket basketnumber in this Branch.
Definition: TBranch.cxx:1184
Int_t fNBaskets
! Number of baskets in memory
Definition: TBranch.h:93
void ReadLeaves1Impl(TBuffer &b)
Read one leaf without the overhead of a loop.
Definition: TBranch.cxx:2062
Bool_t IsFolder() const
Return kTRUE if more than one leaf or browsables, kFALSE otherwise.
Definition: TBranch.cxx:1854
virtual Int_t GetEntryExport(Long64_t entry, Int_t getall, TClonesArray *list, Int_t n)
Read all leaves of an entry and export buffers to real objects in a TClonesArray list.
Definition: TBranch.cxx:1417
Long64_t fZipBytes
Total number of bytes in all leaves after compression.
Definition: TBranch.h:104
TIOFeatures fIOFeatures
IO features for newly-created baskets.
Definition: TBranch.h:90
void SetCompressionAlgorithm(Int_t algorithm=ROOT::RCompressionSetting::EAlgorithm::kUseGlobal)
Set compression algorithm.
Definition: TBranch.cxx:2346
Bool_t IsAutoDelete() const
Return kTRUE if an existing object in a TBranchObject must be deleted.
Definition: TBranch.cxx:1846
virtual TLeaf * FindLeaf(const char *name)
Find the leaf corresponding to the name 'searchname'.
Definition: TBranch.cxx:1042
CacheInfo_t fCacheInfo
! Hold info about which basket are in the cache and if they have been retrieved from the cache.
Definition: TBranch.h:124
TObjArray * GetListOfBaskets()
Definition: TBranch.h:202
virtual void SetBufferAddress(TBuffer *entryBuffer)
Set address of this branch directly from a TBuffer to avoid streaming.
Definition: TBranch.cxx:2328
Long64_t GetEntries() const
Definition: TBranch.h:208
Int_t fNleaves
! Number of leaves
Definition: TBranch.h:95
Int_t fSplitLevel
Branch split level.
Definition: TBranch.h:94
Int_t WriteBasketImpl(TBasket *basket, Int_t where, ROOT::Internal::TBranchIMTHelper *)
Write the current basket to disk and return the number of bytes written to the file.
Definition: TBranch.cxx:2782
TBasket * GetFreshBasket()
Return a fresh basket by either resusing an existing basket that needs to be drop (according to TTree...
Definition: TBranch.cxx:1543
virtual void UpdateFile()
Refresh the value of fDirectory (i.e.
Definition: TBranch.cxx:2883
void SetCompressionSettings(Int_t settings=ROOT::RCompressionSetting::EDefaults::kUseGeneralPurpose)
Set compression settings.
Definition: TBranch.cxx:2388
Int_t * fBasketBytes
[fMaxBaskets] Length of baskets on file
Definition: TBranch.h:108
virtual void Print(Option_t *option="") const
Print TBranch parameters.
Definition: TBranch.cxx:1924
Long64_t fNextBasketEntry
! Next entry that will requires us to go to the next basket
Definition: TBranch.h:99
virtual ~TBranch()
Destructor.
Definition: TBranch.cxx:425
Int_t FillEntryBuffer(TBasket *basket, TBuffer *buf, Int_t &lnew)
Copy the data from fEntryBuffer into the current basket.
Definition: TBranch.cxx:897
virtual TFile * GetFile(Int_t mode=0)
Return pointer to the file where branch buffers reside, returns 0 in case branch buffers reside in th...
Definition: TBranch.cxx:1508
virtual void Browse(TBrowser *b)
Browser interface.
Definition: TBranch.cxx:661
TObjArray fBranches
-> List of Branches of this branch
Definition: TBranch.h:105
virtual void KeepCircular(Long64_t maxEntries)
keep a maximum of fMaxEntries in memory
Definition: TBranch.cxx:1866
virtual void ResetAfterMerge(TFileMergeInfo *)
Reset a Branch.
Definition: TBranch.cxx:2181
void ReadLeaves0Impl(TBuffer &b)
Read zero leaves without the overhead of a loop.
Definition: TBranch.cxx:2055
virtual Bool_t GetMakeClass() const
Return whether this branch is in a mode where the object are decomposed or not (Also known as MakeCla...
Definition: TBranch.cxx:1715
TString GetRealFileName() const
Get real file name.
Definition: TBranch.cxx:1665
virtual TBranch * FindBranch(const char *name)
Find the immediate sub-branch with passed name.
Definition: TBranch.cxx:996
TDirectory * fDirectory
! Pointer to directory where this branch buffers are stored
Definition: TBranch.h:115
void PrintCacheInfo() const
Print the information we have about which basket is currently cached and whether they have been 'used...
Definition: TBranch.cxx:2028
TObjArray fBaskets
-> List of baskets of this branch
Definition: TBranch.h:107
virtual Int_t LoadBaskets()
Baskets associated to this branch are forced to be in memory.
Definition: TBranch.cxx:1892
Bool_t fSkipZip
! After being read, the buffer will not be unzipped.
Definition: TBranch.h:121
TBranch * fMother
! Pointer to top-level parent branch in the tree.
Definition: TBranch.h:112
Long64_t GetTotBytes(Option_t *option="") const
Return total number of bytes in the branch (excluding current buffer) if option ="*" includes all sub...
Definition: TBranch.cxx:1803
virtual Bool_t SetMakeClass(Bool_t decomposeObj=kTRUE)
Set the branch in a mode where the object are decomposed (Also known as MakeClass mode).
Definition: TBranch.cxx:2510
virtual void SetFile(TFile *file=0)
Set file where this branch writes/reads its buffers.
Definition: TBranch.cxx:2446
TBranch * fParent
! Pointer to parent branch.
Definition: TBranch.h:113
Int_t WriteBasket(TBasket *basket, Int_t where)
Definition: TBranch.h:141
Int_t FlushOneBasket(UInt_t which)
If we have a write basket in memory and it contains some entries and has not yet been written to disk...
Definition: TBranch.cxx:1143
virtual Int_t GetExpectedType(TClass *&clptr, EDataType &type)
Fill expectedClass and expectedType with information on the data type of the object/values contained ...
Definition: TBranch.cxx:1489
virtual void SetFirstEntry(Long64_t entry)
set the first entry number (case of TBranchSTL)
Definition: TBranch.cxx:2858
Long64_t GetTotalSize(Option_t *option="") const
Return total number of bytes in the branch (including current buffer)
Definition: TBranch.cxx:1784
Long64_t GetZipBytes(Option_t *option="") const
Return total number of zip bytes in the branch if option ="*" includes all sub-branches of this branc...
Definition: TBranch.cxx:1821
virtual void SetBasketSize(Int_t buffsize)
Set the basket size The function makes sure that the basket size is greater than fEntryOffsetlen.
Definition: TBranch.cxx:2312
virtual void Refresh(TBranch *b)
Refresh this branch using new information in b This function is called by TTree::Refresh.
Definition: TBranch.cxx:2091
Int_t fWriteBasket
Last basket number written.
Definition: TBranch.h:88
Long64_t * fBasketSeek
[fMaxBaskets] Addresses of baskets on file
Definition: TBranch.h:110
virtual void SetStatus(Bool_t status=1)
Set branch status to Process or DoNotProcess.
Definition: TBranch.cxx:2530
TObjArray * GetListOfLeaves()
Definition: TBranch.h:204
virtual void SetEntries(Long64_t entries)
Set the number of entries in this branch.
Definition: TBranch.cxx:2421
Int_t fReadBasket
! Current basket number when reading
Definition: TBranch.h:96
Long64_t fFirstEntry
Number of the first entry in this branch.
Definition: TBranch.h:102
virtual Int_t GetRow(Int_t row)
Return all elements of one row unpacked in internal array fValues [Actually just returns 1 (?...
Definition: TBranch.cxx:1706
Int_t fBasketSize
Initial Size of Basket Buffer.
Definition: TBranch.h:86
Int_t Fill()
Definition: TBranch.h:164
virtual void Reset(Option_t *option="")
Reset a Branch.
Definition: TBranch.cxx:2140
Long64_t fEntryNumber
Current entry number (last one filled in this branch)
Definition: TBranch.h:89
TBranch * GetMother() const
Get our top-level parent branch in the tree.
Definition: TBranch.cxx:1725
Int_t fCompress
Compression level and algorithm.
Definition: TBranch.h:85
TBuffer * GetTransientBuffer(Int_t size)
Returns the transient buffer currently used by this TBranch for reading/writing baskets.
Definition: TBranch.cxx:496
virtual Int_t FillImpl(ROOT::Internal::TBranchIMTHelper *)
Loop on all leaves of this branch to fill Basket buffer.
Definition: TBranch.cxx:818
TBuffer * fEntryBuffer
! Buffer used to directly pass the content without streaming
Definition: TBranch.h:117
TBasket * fCurrentBasket
! Pointer to the current basket.
Definition: TBranch.h:100
Long64_t fFirstBasketEntry
! First entry in the current basket.
Definition: TBranch.h:98
void SetCompressionLevel(Int_t level=ROOT::RCompressionSetting::ELevel::kUseMin)
Set compression level.
Definition: TBranch.cxx:2366
Long64_t fEntries
Number of entries.
Definition: TBranch.h:101
TTree * fTree
! Pointer to Tree header
Definition: TBranch.h:111
Using a TBrowser one can browse all ROOT objects.
Definition: TBrowser.h:37
The concrete implementation of TBuffer for writing/reading to/from a ROOT file or socket.
Definition: TBufferFile.h:46
@ kNotDecompressed
Definition: TBufferIO.h:66
Buffer base class used for serializing objects.
Definition: TBuffer.h:40
void SetWriteMode()
Set buffer in write mode.
Definition: TBuffer.cxx:294
void Expand(Int_t newsize, Bool_t copy=kTRUE)
Expand (or shrink) the I/O buffer to newsize bytes.
Definition: TBuffer.cxx:211
virtual Int_t GetBufferDisplacement() const =0
Int_t BufferSize() const
Definition: TBuffer.h:94
@ kWrite
Definition: TBuffer.h:70
@ kRead
Definition: TBuffer.h:70
Bool_t IsReading() const
Definition: TBuffer.h:83
virtual void ResetMap()=0
void SetBufferOffset(Int_t offset=0)
Definition: TBuffer.h:90
virtual Int_t GetMapCount() const =0
void SetReadMode()
Set buffer in read mode.
Definition: TBuffer.cxx:281
virtual void WriteBuf(const void *buf, Int_t max)=0
virtual void SetBufferDisplacement()=0
virtual char * ReadString(char *s, Int_t max)=0
@ kMinimalSize
Definition: TBuffer.h:75
Int_t Length() const
Definition: TBuffer.h:96
char * Buffer() const
Definition: TBuffer.h:93
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:75
An array of clone (identical) objects.
Definition: TClonesArray.h:32
void Browse(TBrowser *b)
Browse this collection (called by TBrowser).
virtual void RemoveAll(TCollection *col)
Remove all objects in collection col from this collection.
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
Definition: TCollection.h:182
Describe directory structure in memory.
Definition: TDirectory.h:34
virtual TFile * GetFile() const
Definition: TDirectory.h:147
virtual Bool_t IsWritable() const
Definition: TDirectory.h:163
A cache when reading files over the network.
virtual void SetSkipZip(Bool_t=kTRUE)
virtual Bool_t IsLearning() const
virtual Int_t LearnBranch(TBranch *, Bool_t=kFALSE)
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format.
Definition: TFile.h:48
Int_t GetCompressionSettings() const
Definition: TFile.h:391
static TFile * Open(const char *name, Option_t *option="", const char *ftitle="", Int_t compress=ROOT::RCompressionSetting::EDefaults::kUseGeneralPurpose, Int_t netopt=0)
Create / open a file.
Definition: TFile.cxx:3975
virtual Long64_t GetSeekKey() const
Definition: TKey.h:85
Int_t GetKeylen() const
Definition: TKey.h:80
Int_t GetObjlen() const
Definition: TKey.h:83
Int_t GetNbytes() const
Definition: TKey.h:82
virtual void SetParent(const TObject *parent)
Set parent in key buffer.
Definition: TKey.cxx:1266
TBuffer * GetBufferRef() const
Definition: TKey.h:75
A TLeaf for an 8 bit Integer data type.
Definition: TLeafB.h:26
A TLeaf for a variable length string.
Definition: TLeafC.h:26
A TLeaf for a 64 bit floating point data type.
Definition: TLeafD.h:26
A TLeaf for a 32 bit floating point data type.
Definition: TLeafF.h:26
A TLeaf for an Integer data type.
Definition: TLeafI.h:27
A TLeaf for a 64 bit Integer data type.
Definition: TLeafL.h:27
A TLeaf for a bool data type.
Definition: TLeafO.h:26
A TLeaf for a 16 bit Integer data type.
Definition: TLeafS.h:26
A TLeaf describes individual elements of a TBranch See TBranch structure in TTree.
Definition: TLeaf.h:32
virtual Int_t GetLenType() const
Definition: TLeaf.h:87
virtual const char * GetTypeName() const
Definition: TLeaf.h:93
virtual Int_t GetLen() const
Return the number of effective elements of this leaf, for the current entry.
Definition: TLeaf.cxx:311
virtual TLeaf * GetLeafCount() const
If this leaf stores a variable-sized array or a multi-dimensional array whose last dimension has vari...
Definition: TLeaf.h:78
virtual void ReadBasketExport(TBuffer &, TClonesArray *, Int_t)
Definition: TLeaf.h:107
virtual void SetAddress(void *add=0)
Definition: TLeaf.h:137
virtual void FillBasket(TBuffer &b)
Pack leaf elements in Basket output buffer.
Definition: TLeaf.cxx:149
TBranch * GetBranch() const
Definition: TLeaf.h:75
virtual void SetOffset(Int_t offset=0)
Definition: TLeaf.h:116
virtual void SetBranch(TBranch *branch)
Definition: TLeaf.h:113
virtual void SetUnsigned()
Definition: TLeaf.h:118
virtual Int_t GetOffset() const
Definition: TLeaf.h:91
virtual void ReadBasket(TBuffer &)
Definition: TLeaf.h:106
A doubly linked list.
Definition: TList.h:44
The TNamed class is the base class for all named ROOT classes.
Definition: TNamed.h:29
TString fName
Definition: TNamed.h:32
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:48
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
An array of TObjects.
Definition: TObjArray.h:37
Int_t GetEntriesFast() const
Definition: TObjArray.h:64
virtual void Expand(Int_t newSize)
Expand or shrink the array to newSize elements.
Definition: TObjArray.cxx:386
virtual void AddAtAndExpand(TObject *obj, Int_t idx)
Add object at position idx.
Definition: TObjArray.cxx:234
void Add(TObject *obj)
Definition: TObjArray.h:73
Int_t GetEntries() const
Return the number of objects in array (i.e.
Definition: TObjArray.cxx:522
TObject * UncheckedAt(Int_t i) const
Definition: TObjArray.h:89
virtual void Delete(Option_t *option="")
Remove all objects from the array AND delete all heap based objects.
Definition: TObjArray.cxx:355
void SetLast(Int_t last)
Set index of last object in array, effectively truncating the array.
Definition: TObjArray.cxx:759
Int_t GetLast() const
Return index of last object in array.
Definition: TObjArray.cxx:561
virtual void AddAt(TObject *obj, Int_t idx)
Add object at position ids.
Definition: TObjArray.cxx:253
virtual TObject * RemoveAt(Int_t idx)
Remove object at index idx.
Definition: TObjArray.cxx:678
TObject * At(Int_t idx) const
Definition: TObjArray.h:165
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition: TObject.h:172
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition: TObject.cxx:128
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:866
R__ALWAYS_INLINE Bool_t IsZombie() const
Definition: TObject.h:134
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:694
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:443
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:880
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition: TObject.cxx:908
void MakeZombie()
Definition: TObject.h:49
void ResetBit(UInt_t f)
Definition: TObject.h:171
static void * ReAlloc(void *vp, size_t size)
Reallocate (i.e.
Definition: TStorage.cxx:183
static Int_t * ReAllocInt(Int_t *vp, size_t size, size_t oldsize)
Reallocate (i.e.
Definition: TStorage.cxx:295
Basic string class.
Definition: TString.h:131
Ssiz_t Length() const
Definition: TString.h:405
void ToLower()
Change string to lower-case.
Definition: TString.cxx:1100
void Clear()
Clear string without changing its capacity.
Definition: TString.cxx:1151
Ssiz_t First(char c) const
Find first occurrence of a character c.
Definition: TString.cxx:487
const char * Data() const
Definition: TString.h:364
TString & Prepend(const char *cs)
Definition: TString.h:656
TString & Remove(Ssiz_t pos)
Definition: TString.h:668
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2264
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:619
virtual Bool_t ExpandPathName(TString &path)
Expand a pathname getting rid of special shell characters like ~.
Definition: TSystem.cxx:1264
virtual const char * DirName(const char *pathname)
Return the directory name in pathname.
Definition: TSystem.cxx:1013
virtual const char * BaseName(const char *pathname)
Base name of a file name. Base name of /user/root is root.
Definition: TSystem.cxx:941
virtual Bool_t IsAbsoluteFileName(const char *dir)
Return true if dir is an absolute pathname.
Definition: TSystem.cxx:958
Helper class to iterate over cluster of baskets.
Definition: TTree.h:247
Long64_t Previous()
Move on to the previous cluster and return the starting entry of this previous cluster.
Definition: TTree.cxx:659
Long64_t GetStartEntry()
Definition: TTree.h:279
Long64_t Next()
Move on to the next cluster and return the starting entry of this next cluster.
Definition: TTree.cxx:615
Long64_t GetNextEntry()
Definition: TTree.h:284
A TTree object has a header with a name and a title.
Definition: TTree.h:71
virtual TVirtualPerfStats * GetPerfStats() const
Definition: TTree.h:445
virtual TClusterIterator GetClusterIterator(Long64_t firstentry)
Return an iterator over the cluster of baskets starting at firstentry.
Definition: TTree.cxx:5227
void AddAllocationCount(UInt_t count)
Definition: TTree.h:314
virtual TObjArray * GetListOfLeaves()
Definition: TTree.h:428
TFile * GetCurrentFile() const
Return pointer to the current file.
Definition: TTree.cxx:5239
virtual void IncrementTotalBuffers(Int_t nbytes)
Definition: TTree.h:485
TDirectory * GetDirectory() const
Definition: TTree.h:401
TTreeCache * GetReadCache(TFile *file) const
Find and return the TTreeCache registered with the file and which may contain branches for us.
Definition: TTree.cxx:6072
virtual TObjArray * GetListOfBranches()
Definition: TTree.h:427
virtual void AddZipBytes(Int_t zip)
Definition: TTree.h:309
virtual TBasket * CreateBasket(TBranch *)
Create a basket for this tree and given branch.
Definition: TTree.cxx:3555
@ kOnlyFlushAtCluster
Definition: TTree.h:236
@ kCircular
Definition: TTree.h:235
virtual void Draw(Option_t *opt)
Default Draw method for all objects.
Definition: TTree.h:371
virtual Bool_t GetClusterPrefetch() const
Definition: TTree.h:396
virtual void AddTotBytes(Int_t tot)
Definition: TTree.h:308
virtual Long64_t GetAutoFlush() const
Definition: TTree.h:386
virtual Long64_t GetMaxVirtualSize() const
Definition: TTree.h:439
This class represents a WWW compatible URL.
Definition: TUrl.h:35
const char * GetAnchor() const
Definition: TUrl.h:73
const char * GetUrl(Bool_t withDeflt=kFALSE) const
Return full URL.
Definition: TUrl.cxx:385
void SetAnchor(const char *anchor)
Definition: TUrl.h:89
static Int_t FillListOfBrowsables(TList &list, const TBranch *branch, const TVirtualBranchBrowsable *parent=0)
Askes all registered generators to fill their browsables into the list.
virtual void SetUsed(TBranch *b, size_t basketNumber)=0
const Int_t n
Definition: legend1.C:16
Type GetType(const std::string &Name)
Definition: Systematics.cxx:34
static constexpr double s
Short_t Max(Short_t a, Short_t b)
Definition: TMathBase.h:212
Long64_t BinarySearch(Long64_t n, const T *array, T value)
Definition: TMathBase.h:278
Definition: file.py:1
Definition: first.py:1
Definition: tree.py:1
@ kUndefined
Undefined compression algorithm (must be kept the last of the list in case a new algorithm is added).
Definition: Compression.h:91
auto * l
Definition: textangle.C:4