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
35constexpr auto gMaxInt_t = std::numeric_limits<Int_t>::max();
36
37/** \class TBasket
38\ingroup tree
39
40Manages buffers for branches of a Tree.
41
42See picture in TTree.
43*/
44
45////////////////////////////////////////////////////////////////////////////////
46/// Default constructor.
47
51
52////////////////////////////////////////////////////////////////////////////////
53/// Constructor used during reading.
54
58
59////////////////////////////////////////////////////////////////////////////////
60/// Basket normal constructor, used during writing.
61
62TBasket::TBasket(const char *name, const char *title, TBranch *branch)
63 : TKey(branch->GetDirectory()), fBufferSize(branch->GetBasketSize()), fNevBufSize(branch->GetEntryOffsetLen()),
64 fHeaderOnly(true), fIOBits(branch->GetIOFeatures().GetFeatures())
65{
67 SetTitle(title);
68 fClassName = "TBasket";
69 fBuffer = nullptr;
71 fVersion += 1000;
72 if (branch->GetDirectory()) {
73 TFile *file = branch->GetFile();
74 fBufferRef->SetParent(file);
75 }
76 if (branch->GetTree()) {
77#ifdef R__USE_IMT
78 fCompressedBufferRef = branch->GetTransientBuffer(fBufferSize);
79#else
80 fCompressedBufferRef = branch->GetTree()->GetTransientBuffer(fBufferSize);
81#endif
86 }
87 }
92 fLast = fKeylen;
93 fBuffer = nullptr;
94 fHeaderOnly = false;
95 if (fNevBufSize) {
97 for (Int_t i=0;i<fNevBufSize;i++) fEntryOffset[i] = 0;
98 }
99 branch->GetTree()->IncrementTotalBuffers(fBufferSize);
100}
101
102////////////////////////////////////////////////////////////////////////////////
103/// Basket destructor.
104
106{
107 if (fDisplacement) delete [] fDisplacement;
109 if (fBufferRef) delete fBufferRef;
110 fBufferRef = nullptr;
111 fBuffer = nullptr;
112 fDisplacement= nullptr;
113 // Note we only delete the compressed buffer if we own it
116 fCompressedBufferRef = nullptr;
117 }
118 // TKey::~TKey will use fMotherDir to attempt to remove they key
119 // from the directory's list of key. A basket is never in that list
120 // and in some cases (eg. f = new TFile(); TTree t; delete f;) the
121 // directory is gone before the TTree.
122 fMotherDir = nullptr;
123}
124
125////////////////////////////////////////////////////////////////////////////////
126/// Increase the size of the current fBuffer up to newsize.
127
143
144////////////////////////////////////////////////////////////////////////////////
145/// Copy the basket of this branch onto the file to.
146
148{
152 Create(nout, to);
154 fHeaderOnly = true;
156 fHeaderOnly = false;
158
159 return nBytes>0 ? nBytes : -1;
160}
161
162////////////////////////////////////////////////////////////////////////////////
163/// Delete fEntryOffset array.
164
170
171////////////////////////////////////////////////////////////////////////////////
172/// Drop buffers of this basket if it is not the current basket.
173
175{
176 if (!fBuffer && !fBufferRef) return 0;
177
178 if (fDisplacement) delete [] fDisplacement;
180 if (fBufferRef) delete fBufferRef;
182 fBufferRef = nullptr;
183 fCompressedBufferRef = nullptr;
184 fBuffer = nullptr;
185 fDisplacement= nullptr;
186 fEntryOffset = nullptr;
188 return fBufferSize;
189}
190
191////////////////////////////////////////////////////////////////////////////////
192/// Calculates the entry offset array, if possible.
193///
194/// Result is cached, meaning that this should only be invoked once per basket.
195
197{
198 if (fEntryOffset != reinterpret_cast<Int_t *>(-1)) {
199 return fEntryOffset;
200 }
201
202 if (R__unlikely(!fBranch)) {
203 Error("GetCalculatedEntryOffset", "Basket entry offset calculation requested, but no associated TBranch!");
204 return nullptr;
205 }
206 if (R__unlikely(fBranch->GetNleaves() != 1)) {
207 Error("GetCalculatedEntryOffset", "Branch contains multiple leaves - unable to calculated entry offsets!");
208 return nullptr;
209 }
210 TLeaf *leaf = static_cast<TLeaf *>((*fBranch->GetListOfLeaves())[0]);
211 fEntryOffset = leaf->GenerateOffsetArray(fKeylen, fNevBuf);
212 return fEntryOffset;
213}
214
215////////////////////////////////////////////////////////////////////////////////
216/// Determine whether we can generate the offset array when this branch is read.
217///
218
220{
221 if (fBranch->GetNleaves() != 1) {
222 return false;
223 }
224 TLeaf *leaf = static_cast<TLeaf *>((*fBranch->GetListOfLeaves())[0]);
225 return leaf->CanGenerateOffsetArray();
226}
227
228////////////////////////////////////////////////////////////////////////////////
229/// Get pointer to buffer for internal entry.
230
240
241////////////////////////////////////////////////////////////////////////////////
242/// Load basket buffers in memory without unziping.
243/// This function is called by TTreeCloner.
244/// The function returns 0 in case of success, 1 in case of error.
245
247{
248 if (fBufferRef) {
249 // Reuse the buffer if it exist.
250 fBufferRef->Reset();
251
252 // We use this buffer both for reading and writing, we need to
253 // make sure it is properly sized for writing.
255 if (fBufferRef->BufferSize() < len) {
257 }
259 } else {
261 }
262 fBufferRef->SetParent(file);
263 char *buffer = fBufferRef->Buffer();
264 file->Seek(pos);
265 TFileCacheRead *pf = tree->GetReadCache(file);
266 if (pf) {
268 if (tree->GetPerfStats()) gPerfStats = tree->GetPerfStats();
269 Int_t st = pf->ReadBuffer(buffer,pos,len);
270 if (st < 0) {
271 return 1;
272 } else if (st == 0) {
273 // fOffset might have been changed via TFileCacheRead::ReadBuffer(), reset it
274 file->Seek(pos);
275 // If we are using a TTreeCache, disable reading from the default cache
276 // temporarily, to force reading directly from file
277 TTreeCache *fc = dynamic_cast<TTreeCache*>(file->GetCacheRead());
278 if (fc) fc->Disable();
279 Int_t ret = file->ReadBuffer(buffer,len);
280 if (fc) fc->Enable();
281 pf->AddNoCacheBytesRead(len);
282 pf->AddNoCacheReadCalls(1);
283 if (ret) {
284 return 1;
285 }
286 }
287 gPerfStats = temp;
288 // fOffset might have been changed via TFileCacheRead::ReadBuffer(), reset it
289 file->SetOffset(pos + len);
290 } else {
292 if (tree->GetPerfStats() != nullptr) gPerfStats = tree->GetPerfStats();
293 if (file->ReadBuffer(buffer,len)) {
294 gPerfStats = temp;
295 return 1; //error while reading
296 }
297 else gPerfStats = temp;
298 }
299
303
304 return 0;
305}
306
307////////////////////////////////////////////////////////////////////////////////
308/// Remove the first dentries of this basket, moving entries at
309/// dentries to the start of the buffer.
310
312{
313 Int_t i;
314
315 if (dentries >= fNevBuf) return;
317 Int_t moved;
318
320 if (entryOffset) {
323
324 // First store the original location in the fDisplacement array
325 // and record the new start offset
326
327 if (!fDisplacement) {
329 }
330 for (i = 0; i<(fNevBufSize-dentries); ++i) {
333 }
334 for (i = fNevBufSize-dentries; i<fNevBufSize; ++i) {
335 fDisplacement[i] = 0;
336 entryOffset[i] = 0;
337 }
338
339 } else {
340 // If there is no EntryOffset array, this means
341 // that each entry has the same size and that
342 // it does not point to other objects (hence there
343 // is no need for a displacement array).
346 }
347 TBuffer *buf = GetBufferRef();
348 char *buffer = buf->Buffer();
349 memmove(buffer+GetKeylen(),buffer+bufbegin,buf->Length()-bufbegin);
350 buf->SetBufferOffset(buf->Length()-moved);
351 fNevBuf -= dentries;
352}
353
354#define OLD_CASE_EXPRESSION fObjlen==fNbytes-fKeylen && GetBranch()->GetCompressionLevel()!=0 && file->GetVersion()<=30401
355////////////////////////////////////////////////////////////////////////////////
356/// By-passing buffer unzipping has been requested and is
357/// possible (only 1 entry in this basket).
358
360{
362
363 // Make sure that the buffer is set at the END of the data
365
366 // Indicate that this buffer is weird.
368
369 // Usage of this mode assume the existence of only ONE
370 // entry in this basket.
372 delete [] fDisplacement; fDisplacement = nullptr;
373
375 return 0;
376}
377
378////////////////////////////////////////////////////////////////////////////////
379/// We always create the TBuffer for the basket but it hold the buffer from the cache.
380
382{
383 if (fBufferRef) {
386 fBufferRef->Reset();
387 } else {
389 }
390 fBufferRef->SetParent(file);
391
393
394 if (IsZombie()) {
395 return -1;
396 }
397
399
402 }
403
405 return fObjlen+fKeylen;
406}
407
408////////////////////////////////////////////////////////////////////////////////
409/// Initialize a buffer for reading if it is not already initialized
410
412{
414 if (R__likely(bufferRef)) {
415 bufferRef->SetReadMode();
416 Int_t curBufferSize = bufferRef->BufferSize();
417 if (curBufferSize < len) {
418 // Experience shows that giving 5% "wiggle-room" decreases churn.
419 bufferRef->Expand(Int_t(len*1.05));
420 }
421 bufferRef->Reset();
423 } else {
425 }
426 result->SetParent(file);
427 return result;
428}
429
430////////////////////////////////////////////////////////////////////////////////
431/// Initialize the compressed buffer; either from the TTree or create a local one.
432
441
443{
444 if (fEntryOffset != reinterpret_cast<Int_t *>(-1)) {
445 delete[] fEntryOffset;
446 }
447 fEntryOffset = nullptr;
448}
449
450////////////////////////////////////////////////////////////////////////////////
451/// Read basket buffers in memory and cleanup.
452///
453/// Read a basket buffer. Check if buffers of previous ReadBasket
454/// should not be dropped. Remember, we keep buffers in memory up to
455/// fMaxVirtualSize.
456/// The function returns 0 in case of success, 1 in case of error
457/// This function was modified with the addition of the parallel
458/// unzipping, it will try to get the unzipped file from the cache
459/// receiving only a pointer to that buffer (so we shall not
460/// delete that pointer), although we get a new buffer in case
461/// it's not found in the cache.
462/// There is a lot of code duplication but it was necessary to assure
463/// the expected behavior when there is no cache.
464
466{
467 if(!fBranch->GetDirectory()) {
468 return -1;
469 }
470
471 bool oldCase;
474
475 // See if the cache has already unzipped the buffer for us.
476 TFileCacheRead *pf = nullptr;
477 {
478 R__LOCKGUARD_IMT(gROOTMutex); // Lock for parallel TTree I/O
479 pf = fBranch->GetTree()->GetReadCache(file);
480 }
481 if (pf) {
482 Int_t res = -1;
483 bool free = true;
484 char *buffer = nullptr;
485 res = pf->GetUnzipBuffer(&buffer, pos, len, &free);
486 if (R__unlikely(res >= 0)) {
487 len = ReadBasketBuffersUnzip(buffer, res, free, file);
488 // Note that in the kNotDecompressed case, the above function will return 0;
489 // In such a case, we should stop processing
490 if (len <= 0) return -len;
491 goto AfterBuffer;
492 }
493 }
494
495 // Determine which buffer to use, so that we can avoid a memcpy in case of
496 // the basket was not compressed.
499 // Initialize the buffer to hold the uncompressed data.
502 } else {
503 // Initialize the buffer to hold the compressed data.
506 }
507
508 // fBufferSize is likely to be change in the Streamer call (below)
509 // and we will re-add the new size later on.
511
512 if (!readBufferRef) {
513 Error("ReadBasketBuffers", "Unable to allocate buffer.");
514 return 1;
515 }
516
517 if (pf) {
519 if (fBranch->GetTree()->GetPerfStats() != nullptr) gPerfStats = fBranch->GetTree()->GetPerfStats();
520 Int_t st = 0;
521 {
522 R__LOCKGUARD_IMT(gROOTMutex); // Lock for parallel TTree I/O
523 st = pf->ReadBuffer(readBufferRef->Buffer(),pos,len);
524 }
525 if (st < 0) {
526 return 1;
527 } else if (st == 0) {
528 // Read directly from file, not from the cache
529 // If we are using a TTreeCache, disable reading from the default cache
530 // temporarily, to force reading directly from file
531 R__LOCKGUARD_IMT(gROOTMutex); // Lock for parallel TTree I/O
532 TTreeCache *fc = dynamic_cast<TTreeCache*>(file->GetCacheRead());
533 if (fc) fc->Disable();
534 Int_t ret = file->ReadBuffer(readBufferRef->Buffer(),pos,len);
535 if (fc) fc->Enable();
536 pf->AddNoCacheBytesRead(len);
537 pf->AddNoCacheReadCalls(1);
538 if (ret) {
539 return 1;
540 }
541 }
542 gPerfStats = temp;
543 } else {
544 // Read from the file and unstream the header information.
546 if (fBranch->GetTree()->GetPerfStats() != nullptr) gPerfStats = fBranch->GetTree()->GetPerfStats();
547 R__LOCKGUARD_IMT(gROOTMutex); // Lock for parallel TTree I/O
548 if (file->ReadBuffer(readBufferRef->Buffer(),pos,len)) {
549 gPerfStats = temp;
550 return 1;
551 }
552 else gPerfStats = temp;
553 }
555 if (IsZombie()) {
556 return 1;
557 }
558
560
561 // Are we done?
562 if (R__unlikely(readBufferRef == fBufferRef)) // We expect most basket to be compressed.
563 {
565 // The basket was really not compressed as expected.
566 goto AfterBuffer;
567 } else {
568 // Well, somehow the buffer was compressed anyway, we have the compressed data in the uncompressed buffer
569 // Make sure the compressed buffer is initialized, and memcpy.
572 Error("ReadBasketBuffers", "Unable to allocate buffer.");
573 return 1;
574 }
575 fBufferRef->Reset();
578 }
579 }
580 // Sanitize nbytes and lengths
581 if (fKeylen < 0) {
582 Error("ReadBasketBuffers", "The value of fKeylen is incorrect (%d) ; trying to recover by setting it to zero", fKeylen);
583 MakeZombie();
584 fKeylen = 0;
585 return 1;
586 }
587 if (fObjlen < 0) {
588 Error("ReadBasketBuffers", "The value of fObjlen is incorrect (%d) ; trying to recover by setting it to zero", fObjlen);
589 MakeZombie();
590 fObjlen = 0;
591 return 1;
592 }
593 if (fNbytes < 0) {
594 Error("ReadBasketBuffers", "The value of fNbytes is incorrect (%d) ; trying to recover by setting it to zero", fNbytes);
595 MakeZombie();
596 fNbytes = 0;
597 return 1;
598 }
599 if (fKeylen > (gMaxInt_t - fObjlen)) {
600 Error("ReadBasketBuffers", "fObjlen (%d) + fKeylen (%d) > max int (%d): cannot continue to read the key buffer.",
602 MakeZombie();
603 return 1;
604 }
605
606 // Initialize buffer to hold the uncompressed data
607 // Note that in previous versions we didn't allocate buffers until we verified
608 // the zip headers; this is no longer beforehand as the buffer lifetime is scoped
609 // to the TBranch.
614
616 // Case where ROOT thinks the buffer is compressed. Copy over the key and uncompress the object
617 if (fObjlen > fNbytes-fKeylen || oldCase) {
620 }
621
622 // Optional monitor for zip time profiling.
623 Double_t start = 0;
624 if (R__unlikely(gPerfStats)) {
625 start = TTimeStamp();
626 }
627
631
632 // TODO(jblomer): factor out and combine with UnzipObject() in TKey
633 Int_t nin = 0, nbuf = 0;
634 Int_t nout = 0, noutot = 0, nintot = 0;
635
638
639 // Unzip all the compressed objects in the compressed object buffer.
640 while (nbytesRemain >= ROOT::Internal::kZipHeaderSize) {
641 // Check the header for errors.
643 Error("ReadBasketBuffers", "Inconsistency found in header (nin=%d, nbuf=%d)", nin, nbuf);
644 break;
645 }
646 if (R__unlikely(oldCase && (nin > fObjlen || nbuf > fObjlen))) {
647 //buffer was very likely not compressed in an old version
649 goto AfterBuffer;
650 }
651 if (R__unlikely((nin > nbytesRemain) || (nbuf > objlenRemain))) {
652 break;
653 }
654
656 if (!nout) break;
657 noutot += nout;
658 nintot += nin;
659 if (noutot >= fObjlen) break;
662 nbytesRemain -= nin;
664 }
665
666 // Make sure the uncompressed numbers are consistent with header.
667 if (R__unlikely(noutot != fObjlen)) {
668 Error("ReadBasketBuffers", "fNbytes = %d, fKeylen = %d, fObjlen = %d, noutot = %d, nout=%d, nin=%d, nbuf=%d", fNbytes,fKeylen,fObjlen, noutot,nout,nin,nbuf);
670 return 1;
671 }
674 if (fBranch->GetTree()->GetPerfStats() != nullptr) gPerfStats = fBranch->GetTree()->GetPerfStats();
675 if (R__unlikely(gPerfStats)) {
676 gPerfStats->UnzipEvent(fBranch->GetTree(),pos,start,nintot,fObjlen);
677 }
678 gPerfStats = temp;
679 } else {
680 // Nothing is compressed - copy over wholesale.
682 }
683
685
687
688 // Read offsets table if needed.
689 // If there's no EntryOffsetLen in the branch -- or the fEntryOffset is marked to be calculated-on-demand --
690 // then we skip reading out.
691 if (!fBranch->GetEntryOffsetLen() || (fEntryOffset == reinterpret_cast<Int_t *>(-1))) {
692 return 0;
693 }
694 // At this point, we're required to read out an offset array.
695 ResetEntryOffset(); // TODO: every basket, we reset the offset array. Is this necessary?
696 // Could we instead switch to std::vector?
700 fEntryOffset = new Int_t[fNevBuf+1];
702 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);
703 return 0;
704 }
706 // In this case, we cannot regenerate the offset array at runtime -- but we wrote out an array of
707 // sizes instead of offsets (as sizes compress much better).
709 for (Int_t idx = 1; idx < fNevBuf + 1; idx++) {
710 fEntryOffset[idx] += fEntryOffset[idx - 1];
711 }
712 }
713 fReadEntryOffset = true;
714 // Read the array of displacement if any.
715 delete [] fDisplacement;
716 fDisplacement = nullptr;
717 if (fBufferRef->Length() != len) {
718 // There is more data in the buffer! It is the displacement
719 // array. If len is less than TBuffer::kMinimalSize the actual
720 // size of the buffer is too large, so we can not use the
721 // fBufferRef->BufferSize()
723 }
724
725 return 0;
726}
727
728////////////////////////////////////////////////////////////////////////////////
729/// Read basket buffers in memory and cleanup
730///
731/// Read first bytes of a logical record starting at position pos
732/// return record length (first 4 bytes of record).
733
735{
736 const Int_t len = 128;
737 char buffer[len];
739 file->GetRecordHeader(buffer, pos,len, fNbytes, fObjlen, keylen);
740 fKeylen = keylen;
741 return fNbytes;
742}
743
744////////////////////////////////////////////////////////////////////////////////
745/// Disown all references to the internal buffer - some other object likely now
746/// owns it.
747///
748/// This TBasket is now useless and invalid until it is told to adopt a buffer.
750{
751 fBufferRef = nullptr;
752}
753
754
755////////////////////////////////////////////////////////////////////////////////
756/// Adopt a buffer from an external entity
762
763////////////////////////////////////////////////////////////////////////////////
764/// Reset the read basket TBuffer memory allocation if needed.
765///
766/// This allows to reduce the number of memory allocation while avoiding to
767/// always use the maximum size.
768
770{
771 // By default, we don't reallocate.
772 fResetAllocation = false;
773#ifdef R__TRACK_BASKET_ALLOC_TIME
775#endif
776
777 // Downsize the buffer if needed.
778
779 const auto maxbaskets = fBranch->GetMaxBaskets();
781 return;
782
784
786 const auto basketbytes = fBranch->GetBasketBytes();
787
788 Int_t max_size = basketbytes[basketnumber];
789 for(Int_t b = basketnumber + 1; (b < maxbaskets) && (b < (basketnumber+10)); ++b) {
790 max_size = std::max(max_size, basketbytes[b]);
791 }
792
793 Float_t cx = 1;
794 if (fBranch->GetZipBytes())
796
797 Int_t target_size = static_cast<Int_t>(cx * target_mem_ratio * Float_t(max_size));
798
799 if (target_size && (curSize > target_size)) {
800 /// Only reduce the size if significant enough?
801 Int_t newSize = max_size + 512 - max_size % 512; // Wiggle room and alignment, as above.
802 // We only bother with a resize if it saves 8KB (two normal memory pages).
803 if ((newSize <= curSize - 8 * 1024) &&
804 (static_cast<Float_t>(curSize) / static_cast<Float_t>(newSize) > target_mem_ratio))
805 {
806 if (gDebug > 0) {
807 Info("ReadResetBuffer",
808 "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 ",
820 cx, target_mem_ratio, max_size);
821 }
822 fResetAllocation = true;
823#ifdef R__TRACK_BASKET_ALLOC_TIME
824 std::chrono::time_point<std::chrono::system_clock> start, end;
825 start = std::chrono::high_resolution_clock::now();
826#endif
827 fBufferRef->Expand(newSize, false); // Expand without copying the existing data.
828#ifdef R__TRACK_BASKET_ALLOC_TIME
829 end = std::chrono::high_resolution_clock::now();
830 auto us = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
831 fResetAllocationTime = us.count();
832#endif
833 }
834 }
835}
836
837////////////////////////////////////////////////////////////////////////////////
838/// Reset the write basket to the starting state. i.e. as it was after calling
839/// the constructor (and potentially attaching a TBuffer.)
840/// Reduce memory used by fEntryOffset and the TBuffer if needed ..
841
843{
844 // By default, we don't reallocate.
845 fResetAllocation = false;
846#ifdef R__TRACK_BASKET_ALLOC_TIME
848#endif
849
850 // Name, Title, fClassName, fBranch
851 // stay the same.
852
853 // Downsize the buffer if needed.
854 // See if our current buffer size is significantly larger (>2x) than the historical average.
855 // If so, try decreasing it at this flush boundary to closer to the size from OptimizeBaskets
856 // (or this historical average).
858 // fBufferLen at this point is already reset, so use indirect measurements
860 Longptr_t newSize = -1;
861 if (curSize > 2*curLen)
862 {
864 if (curSize > 2*curBsize ) {
865 Longptr_t avgSize = (Longptr_t)(fBranch->GetTotBytes() / (1+fBranch->GetWriteBasket())); // Average number of bytes per basket so far
866 if (curSize > 2*avgSize) {
868 if (curLen > newSize) {
869 newSize = curLen;
870 }
871 if (avgSize > newSize) {
873 }
874 newSize = newSize + 512 - newSize%512; // Wiggle room and alignment (512 is same as in OptimizeBaskets)
875 }
876 }
877 }
878 // If fBufferRef grew since we last saw it, shrink it to "target memory ratio" of the occupied size
879 // This discourages us from having poorly-occupied buffers on branches with little variability.
880 //
881 // Does not help protect against a burst in event sizes, but does help in the cases where the basket
882 // size jumps from 4MB to 8MB while filling the basket, but we only end up utilizing 4.1MB.
883 //
884 // The above code block is meant to protect against extremely large events.
885
888 Int_t target_size = static_cast<Int_t>(target_mem_ratio * Float_t(max_size));
889 if (max_size && (curSize > target_size) && (newSize == -1)) {
891 newSize = newSize + 512 - newSize % 512; // Wiggle room and alignment, as above.
892 // We only bother with a resize if it saves 8KB (two normal memory pages).
893 if ((newSize > curSize - 8 * 1024) ||
894 (static_cast<Float_t>(curSize) / static_cast<Float_t>(newSize) < target_mem_ratio)) {
895 newSize = -1;
896 } else if (gDebug > 0) {
897 Info("Reset", "Resizing to %ld bytes (was %d); last three sizes were [%d, %d, %d].", newSize, curSize,
899 }
900 }
901
902 if (newSize != -1) {
903 fResetAllocation = true;
904#ifdef R__TRACK_BASKET_ALLOC_TIME
905 std::chrono::time_point<std::chrono::system_clock> start, end;
906 start = std::chrono::high_resolution_clock::now();
907#endif
908 fBufferRef->Expand(newSize,false); // Expand without copying the existing data.
909#ifdef R__TRACK_BASKET_ALLOC_TIME
910 end = std::chrono::high_resolution_clock::now();
911 auto us = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
912 fResetAllocationTime = us.count();
913#endif
914 }
915
916 // Record the actual occupied size of the buffer.
919
920 TKey::Reset();
921
923 if (newNevBufSize==0) {
925 } else if ((newNevBufSize != fNevBufSize) || (fEntryOffset <= reinterpret_cast<Int_t *>(-1))) {
928 }
930
931 fNevBuf = 0;
933 fEntryOffset = nullptr;
935 fDisplacement= nullptr;
936 fBuffer = nullptr;
937
938 fBufferRef->Reset();
940
941 fHeaderOnly = true;
942 fLast = 0; //Must initialize before calling Streamer()
943
945
948 fLast = fKeylen;
949 fBuffer = nullptr;
950 fHeaderOnly = false;
953 if (fNevBufSize) {
954 for (Int_t i=0;i<fNevBufSize;i++) fEntryOffset[i] = 0;
955 }
956}
957
958////////////////////////////////////////////////////////////////////////////////
959/// Set read mode of basket.
960
966
967////////////////////////////////////////////////////////////////////////////////
968/// Set write mode of basket.
969
975
976////////////////////////////////////////////////////////////////////////////////
977/// Stream a class object.
978
980{
981 // As in TBranch::GetBasket, this is used as a half-hearted measure to suppress
982 // the error reporting when many failures occur.
983 static std::atomic<Int_t> nerrors(0);
984
985 char flag;
986 if (b.IsReading()) {
987 TKey::Streamer(b); //this must be first
988 Version_t v = b.ReadVersion();
989 b >> fBufferSize;
990 // NOTE: we now use the upper-bit of the fNevBufSize to see if we have serialized any of the
991 // optional IOBits. If that bit is set, we immediately read out the IOBits; to replace this
992 // (minimal) safeguard against corruption, we will set aside the upper-bit of fIOBits to do
993 // the same thing (the fact this bit is reserved is tested in the unit tests). If there is
994 // someday a need for more than 7 IOBits, we'll widen the field using the same trick.
995 //
996 // We like to keep this safeguard because we immediately will allocate a buffer based on
997 // the value of fNevBufSize -- and would like to avoid wildly inappropriate allocations.
998 b >> fNevBufSize;
999 if (fNevBufSize < 0) {
1001 b >> fIOBits;
1002 if (!fIOBits || (fIOBits & (1 << 7))) {
1003 Error("TBasket::Streamer",
1004 "The value of fNevBufSize (%d) or fIOBits (%d) is incorrect ; setting the buffer to a zombie.",
1006 MakeZombie();
1007 fNevBufSize = 0;
1008 } else if (fIOBits && (fIOBits & ~static_cast<Int_t>(EIOBits::kSupported))) {
1009 nerrors++;
1010 if (nerrors < 10) {
1011 Error("Streamer", "The value of fIOBits (%s) contains unknown flags (supported flags "
1012 "are %s), indicating this was written with a newer version of ROOT "
1013 "utilizing critical IO features this version of ROOT does not support."
1014 " Refusing to deserialize.",
1015 std::bitset<32>(static_cast<Int_t>(fIOBits)).to_string().c_str(),
1016 std::bitset<32>(static_cast<Int_t>(EIOBits::kSupported)).to_string().c_str());
1017 } else if (nerrors == 10) {
1018 Error("Streamer", "Maximum number of errors has been reported; disabling further messages"
1019 "from this location until the process exits.");
1020 }
1021 fNevBufSize = 0;
1022 MakeZombie();
1023 }
1024 }
1025 b >> fNevBuf;
1026 b >> fLast;
1027 b >> flag;
1029 bool mustGenerateOffsets = false;
1030 if (flag >= 80) {
1031 mustGenerateOffsets = true;
1032 flag -= 80;
1033 }
1034 if (!mustGenerateOffsets && flag && (flag % 10 != 2)) {
1037 if (fNevBuf) b.ReadArray(fEntryOffset);
1038 if (20<flag && flag<40) {
1039 for(int i=0; i<fNevBuf; i++){
1041 }
1042 }
1043 if (flag>40) {
1045 b.ReadArray(fDisplacement);
1046 }
1047 } else if (mustGenerateOffsets) {
1048 // We currently believe that in all cases when offsets can be generated, then the
1049 // displacement array must be zero.
1050 assert(flag <= 40);
1051 fEntryOffset = reinterpret_cast<Int_t *>(-1);
1052 }
1053 if (flag == 1 || flag > 10) {
1055 fBufferRef->SetParent(b.GetParent());
1056 char *buf = fBufferRef->Buffer();
1057 if (v > 1) b.ReadFastArray(buf,fLast);
1058 else b.ReadArray(buf);
1060 // This is now done in the TBranch streamer since fBranch might not
1061 // yet be set correctly.
1062 // fBranch->GetTree()->IncrementTotalBuffers(fBufferSize);
1063 }
1064 } else {
1065
1066 TKey::Streamer(b); //this must be first
1067 b.WriteVersion(TBasket::IsA());
1068 if (fBufferRef) {
1070 if (!fHeaderOnly && !fSeekKey && curLast > fLast) fLast = curLast;
1071 }
1073
1074 b << fBufferSize;
1075 if (fIOBits) {
1076 b << -fNevBufSize;
1077 b << fIOBits;
1078 } else {
1079 b << fNevBufSize;
1080 }
1081 b << fNevBuf;
1082 b << fLast;
1086 // We currently believe that in all cases when offsets can be generated, then the
1087 // displacement array must be zero.
1089 if (fHeaderOnly) {
1090 flag = mustGenerateOffsets ? 80 : 0;
1091 b << flag;
1092 } else {
1093 // On return from this function, we are guaranteed that fEntryOffset
1094 // is either a valid pointer or nullptr.
1095 if (fNevBuf) {
1097 }
1098 flag = 1;
1099 if (!fNevBuf || !fEntryOffset)
1100 flag = 2;
1101 if (fBufferRef) flag += 10;
1102 if (fDisplacement) flag += 40;
1103 // Test if we can skip writing out the offset map.
1104 if (mustGenerateOffsets) {
1105 flag += 80;
1106 }
1107 b << flag;
1108
1110 b.WriteArray(fEntryOffset, fNevBuf);
1111 if (fDisplacement) b.WriteArray(fDisplacement, fNevBuf);
1112 }
1113 if (fBufferRef) {
1114 char *buf = fBufferRef->Buffer();
1115 b.WriteFastArray(buf, fLast);
1116 }
1117 }
1118 }
1119}
1120
1121////////////////////////////////////////////////////////////////////////////////
1122/// Update basket header and EntryOffset table.
1123
1125{
1127 if (entryOffset) {
1128 if (fNevBuf+1 >= fNevBufSize) {
1131 fNevBufSize);
1132 if (fDisplacement) {
1134 fNevBufSize);
1136 }
1139
1140 //Update branch only for the first 10 baskets
1141 if (fBranch->GetWriteBasket() < 10) {
1143 }
1144 }
1146
1147 if (skipped!=offset && !fDisplacement){
1149 for (Int_t i = 0; i<fNevBufSize; i++) fDisplacement[i] = fEntryOffset[i];
1150 }
1151 if (fDisplacement) {
1154 }
1155 }
1156
1157 fNevBuf++;
1158}
1159
1160////////////////////////////////////////////////////////////////////////////////
1161/// Write buffer of this basket on the current file.
1162///
1163/// The function returns the number of bytes committed to the memory.
1164/// If a write error occurs, the number of bytes returned is -1.
1165/// If no data are written, the number of bytes returned is 0.
1166
1168{
1169 constexpr Int_t kWrite = 1;
1170
1171 TFile *file = fBranch->GetFile(kWrite);
1172 if (!file) return 0;
1173 if (!file->IsWritable()) {
1174 return -1;
1175 }
1176 fMotherDir = file; // fBranch->GetDirectory();
1177
1178 // This mutex prevents multiple TBasket::WriteBuffer invocations from interacting
1179 // with the underlying TFile at once - TFile is assumed to *not* be thread-safe.
1180 //
1181 // The only parallelism we'd like to exploit (right now!) is the compression
1182 // step - everything else should be serialized at the TFile level.
1183#ifdef R__USE_IMT
1184 std::unique_lock<std::mutex> sentry(file->fWriteMutex);
1185#endif // R__USE_IMT
1186
1188 // Read the basket information that was saved inside the buffer.
1189 bool writing = fBufferRef->IsWriting();
1192
1196
1198
1199 Create(nout,file);
1201 fHeaderOnly = true;
1202
1203 Streamer(*fBufferRef); //write key itself again
1205 fHeaderOnly = false;
1206 return nBytes>0 ? fKeylen+nout : -1;
1207 }
1208
1209 // Transfer fEntryOffset table at the end of fBuffer.
1210 fLast = fBufferRef->Length();
1212 if (entryOffset) {
1214 if (!CanGenerateOffsetArray()) {
1215 // If we have set the offset map flag, but cannot dynamically generate the map, then
1216 // we should at least convert the offset array to a size array. Note that we always
1217 // write out (fNevBuf+1) entries to match the original case.
1218 if (hasOffsetBit) {
1219 for (Int_t idx = fNevBuf; idx > 0; idx--) {
1220 entryOffset[idx] -= entryOffset[idx - 1];
1221 }
1222 entryOffset[0] = 0;
1223 }
1225 // Convert back to offset format: keeping both sizes and offsets in-memory were considered,
1226 // but it seems better to use CPU than memory.
1227 if (hasOffsetBit) {
1228 entryOffset[0] = fKeylen;
1229 for (Int_t idx = 1; idx < fNevBuf + 1; idx++) {
1230 entryOffset[idx] += entryOffset[idx - 1];
1231 }
1232 }
1233 } else if (!hasOffsetBit) { // In this case, write out as normal
1235 }
1236 if (fDisplacement) {
1238 delete[] fDisplacement;
1239 fDisplacement = nullptr;
1240 }
1241 }
1242
1243 Int_t nout, noutot, bufmax, nzip;
1244
1246
1247 fHeaderOnly = true;
1251 cxlevel = file->GetCompressionLevel();
1255 if (cxlevel > 0) {
1256 Int_t nbuffers = 1 + (fObjlen - 1) / kMAXZIPBUF;
1257 Int_t buflen = fKeylen + fObjlen + 9 * nbuffers + 28; //add 28 bytes in case object is placed in a deleted gap
1258 InitializeCompressedBuffer(buflen, file);
1259 if (!fCompressedBufferRef) {
1260 Warning("WriteBuffer", "Unable to allocate the compressed buffer");
1261 return -1;
1262 }
1265 char *objbuf = fBufferRef->Buffer() + fKeylen;
1266 char *bufcur = &fBuffer[fKeylen];
1267 noutot = 0;
1268 nzip = 0;
1269 for (Int_t i = 0; i < nbuffers; ++i) {
1270 if (i == nbuffers - 1) bufmax = fObjlen - nzip;
1271 else bufmax = kMAXZIPBUF;
1272 // Compress the buffer. Note that we allow multiple TBasket compressions to occur at once
1273 // for a given TFile: that's because the compression buffer when we use IMT is no longer
1274 // shared amongst several threads.
1275#ifdef R__USE_IMT
1276 sentry.unlock();
1277#endif // R__USE_IMT
1278 // NOTE this is declared with C linkage, so it shouldn't except. Also, when
1279 // USE_IMT is defined, we are guaranteed that the compression buffer is unique per-branch.
1280 // (see fCompressedBufferRef in constructor).
1282#ifdef R__USE_IMT
1283 sentry.lock();
1284#endif // R__USE_IMT
1285
1286 // test if buffer has really been compressed. In case of small buffers
1287 // when the buffer contains random data, it may happen that the compressed
1288 // buffer is larger than the input. In this case, we write the original uncompressed buffer
1289 if (nout == 0 || nout >= fObjlen) {
1290 nout = fObjlen;
1291 // We used to delete fBuffer here, we no longer want to since
1292 // the buffer (held by fCompressedBufferRef) might be re-used later.
1294 Create(fObjlen,file);
1296
1297 Streamer(*fBufferRef); //write key itself again
1298 if ((nout+fKeylen)>buflen) {
1299 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",
1300 (nout+fKeylen-buflen),buflen,fNbytes,fObjlen,fKeylen);
1301 }
1302 goto WriteFile;
1303 }
1304 bufcur += nout;
1305 noutot += nout;
1306 objbuf += kMAXZIPBUF;
1307 nzip += kMAXZIPBUF;
1308 }
1309 nout = noutot;
1310 Create(noutot,file);
1312
1313 Streamer(*fBufferRef); //write key itself again
1315 } else {
1317 Create(fObjlen,file);
1319
1320 Streamer(*fBufferRef); //write key itself again
1321 nout = fObjlen;
1322 }
1323
1324WriteFile:
1326 fHeaderOnly = false;
1327 return nBytes>0 ? fKeylen+nout : -1;
1328}
#define R__likely(expr)
Definition RConfig.hxx:587
#define R__unlikely(expr)
Definition RConfig.hxx:586
#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
constexpr auto gMaxInt_t
Definition TBasket.cxx:35
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:411
#define OLD_CASE_EXPRESSION
Definition TBasket.cxx:354
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:148
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:777
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:231
void AdoptBuffer(TBuffer *user_buffer)
Adopt a buffer from an external entity.
Definition TBasket.cxx:757
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:147
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:433
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:381
void DisownBuffer()
Disown all references to the internal buffer - some other object likely now owns it.
Definition TBasket.cxx:749
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:465
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:174
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:311
bool fOwnsCompressedBuffer
! Whether or not we own the compressed buffer.
Definition TBasket.h:68
void ResetEntryOffset()
Definition TBasket.cxx:442
TBasket()
Default constructor.
Definition TBasket.cxx:48
virtual void AdjustSize(Int_t newsize)
Increase the size of the current fBuffer up to newsize.
Definition TBasket.cxx:128
virtual void SetReadMode()
Set read mode of basket.
Definition TBasket.cxx:961
virtual void SetWriteMode()
Set write mode of basket.
Definition TBasket.cxx:970
Int_t ReadBasketBuffersUncompressedCase()
By-passing buffer unzipping has been requested and is possible (only 1 entry in this basket).
Definition TBasket.cxx:359
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:734
virtual void ReadResetBuffer(Int_t basketnumber)
Reset the read basket TBuffer memory allocation if needed.
Definition TBasket.cxx:769
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:1167
void Streamer(TBuffer &) override
Stream a class object.
Definition TBasket.cxx:979
Int_t LoadBasketBuffers(Long64_t pos, Int_t len, TFile *file, TTree *tree=nullptr)
Load basket buffers in memory without unziping.
Definition TBasket.cxx:246
~TBasket() override
Basket destructor.
Definition TBasket.cxx:105
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:196
TClass * IsA() const override
Definition TBasket.h:156
virtual void DeleteEntryOffset()
Delete fEntryOffset array.
Definition TBasket.cxx:165
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:219
virtual void WriteReset()
Reset the write basket to the starting state.
Definition TBasket.cxx:842
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:315
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 file, usually with extension .root, that stores data and code in the form of serialized objects in ...
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:2326
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:2305
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:1313
virtual Bool_t ReadBuffer(char *buf, Int_t len)
Read a buffer from the file.
Definition TFile.cxx:1823
TFileCacheRead * GetCacheRead(const TObject *tree=nullptr) const
Return a pointer to the current read cache.
Definition TFile.cxx:1274
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:1520
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 whole key on file (key header and data)
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:1331
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:505
virtual Int_t WriteFile(Int_t cycle=1, TFile *f=nullptr)
Write the encoded object supported by this key.
Definition TKey.cxx:1488
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:1387
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:1084
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:888
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1098
void MakeZombie()
Definition TObject.h:55
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition TObject.cxx:1072
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