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
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 "TMath.h"
21#include "TROOT.h"
22#include "TTreeCache.h"
23#include "TVirtualMutex.h"
24#include "TVirtualPerfStats.h"
25#include "TTimeStamp.h"
26#include "ROOT/TIOFeatures.hxx"
27#include "RZip.h"
28
29#include <bitset>
30
31const UInt_t kDisplacementMask = 0xFF000000; // In the streamer the two highest bytes of
32 // the fEntryOffset are used to stored displacement.
33
34
35/** \class TBasket
36\ingroup tree
37
38Manages buffers for branches of a Tree.
39
40See picture in TTree.
41*/
42
43////////////////////////////////////////////////////////////////////////////////
44/// Default constructor.
45
49
50////////////////////////////////////////////////////////////////////////////////
51/// Constructor used during reading.
52
56
57////////////////////////////////////////////////////////////////////////////////
58/// Basket normal constructor, used during writing.
59
60TBasket::TBasket(const char *name, const char *title, TBranch *branch)
61 : TKey(branch->GetDirectory()), fBufferSize(branch->GetBasketSize()), fNevBufSize(branch->GetEntryOffsetLen()),
62 fHeaderOnly(true), fIOBits(branch->GetIOFeatures().GetFeatures())
63{
65 SetTitle(title);
66 fClassName = "TBasket";
67 fBuffer = nullptr;
69 fVersion += 1000;
70 if (branch->GetDirectory()) {
71 TFile *file = branch->GetFile();
72 fBufferRef->SetParent(file);
73 }
74 if (branch->GetTree()) {
75#ifdef R__USE_IMT
76 fCompressedBufferRef = branch->GetTransientBuffer(fBufferSize);
77#else
78 fCompressedBufferRef = branch->GetTree()->GetTransientBuffer(fBufferSize);
79#endif
84 }
85 }
90 fLast = fKeylen;
91 fBuffer = nullptr;
92 fHeaderOnly = false;
93 if (fNevBufSize) {
95 for (Int_t i=0;i<fNevBufSize;i++) fEntryOffset[i] = 0;
96 }
97 branch->GetTree()->IncrementTotalBuffers(fBufferSize);
98}
99
100////////////////////////////////////////////////////////////////////////////////
101/// Basket destructor.
102
104{
105 if (fDisplacement) delete [] fDisplacement;
107 if (fBufferRef) delete fBufferRef;
108 fBufferRef = nullptr;
109 fBuffer = nullptr;
110 fDisplacement= nullptr;
111 // Note we only delete the compressed buffer if we own it
114 fCompressedBufferRef = nullptr;
115 }
116 // TKey::~TKey will use fMotherDir to attempt to remove they key
117 // from the directory's list of key. A basket is never in that list
118 // and in some cases (eg. f = new TFile(); TTree t; delete f;) the
119 // directory is gone before the TTree.
120 fMotherDir = nullptr;
121}
122
123////////////////////////////////////////////////////////////////////////////////
124/// Increase the size of the current fBuffer up to newsize.
125
141
142////////////////////////////////////////////////////////////////////////////////
143/// Copy the basket of this branch onto the file to.
144
146{
150 Create(nout, to);
152 fHeaderOnly = true;
154 fHeaderOnly = false;
156
157 return nBytes>0 ? nBytes : -1;
158}
159
160////////////////////////////////////////////////////////////////////////////////
161/// Delete fEntryOffset array.
162
168
169////////////////////////////////////////////////////////////////////////////////
170/// Drop buffers of this basket if it is not the current basket.
171
173{
174 if (!fBuffer && !fBufferRef) return 0;
175
176 if (fDisplacement) delete [] fDisplacement;
178 if (fBufferRef) delete fBufferRef;
180 fBufferRef = nullptr;
181 fCompressedBufferRef = nullptr;
182 fBuffer = nullptr;
183 fDisplacement= nullptr;
184 fEntryOffset = nullptr;
186 return fBufferSize;
187}
188
189////////////////////////////////////////////////////////////////////////////////
190/// Calculates the entry offset array, if possible.
191///
192/// Result is cached, meaning that this should only be invoked once per basket.
193
195{
196 if (fEntryOffset != reinterpret_cast<Int_t *>(-1)) {
197 return fEntryOffset;
198 }
199
200 if (R__unlikely(!fBranch)) {
201 Error("GetCalculatedEntryOffset", "Basket entry offset calculation requested, but no associated TBranch!");
202 return nullptr;
203 }
204 if (R__unlikely(fBranch->GetNleaves() != 1)) {
205 Error("GetCalculatedEntryOffset", "Branch contains multiple leaves - unable to calculated entry offsets!");
206 return nullptr;
207 }
208 TLeaf *leaf = static_cast<TLeaf *>((*fBranch->GetListOfLeaves())[0]);
209 fEntryOffset = leaf->GenerateOffsetArray(fKeylen, fNevBuf);
210 return fEntryOffset;
211}
212
213////////////////////////////////////////////////////////////////////////////////
214/// Determine whether we can generate the offset array when this branch is read.
215///
216
218{
219 if (fBranch->GetNleaves() != 1) {
220 return false;
221 }
222 TLeaf *leaf = static_cast<TLeaf *>((*fBranch->GetListOfLeaves())[0]);
223 return leaf->CanGenerateOffsetArray();
224}
225
226////////////////////////////////////////////////////////////////////////////////
227/// Get pointer to buffer for internal entry.
228
238
239////////////////////////////////////////////////////////////////////////////////
240/// Load basket buffers in memory without unziping.
241/// This function is called by TTreeCloner.
242/// The function returns 0 in case of success, 1 in case of error.
243
245{
246 if (fBufferRef) {
247 // Reuse the buffer if it exist.
248 fBufferRef->Reset();
249
250 // We use this buffer both for reading and writing, we need to
251 // make sure it is properly sized for writing.
253 if (fBufferRef->BufferSize() < len) {
255 }
257 } else {
259 }
260 fBufferRef->SetParent(file);
261 char *buffer = fBufferRef->Buffer();
262 file->Seek(pos);
263 TFileCacheRead *pf = tree->GetReadCache(file);
264 if (pf) {
266 if (tree->GetPerfStats()) gPerfStats = tree->GetPerfStats();
267 Int_t st = pf->ReadBuffer(buffer,pos,len);
268 if (st < 0) {
269 return 1;
270 } else if (st == 0) {
271 // fOffset might have been changed via TFileCacheRead::ReadBuffer(), reset it
272 file->Seek(pos);
273 // If we are using a TTreeCache, disable reading from the default cache
274 // temporarily, to force reading directly from file
275 TTreeCache *fc = dynamic_cast<TTreeCache*>(file->GetCacheRead());
276 if (fc) fc->Disable();
277 Int_t ret = file->ReadBuffer(buffer,len);
278 if (fc) fc->Enable();
279 pf->AddNoCacheBytesRead(len);
280 pf->AddNoCacheReadCalls(1);
281 if (ret) {
282 return 1;
283 }
284 }
285 gPerfStats = temp;
286 // fOffset might have been changed via TFileCacheRead::ReadBuffer(), reset it
287 file->SetOffset(pos + len);
288 } else {
290 if (tree->GetPerfStats() != nullptr) gPerfStats = tree->GetPerfStats();
291 if (file->ReadBuffer(buffer,len)) {
292 gPerfStats = temp;
293 return 1; //error while reading
294 }
295 else gPerfStats = temp;
296 }
297
301
302 return 0;
303}
304
305////////////////////////////////////////////////////////////////////////////////
306/// Remove the first dentries of this basket, moving entries at
307/// dentries to the start of the buffer.
308
310{
311 Int_t i;
312
313 if (dentries >= fNevBuf) return;
315 Int_t moved;
316
318 if (entryOffset) {
321
322 // First store the original location in the fDisplacement array
323 // and record the new start offset
324
325 if (!fDisplacement) {
327 }
328 for (i = 0; i<(fNevBufSize-dentries); ++i) {
331 }
332 for (i = fNevBufSize-dentries; i<fNevBufSize; ++i) {
333 fDisplacement[i] = 0;
334 entryOffset[i] = 0;
335 }
336
337 } else {
338 // If there is no EntryOffset array, this means
339 // that each entry has the same size and that
340 // it does not point to other objects (hence there
341 // is no need for a displacement array).
344 }
345 TBuffer *buf = GetBufferRef();
346 char *buffer = buf->Buffer();
347 memmove(buffer+GetKeylen(),buffer+bufbegin,buf->Length()-bufbegin);
348 buf->SetBufferOffset(buf->Length()-moved);
349 fNevBuf -= dentries;
350}
351
352#define OLD_CASE_EXPRESSION fObjlen==fNbytes-fKeylen && GetBranch()->GetCompressionLevel()!=0 && file->GetVersion()<=30401
353////////////////////////////////////////////////////////////////////////////////
354/// By-passing buffer unzipping has been requested and is
355/// possible (only 1 entry in this basket).
356
358{
360
361 // Make sure that the buffer is set at the END of the data
363
364 // Indicate that this buffer is weird.
366
367 // Usage of this mode assume the existence of only ONE
368 // entry in this basket.
370 delete [] fDisplacement; fDisplacement = nullptr;
371
373 return 0;
374}
375
376////////////////////////////////////////////////////////////////////////////////
377/// We always create the TBuffer for the basket but it hold the buffer from the cache.
378
380{
381 if (fBufferRef) {
384 fBufferRef->Reset();
385 } else {
387 }
388 fBufferRef->SetParent(file);
389
391
392 if (IsZombie()) {
393 return -1;
394 }
395
397
400 }
401
403 return fObjlen+fKeylen;
404}
405
406////////////////////////////////////////////////////////////////////////////////
407/// Initialize a buffer for reading if it is not already initialized
408
410{
412 if (R__likely(bufferRef)) {
413 bufferRef->SetReadMode();
414 Int_t curBufferSize = bufferRef->BufferSize();
415 if (curBufferSize < len) {
416 // Experience shows that giving 5% "wiggle-room" decreases churn.
417 bufferRef->Expand(Int_t(len*1.05));
418 }
419 bufferRef->Reset();
421 } else {
423 }
424 result->SetParent(file);
425 return result;
426}
427
428////////////////////////////////////////////////////////////////////////////////
429/// Initialize the compressed buffer; either from the TTree or create a local one.
430
439
441{
442 if (fEntryOffset != reinterpret_cast<Int_t *>(-1)) {
443 delete[] fEntryOffset;
444 }
445 fEntryOffset = nullptr;
446}
447
448////////////////////////////////////////////////////////////////////////////////
449/// Read basket buffers in memory and cleanup.
450///
451/// Read a basket buffer. Check if buffers of previous ReadBasket
452/// should not be dropped. Remember, we keep buffers in memory up to
453/// fMaxVirtualSize.
454/// The function returns 0 in case of success, 1 in case of error
455/// This function was modified with the addition of the parallel
456/// unzipping, it will try to get the unzipped file from the cache
457/// receiving only a pointer to that buffer (so we shall not
458/// delete that pointer), although we get a new buffer in case
459/// it's not found in the cache.
460/// There is a lot of code duplication but it was necessary to assure
461/// the expected behavior when there is no cache.
462
464{
465 if(!fBranch->GetDirectory()) {
466 return -1;
467 }
468
469 bool oldCase;
472
473 // See if the cache has already unzipped the buffer for us.
474 TFileCacheRead *pf = nullptr;
475 {
476 R__LOCKGUARD_IMT(gROOTMutex); // Lock for parallel TTree I/O
477 pf = fBranch->GetTree()->GetReadCache(file);
478 }
479 if (pf) {
480 Int_t res = -1;
481 bool free = true;
482 char *buffer = nullptr;
483 res = pf->GetUnzipBuffer(&buffer, pos, len, &free);
484 if (R__unlikely(res >= 0)) {
485 len = ReadBasketBuffersUnzip(buffer, res, free, file);
486 // Note that in the kNotDecompressed case, the above function will return 0;
487 // In such a case, we should stop processing
488 if (len <= 0) return -len;
489 goto AfterBuffer;
490 }
491 }
492
493 // Determine which buffer to use, so that we can avoid a memcpy in case of
494 // the basket was not compressed.
497 // Initialize the buffer to hold the uncompressed data.
500 } else {
501 // Initialize the buffer to hold the compressed data.
504 }
505
506 // fBufferSize is likely to be change in the Streamer call (below)
507 // and we will re-add the new size later on.
509
510 if (!readBufferRef) {
511 Error("ReadBasketBuffers", "Unable to allocate buffer.");
512 return 1;
513 }
514
515 if (pf) {
517 if (fBranch->GetTree()->GetPerfStats() != nullptr) gPerfStats = fBranch->GetTree()->GetPerfStats();
518 Int_t st = 0;
519 {
520 R__LOCKGUARD_IMT(gROOTMutex); // Lock for parallel TTree I/O
521 st = pf->ReadBuffer(readBufferRef->Buffer(),pos,len);
522 }
523 if (st < 0) {
524 return 1;
525 } else if (st == 0) {
526 // Read directly from file, not from the cache
527 // If we are using a TTreeCache, disable reading from the default cache
528 // temporarily, to force reading directly from file
529 R__LOCKGUARD_IMT(gROOTMutex); // Lock for parallel TTree I/O
530 TTreeCache *fc = dynamic_cast<TTreeCache*>(file->GetCacheRead());
531 if (fc) fc->Disable();
532 Int_t ret = file->ReadBuffer(readBufferRef->Buffer(),pos,len);
533 if (fc) fc->Enable();
534 pf->AddNoCacheBytesRead(len);
535 pf->AddNoCacheReadCalls(1);
536 if (ret) {
537 return 1;
538 }
539 }
540 gPerfStats = temp;
541 } else {
542 // Read from the file and unstream the header information.
544 if (fBranch->GetTree()->GetPerfStats() != nullptr) gPerfStats = fBranch->GetTree()->GetPerfStats();
545 R__LOCKGUARD_IMT(gROOTMutex); // Lock for parallel TTree I/O
546 if (file->ReadBuffer(readBufferRef->Buffer(),pos,len)) {
547 gPerfStats = temp;
548 return 1;
549 }
550 else gPerfStats = temp;
551 }
553 if (IsZombie()) {
554 return 1;
555 }
556
558
559 // Are we done?
560 if (R__unlikely(readBufferRef == fBufferRef)) // We expect most basket to be compressed.
561 {
563 // The basket was really not compressed as expected.
564 goto AfterBuffer;
565 } else {
566 // Well, somehow the buffer was compressed anyway, we have the compressed data in the uncompressed buffer
567 // Make sure the compressed buffer is initialized, and memcpy.
570 Error("ReadBasketBuffers", "Unable to allocate buffer.");
571 return 1;
572 }
573 fBufferRef->Reset();
576 }
577 }
578
579 // Initialize buffer to hold the uncompressed data
580 // Note that in previous versions we didn't allocate buffers until we verified
581 // the zip headers; this is no longer beforehand as the buffer lifetime is scoped
582 // to the TBranch.
587
589 // Case where ROOT thinks the buffer is compressed. Copy over the key and uncompress the object
590 if (fObjlen > fNbytes-fKeylen || oldCase) {
593 }
594
595 // Optional monitor for zip time profiling.
596 Double_t start = 0;
597 if (R__unlikely(gPerfStats)) {
598 start = TTimeStamp();
599 }
600
604
605 // TODO(jblomer): factor out and combine with UnzipObject() in TKey
606 Int_t nin = 0, nbuf = 0;
607 Int_t nout = 0, noutot = 0, nintot = 0;
608
611
612 // Unzip all the compressed objects in the compressed object buffer.
613 while (nbytesRemain >= ROOT::Internal::kZipHeaderSize) {
614 // Check the header for errors.
616 Error("ReadBasketBuffers", "Inconsistency found in header (nin=%d, nbuf=%d)", nin, nbuf);
617 break;
618 }
619 if (R__unlikely(oldCase && (nin > fObjlen || nbuf > fObjlen))) {
620 //buffer was very likely not compressed in an old version
622 goto AfterBuffer;
623 }
624 if (R__unlikely((nin > nbytesRemain) || (nbuf > objlenRemain))) {
625 break;
626 }
627
629 if (!nout) break;
630 noutot += nout;
631 nintot += nin;
632 if (noutot >= fObjlen) break;
635 nbytesRemain -= nin;
637 }
638
639 // Make sure the uncompressed numbers are consistent with header.
640 if (R__unlikely(noutot != fObjlen)) {
641 Error("ReadBasketBuffers", "fNbytes = %d, fKeylen = %d, fObjlen = %d, noutot = %d, nout=%d, nin=%d, nbuf=%d", fNbytes,fKeylen,fObjlen, noutot,nout,nin,nbuf);
643 return 1;
644 }
647 if (fBranch->GetTree()->GetPerfStats() != nullptr) gPerfStats = fBranch->GetTree()->GetPerfStats();
648 if (R__unlikely(gPerfStats)) {
649 gPerfStats->UnzipEvent(fBranch->GetTree(),pos,start,nintot,fObjlen);
650 }
651 gPerfStats = temp;
652 } else {
653 // Nothing is compressed - copy over wholesale.
655 }
656
658
660
661 // Read offsets table if needed.
662 // If there's no EntryOffsetLen in the branch -- or the fEntryOffset is marked to be calculated-on-demand --
663 // then we skip reading out.
664 if (!fBranch->GetEntryOffsetLen() || (fEntryOffset == reinterpret_cast<Int_t *>(-1))) {
665 return 0;
666 }
667 // At this point, we're required to read out an offset array.
668 ResetEntryOffset(); // TODO: every basket, we reset the offset array. Is this necessary?
669 // Could we instead switch to std::vector?
673 fEntryOffset = new Int_t[fNevBuf+1];
675 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);
676 return 0;
677 }
679 // In this case, we cannot regenerate the offset array at runtime -- but we wrote out an array of
680 // sizes instead of offsets (as sizes compress much better).
682 for (Int_t idx = 1; idx < fNevBuf + 1; idx++) {
683 fEntryOffset[idx] += fEntryOffset[idx - 1];
684 }
685 }
686 fReadEntryOffset = true;
687 // Read the array of displacement if any.
688 delete [] fDisplacement;
689 fDisplacement = nullptr;
690 if (fBufferRef->Length() != len) {
691 // There is more data in the buffer! It is the displacement
692 // array. If len is less than TBuffer::kMinimalSize the actual
693 // size of the buffer is too large, so we can not use the
694 // fBufferRef->BufferSize()
696 }
697
698 return 0;
699}
700
701////////////////////////////////////////////////////////////////////////////////
702/// Read basket buffers in memory and cleanup
703///
704/// Read first bytes of a logical record starting at position pos
705/// return record length (first 4 bytes of record).
706
708{
709 const Int_t len = 128;
710 char buffer[len];
712 file->GetRecordHeader(buffer, pos,len, fNbytes, fObjlen, keylen);
713 fKeylen = keylen;
714 return fNbytes;
715}
716
717////////////////////////////////////////////////////////////////////////////////
718/// Disown all references to the internal buffer - some other object likely now
719/// owns it.
720///
721/// This TBasket is now useless and invalid until it is told to adopt a buffer.
723{
724 fBufferRef = nullptr;
725}
726
727
728////////////////////////////////////////////////////////////////////////////////
729/// Adopt a buffer from an external entity
735
736////////////////////////////////////////////////////////////////////////////////
737/// Reset the read basket TBuffer memory allocation if needed.
738///
739/// This allows to reduce the number of memory allocation while avoiding to
740/// always use the maximum size.
741
743{
744 // By default, we don't reallocate.
745 fResetAllocation = false;
746#ifdef R__TRACK_BASKET_ALLOC_TIME
748#endif
749
750 // Downsize the buffer if needed.
751
752 const auto maxbaskets = fBranch->GetMaxBaskets();
754 return;
755
757
759 const auto basketbytes = fBranch->GetBasketBytes();
760
761 Int_t max_size = basketbytes[basketnumber];
762 for(Int_t b = basketnumber + 1; (b < maxbaskets) && (b < (basketnumber+10)); ++b) {
763 max_size = std::max(max_size, basketbytes[b]);
764 }
765
766 Float_t cx = 1;
767 if (fBranch->GetZipBytes())
769
770 Int_t target_size = static_cast<Int_t>(cx * target_mem_ratio * Float_t(max_size));
771
772 if (target_size && (curSize > target_size)) {
773 /// Only reduce the size if significant enough?
774 Int_t newSize = max_size + 512 - max_size % 512; // Wiggle room and alignment, as above.
775 // We only bother with a resize if it saves 8KB (two normal memory pages).
776 if ((newSize <= curSize - 8 * 1024) &&
777 (static_cast<Float_t>(curSize) / static_cast<Float_t>(newSize) > target_mem_ratio))
778 {
779 if (gDebug > 0) {
780 Info("ReadResetBuffer",
781 "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 ",
793 cx, target_mem_ratio, max_size);
794 }
795 fResetAllocation = true;
796#ifdef R__TRACK_BASKET_ALLOC_TIME
797 std::chrono::time_point<std::chrono::system_clock> start, end;
798 start = std::chrono::high_resolution_clock::now();
799#endif
800 fBufferRef->Expand(newSize, false); // Expand without copying the existing data.
801#ifdef R__TRACK_BASKET_ALLOC_TIME
802 end = std::chrono::high_resolution_clock::now();
803 auto us = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
804 fResetAllocationTime = us.count();
805#endif
806 }
807 }
808}
809
810////////////////////////////////////////////////////////////////////////////////
811/// Reset the write basket to the starting state. i.e. as it was after calling
812/// the constructor (and potentially attaching a TBuffer.)
813/// Reduce memory used by fEntryOffset and the TBuffer if needed ..
814
816{
817 // By default, we don't reallocate.
818 fResetAllocation = false;
819#ifdef R__TRACK_BASKET_ALLOC_TIME
821#endif
822
823 // Name, Title, fClassName, fBranch
824 // stay the same.
825
826 // Downsize the buffer if needed.
827 // See if our current buffer size is significantly larger (>2x) than the historical average.
828 // If so, try decreasing it at this flush boundary to closer to the size from OptimizeBaskets
829 // (or this historical average).
831 // fBufferLen at this point is already reset, so use indirect measurements
833 Longptr_t newSize = -1;
834 if (curSize > 2*curLen)
835 {
837 if (curSize > 2*curBsize ) {
838 Longptr_t avgSize = (Longptr_t)(fBranch->GetTotBytes() / (1+fBranch->GetWriteBasket())); // Average number of bytes per basket so far
839 if (curSize > 2*avgSize) {
841 if (curLen > newSize) {
842 newSize = curLen;
843 }
844 if (avgSize > newSize) {
846 }
847 newSize = newSize + 512 - newSize%512; // Wiggle room and alignment (512 is same as in OptimizeBaskets)
848 }
849 }
850 }
851 // If fBufferRef grew since we last saw it, shrink it to "target memory ratio" of the occupied size
852 // This discourages us from having poorly-occupied buffers on branches with little variability.
853 //
854 // Does not help protect against a burst in event sizes, but does help in the cases where the basket
855 // size jumps from 4MB to 8MB while filling the basket, but we only end up utilizing 4.1MB.
856 //
857 // The above code block is meant to protect against extremely large events.
858
861 Int_t target_size = static_cast<Int_t>(target_mem_ratio * Float_t(max_size));
862 if (max_size && (curSize > target_size) && (newSize == -1)) {
864 newSize = newSize + 512 - newSize % 512; // Wiggle room and alignment, as above.
865 // We only bother with a resize if it saves 8KB (two normal memory pages).
866 if ((newSize > curSize - 8 * 1024) ||
867 (static_cast<Float_t>(curSize) / static_cast<Float_t>(newSize) < target_mem_ratio)) {
868 newSize = -1;
869 } else if (gDebug > 0) {
870 Info("Reset", "Resizing to %ld bytes (was %d); last three sizes were [%d, %d, %d].", newSize, curSize,
872 }
873 }
874
875 if (newSize != -1) {
876 fResetAllocation = true;
877#ifdef R__TRACK_BASKET_ALLOC_TIME
878 std::chrono::time_point<std::chrono::system_clock> start, end;
879 start = std::chrono::high_resolution_clock::now();
880#endif
881 fBufferRef->Expand(newSize,false); // Expand without copying the existing data.
882#ifdef R__TRACK_BASKET_ALLOC_TIME
883 end = std::chrono::high_resolution_clock::now();
884 auto us = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
885 fResetAllocationTime = us.count();
886#endif
887 }
888
889 // Record the actual occupied size of the buffer.
892
893 TKey::Reset();
894
896 if (newNevBufSize==0) {
898 } else if ((newNevBufSize != fNevBufSize) || (fEntryOffset <= reinterpret_cast<Int_t *>(-1))) {
901 }
903
904 fNevBuf = 0;
906 fEntryOffset = nullptr;
908 fDisplacement= nullptr;
909 fBuffer = nullptr;
910
911 fBufferRef->Reset();
913
914 fHeaderOnly = true;
915 fLast = 0; //Must initialize before calling Streamer()
916
918
921 fLast = fKeylen;
922 fBuffer = nullptr;
923 fHeaderOnly = false;
926 if (fNevBufSize) {
927 for (Int_t i=0;i<fNevBufSize;i++) fEntryOffset[i] = 0;
928 }
929}
930
931////////////////////////////////////////////////////////////////////////////////
932/// Set read mode of basket.
933
939
940////////////////////////////////////////////////////////////////////////////////
941/// Set write mode of basket.
942
948
949////////////////////////////////////////////////////////////////////////////////
950/// Stream a class object.
951
953{
954 // As in TBranch::GetBasket, this is used as a half-hearted measure to suppress
955 // the error reporting when many failures occur.
956 static std::atomic<Int_t> nerrors(0);
957
958 char flag;
959 if (b.IsReading()) {
960 TKey::Streamer(b); //this must be first
961 Version_t v = b.ReadVersion();
962 b >> fBufferSize;
963 // NOTE: we now use the upper-bit of the fNevBufSize to see if we have serialized any of the
964 // optional IOBits. If that bit is set, we immediately read out the IOBits; to replace this
965 // (minimal) safeguard against corruption, we will set aside the upper-bit of fIOBits to do
966 // the same thing (the fact this bit is reserved is tested in the unit tests). If there is
967 // someday a need for more than 7 IOBits, we'll widen the field using the same trick.
968 //
969 // We like to keep this safeguard because we immediately will allocate a buffer based on
970 // the value of fNevBufSize -- and would like to avoid wildly inappropriate allocations.
971 b >> fNevBufSize;
972 if (fNevBufSize < 0) {
974 b >> fIOBits;
975 if (!fIOBits || (fIOBits & (1 << 7))) {
976 Error("TBasket::Streamer",
977 "The value of fNevBufSize (%d) or fIOBits (%d) is incorrect ; setting the buffer to a zombie.",
979 MakeZombie();
980 fNevBufSize = 0;
981 } else if (fIOBits && (fIOBits & ~static_cast<Int_t>(EIOBits::kSupported))) {
982 nerrors++;
983 if (nerrors < 10) {
984 Error("Streamer", "The value of fIOBits (%s) contains unknown flags (supported flags "
985 "are %s), indicating this was written with a newer version of ROOT "
986 "utilizing critical IO features this version of ROOT does not support."
987 " Refusing to deserialize.",
988 std::bitset<32>(static_cast<Int_t>(fIOBits)).to_string().c_str(),
989 std::bitset<32>(static_cast<Int_t>(EIOBits::kSupported)).to_string().c_str());
990 } else if (nerrors == 10) {
991 Error("Streamer", "Maximum number of errors has been reported; disabling further messages"
992 "from this location until the process exits.");
993 }
994 fNevBufSize = 0;
995 MakeZombie();
996 }
997 }
998 b >> fNevBuf;
999 b >> fLast;
1000 b >> flag;
1002 bool mustGenerateOffsets = false;
1003 if (flag >= 80) {
1004 mustGenerateOffsets = true;
1005 flag -= 80;
1006 }
1007 if (!mustGenerateOffsets && flag && (flag % 10 != 2)) {
1010 if (fNevBuf) b.ReadArray(fEntryOffset);
1011 if (20<flag && flag<40) {
1012 for(int i=0; i<fNevBuf; i++){
1014 }
1015 }
1016 if (flag>40) {
1018 b.ReadArray(fDisplacement);
1019 }
1020 } else if (mustGenerateOffsets) {
1021 // We currently believe that in all cases when offsets can be generated, then the
1022 // displacement array must be zero.
1023 assert(flag <= 40);
1024 fEntryOffset = reinterpret_cast<Int_t *>(-1);
1025 }
1026 if (flag == 1 || flag > 10) {
1028 fBufferRef->SetParent(b.GetParent());
1029 char *buf = fBufferRef->Buffer();
1030 if (v > 1) b.ReadFastArray(buf,fLast);
1031 else b.ReadArray(buf);
1033 // This is now done in the TBranch streamer since fBranch might not
1034 // yet be set correctly.
1035 // fBranch->GetTree()->IncrementTotalBuffers(fBufferSize);
1036 }
1037 } else {
1038
1039 TKey::Streamer(b); //this must be first
1040 b.WriteVersion(TBasket::IsA());
1041 if (fBufferRef) {
1043 if (!fHeaderOnly && !fSeekKey && curLast > fLast) fLast = curLast;
1044 }
1046
1047 b << fBufferSize;
1048 if (fIOBits) {
1049 b << -fNevBufSize;
1050 b << fIOBits;
1051 } else {
1052 b << fNevBufSize;
1053 }
1054 b << fNevBuf;
1055 b << fLast;
1059 // We currently believe that in all cases when offsets can be generated, then the
1060 // displacement array must be zero.
1062 if (fHeaderOnly) {
1063 flag = mustGenerateOffsets ? 80 : 0;
1064 b << flag;
1065 } else {
1066 // On return from this function, we are guaranteed that fEntryOffset
1067 // is either a valid pointer or nullptr.
1068 if (fNevBuf) {
1070 }
1071 flag = 1;
1072 if (!fNevBuf || !fEntryOffset)
1073 flag = 2;
1074 if (fBufferRef) flag += 10;
1075 if (fDisplacement) flag += 40;
1076 // Test if we can skip writing out the offset map.
1077 if (mustGenerateOffsets) {
1078 flag += 80;
1079 }
1080 b << flag;
1081
1083 b.WriteArray(fEntryOffset, fNevBuf);
1084 if (fDisplacement) b.WriteArray(fDisplacement, fNevBuf);
1085 }
1086 if (fBufferRef) {
1087 char *buf = fBufferRef->Buffer();
1088 b.WriteFastArray(buf, fLast);
1089 }
1090 }
1091 }
1092}
1093
1094////////////////////////////////////////////////////////////////////////////////
1095/// Update basket header and EntryOffset table.
1096
1098{
1100 if (entryOffset) {
1101 if (fNevBuf+1 >= fNevBufSize) {
1104 fNevBufSize);
1105 if (fDisplacement) {
1107 fNevBufSize);
1109 }
1112
1113 //Update branch only for the first 10 baskets
1114 if (fBranch->GetWriteBasket() < 10) {
1116 }
1117 }
1119
1120 if (skipped!=offset && !fDisplacement){
1122 for (Int_t i = 0; i<fNevBufSize; i++) fDisplacement[i] = fEntryOffset[i];
1123 }
1124 if (fDisplacement) {
1127 }
1128 }
1129
1130 fNevBuf++;
1131}
1132
1133////////////////////////////////////////////////////////////////////////////////
1134/// Write buffer of this basket on the current file.
1135///
1136/// The function returns the number of bytes committed to the memory.
1137/// If a write error occurs, the number of bytes returned is -1.
1138/// If no data are written, the number of bytes returned is 0.
1139
1141{
1142 constexpr Int_t kWrite = 1;
1143
1144 TFile *file = fBranch->GetFile(kWrite);
1145 if (!file) return 0;
1146 if (!file->IsWritable()) {
1147 return -1;
1148 }
1149 fMotherDir = file; // fBranch->GetDirectory();
1150
1151 // This mutex prevents multiple TBasket::WriteBuffer invocations from interacting
1152 // with the underlying TFile at once - TFile is assumed to *not* be thread-safe.
1153 //
1154 // The only parallelism we'd like to exploit (right now!) is the compression
1155 // step - everything else should be serialized at the TFile level.
1156#ifdef R__USE_IMT
1157 std::unique_lock<std::mutex> sentry(file->fWriteMutex);
1158#endif // R__USE_IMT
1159
1161 // Read the basket information that was saved inside the buffer.
1162 bool writing = fBufferRef->IsWriting();
1165
1169
1171
1172 Create(nout,file);
1174 fHeaderOnly = true;
1175
1176 Streamer(*fBufferRef); //write key itself again
1178 fHeaderOnly = false;
1179 return nBytes>0 ? fKeylen+nout : -1;
1180 }
1181
1182 // Transfer fEntryOffset table at the end of fBuffer.
1183 fLast = fBufferRef->Length();
1185 if (entryOffset) {
1187 if (!CanGenerateOffsetArray()) {
1188 // If we have set the offset map flag, but cannot dynamically generate the map, then
1189 // we should at least convert the offset array to a size array. Note that we always
1190 // write out (fNevBuf+1) entries to match the original case.
1191 if (hasOffsetBit) {
1192 for (Int_t idx = fNevBuf; idx > 0; idx--) {
1193 entryOffset[idx] -= entryOffset[idx - 1];
1194 }
1195 entryOffset[0] = 0;
1196 }
1198 // Convert back to offset format: keeping both sizes and offsets in-memory were considered,
1199 // but it seems better to use CPU than memory.
1200 if (hasOffsetBit) {
1201 entryOffset[0] = fKeylen;
1202 for (Int_t idx = 1; idx < fNevBuf + 1; idx++) {
1203 entryOffset[idx] += entryOffset[idx - 1];
1204 }
1205 }
1206 } else if (!hasOffsetBit) { // In this case, write out as normal
1208 }
1209 if (fDisplacement) {
1211 delete[] fDisplacement;
1212 fDisplacement = nullptr;
1213 }
1214 }
1215
1216 Int_t nout, noutot, bufmax, nzip;
1217
1219
1220 fHeaderOnly = true;
1224 cxlevel = file->GetCompressionLevel();
1228 if (cxlevel > 0) {
1229 Int_t nbuffers = 1 + (fObjlen - 1) / kMAXZIPBUF;
1230 Int_t buflen = fKeylen + fObjlen + 9 * nbuffers + 28; //add 28 bytes in case object is placed in a deleted gap
1231 InitializeCompressedBuffer(buflen, file);
1232 if (!fCompressedBufferRef) {
1233 Warning("WriteBuffer", "Unable to allocate the compressed buffer");
1234 return -1;
1235 }
1238 char *objbuf = fBufferRef->Buffer() + fKeylen;
1239 char *bufcur = &fBuffer[fKeylen];
1240 noutot = 0;
1241 nzip = 0;
1242 for (Int_t i = 0; i < nbuffers; ++i) {
1243 if (i == nbuffers - 1) bufmax = fObjlen - nzip;
1244 else bufmax = kMAXZIPBUF;
1245 // Compress the buffer. Note that we allow multiple TBasket compressions to occur at once
1246 // for a given TFile: that's because the compression buffer when we use IMT is no longer
1247 // shared amongst several threads.
1248#ifdef R__USE_IMT
1249 sentry.unlock();
1250#endif // R__USE_IMT
1251 // NOTE this is declared with C linkage, so it shouldn't except. Also, when
1252 // USE_IMT is defined, we are guaranteed that the compression buffer is unique per-branch.
1253 // (see fCompressedBufferRef in constructor).
1255#ifdef R__USE_IMT
1256 sentry.lock();
1257#endif // R__USE_IMT
1258
1259 // test if buffer has really been compressed. In case of small buffers
1260 // when the buffer contains random data, it may happen that the compressed
1261 // buffer is larger than the input. In this case, we write the original uncompressed buffer
1262 if (nout == 0 || nout >= fObjlen) {
1263 nout = fObjlen;
1264 // We used to delete fBuffer here, we no longer want to since
1265 // the buffer (held by fCompressedBufferRef) might be re-used later.
1267 Create(fObjlen,file);
1269
1270 Streamer(*fBufferRef); //write key itself again
1271 if ((nout+fKeylen)>buflen) {
1272 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",
1273 (nout+fKeylen-buflen),buflen,fNbytes,fObjlen,fKeylen);
1274 }
1275 goto WriteFile;
1276 }
1277 bufcur += nout;
1278 noutot += nout;
1279 objbuf += kMAXZIPBUF;
1280 nzip += kMAXZIPBUF;
1281 }
1282 nout = noutot;
1283 Create(noutot,file);
1285
1286 Streamer(*fBufferRef); //write key itself again
1288 } else {
1290 Create(fObjlen,file);
1292
1293 Streamer(*fBufferRef); //write key itself again
1294 nout = fObjlen;
1295 }
1296
1297WriteFile:
1299 fHeaderOnly = false;
1300 return nBytes>0 ? fKeylen+nout : -1;
1301}
#define R__likely(expr)
Definition RConfig.hxx:593
#define R__unlikely(expr)
Definition RConfig.hxx:592
#define b(i)
Definition RSha256.hxx:100
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:59
long Longptr_t
Integer large enough to hold a pointer (platform-dependent)
Definition RtypesCore.h:89
short Version_t
Class version identifier (short)
Definition RtypesCore.h:79
unsigned int UInt_t
Unsigned integer 4 bytes (unsigned int)
Definition RtypesCore.h:60
float Float_t
Float 4 bytes (float)
Definition RtypesCore.h:71
long long Long64_t
Portable signed long integer 8 bytes.
Definition RtypesCore.h:83
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:409
#define OLD_CASE_EXPRESSION
Definition TBasket.cxx:352
const UInt_t kDisplacementMask
Definition TBasket.cxx:31
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
Global variable setting the debug level. Set to 0 to disable, increase it in steps of 1 to increase t...
Definition TROOT.cxx:627
R__EXTERN TVirtualMutex * gROOTMutex
Definition TROOT.h:63
#define R__LOCKGUARD_IMT(mutex)
#define gPerfStats
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:229
void AdoptBuffer(TBuffer *user_buffer)
Adopt a buffer from an external entity.
Definition TBasket.cxx:730
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:145
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:431
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:379
void DisownBuffer()
Disown all references to the internal buffer - some other object likely now owns it.
Definition TBasket.cxx:722
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:463
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:172
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:309
bool fOwnsCompressedBuffer
! Whether or not we own the compressed buffer.
Definition TBasket.h:68
void ResetEntryOffset()
Definition TBasket.cxx:440
TBasket()
Default constructor.
Definition TBasket.cxx:46
virtual void AdjustSize(Int_t newsize)
Increase the size of the current fBuffer up to newsize.
Definition TBasket.cxx:126
virtual void SetReadMode()
Set read mode of basket.
Definition TBasket.cxx:934
virtual void SetWriteMode()
Set write mode of basket.
Definition TBasket.cxx:943
Int_t ReadBasketBuffersUncompressedCase()
By-passing buffer unzipping has been requested and is possible (only 1 entry in this basket).
Definition TBasket.cxx:357
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:707
virtual void ReadResetBuffer(Int_t basketnumber)
Reset the read basket TBuffer memory allocation if needed.
Definition TBasket.cxx:742
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:1140
void Streamer(TBuffer &) override
Stream a class object.
Definition TBasket.cxx:952
Int_t LoadBasketBuffers(Long64_t pos, Int_t len, TFile *file, TTree *tree=nullptr)
Load basket buffers in memory without unziping.
Definition TBasket.cxx:244
~TBasket() override
Basket destructor.
Definition TBasket.cxx:103
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:194
TClass * IsA() const override
Definition TBasket.h:156
virtual void DeleteEntryOffset()
Delete fEntryOffset array.
Definition TBasket.cxx:163
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:217
virtual void WriteReset()
Reset the write basket to the starting state.
Definition TBasket.cxx:815
A TTree is a list of TBranches.
Definition TBranch.h:93
Int_t GetCompressionLevel() const
Definition TBranch.h:314
Int_t GetCompressionAlgorithm() const
Definition TBranch.h:308
TTree * GetTree() const
Definition TBranch.h:261
Int_t GetWriteBasket() const
Definition TBranch.h:247
Int_t GetNleaves() const
Definition TBranch.h:258
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:2833
Int_t GetMaxBaskets() const
Definition TBranch.h:257
Int_t * GetBasketBytes() const
Definition TBranch.h:223
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:1852
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:2219
virtual Int_t GetBasketSize() const
Definition TBranch.h:226
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:2237
TObjArray * GetListOfLeaves()
Definition TBranch.h:256
TDirectory * GetDirectory() const
Definition TBranch.h:233
Int_t GetEntryOffsetLen() const
Definition TBranch.h:236
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:314
virtual void Reset()=0
void SetParent(TObject *parent)
Set parent owning this buffer.
Definition TBuffer.cxx:269
void Expand(Int_t newsize, Bool_t copy=kTRUE)
Expand (or shrink) the I/O buffer to newsize bytes.
Definition TBuffer.cxx:222
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:186
void SetBufferOffset(Int_t offset=0)
Definition TBuffer.h:93
void SetReadMode()
Set buffer in read mode.
Definition TBuffer.cxx:301
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 ROOT file is an on-disk file, usually with extension .root, that stores objects in a file-system-li...
Definition TFile.h:130
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:2304
Int_t GetCompressionLevel() const
Definition TFile.h:483
std::mutex fWriteMutex
!Lock for writing baskets / keys into the file.
Definition TFile.h:196
virtual void SetOffset(Long64_t offset, ERelativeTo pos=kBeg)
Set position from where to start reading.
Definition TFile.cxx:2283
Int_t GetCompressionAlgorithm() const
Definition TFile.h:477
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:1290
virtual Bool_t ReadBuffer(char *buf, Int_t len)
Read a buffer from the file.
Definition TFile.cxx:1800
TFileCacheRead * GetCacheRead(const TObject *tree=nullptr) const
Return a pointer to the current read cache.
Definition TFile.cxx:1251
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:86
Int_t GetObjlen() const
Definition TKey.h:89
TBuffer * fBufferRef
Pointer to the TBuffer object.
Definition TKey.h:52
Int_t fVersion
Key version identifier.
Definition TKey.h:41
Short_t fKeylen
Number of bytes for the key itself.
Definition TKey.h:45
virtual Int_t WriteFileKeepBuffer(TFile *f=nullptr)
Write the encoded object supported by this key.
Definition TKey.cxx:1471
Long64_t fSeekKey
Location of object on file.
Definition TKey.h:47
char * fBuffer
Object buffer.
Definition TKey.h:51
Int_t fNbytes
Number of bytes for the object on file.
Definition TKey.h:42
Int_t fObjlen
Length of uncompressed object in bytes.
Definition TKey.h:43
void Reset()
Reset the key as it had not been 'filled' yet.
Definition TKey.cxx:1286
Short_t fCycle
Cycle number.
Definition TKey.h:46
virtual void Create(Int_t nbytes, TFile *f=nullptr)
Create a TKey object of specified size.
Definition TKey.cxx:492
virtual Int_t WriteFile(Int_t cycle=1, TFile *f=nullptr)
Write the encoded object supported by this key.
Definition TKey.cxx:1439
TDirectory * fMotherDir
!pointer to mother directory
Definition TKey.h:54
TString fClassName
Object Class name.
Definition TKey.h:49
void Streamer(TBuffer &) override
Stream a class object.
Definition TKey.cxx:1342
TBuffer * GetBufferRef() const
Definition TKey.h:81
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:173
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:149
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:204
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:1075
R__ALWAYS_INLINE Bool_t IsZombie() const
Definition TObject.h:161
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:882
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1089
void MakeZombie()
Definition TObject.h:55
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition TObject.cxx:1063
static Int_t * ReAllocInt(Int_t *vp, size_t size, size_t oldsize)
Reallocate (i.e.
Definition TStorage.cxx:257
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:89
virtual TVirtualPerfStats * GetPerfStats() const
Definition TTree.h:593
virtual void IncrementTotalBuffers(Int_t nbytes)
Definition TTree.h:633
TTreeCache * GetReadCache(TFile *file) const
Find and return the TTreeCache registered with the file and which may contain branches for us.
Definition TTree.cxx:6429
Float_t GetTargetMemoryRatio() const
Definition TTree.h:607
Provides the interface for the an internal performance measurement and event tracing.
Short_t Max(Short_t a, Short_t b)
Returns the largest of a and b.
Definition TMathBase.h:249
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