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