ROOT  6.07/01
Reference Guide
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
TBasket.cxx
Go to the documentation of this file.
1 // @(#)root/tree:$Id: 4e77188fbf1e7fd026a984989de66663c49b12fc $
2 // Author: Rene Brun 19/01/96
3 /*************************************************************************
4  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
5  * All rights reserved. *
6  * *
7  * For the licensing terms see $ROOTSYS/LICENSE. *
8  * For the list of contributors see $ROOTSYS/README/CREDITS. *
9  *************************************************************************/
10 
11 #include "TBasket.h"
12 #include "TBuffer.h"
13 #include "TBufferFile.h"
14 #include "TTree.h"
15 #include "TBranch.h"
16 #include "TFile.h"
17 #include "TBufferFile.h"
18 #include "TMath.h"
19 #include "TTreeCache.h"
20 #include "TVirtualPerfStats.h"
21 #include "TTimeStamp.h"
22 #include "RZip.h"
23 
24 // TODO: Copied from TBranch.cxx
25 #if (__GNUC__ >= 3) || defined(__INTEL_COMPILER)
26 #if !defined(R__unlikely)
27  #define R__unlikely(expr) __builtin_expect(!!(expr), 0)
28 #endif
29 #if !defined(R__likely)
30  #define R__likely(expr) __builtin_expect(!!(expr), 1)
31 #endif
32 #else
33  #define R__unlikely(expr) expr
34  #define R__likely(expr) expr
35 #endif
36 
37 const UInt_t kDisplacementMask = 0xFF000000; // In the streamer the two highest bytes of
38  // the fEntryOffset are used to stored displacement.
39 
41 
42 /** \class TBasket
43 Manages buffers for branches of a Tree.
44 
45 See picture in TTree.
46 */
47 
48 ////////////////////////////////////////////////////////////////////////////////
49 /// Default contructor.
50 
51 TBasket::TBasket() : fCompressedBufferRef(0), fOwnsCompressedBuffer(kFALSE), fLastWriteBufferSize(0)
52 {
53  fDisplacement = 0;
54  fEntryOffset = 0;
55  fBufferRef = 0;
56  fBuffer = 0;
57  fHeaderOnly = kFALSE;
58  fBufferSize = 0;
59  fNevBufSize = 0;
60  fNevBuf = 0;
61  fLast = 0;
62  fBranch = 0;
63 }
64 
65 ////////////////////////////////////////////////////////////////////////////////
66 /// Constructor used during reading.
67 
68 TBasket::TBasket(TDirectory *motherDir) : TKey(motherDir),fCompressedBufferRef(0), fOwnsCompressedBuffer(kFALSE), fLastWriteBufferSize(0)
69 {
70  fDisplacement = 0;
71  fEntryOffset = 0;
72  fBufferRef = 0;
73  fBuffer = 0;
75  fBufferSize = 0;
76  fNevBufSize = 0;
77  fNevBuf = 0;
78  fLast = 0;
79  fBranch = 0;
80 }
81 
82 ////////////////////////////////////////////////////////////////////////////////
83 /// Basket normal constructor, used during writing.
84 
85 TBasket::TBasket(const char *name, const char *title, TBranch *branch) :
86  TKey(branch->GetDirectory()),fCompressedBufferRef(0), fOwnsCompressedBuffer(kFALSE), fLastWriteBufferSize(0)
87 {
88  SetName(name);
89  SetTitle(title);
90  fClassName = "TBasket";
91  fBufferSize = branch->GetBasketSize();
92  fNevBufSize = branch->GetEntryOffsetLen();
93  fNevBuf = 0;
94  fEntryOffset = 0;
95  fDisplacement= 0;
96  fBuffer = 0;
97  fBufferRef = new TBufferFile(TBuffer::kWrite, fBufferSize);
98  fVersion += 1000;
99  if (branch->GetDirectory()) {
100  TFile *file = branch->GetFile();
101  fBufferRef->SetParent(file);
102  }
103  fHeaderOnly = kTRUE;
104  fLast = 0; // Must initialize before calling Streamer()
105  if (branch->GetTree()) {
106  fCompressedBufferRef = branch->GetTree()->GetTransientBuffer(fBufferSize);
108  if (!fCompressedBufferRef) {
109  fCompressedBufferRef = new TBufferFile(TBuffer::kRead, fBufferSize);
111  }
112  }
113  Streamer(*fBufferRef);
115  fObjlen = fBufferSize - fKeylen;
116  fLast = fKeylen;
117  fBuffer = 0;
118  fBranch = branch;
120  if (fNevBufSize) {
122  for (Int_t i=0;i<fNevBufSize;i++) fEntryOffset[i] = 0;
123  }
124  branch->GetTree()->IncrementTotalBuffers(fBufferSize);
125 }
126 
127 ////////////////////////////////////////////////////////////////////////////////
128 /// Basket destructor.
129 
131 {
132  if (fDisplacement) delete [] fDisplacement;
133  if (fEntryOffset) delete [] fEntryOffset;
134  if (fBufferRef) delete fBufferRef;
135  fBufferRef = 0;
136  fBuffer = 0;
137  fDisplacement= 0;
138  fEntryOffset = 0;
139  // Note we only delete the compressed buffer if we own it
141  delete fCompressedBufferRef;
143  }
144 }
145 
146 ////////////////////////////////////////////////////////////////////////////////
147 /// Increase the size of the current fBuffer up to newsize.
148 
150 {
151  if (fBuffer == fBufferRef->Buffer()) {
152  fBufferRef->Expand(newsize);
154  } else {
155  fBufferRef->Expand(newsize);
156  }
157  fBranch->GetTree()->IncrementTotalBuffers(newsize-fBufferSize);
158  fBufferSize = newsize;
159 }
160 
161 ////////////////////////////////////////////////////////////////////////////////
162 /// Copy the basket of this branch onto the file to.
163 
165 {
167  Int_t nout = fNbytes - fKeylen;
169  Create(nout, to);
171  fHeaderOnly = kTRUE;
172  Streamer(*fBufferRef);
174  Int_t nBytes = WriteFileKeepBuffer(to);
175 
176  return nBytes>0 ? nBytes : -1;
177 }
178 
179 ////////////////////////////////////////////////////////////////////////////////
180 /// Delete fEntryOffset array.
181 
183 {
184  if (fEntryOffset) delete [] fEntryOffset;
185  fEntryOffset = 0;
186  fNevBufSize = 0;
187 }
188 
189 ////////////////////////////////////////////////////////////////////////////////
190 /// Drop buffers of this basket if it is not the current basket.
191 
193 {
194  if (!fBuffer && !fBufferRef) return 0;
195 
196  if (fDisplacement) delete [] fDisplacement;
197  if (fEntryOffset) delete [] fEntryOffset;
198  if (fBufferRef) delete fBufferRef;
200  fBufferRef = 0;
202  fBuffer = 0;
203  fDisplacement= 0;
204  fEntryOffset = 0;
205  fBranch->GetTree()->IncrementTotalBuffers(-fBufferSize);
206  return fBufferSize;
207 }
208 
209 ////////////////////////////////////////////////////////////////////////////////
210 /// Get pointer to buffer for internal entry.
211 
213 {
214  Int_t offset;
215  if (fEntryOffset) offset = fEntryOffset[entry];
216  else offset = fKeylen + entry*fNevBufSize;
217  fBufferRef->SetBufferOffset(offset);
218  return offset;
219 }
220 
221 ////////////////////////////////////////////////////////////////////////////////
222 /// Load basket buffers in memory without unziping.
223 /// This function is called by TTreeCloner.
224 /// The function returns 0 in case of success, 1 in case of error.
225 
227 {
228  if (fBufferRef) {
229  // Reuse the buffer if it exist.
230  fBufferRef->Reset();
231 
232  // We use this buffer both for reading and writing, we need to
233  // make sure it is properly sized for writing.
235  if (fBufferRef->BufferSize() < len) {
236  fBufferRef->Expand(len);
237  }
239  } else {
241  }
242  fBufferRef->SetParent(file);
243  char *buffer = fBufferRef->Buffer();
244  file->Seek(pos);
245  TFileCacheRead *pf = file->GetCacheRead(tree);
246  if (pf) {
248  if (tree->GetPerfStats()) gPerfStats = tree->GetPerfStats();
249  Int_t st = pf->ReadBuffer(buffer,pos,len);
250  if (st < 0) {
251  return 1;
252  } else if (st == 0) {
253  // fOffset might have been changed via TFileCacheRead::ReadBuffer(), reset it
254  file->Seek(pos);
255  // If we are using a TTreeCache, disable reading from the default cache
256  // temporarily, to force reading directly from file
257  TTreeCache *fc = dynamic_cast<TTreeCache*>(file->GetCacheRead());
258  if (fc) fc->Disable();
259  Int_t ret = file->ReadBuffer(buffer,len);
260  if (fc) fc->Enable();
261  pf->AddNoCacheBytesRead(len);
262  pf->AddNoCacheReadCalls(1);
263  if (ret) {
264  return 1;
265  }
266  }
267  gPerfStats = temp;
268  // fOffset might have been changed via TFileCacheRead::ReadBuffer(), reset it
269  file->SetOffset(pos + len);
270  } else {
272  if (tree->GetPerfStats() != 0) gPerfStats = tree->GetPerfStats();
273  if (file->ReadBuffer(buffer,len)) {
274  gPerfStats = temp;
275  return 1; //error while reading
276  }
277  else gPerfStats = temp;
278  }
279 
282  Streamer(*fBufferRef);
283 
284  return 0;
285 }
286 
287 ////////////////////////////////////////////////////////////////////////////////
288 /// Remove the first dentries of this basket, moving entries at
289 /// dentries to the start of the buffer.
290 
292 {
293  Int_t i;
294 
295  if (dentries >= fNevBuf) return;
296  Int_t bufbegin;
297  Int_t moved;
298 
299  if (fEntryOffset) {
300  bufbegin = fEntryOffset[dentries];
301  moved = bufbegin-GetKeylen();
302 
303  // First store the original location in the fDisplacement array
304  // and record the new start offset
305 
306  if (!fDisplacement) {
308  }
309  for (i = 0; i<(fNevBufSize-dentries); ++i) {
310  fDisplacement[i] = fEntryOffset[i+dentries];
311  fEntryOffset[i] = fEntryOffset[i+dentries] - moved;
312  }
313  for (i = fNevBufSize-dentries; i<fNevBufSize; ++i) {
314  fDisplacement[i] = 0;
315  fEntryOffset[i] = 0;
316  }
317 
318  } else {
319  // If there is no EntryOffset array, this means
320  // that each entry has the same size and that
321  // it does not point to other objects (hence there
322  // is no need for a displacement array).
323  bufbegin = GetKeylen() + dentries*fNevBufSize;
324  moved = bufbegin-GetKeylen();
325  }
326  TBuffer *buf = GetBufferRef();
327  char *buffer = buf->Buffer();
328  memmove(buffer+GetKeylen(),buffer+bufbegin,buf->Length()-bufbegin);
329  buf->SetBufferOffset(buf->Length()-moved);
330  fNevBuf -= dentries;
331 }
332 
333 #define OLD_CASE_EXPRESSION fObjlen==fNbytes-fKeylen && GetBranch()->GetCompressionLevel()!=0 && file->GetVersion()<=30401
334 ////////////////////////////////////////////////////////////////////////////////
335 /// By-passing buffer unzipping has been requested and is
336 /// possible (only 1 entry in this basket).
337 
339 {
341 
342  // Make sure that the buffer is set at the END of the data
344 
345  // Indicate that this buffer is weird.
347 
348  // Usage of this mode assume the existance of only ONE
349  // entry in this basket.
350  delete [] fEntryOffset; fEntryOffset = 0;
351  delete [] fDisplacement; fDisplacement = 0;
352 
353  fBranch->GetTree()->IncrementTotalBuffers(fBufferSize);
354  return 0;
355 }
356 
357 ////////////////////////////////////////////////////////////////////////////////
358 /// We always create the TBuffer for the basket but it hold the buffer from the cache.
359 
361 {
362  if (fBufferRef) {
363  fBufferRef->SetBuffer(buffer, size, mustFree);
365  fBufferRef->Reset();
366  } else {
367  fBufferRef = new TBufferFile(TBuffer::kRead, size, buffer, mustFree);
368  }
369  fBufferRef->SetParent(file);
370 
371  Streamer(*fBufferRef);
372 
373  if (IsZombie()) {
374  return -1;
375  }
376 
377  Bool_t oldCase = OLD_CASE_EXPRESSION;
378 
379  if ((fObjlen > fNbytes-fKeylen || oldCase) && TestBit(TBufferFile::kNotDecompressed) && (fNevBuf==1)) {
381  }
382 
384  return fObjlen+fKeylen;
385 }
386 
387 ////////////////////////////////////////////////////////////////////////////////
388 /// Initialize a buffer for reading if it is not already initialized
389 
390 static inline TBuffer* R__InitializeReadBasketBuffer(TBuffer* bufferRef, Int_t len, TFile* file)
391 {
392  TBuffer* result;
393  if (R__likely(bufferRef)) {
394  bufferRef->SetReadMode();
395  Int_t curBufferSize = bufferRef->BufferSize();
396  if (curBufferSize < len) {
397  // Experience shows that giving 5% "wiggle-room" decreases churn.
398  bufferRef->Expand(Int_t(len*1.05));
399  }
400  bufferRef->Reset();
401  result = bufferRef;
402  } else {
403  result = new TBufferFile(TBuffer::kRead, len);
404  }
405  result->SetParent(file);
406  return result;
407 }
408 
409 ////////////////////////////////////////////////////////////////////////////////
410 /// Initialize the compressed buffer; either from the TTree or create a local one.
411 
413 {
414  Bool_t compressedBufferExists = fCompressedBufferRef != NULL;
416  if (R__unlikely(!compressedBufferExists)) {
418  }
419 }
420 
421 ////////////////////////////////////////////////////////////////////////////////
422 /// Read basket buffers in memory and cleanup.
423 ///
424 /// Read a basket buffer. Check if buffers of previous ReadBasket
425 /// should not be dropped. Remember, we keep buffers in memory up to
426 /// fMaxVirtualSize.
427 /// The function returns 0 in case of success, 1 in case of error
428 /// This function was modified with the addition of the parallel
429 /// unzipping, it will try to get the unzipped file from the cache
430 /// receiving only a pointer to that buffer (so we shall not
431 /// delete that pointer), although we get a new buffer in case
432 /// it's not found in the cache.
433 /// There is a lot of code duplication but it was necesary to assure
434 /// the expected behavior when there is no cache.
435 
437 {
438  if(!fBranch->GetDirectory()) {
439  return -1;
440  }
441 
442  Bool_t oldCase;
443  char *rawUncompressedBuffer, *rawCompressedBuffer;
444  Int_t uncompressedBufferLen;
445 
446  // See if the cache has already unzipped the buffer for us.
447  TFileCacheRead *pf = file->GetCacheRead(fBranch->GetTree());
448  if (pf) {
449  Int_t res = -1;
450  Bool_t free = kTRUE;
451  char *buffer;
452  res = pf->GetUnzipBuffer(&buffer, pos, len, &free);
453  if (R__unlikely(res >= 0)) {
454  len = ReadBasketBuffersUnzip(buffer, res, free, file);
455  // Note that in the kNotDecompressed case, the above function will return 0;
456  // In such a case, we should stop processing
457  if (len <= 0) return -len;
458  goto AfterBuffer;
459  }
460  }
461 
462  // Determine which buffer to use, so that we can avoid a memcpy in case of
463  // the basket was not compressed.
464  TBuffer* readBufferRef;
466  readBufferRef = fBufferRef;
467  } else {
468  readBufferRef = fCompressedBufferRef;
469  }
470 
471  // fBufferSize is likely to be change in the Streamer call (below)
472  // and we will re-add the new size later on.
473  fBranch->GetTree()->IncrementTotalBuffers(-fBufferSize);
474 
475  // Initialize the buffer to hold the compressed data.
476  readBufferRef = R__InitializeReadBasketBuffer(readBufferRef, len, file);
477  if (!readBufferRef) {
478  Error("ReadBasketBuffers", "Unable to allocate buffer.");
479  return 1;
480  }
481 
482  if (pf) {
485  Int_t st = pf->ReadBuffer(readBufferRef->Buffer(),pos,len);
486  if (st < 0) {
487  return 1;
488  } else if (st == 0) {
489  // Read directly from file, not from the cache
490  // If we are using a TTreeCache, disable reading from the default cache
491  // temporarily, to force reading directly from file
492  TTreeCache *fc = dynamic_cast<TTreeCache*>(file->GetCacheRead());
493  if (fc) fc->Disable();
494  Int_t ret = file->ReadBuffer(readBufferRef->Buffer(),pos,len);
495  if (fc) fc->Enable();
496  pf->AddNoCacheBytesRead(len);
497  pf->AddNoCacheReadCalls(1);
498  if (ret) {
499  return 1;
500  }
501  }
502  gPerfStats = temp;
503  } else {
504  // Read from the file and unstream the header information.
507  if (file->ReadBuffer(readBufferRef->Buffer(),pos,len)) {
508  gPerfStats = temp;
509  return 1;
510  }
511  else gPerfStats = temp;
512  }
513  Streamer(*readBufferRef);
514  if (IsZombie()) {
515  return 1;
516  }
517 
518  rawCompressedBuffer = readBufferRef->Buffer();
519 
520  // Are we done?
521  if (R__unlikely(readBufferRef == fBufferRef)) // We expect most basket to be compressed.
522  {
523  if (R__likely(fObjlen+fKeylen == fNbytes)) {
524  // The basket was really not compressed as expected.
525  goto AfterBuffer;
526  } else {
527  // Well, somehow the buffer was compressed anyway, we have the compressed data in the uncompressed buffer
528  // Make sure the compressed buffer is initialized, and memcpy.
529  InitializeCompressedBuffer(len, file);
530  if (!fCompressedBufferRef) {
531  Error("ReadBasketBuffers", "Unable to allocate buffer.");
532  return 1;
533  }
534  fBufferRef->Reset();
535  rawCompressedBuffer = fCompressedBufferRef->Buffer();
536  memcpy(rawCompressedBuffer, fBufferRef->Buffer(), len);
537  }
538  }
539 
540  // Initialize buffer to hold the uncompressed data
541  // Note that in previous versions we didn't allocate buffers until we verified
542  // the zip headers; this is no longer beforehand as the buffer lifetime is scoped
543  // to the TBranch.
544  uncompressedBufferLen = len > fObjlen+fKeylen ? len : fObjlen+fKeylen;
545  fBufferRef = R__InitializeReadBasketBuffer(fBufferRef, uncompressedBufferLen, file);
546  rawUncompressedBuffer = fBufferRef->Buffer();
547  fBuffer = rawUncompressedBuffer;
548 
549  oldCase = OLD_CASE_EXPRESSION;
550  // Case where ROOT thinks the buffer is compressed. Copy over the key and uncompress the object
551  if (fObjlen > fNbytes-fKeylen || oldCase) {
552  if (R__unlikely(TestBit(TBufferFile::kNotDecompressed) && (fNevBuf==1))) {
554  }
555 
556  // Optional monitor for zip time profiling.
557  Double_t start = 0;
558  if (R__unlikely(gPerfStats)) {
559  start = TTimeStamp();
560  }
561 
562  memcpy(rawUncompressedBuffer, rawCompressedBuffer, fKeylen);
563  char *rawUncompressedObjectBuffer = rawUncompressedBuffer+fKeylen;
564  UChar_t *rawCompressedObjectBuffer = (UChar_t*)rawCompressedBuffer+fKeylen;
565  Int_t nin, nbuf;
566  Int_t nout = 0, noutot = 0, nintot = 0;
567 
568  // Unzip all the compressed objects in the compressed object buffer.
569  while (1) {
570  // Check the header for errors.
571  if (R__unlikely(R__unzip_header(&nin, rawCompressedObjectBuffer, &nbuf) != 0)) {
572  Error("ReadBasketBuffers", "Inconsistency found in header (nin=%d, nbuf=%d)", nin, nbuf);
573  break;
574  }
575  if (R__unlikely(oldCase && (nin > fObjlen || nbuf > fObjlen))) {
576  //buffer was very likely not compressed in an old version
577  memcpy(rawUncompressedBuffer+fKeylen, rawCompressedObjectBuffer+fKeylen, fObjlen);
578  goto AfterBuffer;
579  }
580 
581  R__unzip(&nin, rawCompressedObjectBuffer, &nbuf, (unsigned char*) rawUncompressedObjectBuffer, &nout);
582  if (!nout) break;
583  noutot += nout;
584  nintot += nin;
585  if (noutot >= fObjlen) break;
586  rawCompressedObjectBuffer += nin;
587  rawUncompressedObjectBuffer += nout;
588  }
589 
590  // Make sure the uncompressed numbers are consistent with header.
591  if (R__unlikely(noutot != fObjlen)) {
592  Error("ReadBasketBuffers", "fNbytes = %d, fKeylen = %d, fObjlen = %d, noutot = %d, nout=%d, nin=%d, nbuf=%d", fNbytes,fKeylen,fObjlen, noutot,nout,nin,nbuf);
593  fBranch->GetTree()->IncrementTotalBuffers(fBufferSize);
594  return 1;
595  }
596  len = fObjlen+fKeylen;
599  if (R__unlikely(gPerfStats)) {
600  gPerfStats->UnzipEvent(fBranch->GetTree(),pos,start,nintot,fObjlen);
601  }
602  gPerfStats = temp;
603  } else {
604  // Nothing is compressed - copy over wholesale.
605  memcpy(rawUncompressedBuffer, rawCompressedBuffer, len);
606  }
607 
608 AfterBuffer:
609 
610  fBranch->GetTree()->IncrementTotalBuffers(fBufferSize);
611 
612  // Read offsets table if needed.
613  if (!fBranch->GetEntryOffsetLen()) {
614  return 0;
615  }
616  delete [] fEntryOffset;
617  fEntryOffset = 0;
618  fBufferRef->SetBufferOffset(fLast);
620  if (!fEntryOffset) {
621  fEntryOffset = new Int_t[fNevBuf+1];
622  fEntryOffset[0] = fKeylen;
623  Warning("ReadBasketBuffers","basket:%s has fNevBuf=%d but fEntryOffset=0, pos=%lld, len=%d, fNbytes=%d, fObjlen=%d, trying to repair",GetName(),fNevBuf,pos,len,fNbytes,fObjlen);
624  return 0;
625  }
626  // Read the array of diplacement if any.
627  delete [] fDisplacement;
628  fDisplacement = 0;
629  if (fBufferRef->Length() != len) {
630  // There is more data in the buffer! It is the displacement
631  // array. If len is less than TBuffer::kMinimalSize the actual
632  // size of the buffer is too large, so we can not use the
633  // fBufferRef->BufferSize()
635  }
636 
637  return 0;
638 }
639 
640 ////////////////////////////////////////////////////////////////////////////////
641 /// Read basket buffers in memory and cleanup
642 ///
643 /// Read first bytes of a logical record starting at position pos
644 /// return record length (first 4 bytes of record).
645 
647 {
648  const Int_t len = 128;
649  char buffer[len];
650  Int_t keylen;
651  file->GetRecordHeader(buffer, pos,len, fNbytes, fObjlen, keylen);
652  fKeylen = keylen;
653  return fNbytes;
654 }
655 
656 ////////////////////////////////////////////////////////////////////////////////
657 /// Reset the basket to the starting state. i.e. as it was after calling
658 /// the constructor (and potentially attaching a TBuffer.)
659 /// Reduce memory used by fEntryOffset and the TBuffer if needed ..
660 
662 {
663  // Name, Title, fClassName, fBranch
664  // stay the same.
665 
666  // Downsize the buffer if needed.
667  Int_t curSize = fBufferRef->BufferSize();
668  // fBufferLen at this point is already reset, so use indirect measurements
669  Int_t curLen = (GetObjlen() + GetKeylen());
670  Long_t newSize = -1;
671  if (curSize > 2*curLen)
672  {
673  Long_t curBsize = fBranch->GetBasketSize();
674  if (curSize > 2*curBsize ) {
675  Long_t avgSize = (Long_t)(fBranch->GetTotBytes() / (1+fBranch->GetWriteBasket())); // Average number of bytes per basket so far
676  if (curSize > 2*avgSize) {
677  newSize = curBsize;
678  if (curLen > newSize) {
679  newSize = curLen;
680  }
681  if (avgSize > newSize) {
682  newSize = avgSize;
683  }
684  newSize = newSize + 512 - newSize%512; // Wiggle room and alignment (512 is same as in OptimizeBaskets)
685  }
686  }
687  }
688  /*
689  Philippe has asked us to keep this turned off until we finish memory fragmentation studies.
690  // If fBufferRef grew since we last saw it, shrink it to 105% of the occupied size
691  if (curSize > fLastWriteBufferSize) {
692  if (newSize == -1) {
693  newSize = Int_t(1.05*Float_t(fBufferRef->Length()));
694  }
695  fLastWriteBufferSize = newSize;
696  }
697  */
698  if (newSize != -1) {
699  fBufferRef->Expand(newSize,kFALSE); // Expand without copying the existing data.
700  }
701 
702  TKey::Reset();
703 
704  Int_t newNevBufSize = fBranch->GetEntryOffsetLen();
705  if (newNevBufSize==0) {
706  delete [] fEntryOffset;
707  fEntryOffset = 0;
708  } else if (newNevBufSize != fNevBufSize) {
709  delete [] fEntryOffset;
710  fEntryOffset = new Int_t[newNevBufSize];
711  } else if (!fEntryOffset) {
712  fEntryOffset = new Int_t[newNevBufSize];
713  }
714  fNevBufSize = newNevBufSize;
715 
716  fNevBuf = 0;
717  Int_t *storeEntryOffset = fEntryOffset;
718  fEntryOffset = 0;
719  Int_t *storeDisplacement = fDisplacement;
720  fDisplacement= 0;
721  fBuffer = 0;
722 
723  fBufferRef->Reset();
725 
726  fHeaderOnly = kTRUE;
727  fLast = 0; //Must initialize before calling Streamer()
728 
729  Streamer(*fBufferRef);
730 
732  fObjlen = fBufferSize - fKeylen;
733  fLast = fKeylen;
734  fBuffer = 0;
736  fDisplacement= storeDisplacement;
737  fEntryOffset = storeEntryOffset;
738  if (fNevBufSize) {
739  for (Int_t i=0;i<fNevBufSize;i++) fEntryOffset[i] = 0;
740  }
741 }
742 
743 ////////////////////////////////////////////////////////////////////////////////
744 /// Set read mode of basket.
745 
747 {
748  fLast = fBufferRef->Length();
750 }
751 
752 ////////////////////////////////////////////////////////////////////////////////
753 /// Set write mode of basket.
754 
756 {
758  fBufferRef->SetBufferOffset(fLast);
759 }
760 
761 ////////////////////////////////////////////////////////////////////////////////
762 /// Stream a class object.
763 
764 void TBasket::Streamer(TBuffer &b)
765 {
766  char flag;
767  if (b.IsReading()) {
768  TKey::Streamer(b); //this must be first
769  Version_t v = b.ReadVersion();
770  b >> fBufferSize;
771  b >> fNevBufSize;
772  if (fNevBufSize < 0) {
773  Error("Streamer","The value of fNevBufSize is incorrect (%d) ; trying to recover by setting it to zero",fNevBufSize);
774  MakeZombie();
775  fNevBufSize = 0;
776  }
777  b >> fNevBuf;
778  b >> fLast;
779  b >> flag;
780  if (fLast > fBufferSize) fBufferSize = fLast;
781  if (!flag) {
782  return;
783  }
784  if (flag%10 != 2) {
785  delete [] fEntryOffset;
787  if (fNevBuf) b.ReadArray(fEntryOffset);
788  if (20<flag && flag<40) {
789  for(int i=0; i<fNevBuf; i++){
790  fEntryOffset[i] &= ~kDisplacementMask;
791  }
792  }
793  if (flag>40) {
796  }
797  }
798  if (flag == 1 || flag > 10) {
799  fBufferRef = new TBufferFile(TBuffer::kRead,fBufferSize);
801  char *buf = fBufferRef->Buffer();
802  if (v > 1) b.ReadFastArray(buf,fLast);
803  else b.ReadArray(buf);
804  fBufferRef->SetBufferOffset(fLast);
805  // This is now done in the TBranch streamer since fBranch might not
806  // yet be set correctly.
807  // fBranch->GetTree()->IncrementTotalBuffers(fBufferSize);
808  }
809  } else {
810  TKey::Streamer(b); //this must be first
812  if (fBufferRef) {
813  Int_t curLast = fBufferRef->Length();
814  if (!fHeaderOnly && !fSeekKey && curLast > fLast) fLast = curLast;
815  }
816  if (fLast > fBufferSize) fBufferSize = fLast;
817 
818 // static TStopwatch timer;
819 // timer.Start(kFALSE);
820 
821 // // Check may be fEntryOffset is equidistant
822 // // This attempts by Victor fails :(
823 // int equidist = 0;
824 // if (1 && fEntryOffset && fNevBuf>=3) {
825 // equidist = 1;
826 // int dist = fEntryOffset[1]-fEntryOffset[0];
827 // int curr = fEntryOffset[1];
828 // for (int i=1;i<fNevBuf;i++,curr+=dist) {
829 // if (fEntryOffset[i]==curr) continue;
830 // equidist = 0;
831 // break;
832 // }
833 // if (equidist) {
834 // fNevBufSize=dist;
835 // delete [] fEntryOffset; fEntryOffset = 0;
836 // }
837 // if (equidist) {
838 // fprintf(stderr,"detected an equidistant case fNbytes==%d fLast==%d\n",fNbytes,fLast);
839 // }
840 // }
841 // also he add (a little further
842 // if (!fEntryOffset || equidist) flag = 2;
843 
844 // timer.Stop();
845 // Double_t rt1 = timer.RealTime();
846 // Double_t cp1 = timer.CpuTime();
847 // fprintf(stderr,"equidist cost : RT=%6.2f s Cpu=%6.2f s\n",rt1,cp1);
848 
849  b << fBufferSize;
850  b << fNevBufSize;
851  b << fNevBuf;
852  b << fLast;
853  if (fHeaderOnly) {
854  flag = 0;
855  b << flag;
856  } else {
857  flag = 1;
858  if (!fEntryOffset) flag = 2;
859  if (fBufferRef) flag += 10;
860  if (fDisplacement) flag += 40;
861  b << flag;
862 
863  if (fEntryOffset && fNevBuf) {
864  b.WriteArray(fEntryOffset, fNevBuf);
865  if (fDisplacement) b.WriteArray(fDisplacement, fNevBuf);
866  }
867  if (fBufferRef) {
868  char *buf = fBufferRef->Buffer();
869  b.WriteFastArray(buf, fLast);
870  }
871  }
872  }
873 }
874 
875 ////////////////////////////////////////////////////////////////////////////////
876 /// Update basket header and EntryOffset table.
877 
879 {
880  if (fEntryOffset) {
881  if (fNevBuf+1 >= fNevBufSize) {
882  Int_t newsize = TMath::Max(10,2*fNevBufSize);
883  Int_t *newoff = TStorage::ReAllocInt(fEntryOffset, newsize,
884  fNevBufSize);
885  if (fDisplacement) {
886  Int_t *newdisp = TStorage::ReAllocInt(fDisplacement, newsize,
887  fNevBufSize);
888  fDisplacement = newdisp;
889  }
890  fEntryOffset = newoff;
891  fNevBufSize = newsize;
892 
893  //Update branch only for the first 10 baskets
894  if (fBranch->GetWriteBasket() < 10) {
895  fBranch->SetEntryOffsetLen(newsize);
896  }
897  }
899 
900  if (skipped!=offset && !fDisplacement){
902  for (Int_t i = 0; i<fNevBufSize; i++) fDisplacement[i] = fEntryOffset[i];
903  }
904  if (fDisplacement) {
905  fDisplacement[fNevBuf] = skipped;
907  }
908  }
909 
910  fNevBuf++;
911 }
912 
913 ////////////////////////////////////////////////////////////////////////////////
914 /// Write buffer of this basket on the current file.
915 ///
916 /// The function returns the number of bytes committed to the memory.
917 /// If a write error occurs, the number of bytes returned is -1.
918 /// If no data are written, the number of bytes returned is 0.
919 
921 {
922  const Int_t kWrite = 1;
923 
924  TFile *file = fBranch->GetFile(kWrite);
925  if (!file) return 0;
926  if (!file->IsWritable()) {
927  return -1;
928  }
929  fMotherDir = file; // fBranch->GetDirectory();
930 
932  // Read the basket information that was saved inside the buffer.
933  Bool_t writing = fBufferRef->IsWriting();
936 
937  Streamer(*fBufferRef);
938  if (writing) fBufferRef->SetWriteMode();
939  Int_t nout = fNbytes - fKeylen;
940 
942 
943  Create(nout,file);
945  fHeaderOnly = kTRUE;
946 
947  Streamer(*fBufferRef); //write key itself again
948  int nBytes = WriteFileKeepBuffer();
950  return nBytes>0 ? fKeylen+nout : -1;
951  }
952 
953  // Transfer fEntryOffset table at the end of fBuffer.
954  fLast = fBufferRef->Length();
955  if (fEntryOffset) {
956  // Note: We might want to investigate the compression gain if we
957  // transform the Offsets to fBuffer in entry length to optimize
958  // compression algorithm. The aggregate gain on a (random) CMS files
959  // is around 5.5%. So the code could something like:
960  // for(Int_t z = fNevBuf; z > 0; --z) {
961  // if (fEntryOffset[z]) fEntryOffset[z] = fEntryOffset[z] - fEntryOffset[z-1];
962  // }
963  fBufferRef->WriteArray(fEntryOffset,fNevBuf+1);
964  if (fDisplacement) {
965  fBufferRef->WriteArray(fDisplacement,fNevBuf+1);
966  delete [] fDisplacement; fDisplacement = 0;
967  }
968  }
969 
970  Int_t lbuf, nout, noutot, bufmax, nzip;
971  lbuf = fBufferRef->Length();
972  fObjlen = lbuf - fKeylen;
973 
974  fHeaderOnly = kTRUE;
976  Int_t cxlevel = fBranch->GetCompressionLevel();
977  Int_t cxAlgorithm = fBranch->GetCompressionAlgorithm();
978  if (cxlevel > 0) {
979  Int_t nbuffers = 1 + (fObjlen - 1) / kMAXZIPBUF;
980  Int_t buflen = fKeylen + fObjlen + 9 * nbuffers + 28; //add 28 bytes in case object is placed in a deleted gap
981  InitializeCompressedBuffer(buflen, file);
982  if (!fCompressedBufferRef) {
983  Warning("WriteBuffer", "Unable to allocate the compressed buffer");
984  return -1;
985  }
988  char *objbuf = fBufferRef->Buffer() + fKeylen;
989  char *bufcur = &fBuffer[fKeylen];
990  noutot = 0;
991  nzip = 0;
992  for (Int_t i = 0; i < nbuffers; ++i) {
993  if (i == nbuffers - 1) bufmax = fObjlen - nzip;
994  else bufmax = kMAXZIPBUF;
995  //compress the buffer
996  R__zipMultipleAlgorithm(cxlevel, &bufmax, objbuf, &bufmax, bufcur, &nout, cxAlgorithm);
997 
998  // test if buffer has really been compressed. In case of small buffers
999  // when the buffer contains random data, it may happen that the compressed
1000  // buffer is larger than the input. In this case, we write the original uncompressed buffer
1001  if (nout == 0 || nout >= fObjlen) {
1002  nout = fObjlen;
1003  // We used to delete fBuffer here, we no longer want to since
1004  // the buffer (held by fCompressedBufferRef) might be re-used later.
1005  fBuffer = fBufferRef->Buffer();
1006  Create(fObjlen,file);
1008 
1009  Streamer(*fBufferRef); //write key itself again
1010  if ((nout+fKeylen)>buflen) {
1011  Warning("WriteBuffer","Possible memory corruption due to compression algorithm, wrote %d bytes past the end of a block of %d bytes. fNbytes=%d, fObjLen=%d, fKeylen=%d",
1012  (nout+fKeylen-buflen),buflen,fNbytes,fObjlen,fKeylen);
1013  }
1014  goto WriteFile;
1015  }
1016  bufcur += nout;
1017  noutot += nout;
1018  objbuf += kMAXZIPBUF;
1019  nzip += kMAXZIPBUF;
1020  }
1021  nout = noutot;
1022  Create(noutot,file);
1024 
1025  Streamer(*fBufferRef); //write key itself again
1026  memcpy(fBuffer,fBufferRef->Buffer(),fKeylen);
1027  } else {
1028  fBuffer = fBufferRef->Buffer();
1029  Create(fObjlen,file);
1031 
1032  Streamer(*fBufferRef); //write key itself again
1033  nout = fObjlen;
1034  }
1035 
1036 WriteFile:
1037  Int_t nBytes = WriteFileKeepBuffer();
1038  fHeaderOnly = kFALSE;
1039  return nBytes>0 ? fKeylen+nout : -1;
1040 }
1041 
Int_t fVersion
Key version identifier.
Definition: TKey.h:40
TObject * GetParent() const
Return pointer to parent of this buffer.
Definition: TBuffer.cxx:229
Int_t ReadBasketBytes(Long64_t pos, TFile *file)
Read basket buffers in memory and cleanup.
Definition: TBasket.cxx:646
void SetBufferOffset(Int_t offset=0)
Definition: TBuffer.h:90
Bool_t fHeaderOnly
Definition: TBasket.h:56
virtual void SetReadMode()
Set read mode of basket.
Definition: TBasket.cxx:746
void Update(Int_t newlast)
Definition: TBasket.h:95
tuple buffer
Definition: tree.py:99
The concrete implementation of TBuffer for writing/reading to/from a ROOT file or socket...
Definition: TBufferFile.h:51
virtual TVirtualPerfStats * GetPerfStats() const
Definition: TTree.h:427
Int_t ReadBasketBuffers(Long64_t pos, Int_t len, TFile *file)
Read basket buffers in memory and cleanup.
Definition: TBasket.cxx:436
long long Long64_t
Definition: RtypesCore.h:69
Bool_t IsReading() const
Definition: TBuffer.h:83
Int_t * fDisplacement
Definition: TBasket.h:57
virtual void IncrementTotalBuffers(Int_t nbytes)
Definition: TTree.h:464
Int_t GetCompressionAlgorithm() const
Definition: TBranch.h:226
short Version_t
Definition: RtypesCore.h:61
Provides the interface for the PROOF internal performance measurement and event tracing.
A cache when reading files over the network.
tuple offset
Definition: tree.py:93
Int_t fBufferSize
Definition: TBasket.h:52
virtual void SetOffset(Long64_t offset, ERelativeTo pos=kBeg)
Set position from where to start reading.
Definition: TFile.cxx:2064
Int_t * fEntryOffset
[fNevBuf] Displacement of entries in fBuffer(TKey)
Definition: TBasket.h:58
virtual void SetName(const char *name)
Change (i.e.
Definition: TNamed.cxx:128
A specialized TFileCacheRead object for a TTree.
Definition: TTreeCache.h:34
TBranch * fBranch
Definition: TBasket.h:59
virtual void Seek(Long64_t offset, ERelativeTo pos=kBeg)
Seek to a specific position in the file. Pos it either kBeg, kCur or kEnd.
Definition: TFile.cxx:2085
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format...
Definition: TFile.h:45
virtual Bool_t ReadBuffer(char *buf, Int_t len)
Read a buffer from the file.
Definition: TFile.cxx:1596
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:1618
Buffer base class used for serializing objects.
Definition: TBuffer.h:42
Bool_t IsZombie() const
Definition: TObject.h:141
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
const Bool_t kFALSE
Definition: Rtypes.h:92
void SetParent(TObject *parent)
Set parent owning this buffer.
Definition: TBuffer.cxx:237
virtual UInt_t WriteVersion(const TClass *cl, Bool_t useBcnt=kFALSE)=0
Int_t fNevBuf
Definition: TBasket.h:54
char * fBuffer
Object buffer.
Definition: TKey.h:50
TDirectory * fMotherDir
!pointer to mother directory
Definition: TKey.h:53
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:732
TFileCacheRead * GetCacheRead(TObject *tree=0) const
Return a pointer to the current read cache.
Definition: TFile.cxx:1196
static struct mg_connection * fc(struct mg_context *ctx)
Definition: civetweb.c:839
virtual void WriteArray(const Bool_t *b, Int_t n)=0
virtual void Reset()=0
virtual void Reset()
Reset the basket to the starting state.
Definition: TBasket.cxx:661
virtual Int_t WriteBuffer()
Write buffer of this basket on the current file.
Definition: TBasket.cxx:920
virtual Int_t WriteFile(Int_t cycle=1, TFile *f=0)
Write the encoded object supported by this key.
Definition: TKey.cxx:1440
int R__unzip_header(Int_t *nin, UChar_t *bufin, Int_t *lout)
Short_t fKeylen
Number of bytes for the key itself.
Definition: TKey.h:44
Bool_t IsWritable() const
TString fClassName
Object Class name.
Definition: TKey.h:48
char * Buffer() const
Definition: TBuffer.h:93
Book space in a file, create I/O buffers, to fill them, (un)compress them.
Definition: TKey.h:30
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:918
void InitializeCompressedBuffer(Int_t len, TFile *file)
Initialize the compressed buffer; either from the TTree or create a local one.
Definition: TBasket.cxx:412
virtual void Enable()
Definition: TTreeCache.h:79
virtual Int_t WriteFileKeepBuffer(TFile *f=0)
Write the encoded object supported by this key.
Definition: TKey.cxx:1481
void Expand(Int_t newsize, Bool_t copy=kTRUE)
Expand (or shrink) the I/O buffer to newsize bytes.
Definition: TBuffer.cxx:199
Bool_t IsWriting() const
Definition: TBuffer.h:84
Int_t GetRecordHeader(char *buf, Long64_t first, Int_t maxbytes, Int_t &nbytes, Int_t &objlen, Int_t &keylen)
Read the logical record header starting at a certain postion.
Definition: TFile.cxx:1233
TBuffer * GetBufferRef() const
Definition: TKey.h:81
Bool_t fOwnsCompressedBuffer
Compressed buffer.
Definition: TBasket.h:61
virtual void AddNoCacheReadCalls(Int_t reads)
TPaveLabel title(3, 27.1, 15, 28.7,"ROOT Environment and Tools")
virtual void AdjustSize(Int_t newsize)
Increase the size of the current fBuffer up to newsize.
Definition: TBasket.cxx:149
Int_t ReadBasketBuffersUncompressedCase()
By-passing buffer unzipping has been requested and is possible (only 1 entry in this basket)...
Definition: TBasket.cxx:338
TClass * IsA() const
Int_t GetEntryPointer(Int_t Entry)
Get pointer to buffer for internal entry.
Definition: TBasket.cxx:212
#define OLD_CASE_EXPRESSION
Definition: TBasket.cxx:333
unsigned int UInt_t
Definition: RtypesCore.h:42
Bool_t TestBit(UInt_t f) const
Definition: TObject.h:173
Manages buffers for branches of a Tree.
Definition: TBasket.h:38
TBuffer * fCompressedBufferRef
Definition: TBasket.h:60
void SetReadMode()
Set buffer in read mode.
Definition: TBuffer.cxx:269
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:51
virtual void Reset()
Reset the key as it had not been 'filled' yet.
Definition: TKey.cxx:1295
Long64_t entry
virtual void ReadFastArray(Bool_t *b, Int_t n)=0
virtual void WriteFastArray(const Bool_t *b, Int_t n)=0
TTree * GetTree() const
Definition: TBranch.h:183
tuple free
Definition: fildir.py:30
TBuffer * fBufferRef
Pointer to the TBuffer object.
Definition: TKey.h:51
#define gPerfStats
Int_t fNevBufSize
Definition: TBasket.h:53
Long64_t fSeekKey
Location of object on file.
Definition: TKey.h:46
long Long_t
Definition: RtypesCore.h:50
virtual Int_t GetBasketSize() const
Definition: TBranch.h:151
#define R__likely(expr)
Definition: TBasket.cxx:34
tuple tree
Definition: tree.py:24
Short_t fCycle
Cycle number.
Definition: TKey.h:45
#define ClassImp(name)
Definition: Rtypes.h:279
tuple file
Definition: fildir.py:20
double Double_t
Definition: RtypesCore.h:55
Describe directory structure in memory.
Definition: TDirectory.h:44
The TTimeStamp encapsulates seconds and ns since EPOCH.
Definition: TTimeStamp.h:76
Int_t GetObjlen() const
Definition: TKey.h:89
Int_t GetKeylen() const
Definition: TKey.h:86
static TBuffer * R__InitializeReadBasketBuffer(TBuffer *bufferRef, Int_t len, TFile *file)
Initialize a buffer for reading if it is not already initialized.
Definition: TBasket.cxx:390
virtual ~TBasket()
Basket destructor.
Definition: TBasket.cxx:130
void R__unzip(Int_t *nin, UChar_t *bufin, Int_t *lout, char *bufout, Int_t *nout)
#define name(a, b)
Definition: linkTestLib0.cpp:5
Int_t fObjlen
Length of uncompressed object in bytes.
Definition: TKey.h:42
TDirectory * GetDirectory() const
Definition: TBranch.h:157
virtual void Create(Int_t nbytes, TFile *f=0)
Create a TKey object of specified size.
Definition: TKey.cxx:458
virtual Int_t GetUnzipBuffer(char **, Long64_t, Int_t, Bool_t *)
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:2188
Int_t BufferSize() const
Definition: TBuffer.h:94
virtual void DeleteEntryOffset()
Delete fEntryOffset array.
Definition: TBasket.cxx:182
TBuffer * GetTransientBuffer(Int_t size)
Returns the transient buffer currently used by this TTree for reading/writing baskets.
Definition: TTree.cxx:889
virtual Int_t DropBuffers()
Drop buffers of this basket if it is not the current basket.
Definition: TBasket.cxx:192
Int_t Length() const
Definition: TBuffer.h:96
Short_t Max(Short_t a, Short_t b)
Definition: TMathBase.h:202
void MakeZombie()
Definition: TObject.h:68
#define NULL
Definition: Rtypes.h:82
Int_t fLast
Definition: TBasket.h:55
Int_t GetEntryOffsetLen() const
Definition: TBranch.h:160
virtual Int_t ReadBuffer(char *buf, Long64_t pos, Int_t len)
Read buffer at position pos.
Int_t fNbytes
Number of bytes for the object on file.
Definition: TKey.h:41
A TTree object has a header with a name and a title.
Definition: TTree.h:98
Long64_t CopyTo(TFile *to)
Copy the basket of this branch onto the file to.
Definition: TBasket.cxx:164
double result[121]
unsigned char UChar_t
Definition: RtypesCore.h:34
const UInt_t kDisplacementMask
Definition: TBasket.cxx:37
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:1382
virtual void SetBufferDisplacement()=0
Int_t ReadBasketBuffersUnzip(char *, Int_t, Bool_t, TFile *)
We always create the TBuffer for the basket but it hold the buffer from the cache.
Definition: TBasket.cxx:360
A TTree is a list of TBranches.
Definition: TBranch.h:58
const Bool_t kTRUE
Definition: Rtypes.h:91
virtual void SetTitle(const char *title="")
Change (i.e. set) the title of the TNamed.
Definition: TNamed.cxx:152
#define R__unlikely(expr)
Definition: TBasket.cxx:33
Int_t GetCompressionLevel() const
Definition: TBranch.h:232
Int_t GetWriteBasket() const
Definition: TBranch.h:170
TBasket()
Size of the buffer last time we wrote it to disk.
virtual void SetWriteMode()
Set write mode of basket.
Definition: TBasket.cxx:755
static Int_t * ReAllocInt(Int_t *vp, size_t size, size_t oldsize)
Reallocate (i.e.
Definition: TStorage.cxx:289
void SetWriteMode()
Set buffer in write mode.
Definition: TBuffer.cxx:282
virtual Version_t ReadVersion(UInt_t *start=0, UInt_t *bcnt=0, const TClass *cl=0)=0
virtual void Disable()
Definition: TTreeCache.h:78
void SetBuffer(void *buf, UInt_t bufsiz=0, Bool_t adopt=kTRUE, ReAllocCharFun_t reallocfunc=0)
Sets a new buffer in an existing TBuffer object.
Definition: TBuffer.cxx:163
virtual Int_t ReadArray(Bool_t *&b)=0
virtual void AddNoCacheBytesRead(Long64_t len)
Int_t LoadBasketBuffers(Long64_t pos, Int_t len, TFile *file, TTree *tree=0)
Load basket buffers in memory without unziping.
Definition: TBasket.cxx:226
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:291
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:904