32 const UInt_t kDisplacementMask = 0xFF000000;
55 TBasket::TBasket(TDirectory *motherDir) : TKey(motherDir)
62 TBasket::TBasket(
const char *name,
const char *title, TBranch *branch)
63 : TKey(branch->GetDirectory()), fBufferSize(branch->GetBasketSize()), fNevBufSize(branch->GetEntryOffsetLen()),
64 fHeaderOnly(kTRUE), fIOBits(branch->GetIOFeatures().GetFeatures())
68 fClassName =
"TBasket";
70 fBufferRef =
new TBufferFile(TBuffer::kWrite, fBufferSize);
72 if (branch->GetDirectory()) {
73 TFile *file = branch->GetFile();
74 fBufferRef->SetParent(file);
76 if (branch->GetTree()) {
78 fCompressedBufferRef = branch->GetTransientBuffer(fBufferSize);
80 fCompressedBufferRef = branch->GetTree()->GetTransientBuffer(fBufferSize);
82 fOwnsCompressedBuffer = kFALSE;
83 if (!fCompressedBufferRef) {
84 fCompressedBufferRef =
new TBufferFile(TBuffer::kRead, fBufferSize);
85 fOwnsCompressedBuffer = kTRUE;
89 Streamer(*fBufferRef);
90 fKeylen = fBufferRef->Length();
91 fObjlen = fBufferSize - fKeylen;
96 fEntryOffset =
new Int_t[fNevBufSize];
97 for (Int_t i=0;i<fNevBufSize;i++) fEntryOffset[i] = 0;
99 branch->GetTree()->IncrementTotalBuffers(fBufferSize);
107 if (fDisplacement)
delete [] fDisplacement;
109 if (fBufferRef)
delete fBufferRef;
114 if (fCompressedBufferRef && fOwnsCompressedBuffer) {
115 delete fCompressedBufferRef;
116 fCompressedBufferRef = 0;
123 void TBasket::AdjustSize(Int_t newsize)
125 if (fBuffer == fBufferRef->Buffer()) {
126 fBufferRef->Expand(newsize);
127 fBuffer = fBufferRef->Buffer();
129 fBufferRef->Expand(newsize);
131 fBranch->GetTree()->IncrementTotalBuffers(newsize-fBufferSize);
132 fBufferSize = newsize;
133 fLastWriteBufferSize[0] = newsize;
134 fLastWriteBufferSize[1] = 0;
135 fLastWriteBufferSize[2] = 0;
136 fNextBufferSizeRecord = 1;
142 Long64_t TBasket::CopyTo(TFile *to)
144 fBufferRef->SetWriteMode();
145 Int_t nout = fNbytes - fKeylen;
146 fBuffer = fBufferRef->Buffer();
148 fBufferRef->SetBufferOffset(0);
150 Streamer(*fBufferRef);
151 fHeaderOnly = kFALSE;
152 Int_t nBytes = WriteFileKeepBuffer(to);
154 return nBytes>0 ? nBytes : -1;
160 void TBasket::DeleteEntryOffset()
169 Int_t TBasket::DropBuffers()
171 if (!fBuffer && !fBufferRef)
return 0;
173 if (fDisplacement)
delete [] fDisplacement;
175 if (fBufferRef)
delete fBufferRef;
176 if (fCompressedBufferRef && fOwnsCompressedBuffer)
delete fCompressedBufferRef;
178 fCompressedBufferRef = 0;
182 fBranch->GetTree()->IncrementTotalBuffers(-fBufferSize);
191 Int_t *TBasket::GetCalculatedEntryOffset()
193 if (fEntryOffset != reinterpret_cast<Int_t *>(-1)) {
197 if (R__unlikely(!fBranch)) {
198 Error(
"GetCalculatedEntryOffset",
"Basket entry offset calculation requested, but no associated TBranch!");
201 if (R__unlikely(fBranch->GetNleaves() != 1)) {
202 Error(
"GetCalculatedEntryOffset",
"Branch contains multiple leaves - unable to calculated entry offsets!");
205 TLeaf *leaf =
static_cast<TLeaf *
>((*fBranch->GetListOfLeaves())[0]);
206 fEntryOffset = leaf->GenerateOffsetArray(fKeylen, fNevBuf);
214 Bool_t TBasket::CanGenerateOffsetArray()
216 if (fBranch->GetNleaves() != 1) {
219 TLeaf *leaf =
static_cast<TLeaf *
>((*fBranch->GetListOfLeaves())[0]);
220 return leaf->CanGenerateOffsetArray();
226 Int_t TBasket::GetEntryPointer(Int_t entry)
229 Int_t *entryOffset = GetEntryOffset();
230 if (entryOffset) offset = entryOffset[entry];
231 else offset = fKeylen + entry*fNevBufSize;
232 fBufferRef->SetBufferOffset(offset);
241 Int_t TBasket::LoadBasketBuffers(Long64_t pos, Int_t len, TFile *file, TTree *tree)
249 fBufferRef->SetWriteMode();
250 if (fBufferRef->BufferSize() < len) {
251 fBufferRef->Expand(len);
253 fBufferRef->SetReadMode();
255 fBufferRef =
new TBufferFile(TBuffer::kRead, len);
257 fBufferRef->SetParent(file);
258 char *buffer = fBufferRef->Buffer();
260 TFileCacheRead *pf = tree->GetReadCache(file);
262 TVirtualPerfStats* temp = gPerfStats;
263 if (tree->GetPerfStats()) gPerfStats = tree->GetPerfStats();
264 Int_t st = pf->ReadBuffer(buffer,pos,len);
267 }
else if (st == 0) {
272 TTreeCache *fc =
dynamic_cast<TTreeCache*
>(file->GetCacheRead());
273 if (fc) fc->Disable();
274 Int_t ret = file->ReadBuffer(buffer,len);
275 if (fc) fc->Enable();
276 pf->AddNoCacheBytesRead(len);
277 pf->AddNoCacheReadCalls(1);
284 file->SetOffset(pos + len);
286 TVirtualPerfStats* temp = gPerfStats;
287 if (tree->GetPerfStats() != 0) gPerfStats = tree->GetPerfStats();
288 if (file->ReadBuffer(buffer,len)) {
292 else gPerfStats = temp;
295 fBufferRef->SetReadMode();
296 fBufferRef->SetBufferOffset(0);
297 Streamer(*fBufferRef);
306 void TBasket::MoveEntries(Int_t dentries)
310 if (dentries >= fNevBuf)
return;
314 Int_t *entryOffset = GetEntryOffset();
316 bufbegin = entryOffset[dentries];
317 moved = bufbegin-GetKeylen();
322 if (!fDisplacement) {
323 fDisplacement =
new Int_t[fNevBufSize];
325 for (i = 0; i<(fNevBufSize-dentries); ++i) {
326 fDisplacement[i] = entryOffset[i + dentries];
327 entryOffset[i] = entryOffset[i + dentries] - moved;
329 for (i = fNevBufSize-dentries; i<fNevBufSize; ++i) {
330 fDisplacement[i] = 0;
339 bufbegin = GetKeylen() + dentries*fNevBufSize;
340 moved = bufbegin-GetKeylen();
342 TBuffer *buf = GetBufferRef();
343 char *buffer = buf->Buffer();
344 memmove(buffer+GetKeylen(),buffer+bufbegin,buf->Length()-bufbegin);
345 buf->SetBufferOffset(buf->Length()-moved);
349 #define OLD_CASE_EXPRESSION fObjlen==fNbytes-fKeylen && GetBranch()->GetCompressionLevel()!=0 && file->GetVersion()<=30401
354 Int_t TBasket::ReadBasketBuffersUncompressedCase()
356 fBuffer = fBufferRef->Buffer();
359 fBufferRef->SetBufferOffset(fNbytes);
362 fBufferRef->SetBit(TBufferFile::kNotDecompressed);
367 delete [] fDisplacement; fDisplacement = 0;
369 fBranch->GetTree()->IncrementTotalBuffers(fBufferSize);
376 Int_t TBasket::ReadBasketBuffersUnzip(
char* buffer, Int_t size, Bool_t mustFree, TFile* file)
379 fBufferRef->SetBuffer(buffer, size, mustFree);
380 fBufferRef->SetReadMode();
383 fBufferRef =
new TBufferFile(TBuffer::kRead, size, buffer, mustFree);
385 fBufferRef->SetParent(file);
387 Streamer(*fBufferRef);
393 Bool_t oldCase = OLD_CASE_EXPRESSION;
395 if ((fObjlen > fNbytes-fKeylen || oldCase) && TestBit(TBufferFile::kNotDecompressed) && (fNevBuf==1)) {
396 return TBasket::ReadBasketBuffersUncompressedCase();
399 fBuffer = fBufferRef->Buffer();
400 return fObjlen+fKeylen;
406 static inline TBuffer* R__InitializeReadBasketBuffer(TBuffer* bufferRef, Int_t len, TFile* file)
409 if (R__likely(bufferRef)) {
410 bufferRef->SetReadMode();
411 Int_t curBufferSize = bufferRef->BufferSize();
412 if (curBufferSize < len) {
414 bufferRef->Expand(Int_t(len*1.05));
419 result =
new TBufferFile(TBuffer::kRead, len);
421 result->SetParent(file);
428 void inline TBasket::InitializeCompressedBuffer(Int_t len, TFile* file)
430 Bool_t compressedBufferExists = fCompressedBufferRef != NULL;
431 fCompressedBufferRef = R__InitializeReadBasketBuffer(fCompressedBufferRef, len, file);
432 if (R__unlikely(!compressedBufferExists)) {
433 fOwnsCompressedBuffer = kTRUE;
437 void TBasket::ResetEntryOffset()
439 if (fEntryOffset != reinterpret_cast<Int_t *>(-1)) {
440 delete[] fEntryOffset;
442 fEntryOffset =
nullptr;
460 Int_t TBasket::ReadBasketBuffers(Long64_t pos, Int_t len, TFile *file)
462 if(!fBranch->GetDirectory()) {
467 char *rawUncompressedBuffer, *rawCompressedBuffer;
468 Int_t uncompressedBufferLen;
471 TFileCacheRead *pf =
nullptr;
473 R__LOCKGUARD_IMT(gROOTMutex);
474 pf = fBranch->GetTree()->GetReadCache(file);
479 char *buffer =
nullptr;
480 res = pf->GetUnzipBuffer(&buffer, pos, len, &free);
481 if (R__unlikely(res >= 0)) {
482 len = ReadBasketBuffersUnzip(buffer, res, free, file);
485 if (len <= 0)
return -len;
492 TBuffer* readBufferRef;
493 if (R__unlikely(fBranch->GetCompressionLevel()==0)) {
495 fBufferRef = R__InitializeReadBasketBuffer(fBufferRef, len, file);
496 readBufferRef = fBufferRef;
499 fCompressedBufferRef = R__InitializeReadBasketBuffer(fCompressedBufferRef, len, file);
500 readBufferRef = fCompressedBufferRef;
505 fBranch->GetTree()->IncrementTotalBuffers(-fBufferSize);
507 if (!readBufferRef) {
508 Error(
"ReadBasketBuffers",
"Unable to allocate buffer.");
513 TVirtualPerfStats* temp = gPerfStats;
514 if (fBranch->GetTree()->GetPerfStats() != 0) gPerfStats = fBranch->GetTree()->GetPerfStats();
517 R__LOCKGUARD_IMT(gROOTMutex);
518 st = pf->ReadBuffer(readBufferRef->Buffer(),pos,len);
522 }
else if (st == 0) {
526 R__LOCKGUARD_IMT(gROOTMutex);
527 TTreeCache *fc =
dynamic_cast<TTreeCache*
>(file->GetCacheRead());
528 if (fc) fc->Disable();
529 Int_t ret = file->ReadBuffer(readBufferRef->Buffer(),pos,len);
530 if (fc) fc->Enable();
531 pf->AddNoCacheBytesRead(len);
532 pf->AddNoCacheReadCalls(1);
540 TVirtualPerfStats* temp = gPerfStats;
541 if (fBranch->GetTree()->GetPerfStats() != 0) gPerfStats = fBranch->GetTree()->GetPerfStats();
542 R__LOCKGUARD_IMT(gROOTMutex);
543 if (file->ReadBuffer(readBufferRef->Buffer(),pos,len)) {
547 else gPerfStats = temp;
549 Streamer(*readBufferRef);
554 rawCompressedBuffer = readBufferRef->Buffer();
557 if (R__unlikely(readBufferRef == fBufferRef))
559 if (R__likely(fObjlen+fKeylen == fNbytes)) {
565 InitializeCompressedBuffer(len, file);
566 if (!fCompressedBufferRef) {
567 Error(
"ReadBasketBuffers",
"Unable to allocate buffer.");
571 rawCompressedBuffer = fCompressedBufferRef->Buffer();
572 memcpy(rawCompressedBuffer, fBufferRef->Buffer(), len);
580 uncompressedBufferLen = len > fObjlen+fKeylen ? len : fObjlen+fKeylen;
581 fBufferRef = R__InitializeReadBasketBuffer(fBufferRef, uncompressedBufferLen, file);
582 rawUncompressedBuffer = fBufferRef->Buffer();
583 fBuffer = rawUncompressedBuffer;
585 oldCase = OLD_CASE_EXPRESSION;
587 if (fObjlen > fNbytes-fKeylen || oldCase) {
588 if (R__unlikely(TestBit(TBufferFile::kNotDecompressed) && (fNevBuf==1))) {
589 return ReadBasketBuffersUncompressedCase();
594 if (R__unlikely(gPerfStats)) {
595 start = TTimeStamp();
598 memcpy(rawUncompressedBuffer, rawCompressedBuffer, fKeylen);
599 char *rawUncompressedObjectBuffer = rawUncompressedBuffer+fKeylen;
600 UChar_t *rawCompressedObjectBuffer = (UChar_t*)rawCompressedBuffer+fKeylen;
602 Int_t nout = 0, noutot = 0, nintot = 0;
607 if (R__unlikely(R__unzip_header(&nin, rawCompressedObjectBuffer, &nbuf) != 0)) {
608 Error(
"ReadBasketBuffers",
"Inconsistency found in header (nin=%d, nbuf=%d)", nin, nbuf);
611 if (R__unlikely(oldCase && (nin > fObjlen || nbuf > fObjlen))) {
613 memcpy(rawUncompressedBuffer+fKeylen, rawCompressedObjectBuffer+fKeylen, fObjlen);
617 R__unzip(&nin, rawCompressedObjectBuffer, &nbuf, (
unsigned char*) rawUncompressedObjectBuffer, &nout);
621 if (noutot >= fObjlen)
break;
622 rawCompressedObjectBuffer += nin;
623 rawUncompressedObjectBuffer += nout;
627 if (R__unlikely(noutot != fObjlen)) {
628 Error(
"ReadBasketBuffers",
"fNbytes = %d, fKeylen = %d, fObjlen = %d, noutot = %d, nout=%d, nin=%d, nbuf=%d", fNbytes,fKeylen,fObjlen, noutot,nout,nin,nbuf);
629 fBranch->GetTree()->IncrementTotalBuffers(fBufferSize);
632 len = fObjlen+fKeylen;
633 TVirtualPerfStats* temp = gPerfStats;
634 if (fBranch->GetTree()->GetPerfStats() != 0) gPerfStats = fBranch->GetTree()->GetPerfStats();
635 if (R__unlikely(gPerfStats)) {
636 gPerfStats->UnzipEvent(fBranch->GetTree(),pos,start,nintot,fObjlen);
641 memcpy(rawUncompressedBuffer, rawCompressedBuffer, len);
646 fBranch->GetTree()->IncrementTotalBuffers(fBufferSize);
651 if (!fBranch->GetEntryOffsetLen() || (fEntryOffset ==
reinterpret_cast<Int_t *
>(-1))) {
657 fBufferRef->SetBufferOffset(fLast);
658 fBufferRef->ReadArray(fEntryOffset);
659 if (R__unlikely(!fEntryOffset)) {
660 fEntryOffset =
new Int_t[fNevBuf+1];
661 fEntryOffset[0] = fKeylen;
662 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);
665 if (fIOBits & static_cast<UChar_t>(TBasket::EIOBits::kGenerateOffsetMap)) {
668 fEntryOffset[0] = fKeylen;
669 for (Int_t idx = 1; idx < fNevBuf + 1; idx++) {
670 fEntryOffset[idx] += fEntryOffset[idx - 1];
673 fReadEntryOffset = kTRUE;
675 delete [] fDisplacement;
677 if (fBufferRef->Length() != len) {
682 fBufferRef->ReadArray(fDisplacement);
694 Int_t TBasket::ReadBasketBytes(Long64_t pos, TFile *file)
696 const Int_t len = 128;
699 file->GetRecordHeader(buffer, pos,len, fNbytes, fObjlen, keylen);
709 void TBasket::DisownBuffer()
717 void TBasket::AdoptBuffer(TBuffer *user_buffer)
720 fBufferRef = user_buffer;
729 void TBasket::Reset()
732 fResetAllocation =
false;
733 #ifdef R__TRACK_BASKET_ALLOC_TIME
734 fResetAllocationTime = 0;
744 Int_t curSize = fBufferRef->BufferSize();
746 Int_t curLen = (GetObjlen() + GetKeylen());
748 if (curSize > 2*curLen)
750 Long_t curBsize = fBranch->GetBasketSize();
751 if (curSize > 2*curBsize ) {
752 Long_t avgSize = (Long_t)(fBranch->GetTotBytes() / (1+fBranch->GetWriteBasket()));
753 if (curSize > 2*avgSize) {
755 if (curLen > newSize) {
758 if (avgSize > newSize) {
761 newSize = newSize + 512 - newSize%512;
773 Float_t target_mem_ratio = fBranch->GetTree()->GetTargetMemoryRatio();
774 Int_t max_size = TMath::Max(fLastWriteBufferSize[0], std::max(fLastWriteBufferSize[1], fLastWriteBufferSize[2]));
775 Int_t target_size =
static_cast<Int_t
>(target_mem_ratio * Float_t(max_size));
776 if (max_size && (curSize > target_size) && (newSize == -1)) {
777 newSize = target_size;
778 newSize = newSize + 512 - newSize % 512;
780 if ((newSize > curSize - 8 * 1024) ||
781 (
static_cast<Float_t
>(curSize) / static_cast<Float_t>(newSize) < target_mem_ratio)) {
783 }
else if (gDebug > 0) {
784 Info(
"Reset",
"Resizing to %ld bytes (was %d); last three sizes were [%d, %d, %d].", newSize, curSize,
785 fLastWriteBufferSize[0], fLastWriteBufferSize[1], fLastWriteBufferSize[2]);
790 fResetAllocation =
true;
791 #ifdef R__TRACK_BASKET_ALLOC_TIME
792 std::chrono::time_point<std::chrono::system_clock> start, end;
793 start = std::chrono::high_resolution_clock::now();
795 fBufferRef->Expand(newSize,kFALSE);
796 #ifdef R__TRACK_BASKET_ALLOC_TIME
797 end = std::chrono::high_resolution_clock::now();
798 auto us = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
799 fResetAllocationTime = us.count();
804 fLastWriteBufferSize[fNextBufferSizeRecord] = curLen;
805 fNextBufferSizeRecord = (fNextBufferSizeRecord + 1) % 3;
809 Int_t newNevBufSize = fBranch->GetEntryOffsetLen();
810 if (newNevBufSize==0) {
812 }
else if ((newNevBufSize != fNevBufSize) || (fEntryOffset <= reinterpret_cast<Int_t *>(-1))) {
814 fEntryOffset =
new Int_t[newNevBufSize];
816 fNevBufSize = newNevBufSize;
819 Int_t *storeEntryOffset = fEntryOffset;
821 Int_t *storeDisplacement = fDisplacement;
826 fBufferRef->SetWriteMode();
831 Streamer(*fBufferRef);
833 fKeylen = fBufferRef->Length();
834 fObjlen = fBufferSize - fKeylen;
837 fHeaderOnly = kFALSE;
838 fDisplacement= storeDisplacement;
839 fEntryOffset = storeEntryOffset;
841 for (Int_t i=0;i<fNevBufSize;i++) fEntryOffset[i] = 0;
848 void TBasket::SetReadMode()
850 fLast = fBufferRef->Length();
851 fBufferRef->SetReadMode();
857 void TBasket::SetWriteMode()
859 fBufferRef->SetWriteMode();
860 fBufferRef->SetBufferOffset(fLast);
866 void TBasket::Streamer(TBuffer &b)
870 static std::atomic<Int_t> nerrors(0);
875 Version_t v = b.ReadVersion();
886 if (fNevBufSize < 0) {
887 fNevBufSize = -fNevBufSize;
889 if (!fIOBits || (fIOBits & (1 << 7))) {
890 Error(
"TBasket::Streamer",
891 "The value of fNevBufSize (%d) or fIOBits (%d) is incorrect ; setting the buffer to a zombie.",
892 -fNevBufSize, fIOBits);
895 }
else if (fIOBits && (fIOBits & ~static_cast<Int_t>(EIOBits::kSupported))) {
898 Error(
"Streamer",
"The value of fIOBits (%s) contains unknown flags (supported flags "
899 "are %s), indicating this was written with a newer version of ROOT "
900 "utilizing critical IO features this version of ROOT does not support."
901 " Refusing to deserialize.",
902 std::bitset<32>(static_cast<Int_t>(fIOBits)).to_string().c_str(),
903 std::bitset<32>(static_cast<Int_t>(EIOBits::kSupported)).to_string().c_str());
904 }
else if (nerrors == 10) {
905 Error(
"Streamer",
"Maximum number of errors has been reported; disabling further messages"
906 "from this location until the process exits.");
915 if (fLast > fBufferSize) fBufferSize = fLast;
916 Bool_t mustGenerateOffsets =
false;
918 mustGenerateOffsets =
true;
921 if (!mustGenerateOffsets && flag && (flag % 10 != 2)) {
923 fEntryOffset =
new Int_t[fNevBufSize];
924 if (fNevBuf) b.ReadArray(fEntryOffset);
925 if (20<flag && flag<40) {
926 for(
int i=0; i<fNevBuf; i++){
927 fEntryOffset[i] &= ~kDisplacementMask;
931 fDisplacement =
new Int_t[fNevBufSize];
932 b.ReadArray(fDisplacement);
934 }
else if (mustGenerateOffsets) {
938 fEntryOffset =
reinterpret_cast<Int_t *
>(-1);
940 if (flag == 1 || flag > 10) {
941 fBufferRef =
new TBufferFile(TBuffer::kRead,fBufferSize);
942 fBufferRef->SetParent(b.GetParent());
943 char *buf = fBufferRef->Buffer();
944 if (v > 1) b.ReadFastArray(buf,fLast);
945 else b.ReadArray(buf);
946 fBufferRef->SetBufferOffset(fLast);
954 b.WriteVersion(TBasket::IsA());
956 Int_t curLast = fBufferRef->Length();
957 if (!fHeaderOnly && !fSeekKey && curLast > fLast) fLast = curLast;
959 if (fLast > fBufferSize) fBufferSize = fLast;
970 Bool_t mustGenerateOffsets = fEntryOffset && fNevBuf &&
971 (fIOBits &
static_cast<UChar_t
>(TBasket::EIOBits::kGenerateOffsetMap)) &&
972 CanGenerateOffsetArray();
975 assert(!mustGenerateOffsets || fDisplacement ==
nullptr);
977 flag = mustGenerateOffsets ? 80 : 0;
986 if (!fNevBuf || !fEntryOffset)
988 if (fBufferRef) flag += 10;
989 if (fDisplacement) flag += 40;
991 if (mustGenerateOffsets) {
996 if (!mustGenerateOffsets && fEntryOffset && fNevBuf) {
997 b.WriteArray(fEntryOffset, fNevBuf);
998 if (fDisplacement) b.WriteArray(fDisplacement, fNevBuf);
1001 char *buf = fBufferRef->Buffer();
1002 b.WriteFastArray(buf, fLast);
1011 void TBasket::Update(Int_t offset, Int_t skipped)
1013 Int_t *entryOffset = GetEntryOffset();
1015 if (fNevBuf+1 >= fNevBufSize) {
1016 Int_t newsize = TMath::Max(10,2*fNevBufSize);
1017 Int_t *newoff = TStorage::ReAllocInt(fEntryOffset, newsize,
1019 if (fDisplacement) {
1020 Int_t *newdisp = TStorage::ReAllocInt(fDisplacement, newsize,
1022 fDisplacement = newdisp;
1024 fEntryOffset = newoff;
1025 fNevBufSize = newsize;
1028 if (fBranch->GetWriteBasket() < 10) {
1029 fBranch->SetEntryOffsetLen(newsize);
1032 fEntryOffset[fNevBuf] = offset;
1034 if (skipped!=offset && !fDisplacement){
1035 fDisplacement =
new Int_t[fNevBufSize];
1036 for (Int_t i = 0; i<fNevBufSize; i++) fDisplacement[i] = fEntryOffset[i];
1038 if (fDisplacement) {
1039 fDisplacement[fNevBuf] = skipped;
1040 fBufferRef->SetBufferDisplacement(skipped);
1054 Int_t TBasket::WriteBuffer()
1056 const Int_t kWrite = 1;
1058 TFile *file = fBranch->GetFile(kWrite);
1059 if (!file)
return 0;
1060 if (!file->IsWritable()) {
1071 std::unique_lock<std::mutex> sentry(file->fWriteMutex);
1072 #endif // R__USE_IMT
1074 if (R__unlikely(fBufferRef->TestBit(TBufferFile::kNotDecompressed))) {
1076 Bool_t writing = fBufferRef->IsWriting();
1077 fBufferRef->SetReadMode();
1078 fBufferRef->SetBufferOffset(0);
1080 Streamer(*fBufferRef);
1081 if (writing) fBufferRef->SetWriteMode();
1082 Int_t nout = fNbytes - fKeylen;
1084 fBuffer = fBufferRef->Buffer();
1087 fBufferRef->SetBufferOffset(0);
1088 fHeaderOnly = kTRUE;
1090 Streamer(*fBufferRef);
1091 int nBytes = WriteFileKeepBuffer();
1092 fHeaderOnly = kFALSE;
1093 return nBytes>0 ? fKeylen+nout : -1;
1097 fLast = fBufferRef->Length();
1098 Int_t *entryOffset = GetEntryOffset();
1100 Bool_t hasOffsetBit = fIOBits &
static_cast<UChar_t
>(TBasket::EIOBits::kGenerateOffsetMap);
1101 if (!CanGenerateOffsetArray()) {
1106 for (Int_t idx = fNevBuf; idx > 0; idx--) {
1107 entryOffset[idx] -= entryOffset[idx - 1];
1111 fBufferRef->WriteArray(entryOffset, fNevBuf + 1);
1115 entryOffset[0] = fKeylen;
1116 for (Int_t idx = 1; idx < fNevBuf + 1; idx++) {
1117 entryOffset[idx] += entryOffset[idx - 1];
1120 }
else if (!hasOffsetBit) {
1121 fBufferRef->WriteArray(entryOffset, fNevBuf + 1);
1123 if (fDisplacement) {
1124 fBufferRef->WriteArray(fDisplacement, fNevBuf + 1);
1125 delete[] fDisplacement;
1130 Int_t lbuf, nout, noutot, bufmax, nzip;
1131 lbuf = fBufferRef->Length();
1132 fObjlen = lbuf - fKeylen;
1134 fHeaderOnly = kTRUE;
1135 fCycle = fBranch->GetWriteBasket();
1136 Int_t cxlevel = fBranch->GetCompressionLevel();
1137 ROOT::RCompressionSetting::EAlgorithm::EValues cxAlgorithm =
static_cast<ROOT::RCompressionSetting::EAlgorithm::EValues
>(fBranch->GetCompressionAlgorithm());
1139 Int_t nbuffers = 1 + (fObjlen - 1) / kMAXZIPBUF;
1140 Int_t buflen = fKeylen + fObjlen + 9 * nbuffers + 28;
1141 InitializeCompressedBuffer(buflen, file);
1142 if (!fCompressedBufferRef) {
1143 Warning(
"WriteBuffer",
"Unable to allocate the compressed buffer");
1146 fCompressedBufferRef->SetWriteMode();
1147 fBuffer = fCompressedBufferRef->Buffer();
1148 char *objbuf = fBufferRef->Buffer() + fKeylen;
1149 char *bufcur = &fBuffer[fKeylen];
1152 for (Int_t i = 0; i < nbuffers; ++i) {
1153 if (i == nbuffers - 1) bufmax = fObjlen - nzip;
1154 else bufmax = kMAXZIPBUF;
1160 #endif // R__USE_IMT
1164 R__zipMultipleAlgorithm(cxlevel, &bufmax, objbuf, &bufmax, bufcur, &nout, cxAlgorithm);
1167 #endif // R__USE_IMT
1172 if (nout == 0 || nout >= fObjlen) {
1176 fBuffer = fBufferRef->Buffer();
1177 Create(fObjlen,file);
1178 fBufferRef->SetBufferOffset(0);
1180 Streamer(*fBufferRef);
1181 if ((nout+fKeylen)>buflen) {
1182 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",
1183 (nout+fKeylen-buflen),buflen,fNbytes,fObjlen,fKeylen);
1189 objbuf += kMAXZIPBUF;
1193 Create(noutot,file);
1194 fBufferRef->SetBufferOffset(0);
1196 Streamer(*fBufferRef);
1197 memcpy(fBuffer,fBufferRef->Buffer(),fKeylen);
1199 fBuffer = fBufferRef->Buffer();
1200 Create(fObjlen,file);
1201 fBufferRef->SetBufferOffset(0);
1203 Streamer(*fBufferRef);
1208 Int_t nBytes = WriteFileKeepBuffer();
1209 fHeaderOnly = kFALSE;
1210 return nBytes>0 ? fKeylen+nout : -1;