Logo ROOT   6.16/01
Reference Guide
•All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules 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 <chrono>
12
13#include "TBasket.h"
14#include "TBuffer.h"
15#include "TBufferFile.h"
16#include "TTree.h"
17#include "TBranch.h"
18#include "TFile.h"
19#include "TLeaf.h"
20#include "TBufferFile.h"
21#include "TMath.h"
22#include "TROOT.h"
23#include "TTreeCache.h"
24#include "TVirtualMutex.h"
25#include "TVirtualPerfStats.h"
26#include "TTimeStamp.h"
27#include "ROOT/TIOFeatures.hxx"
28#include "RZip.h"
29
30#include <bitset>
31
32const UInt_t kDisplacementMask = 0xFF000000; // In the streamer the two highest bytes of
33 // the fEntryOffset are used to stored displacement.
34
36
37/** \class TBasket
38\ingroup tree
39
40Manages buffers for branches of a Tree.
41
42See picture in TTree.
43*/
44
45////////////////////////////////////////////////////////////////////////////////
46/// Default contructor.
47
49{
50}
51
52////////////////////////////////////////////////////////////////////////////////
53/// Constructor used during reading.
54
55TBasket::TBasket(TDirectory *motherDir) : TKey(motherDir)
56{
57}
58
59////////////////////////////////////////////////////////////////////////////////
60/// Basket normal constructor, used during writing.
61
62TBasket::TBasket(const char *name, const char *title, TBranch *branch)
63 : TKey(branch->GetDirectory()), fBufferSize(branch->GetBasketSize()), fNevBufSize(branch->GetEntryOffsetLen()),
64 fHeaderOnly(kTRUE), fIOBits(branch->GetIOFeatures().GetFeatures())
65{
67 SetTitle(title);
68 fClassName = "TBasket";
69 fBuffer = nullptr;
71 fVersion += 1000;
72 if (branch->GetDirectory()) {
73 TFile *file = branch->GetFile();
75 }
76 if (branch->GetTree()) {
77#ifdef R__USE_IMT
79#else
81#endif
86 }
87 }
88 fBranch = branch;
89 Streamer(*fBufferRef);
92 fLast = fKeylen;
93 fBuffer = 0;
95 if (fNevBufSize) {
97 for (Int_t i=0;i<fNevBufSize;i++) fEntryOffset[i] = 0;
98 }
100}
101
102////////////////////////////////////////////////////////////////////////////////
103/// Basket destructor.
104
106{
107 if (fDisplacement) delete [] fDisplacement;
109 if (fBufferRef) delete fBufferRef;
110 fBufferRef = 0;
111 fBuffer = 0;
112 fDisplacement= 0;
113 // Note we only delete the compressed buffer if we own it
117 }
118}
119
120////////////////////////////////////////////////////////////////////////////////
121/// Increase the size of the current fBuffer up to newsize.
122
124{
125 if (fBuffer == fBufferRef->Buffer()) {
126 fBufferRef->Expand(newsize);
128 } else {
129 fBufferRef->Expand(newsize);
130 }
132 fBufferSize = newsize;
133 fLastWriteBufferSize[0] = newsize;
137}
138
139////////////////////////////////////////////////////////////////////////////////
140/// Copy the basket of this branch onto the file to.
141
143{
145 Int_t nout = fNbytes - fKeylen;
147 Create(nout, to);
150 Streamer(*fBufferRef);
152 Int_t nBytes = WriteFileKeepBuffer(to);
153
154 return nBytes>0 ? nBytes : -1;
155}
156
157////////////////////////////////////////////////////////////////////////////////
158/// Delete fEntryOffset array.
159
161{
163 fNevBufSize = 0;
164}
165
166////////////////////////////////////////////////////////////////////////////////
167/// Drop buffers of this basket if it is not the current basket.
168
170{
171 if (!fBuffer && !fBufferRef) return 0;
172
173 if (fDisplacement) delete [] fDisplacement;
175 if (fBufferRef) delete fBufferRef;
177 fBufferRef = 0;
179 fBuffer = 0;
180 fDisplacement= 0;
181 fEntryOffset = 0;
183 return fBufferSize;
184}
185
186////////////////////////////////////////////////////////////////////////////////
187/// Calculates the entry offset array, if possible.
188///
189/// Result is cached, meaning that this should only be invoked once per basket.
190
192{
193 if (fEntryOffset != reinterpret_cast<Int_t *>(-1)) {
194 return fEntryOffset;
195 }
196
197 if (R__unlikely(!fBranch)) {
198 Error("GetCalculatedEntryOffset", "Basket entry offset calculation requested, but no associated TBranch!");
199 return nullptr;
200 }
201 if (R__unlikely(fBranch->GetNleaves() != 1)) {
202 Error("GetCalculatedEntryOffset", "Branch contains multiple leaves - unable to calculated entry offsets!");
203 return nullptr;
204 }
205 TLeaf *leaf = static_cast<TLeaf *>((*fBranch->GetListOfLeaves())[0]);
207 return fEntryOffset;
208}
209
210////////////////////////////////////////////////////////////////////////////////
211/// Determine whether we can generate the offset array when this branch is read.
212///
213
215{
216 if (fBranch->GetNleaves() != 1) {
217 return kFALSE;
218 }
219 TLeaf *leaf = static_cast<TLeaf *>((*fBranch->GetListOfLeaves())[0]);
220 return leaf->CanGenerateOffsetArray();
221}
222
223////////////////////////////////////////////////////////////////////////////////
224/// Get pointer to buffer for internal entry.
225
227{
228 Int_t offset;
229 Int_t *entryOffset = GetEntryOffset();
230 if (entryOffset) offset = entryOffset[entry];
231 else offset = fKeylen + entry*fNevBufSize;
233 return offset;
234}
235
236////////////////////////////////////////////////////////////////////////////////
237/// Load basket buffers in memory without unziping.
238/// This function is called by TTreeCloner.
239/// The function returns 0 in case of success, 1 in case of error.
240
242{
243 if (fBufferRef) {
244 // Reuse the buffer if it exist.
245 fBufferRef->Reset();
246
247 // We use this buffer both for reading and writing, we need to
248 // make sure it is properly sized for writing.
250 if (fBufferRef->BufferSize() < len) {
251 fBufferRef->Expand(len);
252 }
254 } else {
256 }
258 char *buffer = fBufferRef->Buffer();
259 file->Seek(pos);
260 TFileCacheRead *pf = tree->GetReadCache(file);
261 if (pf) {
263 if (tree->GetPerfStats()) gPerfStats = tree->GetPerfStats();
264 Int_t st = pf->ReadBuffer(buffer,pos,len);
265 if (st < 0) {
266 return 1;
267 } else if (st == 0) {
268 // fOffset might have been changed via TFileCacheRead::ReadBuffer(), reset it
269 file->Seek(pos);
270 // If we are using a TTreeCache, disable reading from the default cache
271 // temporarily, to force reading directly from file
272 TTreeCache *fc = dynamic_cast<TTreeCache*>(file->GetCacheRead());
273 if (fc) fc->Disable();
274 Int_t ret = file->ReadBuffer(buffer,len);
275 if (fc) fc->Enable();
276 pf->AddNoCacheBytesRead(len);
277 pf->AddNoCacheReadCalls(1);
278 if (ret) {
279 return 1;
280 }
281 }
282 gPerfStats = temp;
283 // fOffset might have been changed via TFileCacheRead::ReadBuffer(), reset it
284 file->SetOffset(pos + len);
285 } else {
287 if (tree->GetPerfStats() != 0) gPerfStats = tree->GetPerfStats();
288 if (file->ReadBuffer(buffer,len)) {
289 gPerfStats = temp;
290 return 1; //error while reading
291 }
292 else gPerfStats = temp;
293 }
294
297 Streamer(*fBufferRef);
298
299 return 0;
300}
301
302////////////////////////////////////////////////////////////////////////////////
303/// Remove the first dentries of this basket, moving entries at
304/// dentries to the start of the buffer.
305
307{
308 Int_t i;
309
310 if (dentries >= fNevBuf) return;
311 Int_t bufbegin;
312 Int_t moved;
313
314 Int_t *entryOffset = GetEntryOffset();
315 if (entryOffset) {
316 bufbegin = entryOffset[dentries];
317 moved = bufbegin-GetKeylen();
318
319 // First store the original location in the fDisplacement array
320 // and record the new start offset
321
322 if (!fDisplacement) {
324 }
325 for (i = 0; i<(fNevBufSize-dentries); ++i) {
326 fDisplacement[i] = entryOffset[i + dentries];
327 entryOffset[i] = entryOffset[i + dentries] - moved;
328 }
329 for (i = fNevBufSize-dentries; i<fNevBufSize; ++i) {
330 fDisplacement[i] = 0;
331 entryOffset[i] = 0;
332 }
333
334 } else {
335 // If there is no EntryOffset array, this means
336 // that each entry has the same size and that
337 // it does not point to other objects (hence there
338 // is no need for a displacement array).
339 bufbegin = GetKeylen() + dentries*fNevBufSize;
340 moved = bufbegin-GetKeylen();
341 }
342 TBuffer *buf = GetBufferRef();
343 char *buffer = buf->Buffer();
344 memmove(buffer+GetKeylen(),buffer+bufbegin,buf->Length()-bufbegin);
345 buf->SetBufferOffset(buf->Length()-moved);
346 fNevBuf -= dentries;
347}
348
349#define OLD_CASE_EXPRESSION fObjlen==fNbytes-fKeylen && GetBranch()->GetCompressionLevel()!=0 && file->GetVersion()<=30401
350////////////////////////////////////////////////////////////////////////////////
351/// By-passing buffer unzipping has been requested and is
352/// possible (only 1 entry in this basket).
353
355{
357
358 // Make sure that the buffer is set at the END of the data
360
361 // Indicate that this buffer is weird.
363
364 // Usage of this mode assume the existance of only ONE
365 // entry in this basket.
367 delete [] fDisplacement; fDisplacement = 0;
368
370 return 0;
371}
372
373////////////////////////////////////////////////////////////////////////////////
374/// We always create the TBuffer for the basket but it hold the buffer from the cache.
375
377{
378 if (fBufferRef) {
379 fBufferRef->SetBuffer(buffer, size, mustFree);
381 fBufferRef->Reset();
382 } else {
383 fBufferRef = new TBufferFile(TBuffer::kRead, size, buffer, mustFree);
384 }
386
387 Streamer(*fBufferRef);
388
389 if (IsZombie()) {
390 return -1;
391 }
392
393 Bool_t oldCase = OLD_CASE_EXPRESSION;
394
395 if ((fObjlen > fNbytes-fKeylen || oldCase) && TestBit(TBufferFile::kNotDecompressed) && (fNevBuf==1)) {
397 }
398
400 return fObjlen+fKeylen;
401}
402
403////////////////////////////////////////////////////////////////////////////////
404/// Initialize a buffer for reading if it is not already initialized
405
407{
408 TBuffer* result;
409 if (R__likely(bufferRef)) {
410 bufferRef->SetReadMode();
411 Int_t curBufferSize = bufferRef->BufferSize();
412 if (curBufferSize < len) {
413 // Experience shows that giving 5% "wiggle-room" decreases churn.
414 bufferRef->Expand(Int_t(len*1.05));
415 }
416 bufferRef->Reset();
417 result = bufferRef;
418 } else {
419 result = new TBufferFile(TBuffer::kRead, len);
420 }
421 result->SetParent(file);
422 return result;
423}
424
425////////////////////////////////////////////////////////////////////////////////
426/// Initialize the compressed buffer; either from the TTree or create a local one.
427
429{
430 Bool_t compressedBufferExists = fCompressedBufferRef != NULL;
432 if (R__unlikely(!compressedBufferExists)) {
434 }
435}
436
438{
439 if (fEntryOffset != reinterpret_cast<Int_t *>(-1)) {
440 delete[] fEntryOffset;
441 }
442 fEntryOffset = nullptr;
443}
444
445////////////////////////////////////////////////////////////////////////////////
446/// Read basket buffers in memory and cleanup.
447///
448/// Read a basket buffer. Check if buffers of previous ReadBasket
449/// should not be dropped. Remember, we keep buffers in memory up to
450/// fMaxVirtualSize.
451/// The function returns 0 in case of success, 1 in case of error
452/// This function was modified with the addition of the parallel
453/// unzipping, it will try to get the unzipped file from the cache
454/// receiving only a pointer to that buffer (so we shall not
455/// delete that pointer), although we get a new buffer in case
456/// it's not found in the cache.
457/// There is a lot of code duplication but it was necesary to assure
458/// the expected behavior when there is no cache.
459
461{
462 if(!fBranch->GetDirectory()) {
463 return -1;
464 }
465
466 Bool_t oldCase;
467 char *rawUncompressedBuffer, *rawCompressedBuffer;
468 Int_t uncompressedBufferLen;
469
470 // See if the cache has already unzipped the buffer for us.
471 TFileCacheRead *pf = nullptr;
472 {
473 R__LOCKGUARD_IMT(gROOTMutex); // Lock for parallel TTree I/O
475 }
476 if (pf) {
477 Int_t res = -1;
478 Bool_t free = kTRUE;
479 char *buffer = nullptr;
480 res = pf->GetUnzipBuffer(&buffer, pos, len, &free);
481 if (R__unlikely(res >= 0)) {
482 len = ReadBasketBuffersUnzip(buffer, res, free, file);
483 // Note that in the kNotDecompressed case, the above function will return 0;
484 // In such a case, we should stop processing
485 if (len <= 0) return -len;
486 goto AfterBuffer;
487 }
488 }
489
490 // Determine which buffer to use, so that we can avoid a memcpy in case of
491 // the basket was not compressed.
492 TBuffer* readBufferRef;
494 readBufferRef = fBufferRef;
495 } else {
496 readBufferRef = fCompressedBufferRef;
497 }
498
499 // fBufferSize is likely to be change in the Streamer call (below)
500 // and we will re-add the new size later on.
502
503 // Initialize the buffer to hold the compressed data.
504 readBufferRef = R__InitializeReadBasketBuffer(readBufferRef, len, file);
505 if (!readBufferRef) {
506 Error("ReadBasketBuffers", "Unable to allocate buffer.");
507 return 1;
508 }
509
510 if (pf) {
513 Int_t st = 0;
514 {
515 R__LOCKGUARD_IMT(gROOTMutex); // Lock for parallel TTree I/O
516 st = pf->ReadBuffer(readBufferRef->Buffer(),pos,len);
517 }
518 if (st < 0) {
519 return 1;
520 } else if (st == 0) {
521 // Read directly from file, not from the cache
522 // If we are using a TTreeCache, disable reading from the default cache
523 // temporarily, to force reading directly from file
524 R__LOCKGUARD_IMT(gROOTMutex); // Lock for parallel TTree I/O
525 TTreeCache *fc = dynamic_cast<TTreeCache*>(file->GetCacheRead());
526 if (fc) fc->Disable();
527 Int_t ret = file->ReadBuffer(readBufferRef->Buffer(),pos,len);
528 if (fc) fc->Enable();
529 pf->AddNoCacheBytesRead(len);
530 pf->AddNoCacheReadCalls(1);
531 if (ret) {
532 return 1;
533 }
534 }
535 gPerfStats = temp;
536 } else {
537 // Read from the file and unstream the header information.
540 R__LOCKGUARD_IMT(gROOTMutex); // Lock for parallel TTree I/O
541 if (file->ReadBuffer(readBufferRef->Buffer(),pos,len)) {
542 gPerfStats = temp;
543 return 1;
544 }
545 else gPerfStats = temp;
546 }
547 Streamer(*readBufferRef);
548 if (IsZombie()) {
549 return 1;
550 }
551
552 rawCompressedBuffer = readBufferRef->Buffer();
553
554 // Are we done?
555 if (R__unlikely(readBufferRef == fBufferRef)) // We expect most basket to be compressed.
556 {
558 // The basket was really not compressed as expected.
559 goto AfterBuffer;
560 } else {
561 // Well, somehow the buffer was compressed anyway, we have the compressed data in the uncompressed buffer
562 // Make sure the compressed buffer is initialized, and memcpy.
565 Error("ReadBasketBuffers", "Unable to allocate buffer.");
566 return 1;
567 }
568 fBufferRef->Reset();
569 rawCompressedBuffer = fCompressedBufferRef->Buffer();
570 memcpy(rawCompressedBuffer, fBufferRef->Buffer(), len);
571 }
572 }
573
574 // Initialize buffer to hold the uncompressed data
575 // Note that in previous versions we didn't allocate buffers until we verified
576 // the zip headers; this is no longer beforehand as the buffer lifetime is scoped
577 // to the TBranch.
578 uncompressedBufferLen = len > fObjlen+fKeylen ? len : fObjlen+fKeylen;
579 fBufferRef = R__InitializeReadBasketBuffer(fBufferRef, uncompressedBufferLen, file);
580 rawUncompressedBuffer = fBufferRef->Buffer();
581 fBuffer = rawUncompressedBuffer;
582
583 oldCase = OLD_CASE_EXPRESSION;
584 // Case where ROOT thinks the buffer is compressed. Copy over the key and uncompress the object
585 if (fObjlen > fNbytes-fKeylen || oldCase) {
588 }
589
590 // Optional monitor for zip time profiling.
591 Double_t start = 0;
592 if (R__unlikely(gPerfStats)) {
593 start = TTimeStamp();
594 }
595
596 memcpy(rawUncompressedBuffer, rawCompressedBuffer, fKeylen);
597 char *rawUncompressedObjectBuffer = rawUncompressedBuffer+fKeylen;
598 UChar_t *rawCompressedObjectBuffer = (UChar_t*)rawCompressedBuffer+fKeylen;
599 Int_t nin, nbuf;
600 Int_t nout = 0, noutot = 0, nintot = 0;
601
602 // Unzip all the compressed objects in the compressed object buffer.
603 while (1) {
604 // Check the header for errors.
605 if (R__unlikely(R__unzip_header(&nin, rawCompressedObjectBuffer, &nbuf) != 0)) {
606 Error("ReadBasketBuffers", "Inconsistency found in header (nin=%d, nbuf=%d)", nin, nbuf);
607 break;
608 }
609 if (R__unlikely(oldCase && (nin > fObjlen || nbuf > fObjlen))) {
610 //buffer was very likely not compressed in an old version
611 memcpy(rawUncompressedBuffer+fKeylen, rawCompressedObjectBuffer+fKeylen, fObjlen);
612 goto AfterBuffer;
613 }
614
615 R__unzip(&nin, rawCompressedObjectBuffer, &nbuf, (unsigned char*) rawUncompressedObjectBuffer, &nout);
616 if (!nout) break;
617 noutot += nout;
618 nintot += nin;
619 if (noutot >= fObjlen) break;
620 rawCompressedObjectBuffer += nin;
621 rawUncompressedObjectBuffer += nout;
622 }
623
624 // Make sure the uncompressed numbers are consistent with header.
625 if (R__unlikely(noutot != fObjlen)) {
626 Error("ReadBasketBuffers", "fNbytes = %d, fKeylen = %d, fObjlen = %d, noutot = %d, nout=%d, nin=%d, nbuf=%d", fNbytes,fKeylen,fObjlen, noutot,nout,nin,nbuf);
628 return 1;
629 }
630 len = fObjlen+fKeylen;
633 if (R__unlikely(gPerfStats)) {
634 gPerfStats->UnzipEvent(fBranch->GetTree(),pos,start,nintot,fObjlen);
635 }
636 gPerfStats = temp;
637 } else {
638 // Nothing is compressed - copy over wholesale.
639 memcpy(rawUncompressedBuffer, rawCompressedBuffer, len);
640 }
641
642AfterBuffer:
643
645
646 // Read offsets table if needed.
647 // If there's no EntryOffsetLen in the branch -- or the fEntryOffset is marked to be calculated-on-demand --
648 // then we skip reading out.
649 if (!fBranch->GetEntryOffsetLen() || (fEntryOffset == reinterpret_cast<Int_t *>(-1))) {
650 return 0;
651 }
652 // At this point, we're required to read out an offset array.
653 ResetEntryOffset(); // TODO: every basket, we reset the offset array. Is this necessary?
654 // Could we instead switch to std::vector?
658 fEntryOffset = new Int_t[fNevBuf+1];
660 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);
661 return 0;
662 }
664 // In this case, we cannot regenerate the offset array at runtime -- but we wrote out an array of
665 // sizes instead of offsets (as sizes compress much better).
667 for (Int_t idx = 1; idx < fNevBuf + 1; idx++) {
668 fEntryOffset[idx] += fEntryOffset[idx - 1];
669 }
670 }
672 // Read the array of diplacement if any.
673 delete [] fDisplacement;
674 fDisplacement = 0;
675 if (fBufferRef->Length() != len) {
676 // There is more data in the buffer! It is the displacement
677 // array. If len is less than TBuffer::kMinimalSize the actual
678 // size of the buffer is too large, so we can not use the
679 // fBufferRef->BufferSize()
681 }
682
683 return 0;
684}
685
686////////////////////////////////////////////////////////////////////////////////
687/// Read basket buffers in memory and cleanup
688///
689/// Read first bytes of a logical record starting at position pos
690/// return record length (first 4 bytes of record).
691
693{
694 const Int_t len = 128;
695 char buffer[len];
696 Int_t keylen;
697 file->GetRecordHeader(buffer, pos,len, fNbytes, fObjlen, keylen);
698 fKeylen = keylen;
699 return fNbytes;
700}
701
702////////////////////////////////////////////////////////////////////////////////
703/// Reset the basket to the starting state. i.e. as it was after calling
704/// the constructor (and potentially attaching a TBuffer.)
705/// Reduce memory used by fEntryOffset and the TBuffer if needed ..
706
708{
709 // By default, we don't reallocate.
710 fResetAllocation = false;
711#ifdef R__TRACK_BASKET_ALLOC_TIME
712 fResetAllocationTime = 0;
713#endif
714
715 // Name, Title, fClassName, fBranch
716 // stay the same.
717
718 // Downsize the buffer if needed.
719 // See if our current buffer size is significantly larger (>2x) than the historical average.
720 // If so, try decreasing it at this flush boundary to closer to the size from OptimizeBaskets
721 // (or this historical average).
722 Int_t curSize = fBufferRef->BufferSize();
723 // fBufferLen at this point is already reset, so use indirect measurements
724 Int_t curLen = (GetObjlen() + GetKeylen());
725 Long_t newSize = -1;
726 if (curSize > 2*curLen)
727 {
728 Long_t curBsize = fBranch->GetBasketSize();
729 if (curSize > 2*curBsize ) {
730 Long_t avgSize = (Long_t)(fBranch->GetTotBytes() / (1+fBranch->GetWriteBasket())); // Average number of bytes per basket so far
731 if (curSize > 2*avgSize) {
732 newSize = curBsize;
733 if (curLen > newSize) {
734 newSize = curLen;
735 }
736 if (avgSize > newSize) {
737 newSize = avgSize;
738 }
739 newSize = newSize + 512 - newSize%512; // Wiggle room and alignment (512 is same as in OptimizeBaskets)
740 }
741 }
742 }
743 // If fBufferRef grew since we last saw it, shrink it to "target memory ratio" of the occupied size
744 // This discourages us from having poorly-occupied buffers on branches with little variability.
745 //
746 // Does not help protect against a burst in event sizes, but does help in the cases where the basket
747 // size jumps from 4MB to 8MB while filling the basket, but we only end up utilizing 4.1MB.
748 //
749 // The above code block is meant to protect against extremely large events.
750
751 Float_t target_mem_ratio = fBranch->GetTree()->GetTargetMemoryRatio();
753 Int_t target_size = static_cast<Int_t>(target_mem_ratio * Float_t(max_size));
754 if (max_size && (curSize > target_size) && (newSize == -1)) {
755 newSize = target_size;
756 newSize = newSize + 512 - newSize % 512; // Wiggle room and alignment, as above.
757 // We only bother with a resize if it saves 8KB (two normal memory pages).
758 if ((newSize > curSize - 8 * 1024) ||
759 (static_cast<Float_t>(curSize) / static_cast<Float_t>(newSize) < target_mem_ratio)) {
760 newSize = -1;
761 } else if (gDebug > 0) {
762 Info("Reset", "Resizing to %ld bytes (was %d); last three sizes were [%d, %d, %d].", newSize, curSize,
764 }
765 }
766
767 if (newSize != -1) {
768 fResetAllocation = true;
769#ifdef R__TRACK_BASKET_ALLOC_TIME
770 std::chrono::time_point<std::chrono::system_clock> start, end;
771 start = std::chrono::high_resolution_clock::now();
772#endif
773 fBufferRef->Expand(newSize,kFALSE); // Expand without copying the existing data.
774#ifdef R__TRACK_BASKET_ALLOC_TIME
775 end = std::chrono::high_resolution_clock::now();
776 auto us = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
777 fResetAllocationTime = us.count();
778#endif
779 }
780
781 // Record the actual occupied size of the buffer.
784
785 TKey::Reset();
786
787 Int_t newNevBufSize = fBranch->GetEntryOffsetLen();
788 if (newNevBufSize==0) {
790 } else if ((newNevBufSize != fNevBufSize) || (fEntryOffset <= reinterpret_cast<Int_t *>(-1))) {
792 fEntryOffset = new Int_t[newNevBufSize];
793 }
794 fNevBufSize = newNevBufSize;
795
796 fNevBuf = 0;
797 Int_t *storeEntryOffset = fEntryOffset;
798 fEntryOffset = 0;
799 Int_t *storeDisplacement = fDisplacement;
800 fDisplacement= 0;
801 fBuffer = 0;
802
803 fBufferRef->Reset();
805
807 fLast = 0; //Must initialize before calling Streamer()
808
809 Streamer(*fBufferRef);
810
813 fLast = fKeylen;
814 fBuffer = 0;
816 fDisplacement= storeDisplacement;
817 fEntryOffset = storeEntryOffset;
818 if (fNevBufSize) {
819 for (Int_t i=0;i<fNevBufSize;i++) fEntryOffset[i] = 0;
820 }
821}
822
823////////////////////////////////////////////////////////////////////////////////
824/// Set read mode of basket.
825
827{
830}
831
832////////////////////////////////////////////////////////////////////////////////
833/// Set write mode of basket.
834
836{
839}
840
841////////////////////////////////////////////////////////////////////////////////
842/// Stream a class object.
843
844void TBasket::Streamer(TBuffer &b)
845{
846 // As in TBranch::GetBasket, this is used as a half-hearted measure to suppress
847 // the error reporting when many failures occur.
848 static std::atomic<Int_t> nerrors(0);
849
850 char flag;
851 if (b.IsReading()) {
852 TKey::Streamer(b); //this must be first
853 Version_t v = b.ReadVersion();
854 b >> fBufferSize;
855 // NOTE: we now use the upper-bit of the fNevBufSize to see if we have serialized any of the
856 // optional IOBits. If that bit is set, we immediately read out the IOBits; to replace this
857 // (minimal) safeguard against corruption, we will set aside the upper-bit of fIOBits to do
858 // the same thing (the fact this bit is reserved is tested in the unit tests). If there is
859 // someday a need for more than 7 IOBits, we'll widen the field using the same trick.
860 //
861 // We like to keep this safeguard because we immediately will allocate a buffer based on
862 // the value of fNevBufSize -- and would like to avoid wildly inappropriate allocations.
863 b >> fNevBufSize;
864 if (fNevBufSize < 0) {
866 b >> fIOBits;
867 if (!fIOBits || (fIOBits & (1 << 7))) {
868 Error("TBasket::Streamer",
869 "The value of fNevBufSize (%d) or fIOBits (%d) is incorrect ; setting the buffer to a zombie.",
871 MakeZombie();
872 fNevBufSize = 0;
873 } else if (fIOBits && (fIOBits & ~static_cast<Int_t>(EIOBits::kSupported))) {
874 nerrors++;
875 if (nerrors < 10) {
876 Error("Streamer", "The value of fIOBits (%s) contains unknown flags (supported flags "
877 "are %s), indicating this was written with a newer version of ROOT "
878 "utilizing critical IO features this version of ROOT does not support."
879 " Refusing to deserialize.",
880 std::bitset<32>(static_cast<Int_t>(fIOBits)).to_string().c_str(),
881 std::bitset<32>(static_cast<Int_t>(EIOBits::kSupported)).to_string().c_str());
882 } else if (nerrors == 10) {
883 Error("Streamer", "Maximum number of errors has been reported; disabling further messages"
884 "from this location until the process exits.");
885 }
886 fNevBufSize = 0;
887 MakeZombie();
888 }
889 }
890 b >> fNevBuf;
891 b >> fLast;
892 b >> flag;
894 Bool_t mustGenerateOffsets = false;
895 if (flag >= 80) {
896 mustGenerateOffsets = true;
897 flag -= 80;
898 }
899 if (!mustGenerateOffsets && flag && (flag % 10 != 2)) {
902 if (fNevBuf) b.ReadArray(fEntryOffset);
903 if (20<flag && flag<40) {
904 for(int i=0; i<fNevBuf; i++){
905 fEntryOffset[i] &= ~kDisplacementMask;
906 }
907 }
908 if (flag>40) {
910 b.ReadArray(fDisplacement);
911 }
912 } else if (mustGenerateOffsets) {
913 // We currently believe that in all cases when offsets can be generated, then the
914 // displacement array must be zero.
915 assert(flag <= 40);
916 fEntryOffset = reinterpret_cast<Int_t *>(-1);
917 }
918 if (flag == 1 || flag > 10) {
920 fBufferRef->SetParent(b.GetParent());
921 char *buf = fBufferRef->Buffer();
922 if (v > 1) b.ReadFastArray(buf,fLast);
923 else b.ReadArray(buf);
925 // This is now done in the TBranch streamer since fBranch might not
926 // yet be set correctly.
927 // fBranch->GetTree()->IncrementTotalBuffers(fBufferSize);
928 }
929 } else {
930
931 TKey::Streamer(b); //this must be first
932 b.WriteVersion(TBasket::IsA());
933 if (fBufferRef) {
934 Int_t curLast = fBufferRef->Length();
935 if (!fHeaderOnly && !fSeekKey && curLast > fLast) fLast = curLast;
936 }
938
939 b << fBufferSize;
940 if (fIOBits) {
941 b << -fNevBufSize;
942 b << fIOBits;
943 } else {
944 b << fNevBufSize;
945 }
946 b << fNevBuf;
947 b << fLast;
948 Bool_t mustGenerateOffsets = fEntryOffset && fNevBuf &&
951 // We currently believe that in all cases when offsets can be generated, then the
952 // displacement array must be zero.
953 assert(!mustGenerateOffsets || fDisplacement == nullptr);
954 if (fHeaderOnly) {
955 flag = mustGenerateOffsets ? 80 : 0;
956 b << flag;
957 } else {
958 // On return from this function, we are guaranteed that fEntryOffset
959 // is either a valid pointer or nullptr.
960 if (fNevBuf) {
962 }
963 flag = 1;
964 if (!fNevBuf || !fEntryOffset)
965 flag = 2;
966 if (fBufferRef) flag += 10;
967 if (fDisplacement) flag += 40;
968 // Test if we can skip writing out the offset map.
969 if (mustGenerateOffsets) {
970 flag += 80;
971 }
972 b << flag;
973
974 if (!mustGenerateOffsets && fEntryOffset && fNevBuf) {
975 b.WriteArray(fEntryOffset, fNevBuf);
976 if (fDisplacement) b.WriteArray(fDisplacement, fNevBuf);
977 }
978 if (fBufferRef) {
979 char *buf = fBufferRef->Buffer();
980 b.WriteFastArray(buf, fLast);
981 }
982 }
983 }
984}
985
986////////////////////////////////////////////////////////////////////////////////
987/// Update basket header and EntryOffset table.
988
989void TBasket::Update(Int_t offset, Int_t skipped)
990{
991 Int_t *entryOffset = GetEntryOffset();
992 if (entryOffset) {
993 if (fNevBuf+1 >= fNevBufSize) {
994 Int_t newsize = TMath::Max(10,2*fNevBufSize);
995 Int_t *newoff = TStorage::ReAllocInt(fEntryOffset, newsize,
997 if (fDisplacement) {
998 Int_t *newdisp = TStorage::ReAllocInt(fDisplacement, newsize,
1000 fDisplacement = newdisp;
1001 }
1002 fEntryOffset = newoff;
1003 fNevBufSize = newsize;
1004
1005 //Update branch only for the first 10 baskets
1006 if (fBranch->GetWriteBasket() < 10) {
1007 fBranch->SetEntryOffsetLen(newsize);
1008 }
1009 }
1010 fEntryOffset[fNevBuf] = offset;
1011
1012 if (skipped!=offset && !fDisplacement){
1014 for (Int_t i = 0; i<fNevBufSize; i++) fDisplacement[i] = fEntryOffset[i];
1015 }
1016 if (fDisplacement) {
1017 fDisplacement[fNevBuf] = skipped;
1019 }
1020 }
1021
1022 fNevBuf++;
1023}
1024
1025////////////////////////////////////////////////////////////////////////////////
1026/// Write buffer of this basket on the current file.
1027///
1028/// The function returns the number of bytes committed to the memory.
1029/// If a write error occurs, the number of bytes returned is -1.
1030/// If no data are written, the number of bytes returned is 0.
1031
1033{
1034 const Int_t kWrite = 1;
1035
1036 TFile *file = fBranch->GetFile(kWrite);
1037 if (!file) return 0;
1038 if (!file->IsWritable()) {
1039 return -1;
1040 }
1041 fMotherDir = file; // fBranch->GetDirectory();
1042
1043 // This mutex prevents multiple TBasket::WriteBuffer invocations from interacting
1044 // with the underlying TFile at once - TFile is assumed to *not* be thread-safe.
1045 //
1046 // The only parallelism we'd like to exploit (right now!) is the compression
1047 // step - everything else should be serialized at the TFile level.
1048#ifdef R__USE_IMT
1049 std::unique_lock<std::mutex> sentry(file->fWriteMutex);
1050#endif // R__USE_IMT
1051
1053 // Read the basket information that was saved inside the buffer.
1054 Bool_t writing = fBufferRef->IsWriting();
1057
1058 Streamer(*fBufferRef);
1059 if (writing) fBufferRef->SetWriteMode();
1060 Int_t nout = fNbytes - fKeylen;
1061
1063
1064 Create(nout,file);
1067
1068 Streamer(*fBufferRef); //write key itself again
1069 int nBytes = WriteFileKeepBuffer();
1071 return nBytes>0 ? fKeylen+nout : -1;
1072 }
1073
1074 // Transfer fEntryOffset table at the end of fBuffer.
1075 fLast = fBufferRef->Length();
1076 Int_t *entryOffset = GetEntryOffset();
1077 if (entryOffset) {
1078 Bool_t hasOffsetBit = fIOBits & static_cast<UChar_t>(TBasket::EIOBits::kGenerateOffsetMap);
1079 if (!CanGenerateOffsetArray()) {
1080 // If we have set the offset map flag, but cannot dynamically generate the map, then
1081 // we should at least convert the offset array to a size array. Note that we always
1082 // write out (fNevBuf+1) entries to match the original case.
1083 if (hasOffsetBit) {
1084 for (Int_t idx = fNevBuf; idx > 0; idx--) {
1085 entryOffset[idx] -= entryOffset[idx - 1];
1086 }
1087 entryOffset[0] = 0;
1088 }
1089 fBufferRef->WriteArray(entryOffset, fNevBuf + 1);
1090 // Convert back to offset format: keeping both sizes and offsets in-memory were considered,
1091 // but it seems better to use CPU than memory.
1092 if (hasOffsetBit) {
1093 entryOffset[0] = fKeylen;
1094 for (Int_t idx = 1; idx < fNevBuf + 1; idx++) {
1095 entryOffset[idx] += entryOffset[idx - 1];
1096 }
1097 }
1098 } else if (!hasOffsetBit) { // In this case, write out as normal
1099 fBufferRef->WriteArray(entryOffset, fNevBuf + 1);
1100 }
1101 if (fDisplacement) {
1103 delete[] fDisplacement;
1104 fDisplacement = 0;
1105 }
1106 }
1107
1108 Int_t lbuf, nout, noutot, bufmax, nzip;
1109 lbuf = fBufferRef->Length();
1110 fObjlen = lbuf - fKeylen;
1111
1114 Int_t cxlevel = fBranch->GetCompressionLevel();
1116 if (cxlevel > 0) {
1117 Int_t nbuffers = 1 + (fObjlen - 1) / kMAXZIPBUF;
1118 Int_t buflen = fKeylen + fObjlen + 9 * nbuffers + 28; //add 28 bytes in case object is placed in a deleted gap
1120 if (!fCompressedBufferRef) {
1121 Warning("WriteBuffer", "Unable to allocate the compressed buffer");
1122 return -1;
1123 }
1126 char *objbuf = fBufferRef->Buffer() + fKeylen;
1127 char *bufcur = &fBuffer[fKeylen];
1128 noutot = 0;
1129 nzip = 0;
1130 for (Int_t i = 0; i < nbuffers; ++i) {
1131 if (i == nbuffers - 1) bufmax = fObjlen - nzip;
1132 else bufmax = kMAXZIPBUF;
1133 // Compress the buffer. Note that we allow multiple TBasket compressions to occur at once
1134 // for a given TFile: that's because the compression buffer when we use IMT is no longer
1135 // shared amongst several threads.
1136#ifdef R__USE_IMT
1137 sentry.unlock();
1138#endif // R__USE_IMT
1139 // NOTE this is declared with C linkage, so it shouldn't except. Also, when
1140 // USE_IMT is defined, we are guaranteed that the compression buffer is unique per-branch.
1141 // (see fCompressedBufferRef in constructor).
1142 R__zipMultipleAlgorithm(cxlevel, &bufmax, objbuf, &bufmax, bufcur, &nout, cxAlgorithm);
1143#ifdef R__USE_IMT
1144 sentry.lock();
1145#endif // R__USE_IMT
1146
1147 // test if buffer has really been compressed. In case of small buffers
1148 // when the buffer contains random data, it may happen that the compressed
1149 // buffer is larger than the input. In this case, we write the original uncompressed buffer
1150 if (nout == 0 || nout >= fObjlen) {
1151 nout = fObjlen;
1152 // We used to delete fBuffer here, we no longer want to since
1153 // the buffer (held by fCompressedBufferRef) might be re-used later.
1157
1158 Streamer(*fBufferRef); //write key itself again
1159 if ((nout+fKeylen)>buflen) {
1160 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",
1161 (nout+fKeylen-buflen),buflen,fNbytes,fObjlen,fKeylen);
1162 }
1163 goto WriteFile;
1164 }
1165 bufcur += nout;
1166 noutot += nout;
1167 objbuf += kMAXZIPBUF;
1168 nzip += kMAXZIPBUF;
1169 }
1170 nout = noutot;
1171 Create(noutot,file);
1173
1174 Streamer(*fBufferRef); //write key itself again
1175 memcpy(fBuffer,fBufferRef->Buffer(),fKeylen);
1176 } else {
1180
1181 Streamer(*fBufferRef); //write key itself again
1182 nout = fObjlen;
1183 }
1184
1185WriteFile:
1186 Int_t nBytes = WriteFileKeepBuffer();
1188 return nBytes>0 ? fKeylen+nout : -1;
1189}
SVector< double, 2 > v
Definition: Dict.h:5
#define R__likely(expr)
Definition: RConfig.hxx:579
#define R__unlikely(expr)
Definition: RConfig.hxx:578
#define b(i)
Definition: RSha256.hxx:100
int Int_t
Definition: RtypesCore.h:41
short Version_t
Definition: RtypesCore.h:61
unsigned char UChar_t
Definition: RtypesCore.h:34
unsigned int UInt_t
Definition: RtypesCore.h:42
const Bool_t kFALSE
Definition: RtypesCore.h:88
long Long_t
Definition: RtypesCore.h:50
bool Bool_t
Definition: RtypesCore.h:59
double Double_t
Definition: RtypesCore.h:55
long long Long64_t
Definition: RtypesCore.h:69
float Float_t
Definition: RtypesCore.h:53
const Bool_t kTRUE
Definition: RtypesCore.h:87
#define ClassImp(name)
Definition: Rtypes.h:363
R__EXTERN Int_t gDebug
Definition: Rtypes.h:90
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:406
#define OLD_CASE_EXPRESSION
Definition: TBasket.cxx:349
const UInt_t kDisplacementMask
Definition: TBasket.cxx:32
R__EXTERN TVirtualMutex * gROOTMutex
Definition: TROOT.h:57
void R__unzip(Int_t *nin, UChar_t *bufin, Int_t *lout, char *bufout, Int_t *nout)
int R__unzip_header(Int_t *nin, UChar_t *bufin, Int_t *lout)
#define R__LOCKGUARD_IMT(mutex)
#define gPerfStats
#define free
Definition: civetweb.c:1539
static struct mg_connection * fc(struct mg_context *ctx)
Definition: civetweb.c:3728
Manages buffers for branches of a Tree.
Definition: TBasket.h:34
virtual void Reset()
Reset the basket to the starting state.
Definition: TBasket.cxx:707
Int_t * fEntryOffset
[fNevBuf] Offset of entries in fBuffer(TKey); generated at runtime.
Definition: TBasket.h:66
Int_t GetEntryPointer(Int_t Entry)
Get pointer to buffer for internal entry.
Definition: TBasket.cxx:226
Bool_t fOwnsCompressedBuffer
! Whether or not we own the compressed buffer.
Definition: TBasket.h:63
TBranch * fBranch
Pointer to the basket support branch.
Definition: TBasket.h:68
Long64_t CopyTo(TFile *to)
Copy the basket of this branch onto the file to.
Definition: TBasket.cxx:142
Int_t * GetEntryOffset()
Definition: TBasket.h:117
void InitializeCompressedBuffer(Int_t len, TFile *file)
Initialize the compressed buffer; either from the TTree or create a local one.
Definition: TBasket.cxx:428
UChar_t fNextBufferSizeRecord
! Index into fLastWriteBufferSize of the last buffer written to disk
Definition: TBasket.h:72
Bool_t CanGenerateOffsetArray()
Determine whether we can generate the offset array when this branch is read.
Definition: TBasket.cxx:214
Bool_t fHeaderOnly
True when only the basket header must be read/written.
Definition: TBasket.h:61
Int_t fLastWriteBufferSize[3]
! Size of the buffer last three buffers we wrote it to disk
Definition: TBasket.h:70
Int_t ReadBasketBuffers(Long64_t pos, Int_t len, TFile *file)
Read basket buffers in memory and cleanup.
Definition: TBasket.cxx:460
UChar_t fIOBits
!IO feature flags. Serialized in custom portion of streamer to avoid forward compat issues unless nee...
Definition: TBasket.h:62
virtual Int_t DropBuffers()
Drop buffers of this basket if it is not the current basket.
Definition: TBasket.cxx:169
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:306
void ResetEntryOffset()
Definition: TBasket.cxx:437
TBasket()
Default contructor.
Definition: TBasket.cxx:48
virtual void AdjustSize(Int_t newsize)
Increase the size of the current fBuffer up to newsize.
Definition: TBasket.cxx:123
Int_t LoadBasketBuffers(Long64_t pos, Int_t len, TFile *file, TTree *tree=0)
Load basket buffers in memory without unziping.
Definition: TBasket.cxx:241
Bool_t fResetAllocation
! True if last reset re-allocated the memory
Definition: TBasket.h:71
virtual void SetReadMode()
Set read mode of basket.
Definition: TBasket.cxx:826
virtual void SetWriteMode()
Set write mode of basket.
Definition: TBasket.cxx:835
Int_t ReadBasketBuffersUncompressedCase()
By-passing buffer unzipping has been requested and is possible (only 1 entry in this basket).
Definition: TBasket.cxx:354
Int_t fBufferSize
fBuffer length in bytes
Definition: TBasket.h:57
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:376
Int_t ReadBasketBytes(Long64_t pos, TFile *file)
Read basket buffers in memory and cleanup.
Definition: TBasket.cxx:692
virtual Int_t WriteBuffer()
Write buffer of this basket on the current file.
Definition: TBasket.cxx:1032
void Update(Int_t newlast)
Definition: TBasket.h:145
Int_t fNevBufSize
Length in Int_t of fEntryOffset OR fixed length of each entry if fEntryOffset is null!
Definition: TBasket.h:58
Int_t fNevBuf
Number of entries in basket.
Definition: TBasket.h:59
Int_t * GetCalculatedEntryOffset()
Calculates the entry offset array, if possible.
Definition: TBasket.cxx:191
Bool_t fReadEntryOffset
!Set to true if offset array was read from a file.
Definition: TBasket.h:64
virtual ~TBasket()
Basket destructor.
Definition: TBasket.cxx:105
virtual void DeleteEntryOffset()
Delete fEntryOffset array.
Definition: TBasket.cxx:160
TBuffer * fCompressedBufferRef
! Compressed buffer.
Definition: TBasket.h:69
Int_t fLast
Pointer to last used byte in basket.
Definition: TBasket.h:60
Int_t * fDisplacement
![fNevBuf] Displacement of entries in fBuffer(TKey)
Definition: TBasket.h:65
A TTree is a list of TBranches.
Definition: TBranch.h:64
Int_t GetCompressionLevel() const
Definition: TBranch.h:261
Int_t GetCompressionAlgorithm() const
Definition: TBranch.h:255
TTree * GetTree() const
Definition: TBranch.h:209
Int_t GetWriteBasket() const
Definition: TBranch.h:195
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:2404
Int_t GetNleaves() const
Definition: TBranch.h:206
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:1508
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:1803
virtual Int_t GetBasketSize() const
Definition: TBranch.h:176
TObjArray * GetListOfLeaves()
Definition: TBranch.h:204
TDirectory * GetDirectory() const
Definition: TBranch.h:182
TBuffer * GetTransientBuffer(Int_t size)
Returns the transient buffer currently used by this TBranch for reading/writing baskets.
Definition: TBranch.cxx:496
Int_t GetEntryOffsetLen() const
Definition: TBranch.h:185
The concrete implementation of TBuffer for writing/reading to/from a ROOT file or socket.
Definition: TBufferFile.h:46
@ kNotDecompressed
Definition: TBufferIO.h:66
Buffer base class used for serializing objects.
Definition: TBuffer.h:40
void SetWriteMode()
Set buffer in write mode.
Definition: TBuffer.cxx:294
virtual void Reset()=0
void SetParent(TObject *parent)
Set parent owning this buffer.
Definition: TBuffer.cxx:249
void Expand(Int_t newsize, Bool_t copy=kTRUE)
Expand (or shrink) the I/O buffer to newsize bytes.
Definition: TBuffer.cxx:211
Int_t BufferSize() const
Definition: TBuffer.h:94
virtual void WriteArray(const Bool_t *b, Int_t n)=0
virtual Int_t ReadArray(Bool_t *&b)=0
@ kWrite
Definition: TBuffer.h:70
@ kRead
Definition: TBuffer.h:70
Bool_t IsWriting() const
Definition: TBuffer.h:84
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:175
void SetBufferOffset(Int_t offset=0)
Definition: TBuffer.h:90
void SetReadMode()
Set buffer in read mode.
Definition: TBuffer.cxx:281
virtual void SetBufferDisplacement()=0
Int_t Length() const
Definition: TBuffer.h:96
char * Buffer() const
Definition: TBuffer.h:93
Describe directory structure in memory.
Definition: TDirectory.h:34
A cache when reading files over the network.
virtual Int_t GetUnzipBuffer(char **, Long64_t, Int_t, Bool_t *)
virtual Int_t ReadBuffer(char *buf, Long64_t pos, Int_t len)
Read buffer at position pos.
virtual void AddNoCacheReadCalls(Int_t reads)
virtual void AddNoCacheBytesRead(Long64_t len)
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format.
Definition: TFile.h:48
Book space in a file, create I/O buffers, to fill them, (un)compress them.
Definition: TKey.h:24
virtual Int_t WriteFileKeepBuffer(TFile *f=0)
Write the encoded object supported by this key.
Definition: TKey.cxx:1460
Int_t GetKeylen() const
Definition: TKey.h:80
Int_t GetObjlen() const
Definition: TKey.h:83
TBuffer * fBufferRef
Pointer to the TBuffer object.
Definition: TKey.h:45
Int_t fVersion
Key version identifier.
Definition: TKey.h:34
virtual void Create(Int_t nbytes, TFile *f=0)
Create a TKey object of specified size.
Definition: TKey.cxx:458
Short_t fKeylen
Number of bytes for the key itself.
Definition: TKey.h:38
virtual Int_t WriteFile(Int_t cycle=1, TFile *f=0)
Write the encoded object supported by this key.
Definition: TKey.cxx:1419
Long64_t fSeekKey
Location of object on file.
Definition: TKey.h:40
char * fBuffer
Object buffer.
Definition: TKey.h:44
Int_t fNbytes
Number of bytes for the object on file.
Definition: TKey.h:35
Int_t fObjlen
Length of uncompressed object in bytes.
Definition: TKey.h:36
virtual void Reset()
Reset the key as it had not been 'filled' yet.
Definition: TKey.cxx:1274
Short_t fCycle
Cycle number.
Definition: TKey.h:39
TDirectory * fMotherDir
!pointer to mother directory
Definition: TKey.h:47
TString fClassName
Object Class name.
Definition: TKey.h:42
TBuffer * GetBufferRef() const
Definition: TKey.h:75
A TLeaf describes individual elements of a TBranch See TBranch structure in TTree.
Definition: TLeaf.h:32
virtual Bool_t CanGenerateOffsetArray()
Definition: TLeaf.h:71
virtual Int_t * GenerateOffsetArray(Int_t base, Int_t events)
Definition: TLeaf.h:74
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition: TNamed.cxx:164
virtual void SetName(const char *name)
Set the name of the TNamed.
Definition: TNamed.cxx:140
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition: TObject.h:172
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:866
R__ALWAYS_INLINE Bool_t IsZombie() const
Definition: TObject.h:134
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:694
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:880
void MakeZombie()
Definition: TObject.h:49
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:854
static Int_t * ReAllocInt(Int_t *vp, size_t size, size_t oldsize)
Reallocate (i.e.
Definition: TStorage.cxx:295
The TTimeStamp encapsulates seconds and ns since EPOCH.
Definition: TTimeStamp.h:71
A TTree object has a header with a name and a title.
Definition: TTree.h:71
virtual TVirtualPerfStats * GetPerfStats() const
Definition: TTree.h:445
virtual void IncrementTotalBuffers(Int_t nbytes)
Definition: TTree.h:485
TTreeCache * GetReadCache(TFile *file) const
Find and return the TTreeCache registered with the file and which may contain branches for us.
Definition: TTree.cxx:6072
Float_t GetTargetMemoryRatio() const
Definition: TTree.h:459
TBuffer * GetTransientBuffer(Int_t size)
Returns the transient buffer currently used by this TTree for reading/writing baskets.
Definition: TTree.cxx:985
Provides the interface for the PROOF internal performance measurement and event tracing.
static constexpr double us
Short_t Max(Short_t a, Short_t b)
Definition: TMathBase.h:212
Definition: file.py:1
Definition: tree.py:1
EValues
Note: this is only temporarily a struct and will become a enum class hence the name.
Definition: Compression.h:76