Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
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#include <limits>
13
14#include "TBasket.h"
15#include "TBuffer.h"
16#include "TBufferFile.h"
17#include "TTree.h"
18#include "TBranch.h"
19#include "TFile.h"
20#include "TLeaf.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
36constexpr auto gMaxInt_t = std::numeric_limits<Int_t>::max();
37
38/** \class TBasket
39\ingroup tree
40
41Manages buffers for branches of a Tree.
42
43See picture in TTree.
44*/
45
46////////////////////////////////////////////////////////////////////////////////
47/// Default constructor.
48
52
53////////////////////////////////////////////////////////////////////////////////
54/// Constructor used during reading.
55
59
60////////////////////////////////////////////////////////////////////////////////
61/// Basket normal constructor, used during writing.
62
63TBasket::TBasket(const char *name, const char *title, TBranch *branch)
64 : TKey(branch->GetDirectory()), fBufferSize(branch->GetBasketSize()), fNevBufSize(branch->GetEntryOffsetLen()),
65 fHeaderOnly(true), fIOBits(branch->GetIOFeatures().GetFeatures())
66{
68 SetTitle(title);
69 fClassName = "TBasket";
70 fBuffer = nullptr;
72 fVersion += 1000;
73 if (branch->GetDirectory()) {
74 TFile *file = branch->GetFile();
75 fBufferRef->SetParent(file);
76 }
77 if (branch->GetTree()) {
78#ifdef R__USE_IMT
79 fCompressedBufferRef = branch->GetTransientBuffer(fBufferSize);
80#else
81 fCompressedBufferRef = branch->GetTree()->GetTransientBuffer(fBufferSize);
82#endif
87 }
88 }
93 fLast = fKeylen;
94 fBuffer = nullptr;
95 fHeaderOnly = false;
96 if (fNevBufSize) {
98 for (Int_t i=0;i<fNevBufSize;i++) fEntryOffset[i] = 0;
99 }
100 branch->GetTree()->IncrementTotalBuffers(fBufferSize);
101}
102
103////////////////////////////////////////////////////////////////////////////////
104/// Basket destructor.
105
107{
108 if (fDisplacement) delete [] fDisplacement;
110 if (fBufferRef) delete fBufferRef;
111 fBufferRef = nullptr;
112 fBuffer = nullptr;
113 fDisplacement= nullptr;
114 // Note we only delete the compressed buffer if we own it
117 fCompressedBufferRef = nullptr;
118 }
119 // TKey::~TKey will use fMotherDir to attempt to remove they key
120 // from the directory's list of key. A basket is never in that list
121 // and in some cases (eg. f = new TFile(); TTree t; delete f;) the
122 // directory is gone before the TTree.
123 fMotherDir = nullptr;
124}
125
126////////////////////////////////////////////////////////////////////////////////
127/// Increase the size of the current fBuffer up to newsize.
128
144
145////////////////////////////////////////////////////////////////////////////////
146/// Copy the basket of this branch onto the file to.
147
149{
153 Create(nout, to);
155 fHeaderOnly = true;
157 fHeaderOnly = false;
159
160 return nBytes>0 ? nBytes : -1;
161}
162
163////////////////////////////////////////////////////////////////////////////////
164/// Delete fEntryOffset array.
165
171
172////////////////////////////////////////////////////////////////////////////////
173/// Drop buffers of this basket if it is not the current basket.
174
176{
177 if (!fBuffer && !fBufferRef) return 0;
178
179 if (fDisplacement) delete [] fDisplacement;
181 if (fBufferRef) delete fBufferRef;
183 fBufferRef = nullptr;
184 fCompressedBufferRef = nullptr;
185 fBuffer = nullptr;
186 fDisplacement= nullptr;
187 fEntryOffset = nullptr;
189 return fBufferSize;
190}
191
192////////////////////////////////////////////////////////////////////////////////
193/// Calculates the entry offset array, if possible.
194///
195/// Result is cached, meaning that this should only be invoked once per basket.
196
198{
199 if (fEntryOffset != reinterpret_cast<Int_t *>(-1)) {
200 return fEntryOffset;
201 }
202
203 if (R__unlikely(!fBranch)) {
204 Error("GetCalculatedEntryOffset", "Basket entry offset calculation requested, but no associated TBranch!");
205 return nullptr;
206 }
207 if (R__unlikely(fBranch->GetNleaves() != 1)) {
208 Error("GetCalculatedEntryOffset", "Branch contains multiple leaves - unable to calculated entry offsets!");
209 return nullptr;
210 }
211 TLeaf *leaf = static_cast<TLeaf *>((*fBranch->GetListOfLeaves())[0]);
212 fEntryOffset = leaf->GenerateOffsetArray(fKeylen, fNevBuf);
213 return fEntryOffset;
214}
215
216////////////////////////////////////////////////////////////////////////////////
217/// Determine whether we can generate the offset array when this branch is read.
218///
219
221{
222 if (fBranch->GetNleaves() != 1) {
223 return false;
224 }
225 TLeaf *leaf = static_cast<TLeaf *>((*fBranch->GetListOfLeaves())[0]);
226 return leaf->CanGenerateOffsetArray();
227}
228
229////////////////////////////////////////////////////////////////////////////////
230/// Get pointer to buffer for internal entry.
231
241
242////////////////////////////////////////////////////////////////////////////////
243/// Load basket buffers in memory without unziping.
244/// This function is called by TTreeCloner.
245/// The function returns 0 in case of success, 1 in case of error.
246
248{
249 if (fBufferRef) {
250 // Reuse the buffer if it exist.
251 fBufferRef->Reset();
252
253 // We use this buffer both for reading and writing, we need to
254 // make sure it is properly sized for writing.
256 if (fBufferRef->BufferSize() < len) {
258 }
260 } else {
262 }
263 fBufferRef->SetParent(file);
264 char *buffer = fBufferRef->Buffer();
265 file->Seek(pos);
266 TFileCacheRead *pf = tree->GetReadCache(file);
267 if (pf) {
269 if (tree->GetPerfStats()) gPerfStats = tree->GetPerfStats();
270 Int_t st = pf->ReadBuffer(buffer,pos,len);
271 if (st < 0) {
272 return 1;
273 } else if (st == 0) {
274 // fOffset might have been changed via TFileCacheRead::ReadBuffer(), reset it
275 file->Seek(pos);
276 // If we are using a TTreeCache, disable reading from the default cache
277 // temporarily, to force reading directly from file
278 TTreeCache *fc = dynamic_cast<TTreeCache*>(file->GetCacheRead());
279 if (fc) fc->Disable();
280 Int_t ret = file->ReadBuffer(buffer,len);
281 if (fc) fc->Enable();
282 pf->AddNoCacheBytesRead(len);
283 pf->AddNoCacheReadCalls(1);
284 if (ret) {
285 return 1;
286 }
287 }
288 gPerfStats = temp;
289 // fOffset might have been changed via TFileCacheRead::ReadBuffer(), reset it
290 file->SetOffset(pos + len);
291 } else {
293 if (tree->GetPerfStats() != nullptr) gPerfStats = tree->GetPerfStats();
294 if (file->ReadBuffer(buffer,len)) {
295 gPerfStats = temp;
296 return 1; //error while reading
297 }
298 else gPerfStats = temp;
299 }
300
304
305 return 0;
306}
307
308////////////////////////////////////////////////////////////////////////////////
309/// Remove the first dentries of this basket, moving entries at
310/// dentries to the start of the buffer.
311
313{
314 Int_t i;
315
316 if (dentries >= fNevBuf) return;
318 Int_t moved;
319
321 if (entryOffset) {
324
325 // First store the original location in the fDisplacement array
326 // and record the new start offset
327
328 if (!fDisplacement) {
330 }
331 for (i = 0; i<(fNevBufSize-dentries); ++i) {
334 }
335 for (i = fNevBufSize-dentries; i<fNevBufSize; ++i) {
336 fDisplacement[i] = 0;
337 entryOffset[i] = 0;
338 }
339
340 } else {
341 // If there is no EntryOffset array, this means
342 // that each entry has the same size and that
343 // it does not point to other objects (hence there
344 // is no need for a displacement array).
347 }
348 TBuffer *buf = GetBufferRef();
349 char *buffer = buf->Buffer();
350 memmove(buffer+GetKeylen(),buffer+bufbegin,buf->Length()-bufbegin);
351 buf->SetBufferOffset(buf->Length()-moved);
352 fNevBuf -= dentries;
353}
354
355#define OLD_CASE_EXPRESSION fObjlen==fNbytes-fKeylen && GetBranch()->GetCompressionLevel()!=0 && file->GetVersion()<=30401
356////////////////////////////////////////////////////////////////////////////////
357/// By-passing buffer unzipping has been requested and is
358/// possible (only 1 entry in this basket).
359
361{
363
364 // Make sure that the buffer is set at the END of the data
366
367 // Indicate that this buffer is weird.
369
370 // Usage of this mode assume the existence of only ONE
371 // entry in this basket.
373 delete [] fDisplacement; fDisplacement = nullptr;
374
376 return 0;
377}
378
379////////////////////////////////////////////////////////////////////////////////
380/// We always create the TBuffer for the basket but it hold the buffer from the cache.
381
383{
384 if (fBufferRef) {
387 fBufferRef->Reset();
388 } else {
390 }
391 fBufferRef->SetParent(file);
392
394
395 if (IsZombie()) {
396 return -1;
397 }
398
400
403 }
404
406 return fObjlen+fKeylen;
407}
408
409////////////////////////////////////////////////////////////////////////////////
410/// Initialize a buffer for reading if it is not already initialized
411
413{
415 if (R__likely(bufferRef)) {
416 bufferRef->SetReadMode();
417 Int_t curBufferSize = bufferRef->BufferSize();
418 if (curBufferSize < len) {
419 // Experience shows that giving 5% "wiggle-room" decreases churn.
420 bufferRef->Expand(Int_t(len*1.05));
421 }
422 bufferRef->Reset();
424 } else {
426 }
427 result->SetParent(file);
428 return result;
429}
430
431////////////////////////////////////////////////////////////////////////////////
432/// Initialize the compressed buffer; either from the TTree or create a local one.
433
442
444{
445 if (fEntryOffset != reinterpret_cast<Int_t *>(-1)) {
446 delete[] fEntryOffset;
447 }
448 fEntryOffset = nullptr;
449}
450
451////////////////////////////////////////////////////////////////////////////////
452/// Read basket buffers in memory and cleanup.
453///
454/// Read a basket buffer. Check if buffers of previous ReadBasket
455/// should not be dropped. Remember, we keep buffers in memory up to
456/// fMaxVirtualSize.
457/// The function returns 0 in case of success, 1 in case of error
458/// This function was modified with the addition of the parallel
459/// unzipping, it will try to get the unzipped file from the cache
460/// receiving only a pointer to that buffer (so we shall not
461/// delete that pointer), although we get a new buffer in case
462/// it's not found in the cache.
463/// There is a lot of code duplication but it was necessary to assure
464/// the expected behavior when there is no cache.
465
467{
468 if(!fBranch->GetDirectory()) {
469 return -1;
470 }
471
472 bool oldCase;
475
476 // See if the cache has already unzipped the buffer for us.
477 TFileCacheRead *pf = nullptr;
478 {
479 R__LOCKGUARD_IMT(gROOTMutex); // Lock for parallel TTree I/O
480 pf = fBranch->GetTree()->GetReadCache(file);
481 }
482 if (pf) {
483 Int_t res = -1;
484 bool free = true;
485 char *buffer = nullptr;
486 res = pf->GetUnzipBuffer(&buffer, pos, len, &free);
487 if (R__unlikely(res >= 0)) {
488 len = ReadBasketBuffersUnzip(buffer, res, free, file);
489 // Note that in the kNotDecompressed case, the above function will return 0;
490 // In such a case, we should stop processing
491 if (len <= 0) return -len;
492 goto AfterBuffer;
493 }
494 }
495
496 // Determine which buffer to use, so that we can avoid a memcpy in case of
497 // the basket was not compressed.
500 // Initialize the buffer to hold the uncompressed data.
503 } else {
504 // Initialize the buffer to hold the compressed data.
507 }
508
509 // fBufferSize is likely to be change in the Streamer call (below)
510 // and we will re-add the new size later on.
512
513 if (!readBufferRef) {
514 Error("ReadBasketBuffers", "Unable to allocate buffer.");
515 return 1;
516 }
517
518 if (pf) {
520 if (fBranch->GetTree()->GetPerfStats() != nullptr) gPerfStats = fBranch->GetTree()->GetPerfStats();
521 Int_t st = 0;
522 {
523 R__LOCKGUARD_IMT(gROOTMutex); // Lock for parallel TTree I/O
524 st = pf->ReadBuffer(readBufferRef->Buffer(),pos,len);
525 }
526 if (st < 0) {
527 return 1;
528 } else if (st == 0) {
529 // Read directly from file, not from the cache
530 // If we are using a TTreeCache, disable reading from the default cache
531 // temporarily, to force reading directly from file
532 R__LOCKGUARD_IMT(gROOTMutex); // Lock for parallel TTree I/O
533 TTreeCache *fc = dynamic_cast<TTreeCache*>(file->GetCacheRead());
534 if (fc) fc->Disable();
535 Int_t ret = file->ReadBuffer(readBufferRef->Buffer(),pos,len);
536 if (fc) fc->Enable();
537 pf->AddNoCacheBytesRead(len);
538 pf->AddNoCacheReadCalls(1);
539 if (ret) {
540 return 1;
541 }
542 }
543 gPerfStats = temp;
544 } else {
545 // Read from the file and unstream the header information.
547 if (fBranch->GetTree()->GetPerfStats() != nullptr) gPerfStats = fBranch->GetTree()->GetPerfStats();
548 R__LOCKGUARD_IMT(gROOTMutex); // Lock for parallel TTree I/O
549 if (file->ReadBuffer(readBufferRef->Buffer(),pos,len)) {
550 gPerfStats = temp;
551 return 1;
552 }
553 else gPerfStats = temp;
554 }
556 if (IsZombie()) {
557 return 1;
558 }
559
561
562 // Are we done?
563 if (R__unlikely(readBufferRef == fBufferRef)) // We expect most basket to be compressed.
564 {
566 // The basket was really not compressed as expected.
567 goto AfterBuffer;
568 } else {
569 // Well, somehow the buffer was compressed anyway, we have the compressed data in the uncompressed buffer
570 // Make sure the compressed buffer is initialized, and memcpy.
573 Error("ReadBasketBuffers", "Unable to allocate buffer.");
574 return 1;
575 }
576 fBufferRef->Reset();
579 }
580 }
581 // Sanitize nbytes and lengths
582 if (fKeylen < 0) {
583 Error("ReadBasketBuffers", "The value of fKeylen is incorrect (%d) ; trying to recover by setting it to zero", fKeylen);
584 MakeZombie();
585 fKeylen = 0;
586 return 1;
587 }
588 if (fObjlen < 0) {
589 Error("ReadBasketBuffers", "The value of fObjlen is incorrect (%d) ; trying to recover by setting it to zero", fObjlen);
590 MakeZombie();
591 fObjlen = 0;
592 return 1;
593 }
594 if (fNbytes < 0) {
595 Error("ReadBasketBuffers", "The value of fNbytes is incorrect (%d) ; trying to recover by setting it to zero", fNbytes);
596 MakeZombie();
597 fNbytes = 0;
598 return 1;
599 }
600 if (fKeylen > (gMaxInt_t - fObjlen)) {
601 Error("ReadBasketBuffers", "fObjlen (%d) + fKeylen (%d) > max int (%d): cannot continue to read the key buffer.",
603 MakeZombie();
604 return 1;
605 }
606
607 // Initialize buffer to hold the uncompressed data
608 // Note that in previous versions we didn't allocate buffers until we verified
609 // the zip headers; this is no longer beforehand as the buffer lifetime is scoped
610 // to the TBranch.
615
617 // Case where ROOT thinks the buffer is compressed. Copy over the key and uncompress the object
618 if (fObjlen > fNbytes-fKeylen || oldCase) {
621 }
622
623 // Optional monitor for zip time profiling.
624 Double_t start = 0;
625 if (R__unlikely(gPerfStats)) {
626 start = TTimeStamp();
627 }
628
632 Int_t nin, nbuf;
633 Int_t nout = 0, noutot = 0, nintot = 0;
634
635 // Unzip all the compressed objects in the compressed object buffer.
636 while (true) {
637 // Check the header for errors.
639 Error("ReadBasketBuffers", "Inconsistency found in header (nin=%d, nbuf=%d)", nin, nbuf);
640 break;
641 }
642 if (R__unlikely(oldCase && (nin > fObjlen || nbuf > fObjlen))) {
643 //buffer was very likely not compressed in an old version
645 goto AfterBuffer;
646 }
647
649 if (!nout) break;
650 noutot += nout;
651 nintot += nin;
652 if (noutot >= fObjlen) break;
655 }
656
657 // Make sure the uncompressed numbers are consistent with header.
658 if (R__unlikely(noutot != fObjlen)) {
659 Error("ReadBasketBuffers", "fNbytes = %d, fKeylen = %d, fObjlen = %d, noutot = %d, nout=%d, nin=%d, nbuf=%d", fNbytes,fKeylen,fObjlen, noutot,nout,nin,nbuf);
661 return 1;
662 }
665 if (fBranch->GetTree()->GetPerfStats() != nullptr) gPerfStats = fBranch->GetTree()->GetPerfStats();
666 if (R__unlikely(gPerfStats)) {
667 gPerfStats->UnzipEvent(fBranch->GetTree(),pos,start,nintot,fObjlen);
668 }
669 gPerfStats = temp;
670 } else {
671 // Nothing is compressed - copy over wholesale.
673 }
674
676
678
679 // Read offsets table if needed.
680 // If there's no EntryOffsetLen in the branch -- or the fEntryOffset is marked to be calculated-on-demand --
681 // then we skip reading out.
682 if (!fBranch->GetEntryOffsetLen() || (fEntryOffset == reinterpret_cast<Int_t *>(-1))) {
683 return 0;
684 }
685 // At this point, we're required to read out an offset array.
686 ResetEntryOffset(); // TODO: every basket, we reset the offset array. Is this necessary?
687 // Could we instead switch to std::vector?
691 fEntryOffset = new Int_t[fNevBuf+1];
693 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);
694 return 0;
695 }
697 // In this case, we cannot regenerate the offset array at runtime -- but we wrote out an array of
698 // sizes instead of offsets (as sizes compress much better).
700 for (Int_t idx = 1; idx < fNevBuf + 1; idx++) {
701 fEntryOffset[idx] += fEntryOffset[idx - 1];
702 }
703 }
704 fReadEntryOffset = true;
705 // Read the array of displacement if any.
706 delete [] fDisplacement;
707 fDisplacement = nullptr;
708 if (fBufferRef->Length() != len) {
709 // There is more data in the buffer! It is the displacement
710 // array. If len is less than TBuffer::kMinimalSize the actual
711 // size of the buffer is too large, so we can not use the
712 // fBufferRef->BufferSize()
714 }
715
716 return 0;
717}
718
719////////////////////////////////////////////////////////////////////////////////
720/// Read basket buffers in memory and cleanup
721///
722/// Read first bytes of a logical record starting at position pos
723/// return record length (first 4 bytes of record).
724
726{
727 const Int_t len = 128;
728 char buffer[len];
730 file->GetRecordHeader(buffer, pos,len, fNbytes, fObjlen, keylen);
731 fKeylen = keylen;
732 return fNbytes;
733}
734
735////////////////////////////////////////////////////////////////////////////////
736/// Disown all references to the internal buffer - some other object likely now
737/// owns it.
738///
739/// This TBasket is now useless and invalid until it is told to adopt a buffer.
741{
742 fBufferRef = nullptr;
743}
744
745
746////////////////////////////////////////////////////////////////////////////////
747/// Adopt a buffer from an external entity
753
754////////////////////////////////////////////////////////////////////////////////
755/// Reset the read basket TBuffer memory allocation if needed.
756///
757/// This allows to reduce the number of memory allocation while avoiding to
758/// always use the maximum size.
759
761{
762 // By default, we don't reallocate.
763 fResetAllocation = false;
764#ifdef R__TRACK_BASKET_ALLOC_TIME
766#endif
767
768 // Downsize the buffer if needed.
769
770 const auto maxbaskets = fBranch->GetMaxBaskets();
772 return;
773
775
777 const auto basketbytes = fBranch->GetBasketBytes();
778
779 Int_t max_size = basketbytes[basketnumber];
780 for(Int_t b = basketnumber + 1; (b < maxbaskets) && (b < (basketnumber+10)); ++b) {
781 max_size = std::max(max_size, basketbytes[b]);
782 }
783
784 Float_t cx = 1;
785 if (fBranch->GetZipBytes())
787
788 Int_t target_size = static_cast<Int_t>(cx * target_mem_ratio * Float_t(max_size));
789
790 if (target_size && (curSize > target_size)) {
791 /// Only reduce the size if significant enough?
792 Int_t newSize = max_size + 512 - max_size % 512; // Wiggle room and alignment, as above.
793 // We only bother with a resize if it saves 8KB (two normal memory pages).
794 if ((newSize <= curSize - 8 * 1024) &&
795 (static_cast<Float_t>(curSize) / static_cast<Float_t>(newSize) > target_mem_ratio))
796 {
797 if (gDebug > 0) {
798 Info("ReadResetBuffer",
799 "Resizing %d to %d bytes (was %d); next 10 sizes are [%d, %d, %d, %d, %d, %d, %d, %d, %d, %d]. cx=%f ratio=%f max_size = %d ",
811 cx, target_mem_ratio, max_size);
812 }
813 fResetAllocation = true;
814#ifdef R__TRACK_BASKET_ALLOC_TIME
815 std::chrono::time_point<std::chrono::system_clock> start, end;
816 start = std::chrono::high_resolution_clock::now();
817#endif
818 fBufferRef->Expand(newSize, false); // Expand without copying the existing data.
819#ifdef R__TRACK_BASKET_ALLOC_TIME
820 end = std::chrono::high_resolution_clock::now();
821 auto us = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
822 fResetAllocationTime = us.count();
823#endif
824 }
825 }
826}
827
828////////////////////////////////////////////////////////////////////////////////
829/// Reset the write basket to the starting state. i.e. as it was after calling
830/// the constructor (and potentially attaching a TBuffer.)
831/// Reduce memory used by fEntryOffset and the TBuffer if needed ..
832
834{
835 // By default, we don't reallocate.
836 fResetAllocation = false;
837#ifdef R__TRACK_BASKET_ALLOC_TIME
839#endif
840
841 // Name, Title, fClassName, fBranch
842 // stay the same.
843
844 // Downsize the buffer if needed.
845 // See if our current buffer size is significantly larger (>2x) than the historical average.
846 // If so, try decreasing it at this flush boundary to closer to the size from OptimizeBaskets
847 // (or this historical average).
849 // fBufferLen at this point is already reset, so use indirect measurements
851 Longptr_t newSize = -1;
852 if (curSize > 2*curLen)
853 {
855 if (curSize > 2*curBsize ) {
856 Longptr_t avgSize = (Longptr_t)(fBranch->GetTotBytes() / (1+fBranch->GetWriteBasket())); // Average number of bytes per basket so far
857 if (curSize > 2*avgSize) {
859 if (curLen > newSize) {
860 newSize = curLen;
861 }
862 if (avgSize > newSize) {
864 }
865 newSize = newSize + 512 - newSize%512; // Wiggle room and alignment (512 is same as in OptimizeBaskets)
866 }
867 }
868 }
869 // If fBufferRef grew since we last saw it, shrink it to "target memory ratio" of the occupied size
870 // This discourages us from having poorly-occupied buffers on branches with little variability.
871 //
872 // Does not help protect against a burst in event sizes, but does help in the cases where the basket
873 // size jumps from 4MB to 8MB while filling the basket, but we only end up utilizing 4.1MB.
874 //
875 // The above code block is meant to protect against extremely large events.
876
879 Int_t target_size = static_cast<Int_t>(target_mem_ratio * Float_t(max_size));
880 if (max_size && (curSize > target_size) && (newSize == -1)) {
882 newSize = newSize + 512 - newSize % 512; // Wiggle room and alignment, as above.
883 // We only bother with a resize if it saves 8KB (two normal memory pages).
884 if ((newSize > curSize - 8 * 1024) ||
885 (static_cast<Float_t>(curSize) / static_cast<Float_t>(newSize) < target_mem_ratio)) {
886 newSize = -1;
887 } else if (gDebug > 0) {
888 Info("Reset", "Resizing to %ld bytes (was %d); last three sizes were [%d, %d, %d].", newSize, curSize,
890 }
891 }
892
893 if (newSize != -1) {
894 fResetAllocation = true;
895#ifdef R__TRACK_BASKET_ALLOC_TIME
896 std::chrono::time_point<std::chrono::system_clock> start, end;
897 start = std::chrono::high_resolution_clock::now();
898#endif
899 fBufferRef->Expand(newSize,false); // Expand without copying the existing data.
900#ifdef R__TRACK_BASKET_ALLOC_TIME
901 end = std::chrono::high_resolution_clock::now();
902 auto us = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
903 fResetAllocationTime = us.count();
904#endif
905 }
906
907 // Record the actual occupied size of the buffer.
910
911 TKey::Reset();
912
914 if (newNevBufSize==0) {
916 } else if ((newNevBufSize != fNevBufSize) || (fEntryOffset <= reinterpret_cast<Int_t *>(-1))) {
919 }
921
922 fNevBuf = 0;
924 fEntryOffset = nullptr;
926 fDisplacement= nullptr;
927 fBuffer = nullptr;
928
929 fBufferRef->Reset();
931
932 fHeaderOnly = true;
933 fLast = 0; //Must initialize before calling Streamer()
934
936
939 fLast = fKeylen;
940 fBuffer = nullptr;
941 fHeaderOnly = false;
944 if (fNevBufSize) {
945 for (Int_t i=0;i<fNevBufSize;i++) fEntryOffset[i] = 0;
946 }
947}
948
949////////////////////////////////////////////////////////////////////////////////
950/// Set read mode of basket.
951
957
958////////////////////////////////////////////////////////////////////////////////
959/// Set write mode of basket.
960
966
967////////////////////////////////////////////////////////////////////////////////
968/// Stream a class object.
969
971{
972 // As in TBranch::GetBasket, this is used as a half-hearted measure to suppress
973 // the error reporting when many failures occur.
974 static std::atomic<Int_t> nerrors(0);
975
976 char flag;
977 if (b.IsReading()) {
978 TKey::Streamer(b); //this must be first
979 Version_t v = b.ReadVersion();
980 b >> fBufferSize;
981 // NOTE: we now use the upper-bit of the fNevBufSize to see if we have serialized any of the
982 // optional IOBits. If that bit is set, we immediately read out the IOBits; to replace this
983 // (minimal) safeguard against corruption, we will set aside the upper-bit of fIOBits to do
984 // the same thing (the fact this bit is reserved is tested in the unit tests). If there is
985 // someday a need for more than 7 IOBits, we'll widen the field using the same trick.
986 //
987 // We like to keep this safeguard because we immediately will allocate a buffer based on
988 // the value of fNevBufSize -- and would like to avoid wildly inappropriate allocations.
989 b >> fNevBufSize;
990 if (fNevBufSize < 0) {
992 b >> fIOBits;
993 if (!fIOBits || (fIOBits & (1 << 7))) {
994 Error("TBasket::Streamer",
995 "The value of fNevBufSize (%d) or fIOBits (%d) is incorrect ; setting the buffer to a zombie.",
997 MakeZombie();
998 fNevBufSize = 0;
999 } else if (fIOBits && (fIOBits & ~static_cast<Int_t>(EIOBits::kSupported))) {
1000 nerrors++;
1001 if (nerrors < 10) {
1002 Error("Streamer", "The value of fIOBits (%s) contains unknown flags (supported flags "
1003 "are %s), indicating this was written with a newer version of ROOT "
1004 "utilizing critical IO features this version of ROOT does not support."
1005 " Refusing to deserialize.",
1006 std::bitset<32>(static_cast<Int_t>(fIOBits)).to_string().c_str(),
1007 std::bitset<32>(static_cast<Int_t>(EIOBits::kSupported)).to_string().c_str());
1008 } else if (nerrors == 10) {
1009 Error("Streamer", "Maximum number of errors has been reported; disabling further messages"
1010 "from this location until the process exits.");
1011 }
1012 fNevBufSize = 0;
1013 MakeZombie();
1014 }
1015 }
1016 b >> fNevBuf;
1017 b >> fLast;
1018 b >> flag;
1020 bool mustGenerateOffsets = false;
1021 if (flag >= 80) {
1022 mustGenerateOffsets = true;
1023 flag -= 80;
1024 }
1025 if (!mustGenerateOffsets && flag && (flag % 10 != 2)) {
1028 if (fNevBuf) b.ReadArray(fEntryOffset);
1029 if (20<flag && flag<40) {
1030 for(int i=0; i<fNevBuf; i++){
1032 }
1033 }
1034 if (flag>40) {
1036 b.ReadArray(fDisplacement);
1037 }
1038 } else if (mustGenerateOffsets) {
1039 // We currently believe that in all cases when offsets can be generated, then the
1040 // displacement array must be zero.
1041 assert(flag <= 40);
1042 fEntryOffset = reinterpret_cast<Int_t *>(-1);
1043 }
1044 if (flag == 1 || flag > 10) {
1046 fBufferRef->SetParent(b.GetParent());
1047 char *buf = fBufferRef->Buffer();
1048 if (v > 1) b.ReadFastArray(buf,fLast);
1049 else b.ReadArray(buf);
1051 // This is now done in the TBranch streamer since fBranch might not
1052 // yet be set correctly.
1053 // fBranch->GetTree()->IncrementTotalBuffers(fBufferSize);
1054 }
1055 } else {
1056
1057 TKey::Streamer(b); //this must be first
1058 b.WriteVersion(TBasket::IsA());
1059 if (fBufferRef) {
1061 if (!fHeaderOnly && !fSeekKey && curLast > fLast) fLast = curLast;
1062 }
1064
1065 b << fBufferSize;
1066 if (fIOBits) {
1067 b << -fNevBufSize;
1068 b << fIOBits;
1069 } else {
1070 b << fNevBufSize;
1071 }
1072 b << fNevBuf;
1073 b << fLast;
1077 // We currently believe that in all cases when offsets can be generated, then the
1078 // displacement array must be zero.
1080 if (fHeaderOnly) {
1081 flag = mustGenerateOffsets ? 80 : 0;
1082 b << flag;
1083 } else {
1084 // On return from this function, we are guaranteed that fEntryOffset
1085 // is either a valid pointer or nullptr.
1086 if (fNevBuf) {
1088 }
1089 flag = 1;
1090 if (!fNevBuf || !fEntryOffset)
1091 flag = 2;
1092 if (fBufferRef) flag += 10;
1093 if (fDisplacement) flag += 40;
1094 // Test if we can skip writing out the offset map.
1095 if (mustGenerateOffsets) {
1096 flag += 80;
1097 }
1098 b << flag;
1099
1101 b.WriteArray(fEntryOffset, fNevBuf);
1102 if (fDisplacement) b.WriteArray(fDisplacement, fNevBuf);
1103 }
1104 if (fBufferRef) {
1105 char *buf = fBufferRef->Buffer();
1106 b.WriteFastArray(buf, fLast);
1107 }
1108 }
1109 }
1110}
1111
1112////////////////////////////////////////////////////////////////////////////////
1113/// Update basket header and EntryOffset table.
1114
1116{
1118 if (entryOffset) {
1119 if (fNevBuf+1 >= fNevBufSize) {
1122 fNevBufSize);
1123 if (fDisplacement) {
1125 fNevBufSize);
1127 }
1130
1131 //Update branch only for the first 10 baskets
1132 if (fBranch->GetWriteBasket() < 10) {
1134 }
1135 }
1137
1138 if (skipped!=offset && !fDisplacement){
1140 for (Int_t i = 0; i<fNevBufSize; i++) fDisplacement[i] = fEntryOffset[i];
1141 }
1142 if (fDisplacement) {
1145 }
1146 }
1147
1148 fNevBuf++;
1149}
1150
1151////////////////////////////////////////////////////////////////////////////////
1152/// Write buffer of this basket on the current file.
1153///
1154/// The function returns the number of bytes committed to the memory.
1155/// If a write error occurs, the number of bytes returned is -1.
1156/// If no data are written, the number of bytes returned is 0.
1157
1159{
1160 constexpr Int_t kWrite = 1;
1161
1162 TFile *file = fBranch->GetFile(kWrite);
1163 if (!file) return 0;
1164 if (!file->IsWritable()) {
1165 return -1;
1166 }
1167 fMotherDir = file; // fBranch->GetDirectory();
1168
1169 // This mutex prevents multiple TBasket::WriteBuffer invocations from interacting
1170 // with the underlying TFile at once - TFile is assumed to *not* be thread-safe.
1171 //
1172 // The only parallelism we'd like to exploit (right now!) is the compression
1173 // step - everything else should be serialized at the TFile level.
1174#ifdef R__USE_IMT
1175 std::unique_lock<std::mutex> sentry(file->fWriteMutex);
1176#endif // R__USE_IMT
1177
1179 // Read the basket information that was saved inside the buffer.
1180 bool writing = fBufferRef->IsWriting();
1183
1187
1189
1190 Create(nout,file);
1192 fHeaderOnly = true;
1193
1194 Streamer(*fBufferRef); //write key itself again
1196 fHeaderOnly = false;
1197 return nBytes>0 ? fKeylen+nout : -1;
1198 }
1199
1200 // Transfer fEntryOffset table at the end of fBuffer.
1201 fLast = fBufferRef->Length();
1203 if (entryOffset) {
1205 if (!CanGenerateOffsetArray()) {
1206 // If we have set the offset map flag, but cannot dynamically generate the map, then
1207 // we should at least convert the offset array to a size array. Note that we always
1208 // write out (fNevBuf+1) entries to match the original case.
1209 if (hasOffsetBit) {
1210 for (Int_t idx = fNevBuf; idx > 0; idx--) {
1211 entryOffset[idx] -= entryOffset[idx - 1];
1212 }
1213 entryOffset[0] = 0;
1214 }
1216 // Convert back to offset format: keeping both sizes and offsets in-memory were considered,
1217 // but it seems better to use CPU than memory.
1218 if (hasOffsetBit) {
1219 entryOffset[0] = fKeylen;
1220 for (Int_t idx = 1; idx < fNevBuf + 1; idx++) {
1221 entryOffset[idx] += entryOffset[idx - 1];
1222 }
1223 }
1224 } else if (!hasOffsetBit) { // In this case, write out as normal
1226 }
1227 if (fDisplacement) {
1229 delete[] fDisplacement;
1230 fDisplacement = nullptr;
1231 }
1232 }
1233
1234 Int_t nout, noutot, bufmax, nzip;
1235
1237
1238 fHeaderOnly = true;
1242 cxlevel = file->GetCompressionLevel();
1246 if (cxlevel > 0) {
1247 Int_t nbuffers = 1 + (fObjlen - 1) / kMAXZIPBUF;
1248 Int_t buflen = fKeylen + fObjlen + 9 * nbuffers + 28; //add 28 bytes in case object is placed in a deleted gap
1249 InitializeCompressedBuffer(buflen, file);
1250 if (!fCompressedBufferRef) {
1251 Warning("WriteBuffer", "Unable to allocate the compressed buffer");
1252 return -1;
1253 }
1256 char *objbuf = fBufferRef->Buffer() + fKeylen;
1257 char *bufcur = &fBuffer[fKeylen];
1258 noutot = 0;
1259 nzip = 0;
1260 for (Int_t i = 0; i < nbuffers; ++i) {
1261 if (i == nbuffers - 1) bufmax = fObjlen - nzip;
1262 else bufmax = kMAXZIPBUF;
1263 // Compress the buffer. Note that we allow multiple TBasket compressions to occur at once
1264 // for a given TFile: that's because the compression buffer when we use IMT is no longer
1265 // shared amongst several threads.
1266#ifdef R__USE_IMT
1267 sentry.unlock();
1268#endif // R__USE_IMT
1269 // NOTE this is declared with C linkage, so it shouldn't except. Also, when
1270 // USE_IMT is defined, we are guaranteed that the compression buffer is unique per-branch.
1271 // (see fCompressedBufferRef in constructor).
1273#ifdef R__USE_IMT
1274 sentry.lock();
1275#endif // R__USE_IMT
1276
1277 // test if buffer has really been compressed. In case of small buffers
1278 // when the buffer contains random data, it may happen that the compressed
1279 // buffer is larger than the input. In this case, we write the original uncompressed buffer
1280 if (nout == 0 || nout >= fObjlen) {
1281 nout = fObjlen;
1282 // We used to delete fBuffer here, we no longer want to since
1283 // the buffer (held by fCompressedBufferRef) might be re-used later.
1285 Create(fObjlen,file);
1287
1288 Streamer(*fBufferRef); //write key itself again
1289 if ((nout+fKeylen)>buflen) {
1290 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",
1291 (nout+fKeylen-buflen),buflen,fNbytes,fObjlen,fKeylen);
1292 }
1293 goto WriteFile;
1294 }
1295 bufcur += nout;
1296 noutot += nout;
1297 objbuf += kMAXZIPBUF;
1298 nzip += kMAXZIPBUF;
1299 }
1300 nout = noutot;
1301 Create(noutot,file);
1303
1304 Streamer(*fBufferRef); //write key itself again
1306 } else {
1308 Create(fObjlen,file);
1310
1311 Streamer(*fBufferRef); //write key itself again
1312 nout = fObjlen;
1313 }
1314
1315WriteFile:
1317 fHeaderOnly = false;
1318 return nBytes>0 ? fKeylen+nout : -1;
1319}
#define R__likely(expr)
Definition RConfig.hxx:600
#define R__unlikely(expr)
Definition RConfig.hxx:599
#define b(i)
Definition RSha256.hxx:100
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
int Int_t
Definition RtypesCore.h:45
long Longptr_t
Definition RtypesCore.h:75
short Version_t
Definition RtypesCore.h:65
unsigned int UInt_t
Definition RtypesCore.h:46
float Float_t
Definition RtypesCore.h:57
long long Long64_t
Definition RtypesCore.h:69
#define ClassImp(name)
Definition Rtypes.h:374
constexpr auto gMaxInt_t
Definition TBasket.cxx:36
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:412
#define OLD_CASE_EXPRESSION
Definition TBasket.cxx:355
const UInt_t kDisplacementMask
Definition TBasket.cxx:32
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t UChar_t len
char name[80]
Definition TGX11.cxx:110
Int_t gDebug
Definition TROOT.cxx:622
R__EXTERN TVirtualMutex * gROOTMutex
Definition TROOT.h:63
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
Manages buffers for branches of a Tree.
Definition TBasket.h:34
Int_t * fEntryOffset
[fNevBuf] Offset of entries in fBuffer(TKey); generated at runtime.
Definition TBasket.h:71
Int_t GetEntryPointer(Int_t Entry)
Get pointer to buffer for internal entry.
Definition TBasket.cxx:232
void AdoptBuffer(TBuffer *user_buffer)
Adopt a buffer from an external entity.
Definition TBasket.cxx:748
bool fHeaderOnly
True when only the basket header must be read/written.
Definition TBasket.h:66
TBranch * fBranch
Pointer to the basket support branch.
Definition TBasket.h:73
Long64_t CopyTo(TFile *to)
Copy the basket of this branch onto the file to.
Definition TBasket.cxx:148
Int_t * GetEntryOffset()
Definition TBasket.h:124
void InitializeCompressedBuffer(Int_t len, TFile *file)
Initialize the compressed buffer; either from the TTree or create a local one.
Definition TBasket.cxx:434
UChar_t fNextBufferSizeRecord
! Index into fLastWriteBufferSize of the last buffer written to disk
Definition TBasket.h:77
Int_t ReadBasketBuffersUnzip(char *, Int_t, bool, TFile *)
We always create the TBuffer for the basket but it hold the buffer from the cache.
Definition TBasket.cxx:382
void DisownBuffer()
Disown all references to the internal buffer - some other object likely now owns it.
Definition TBasket.cxx:740
Int_t fLastWriteBufferSize[3]
! Size of the buffer last three buffers we wrote it to disk
Definition TBasket.h:75
Int_t ReadBasketBuffers(Long64_t pos, Int_t len, TFile *file)
Read basket buffers in memory and cleanup.
Definition TBasket.cxx:466
UChar_t fIOBits
!IO feature flags. Serialized in custom portion of streamer to avoid forward compat issues unless nee...
Definition TBasket.h:67
virtual Int_t DropBuffers()
Drop buffers of this basket if it is not the current basket.
Definition TBasket.cxx:175
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:312
bool fOwnsCompressedBuffer
! Whether or not we own the compressed buffer.
Definition TBasket.h:68
void ResetEntryOffset()
Definition TBasket.cxx:443
TBasket()
Default constructor.
Definition TBasket.cxx:49
virtual void AdjustSize(Int_t newsize)
Increase the size of the current fBuffer up to newsize.
Definition TBasket.cxx:129
virtual void SetReadMode()
Set read mode of basket.
Definition TBasket.cxx:952
virtual void SetWriteMode()
Set write mode of basket.
Definition TBasket.cxx:961
Int_t ReadBasketBuffersUncompressedCase()
By-passing buffer unzipping has been requested and is possible (only 1 entry in this basket).
Definition TBasket.cxx:360
Int_t fBufferSize
fBuffer length in bytes
Definition TBasket.h:62
bool fReadEntryOffset
!Set to true if offset array was read from a file.
Definition TBasket.h:69
Int_t ReadBasketBytes(Long64_t pos, TFile *file)
Read basket buffers in memory and cleanup.
Definition TBasket.cxx:725
virtual void ReadResetBuffer(Int_t basketnumber)
Reset the read basket TBuffer memory allocation if needed.
Definition TBasket.cxx:760
bool fResetAllocation
! True if last reset re-allocated the memory
Definition TBasket.h:76
virtual Int_t WriteBuffer()
Write buffer of this basket on the current file.
Definition TBasket.cxx:1158
void Streamer(TBuffer &) override
Stream a class object.
Definition TBasket.cxx:970
Int_t LoadBasketBuffers(Long64_t pos, Int_t len, TFile *file, TTree *tree=nullptr)
Load basket buffers in memory without unziping.
Definition TBasket.cxx:247
~TBasket() override
Basket destructor.
Definition TBasket.cxx:106
void Update(Int_t newlast)
Definition TBasket.h:152
Int_t fNevBufSize
Length in Int_t of fEntryOffset OR fixed length of each entry if fEntryOffset is null!
Definition TBasket.h:63
Int_t fNevBuf
Number of entries in basket.
Definition TBasket.h:64
Int_t * GetCalculatedEntryOffset()
Calculates the entry offset array, if possible.
Definition TBasket.cxx:197
TClass * IsA() const override
Definition TBasket.h:156
virtual void DeleteEntryOffset()
Delete fEntryOffset array.
Definition TBasket.cxx:166
TBuffer * fCompressedBufferRef
! Compressed buffer.
Definition TBasket.h:74
Int_t fLast
Pointer to last used byte in basket.
Definition TBasket.h:65
Int_t * fDisplacement
![fNevBuf] Displacement of entries in fBuffer(TKey)
Definition TBasket.h:70
bool CanGenerateOffsetArray()
Determine whether we can generate the offset array when this branch is read.
Definition TBasket.cxx:220
virtual void WriteReset()
Reset the write basket to the starting state.
Definition TBasket.cxx:833
A TTree is a list of TBranches.
Definition TBranch.h:93
Int_t GetCompressionLevel() const
Definition TBranch.h:305
Int_t GetCompressionAlgorithm() const
Definition TBranch.h:299
TTree * GetTree() const
Definition TBranch.h:252
Int_t GetWriteBasket() const
Definition TBranch.h:238
Int_t GetNleaves() const
Definition TBranch.h:249
virtual void SetEntryOffsetLen(Int_t len, bool updateSubBranches=false)
Update the default value for the branch's fEntryOffsetLen if and only if it was already non zero (and...
Definition TBranch.cxx:2834
Int_t GetMaxBaskets() const
Definition TBranch.h:248
Int_t * GetBasketBytes() const
Definition TBranch.h:214
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:1853
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:2220
virtual Int_t GetBasketSize() const
Definition TBranch.h:217
Long64_t GetZipBytes(Option_t *option="") const
Return total number of zip bytes in the branch if option ="*" includes all sub-branches of this branc...
Definition TBranch.cxx:2238
TObjArray * GetListOfLeaves()
Definition TBranch.h:247
TDirectory * GetDirectory() const
Definition TBranch.h:224
Int_t GetEntryOffsetLen() const
Definition TBranch.h:227
The concrete implementation of TBuffer for writing/reading to/from a ROOT file or socket.
Definition TBufferFile.h:47
@ kNotDecompressed
Definition TBufferIO.h:66
Buffer base class used for serializing objects.
Definition TBuffer.h:43
void SetWriteMode()
Set buffer in write mode.
Definition TBuffer.cxx:316
virtual void Reset()=0
void SetParent(TObject *parent)
Set parent owning this buffer.
Definition TBuffer.cxx:270
void Expand(Int_t newsize, Bool_t copy=kTRUE)
Expand (or shrink) the I/O buffer to newsize bytes.
Definition TBuffer.cxx:223
Int_t BufferSize() const
Definition TBuffer.h:98
virtual void WriteArray(const Bool_t *b, Int_t n)=0
virtual Int_t ReadArray(Bool_t *&b)=0
@ kWrite
Definition TBuffer.h:73
@ kRead
Definition TBuffer.h:73
Bool_t IsWriting() const
Definition TBuffer.h:87
void SetBuffer(void *buf, UInt_t bufsize=0, Bool_t adopt=kTRUE, ReAllocCharFun_t reallocfunc=nullptr)
Sets a new buffer in an existing TBuffer object.
Definition TBuffer.cxx:187
void SetBufferOffset(Int_t offset=0)
Definition TBuffer.h:93
void SetReadMode()
Set buffer in read mode.
Definition TBuffer.cxx:302
virtual void SetBufferDisplacement()=0
Int_t Length() const
Definition TBuffer.h:100
char * Buffer() const
Definition TBuffer.h:96
Bool_t IsWritable() const override
Describe directory structure in memory.
Definition TDirectory.h:45
A cache when reading files over the network.
A file, usually with extension .root, that stores data and code in the form of serialized objects in ...
Definition TFile.h:131
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:2333
Int_t GetCompressionLevel() const
Definition TFile.h:478
std::mutex fWriteMutex
!Lock for writing baskets / keys into the file.
Definition TFile.h:197
virtual void SetOffset(Long64_t offset, ERelativeTo pos=kBeg)
Set position from where to start reading.
Definition TFile.cxx:2312
Int_t GetCompressionAlgorithm() const
Definition TFile.h:472
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:1324
virtual Bool_t ReadBuffer(char *buf, Int_t len)
Read a buffer from the file.
Definition TFile.cxx:1829
TFileCacheRead * GetCacheRead(const TObject *tree=nullptr) const
Return a pointer to the current read cache.
Definition TFile.cxx:1285
Book space in a file, create I/O buffers, to fill them, (un)compress them.
Definition TKey.h:28
Int_t GetKeylen() const
Definition TKey.h:84
Int_t GetObjlen() const
Definition TKey.h:87
TBuffer * fBufferRef
Pointer to the TBuffer object.
Definition TKey.h:50
Int_t fVersion
Key version identifier.
Definition TKey.h:39
Short_t fKeylen
Number of bytes for the key itself.
Definition TKey.h:43
virtual Int_t WriteFileKeepBuffer(TFile *f=nullptr)
Write the encoded object supported by this key.
Definition TKey.cxx:1538
Long64_t fSeekKey
Location of object on file.
Definition TKey.h:45
char * fBuffer
Object buffer.
Definition TKey.h:49
Int_t fNbytes
Number of bytes for the whole key on file (key header and data)
Definition TKey.h:40
Int_t fObjlen
Length of uncompressed object in bytes.
Definition TKey.h:41
void Reset()
Reset the key as it had not been 'filled' yet.
Definition TKey.cxx:1349
Short_t fCycle
Cycle number.
Definition TKey.h:44
virtual void Create(Int_t nbytes, TFile *f=nullptr)
Create a TKey object of specified size.
Definition TKey.cxx:472
virtual Int_t WriteFile(Int_t cycle=1, TFile *f=nullptr)
Write the encoded object supported by this key.
Definition TKey.cxx:1506
TDirectory * fMotherDir
!pointer to mother directory
Definition TKey.h:52
TString fClassName
Object Class name.
Definition TKey.h:47
void Streamer(TBuffer &) override
Stream a class object.
Definition TKey.cxx:1405
TBuffer * GetBufferRef() const
Definition TKey.h:79
A TLeaf describes individual elements of a TBranch See TBranch structure in TTree.
Definition TLeaf.h:57
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition TNamed.cxx:174
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
virtual void SetName(const char *name)
Set the name of the TNamed.
Definition TNamed.cxx:150
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:205
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:1057
R__ALWAYS_INLINE Bool_t IsZombie() const
Definition TObject.h:159
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:864
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1071
void MakeZombie()
Definition TObject.h:53
static Int_t * ReAllocInt(Int_t *vp, size_t size, size_t oldsize)
Reallocate (i.e.
Definition TStorage.cxx:258
The TTimeStamp encapsulates seconds and ns since EPOCH.
Definition TTimeStamp.h:45
A cache to speed-up the reading of ROOT datasets.
Definition TTreeCache.h:32
A TTree represents a columnar dataset.
Definition TTree.h:84
virtual TVirtualPerfStats * GetPerfStats() const
Definition TTree.h:561
virtual void IncrementTotalBuffers(Int_t nbytes)
Definition TTree.h:601
TTreeCache * GetReadCache(TFile *file) const
Find and return the TTreeCache registered with the file and which may contain branches for us.
Definition TTree.cxx:6328
Float_t GetTargetMemoryRatio() const
Definition TTree.h:575
Provides the interface for the PROOF internal performance measurement and event tracing.
std::ostream & Info()
Definition hadd.cxx:171
Short_t Max(Short_t a, Short_t b)
Returns the largest of a and b.
Definition TMathBase.h:250
EValues
Note: this is only temporarily a struct and will become a enum class hence the name convention used.
Definition Compression.h:88
@ kInherit
Some objects use this value to denote that the compression algorithm should be inherited from the par...
Definition Compression.h:91
@ kInherit
Some objects use this value to denote that the compression algorithm should be inherited from the par...
Definition Compression.h:68