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