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