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