50#ifndef R__LITTLE_ENDIAN
53#define R__LITTLE_ENDIAN 1
55#define R__LITTLE_ENDIAN 0
66 std::uint16_t fValBE = 0;
67 static std::uint16_t
Swap(std::uint16_t val)
69#if R__LITTLE_ENDIAN == 1
70 return RByteSwap<
sizeof(val)>::bswap(val);
77 RUInt16BE() =
default;
78 explicit RUInt16BE(
const std::uint16_t val) : fValBE(
Swap(val)) {}
79 operator std::uint16_t()
const {
return Swap(fValBE); }
80 RUInt16BE &
operator=(
const std::uint16_t val)
90 std::uint32_t fValBE = 0;
91 static std::uint32_t
Swap(std::uint32_t val)
93#if R__LITTLE_ENDIAN == 1
94 return RByteSwap<
sizeof(val)>::bswap(val);
101 RUInt32BE() =
default;
102 explicit RUInt32BE(
const std::uint32_t val) : fValBE(
Swap(val)) {}
103 operator std::uint32_t()
const {
return Swap(fValBE); }
104 RUInt32BE &
operator=(
const std::uint32_t val)
114 std::int32_t fValBE = 0;
115 static std::int32_t
Swap(std::int32_t val)
117#if R__LITTLE_ENDIAN == 1
118 return RByteSwap<
sizeof(val)>::bswap(val);
125 RInt32BE() =
default;
126 explicit RInt32BE(
const std::int32_t val) : fValBE(
Swap(val)) {}
127 operator std::int32_t()
const {
return Swap(fValBE); }
128 RInt32BE &
operator=(
const std::int32_t val)
138 std::uint64_t fValBE = 0;
139 static std::uint64_t
Swap(std::uint64_t val)
141#if R__LITTLE_ENDIAN == 1
142 return RByteSwap<
sizeof(val)>::bswap(val);
149 RUInt64BE() =
default;
150 explicit RUInt64BE(
const std::uint64_t val) : fValBE(
Swap(val)) {}
151 operator std::uint64_t()
const {
return Swap(fValBE); }
152 RUInt64BE &
operator=(
const std::uint64_t val)
162 unsigned char fLName{0};
164 RTFString() =
default;
165 RTFString(
const std::string &str)
170 fLName = str.length();
171 memcpy(fData, str.data(), fLName);
173 std::size_t GetSize()
const
187 auto now = std::chrono::system_clock::now();
188 auto tt = std::chrono::system_clock::to_time_t(now);
189 auto tm = *localtime(&
tt);
190 fDatetime = (tm.tm_year + 1900 - 1995) << 26 | (tm.tm_mon + 1) << 22 | tm.tm_mday << 17 | tm.tm_hour << 12 |
191 tm.tm_min << 6 | tm.tm_sec;
193 explicit RTFDatetime(RUInt32BE val) : fDatetime(val) {}
198 static constexpr unsigned kBigKeyVersion = 1000;
201 RUInt16BE fVersion{4};
202 RUInt32BE fObjLen{0};
203 RTFDatetime fDatetime;
204 RUInt16BE fKeyLen{0};
208 RUInt32BE fSeekKey{0};
209 RUInt32BE fSeekPdir{0};
212 RUInt64BE fSeekKey{0};
213 RUInt64BE fSeekPdir{0};
217 RTFKey() : fInfoLong() {}
218 RTFKey(std::uint64_t seekKey, std::uint64_t seekPdir,
const RTFString &clName,
const RTFString &objName,
219 const RTFString &titleName, std::size_t szObjInMem, std::size_t szObjOnDisk = 0)
221 R__ASSERT(szObjInMem <= std::numeric_limits<std::uint32_t>::max());
222 R__ASSERT(szObjOnDisk <= std::numeric_limits<std::uint32_t>::max());
224 fVersion = fVersion + kBigKeyVersion;
225 fObjLen = szObjInMem;
226 fKeyLen = GetHeaderSize() + clName.GetSize() + objName.GetSize() + titleName.GetSize();
227 fInfoLong.fSeekKey = seekKey;
228 fInfoLong.fSeekPdir = seekPdir;
230 fNbytes = fKeyLen + ((szObjOnDisk == 0) ? szObjInMem : szObjOnDisk);
233 std::uint32_t GetSize()
const
241 std::uint32_t GetHeaderSize()
const
243 if (fVersion >= kBigKeyVersion)
244 return 18 +
sizeof(fInfoLong);
245 return 18 +
sizeof(fInfoShort);
248 std::uint64_t GetSeekKey()
const
250 if (fVersion >= kBigKeyVersion)
251 return fInfoLong.fSeekKey;
252 return fInfoShort.fSeekKey;
258 static constexpr unsigned kBEGIN = 100;
259 static constexpr unsigned kBigHeaderVersion = 1000000;
261 char fMagic[4]{
'r',
'o',
'o',
't'};
268 RUInt32BE fSeekFree{0};
269 RUInt32BE fNbytesFree{0};
271 RUInt32BE fNbytesName{0};
272 unsigned char fUnits{4};
273 RUInt32BE fCompress{0};
274 RUInt32BE fSeekInfo{0};
275 RUInt32BE fNbytesInfo{0};
279 RUInt64BE fSeekFree{0};
280 RUInt32BE fNbytesFree{0};
282 RUInt32BE fNbytesName{0};
283 unsigned char fUnits{8};
284 RUInt32BE fCompress{0};
285 RUInt64BE fSeekInfo{0};
286 RUInt32BE fNbytesInfo{0};
290 RTFHeader() : fInfoShort() {}
291 RTFHeader(
int compression) : fInfoShort() { fInfoShort.fCompress = compression; }
295 if (fVersion >= kBigHeaderVersion)
299 std::uint32_t end = fInfoShort.fEND;
300 std::uint32_t seekFree = fInfoShort.fSeekFree;
301 std::uint32_t nbytesFree = fInfoShort.fNbytesFree;
302 std::uint32_t nFree = fInfoShort.fNfree;
303 std::uint32_t nbytesName = fInfoShort.fNbytesName;
304 std::uint32_t compress = fInfoShort.fCompress;
305 std::uint32_t seekInfo = fInfoShort.fSeekInfo;
306 std::uint32_t nbytesInfo = fInfoShort.fNbytesInfo;
307 fInfoLong.fEND = end;
308 fInfoLong.fSeekFree = seekFree;
309 fInfoLong.fNbytesFree = nbytesFree;
310 fInfoLong.fNfree = nFree;
311 fInfoLong.fNbytesName = nbytesName;
312 fInfoLong.fUnits = 8;
313 fInfoLong.fCompress = compress;
314 fInfoLong.fSeekInfo = seekInfo;
315 fInfoLong.fNbytesInfo = nbytesInfo;
316 fVersion = fVersion + kBigHeaderVersion;
320 bool IsBigFile(std::uint64_t
offset = 0)
const
322 return (fVersion >= kBigHeaderVersion) ||
323 (
offset >
static_cast<unsigned int>(std::numeric_limits<std::int32_t>::max()));
326 std::uint32_t GetSize()
const
328 std::uint32_t sizeHead =
sizeof(fMagic) +
sizeof(fVersion) +
sizeof(fBEGIN);
330 return sizeHead +
sizeof(fInfoLong);
331 return sizeHead +
sizeof(fInfoShort);
334 std::uint64_t GetEnd()
const
337 return fInfoLong.fEND;
338 return fInfoShort.fEND;
341 void SetEnd(std::uint64_t
value)
343 if (IsBigFile(
value)) {
345 fInfoLong.fEND =
value;
347 fInfoShort.fEND =
value;
351 std::uint64_t GetSeekFree()
const
354 return fInfoLong.fSeekFree;
355 return fInfoShort.fSeekFree;
358 void SetSeekFree(std::uint64_t
value)
360 if (IsBigFile(
value)) {
362 fInfoLong.fSeekFree =
value;
364 fInfoShort.fSeekFree =
value;
368 void SetNbytesFree(std::uint32_t
value)
371 fInfoLong.fNbytesFree =
value;
373 fInfoShort.fNbytesFree =
value;
377 void SetNbytesName(std::uint32_t
value)
380 fInfoLong.fNbytesName =
value;
382 fInfoShort.fNbytesName =
value;
386 std::uint64_t GetSeekInfo()
const
389 return fInfoLong.fSeekInfo;
390 return fInfoShort.fSeekInfo;
393 void SetSeekInfo(std::uint64_t
value)
395 if (IsBigFile(
value)) {
397 fInfoLong.fSeekInfo =
value;
399 fInfoShort.fSeekInfo =
value;
403 void SetNbytesInfo(std::uint32_t
value)
406 fInfoLong.fNbytesInfo =
value;
408 fInfoShort.fNbytesInfo =
value;
412 void SetCompression(std::uint32_t
value)
415 fInfoLong.fCompress =
value;
417 fInfoShort.fCompress =
value;
424 static constexpr unsigned kBigFreeEntryVersion = 1000;
426 RUInt16BE fVersion{1};
438 RTFFreeEntry() : fInfoShort() {}
439 void Set(std::uint64_t first, std::uint64_t last)
441 if (last >
static_cast<unsigned int>(std::numeric_limits<std::int32_t>::max())) {
442 fVersion = fVersion + kBigFreeEntryVersion;
443 fInfoLong.fFirst = first;
444 fInfoLong.fLast = last;
446 fInfoShort.fFirst = first;
447 fInfoShort.fLast = last;
450 std::uint32_t GetSize() {
return (fVersion >= kBigFreeEntryVersion) ? 18 : 10; }
456 std::uint32_t GetSize()
const {
return sizeof(RTFKeyList); }
457 explicit RTFKeyList(std::uint32_t nKeys) : fNKeys(nKeys) {}
462 static constexpr unsigned kBigFileVersion = 1000;
464 RUInt16BE fClassVersion{5};
467 RUInt32BE fNBytesKeys{0};
468 RUInt32BE fNBytesName{0};
472 RUInt32BE fSeekDir{RTFHeader::kBEGIN};
473 RUInt32BE fSeekParent{0};
474 RUInt32BE fSeekKeys{0};
477 RUInt64BE fSeekDir{RTFHeader::kBEGIN};
478 RUInt64BE fSeekParent{0};
479 RUInt64BE fSeekKeys{0};
483 RTFDirectory() : fInfoShort() {}
486 std::uint32_t GetSize()
const
488 if (fClassVersion >= kBigFileVersion)
489 return sizeof(RTFDirectory);
490 return 18 +
sizeof(fInfoShort);
493 std::uint64_t GetSeekKeys()
const
495 if (fClassVersion >= kBigFileVersion)
496 return fInfoLong.fSeekKeys;
497 return fInfoShort.fSeekKeys;
500 void SetSeekKeys(std::uint64_t seekKeys)
502 if (seekKeys >
static_cast<unsigned int>(std::numeric_limits<std::int32_t>::max())) {
503 std::uint32_t seekDir = fInfoShort.fSeekDir;
504 std::uint32_t seekParent = fInfoShort.fSeekParent;
505 fInfoLong.fSeekDir = seekDir;
506 fInfoLong.fSeekParent = seekParent;
507 fInfoLong.fSeekKeys = seekKeys;
508 fClassVersion = fClassVersion + kBigFileVersion;
510 fInfoShort.fSeekKeys = seekKeys;
517 RUInt16BE fVersionClass{1};
518 unsigned char fUUID[16];
523 char *buffer =
reinterpret_cast<char *
>(
this);
525 assert(
reinterpret_cast<RTFUUID *
>(buffer) <= (
this + 1));
527 std::uint32_t GetSize()
const {
return sizeof(RTFUUID); }
536 RUInt32BE fByteCount{0x40000000 | (
sizeof(RTFNTuple) -
sizeof(fByteCount))};
537 RUInt16BE fVersionClass{2};
538 RUInt16BE fVersionEpoch{0};
539 RUInt16BE fVersionMajor{0};
540 RUInt16BE fVersionMinor{0};
541 RUInt16BE fVersionPatch{0};
542 RUInt64BE fSeekHeader{0};
543 RUInt64BE fNBytesHeader{0};
544 RUInt64BE fLenHeader{0};
545 RUInt64BE fSeekFooter{0};
546 RUInt64BE fNBytesFooter{0};
547 RUInt64BE fLenFooter{0};
548 RUInt64BE fMaxKeySize{0};
550 static constexpr std::uint32_t GetSizePlusChecksum() {
return sizeof(RTFNTuple) +
sizeof(std::uint64_t); }
552 RTFNTuple() =
default;
567 std::uint32_t GetSize()
const {
return sizeof(RTFNTuple); }
569 std::uint32_t GetOffsetCkData() {
return sizeof(fByteCount) +
sizeof(fVersionClass); }
570 std::uint32_t GetSizeCkData() {
return GetSize() - GetOffsetCkData(); }
571 unsigned char *GetPtrCkData() {
return reinterpret_cast<unsigned char *
>(
this) + GetOffsetCkData(); }
575struct RBareFileHeader {
576 char fMagic[7]{
'r',
'n',
't',
'u',
'p',
'l',
'e'};
579 RUInt32BE fFormatVersion{1};
580 RUInt32BE fCompress{0};
587constexpr char const *kBlobClassName =
"RBlob";
589constexpr char const *kNTupleClassName =
"ROOT::RNTuple";
594namespace Experimental {
621 void Reserve(
size_t nbytes, std::uint64_t *seekKey)
639 constexpr size_t kChunkOffsetSize =
sizeof(std::uint64_t);
641 assert(nbytes > maxChunkSize);
642 size_t nChunks = (nbytes + maxChunkSize - 1) / maxChunkSize;
644 size_t nbytesTail = nbytes % maxChunkSize;
645 size_t nbytesExtra = (nbytesTail > 0) * (maxChunkSize - nbytesTail);
646 size_t nbytesChunkOffsets = (nChunks - 1) * kChunkOffsetSize;
647 if (nbytesChunkOffsets > nbytesExtra) {
649 nbytesChunkOffsets += kChunkOffsetSize;
656 R__ASSERT(nbytesChunkOffsets <= maxChunkSize);
668 if (std::string(ident, 4) ==
"root")
669 return GetNTupleProper(ntupleName);
671 return GetNTupleBare(ntupleName);
677 std::string_view keyName,
678 std::string_view typeName)
680 RTFDirectory directory;
681 ReadBuffer(&directory,
sizeof(directory), offsetDir);
685 std::uint64_t
offset = directory.GetSeekKeys();
691 for (
unsigned int i = 0; i < nKeys; ++i) {
693 auto offsetNextKey =
offset + key.fKeyLen;
695 offset += key.GetHeaderSize();
699 if (std::string_view(
name.fData,
name.fLName) != typeName) {
706 if (std::string_view(
name.fData,
name.fLName) == keyName) {
707 return key.GetSeekKey();
719 RTFHeader fileHeader;
720 ReadBuffer(&fileHeader,
sizeof(fileHeader), 0);
724 ReadBuffer(&key,
sizeof(key), fileHeader.fBEGIN);
726 std::uint64_t
offset = fileHeader.fBEGIN + key.fKeyLen;
734 std::string ntuplePathTail(ntuplePath);
735 if (!ntuplePathTail.empty() && ntuplePathTail[0] ==
'/')
736 ntuplePathTail = ntuplePathTail.substr(1);
737 auto pos = std::string::npos;
738 while ((pos = ntuplePathTail.find(
'/')) != std::string::npos) {
739 auto directoryName = ntuplePathTail.substr(0, pos);
740 ntuplePathTail.erase(0, pos + 1);
742 offset = SearchInDirectory(
offset, directoryName,
"TDirectory");
744 return R__FAIL(
"no directory named '" + std::string(directoryName) +
"' in file '" + fRawFile->GetUrl() +
"'");
747 offset = key.GetSeekKey() + key.fKeyLen;
750 auto ntupleName = ntuplePathTail;
752 offset = SearchInDirectory(
offset, ntupleName, kNTupleClassName);
754 return R__FAIL(
"no RNTuple named '" + std::string(ntupleName) +
"' in file '" + fRawFile->GetUrl() +
"'");
758 offset = key.GetSeekKey() + key.fKeyLen;
761 constexpr size_t kMinNTupleSize = 78;
762 static_assert(kMinNTupleSize == RTFNTuple::GetSizePlusChecksum());
763 if (key.fObjLen < kMinNTupleSize) {
764 return R__FAIL(
"invalid anchor size: " + std::to_string(key.fObjLen) +
" < " + std::to_string(
sizeof(RTFNTuple)));
768 auto bufAnchor = MakeUninitArray<unsigned char>(std::max<size_t>(key.fObjLen,
sizeof(RTFNTuple)));
769 RTFNTuple *ntuple =
new (bufAnchor.get()) RTFNTuple;
771 auto objNbytes = key.GetSize() - key.fKeyLen;
773 if (objNbytes != key.fObjLen) {
775 decompressor.
Unzip(bufAnchor.get(), objNbytes, key.fObjLen);
780 auto lenCkData = key.fObjLen - ntuple->GetOffsetCkData() -
sizeof(uint64_t);
781 auto ckCalc = XXH3_64bits(ntuple->GetPtrCkData(), lenCkData);
784 RUInt64BE *ckOnDiskPtr =
reinterpret_cast<RUInt64BE *
>(bufAnchor.get() + key.fObjLen -
sizeof(uint64_t));
785 ckOnDisk =
static_cast<uint64_t
>(*ckOnDiskPtr);
786 if (ckCalc != ckOnDisk) {
787 return R__FAIL(
"RNTuple anchor checksum mismatch");
790 return CreateAnchor(ntuple->fVersionEpoch, ntuple->fVersionMajor, ntuple->fVersionMinor, ntuple->fVersionPatch,
791 ntuple->fSeekHeader, ntuple->fNBytesHeader, ntuple->fLenHeader, ntuple->fSeekFooter,
792 ntuple->fNBytesFooter, ntuple->fLenFooter, ntuple->fMaxKeySize);
798 RBareFileHeader fileHeader;
799 ReadBuffer(&fileHeader,
sizeof(fileHeader), 0);
801 auto offset =
sizeof(fileHeader);
804 std::string_view foundName(
name.fData,
name.fLName);
805 if (foundName != ntupleName) {
806 return R__FAIL(
"expected RNTuple named '" + std::string(ntupleName) +
"' but instead found '" +
807 std::string(foundName) +
"' in file '" + fRawFile->GetUrl() +
"'");
813 std::uint64_t onDiskChecksum;
814 ReadBuffer(&onDiskChecksum,
sizeof(onDiskChecksum),
offset +
sizeof(ntuple));
815 auto checksum = XXH3_64bits(ntuple.GetPtrCkData(), ntuple.GetSizeCkData());
816 if (checksum !=
static_cast<uint64_t
>(onDiskChecksum))
817 return R__FAIL(
"RNTuple bare file: anchor checksum mismatch");
819 return CreateAnchor(ntuple.fVersionEpoch, ntuple.fVersionMajor, ntuple.fVersionMinor, ntuple.fVersionPatch,
820 ntuple.fSeekHeader, ntuple.fNBytesHeader, ntuple.fLenHeader, ntuple.fSeekFooter,
821 ntuple.fNBytesFooter, ntuple.fLenFooter, ntuple.fMaxKeySize);
827 if (fMaxKeySize == 0 || nbytes <= fMaxKeySize) {
829 nread = fRawFile->ReadAt(buffer, nbytes,
offset);
833 const size_t nbytesChunkOffsets = (nChunks - 1) *
sizeof(std::uint64_t);
834 const size_t nbytesFirstChunk = fMaxKeySize - nbytesChunkOffsets;
835 uint8_t *bufCur =
reinterpret_cast<uint8_t *
>(buffer);
838 nread = fRawFile->ReadAt(bufCur, fMaxKeySize,
offset);
843 bufCur += nbytesFirstChunk;
844 nread -= nbytesChunkOffsets;
846 const auto chunkOffsets = MakeUninitArray<std::uint64_t>(nChunks - 1);
847 memcpy(chunkOffsets.get(), bufCur, nbytesChunkOffsets);
849 size_t remainingBytes = nbytes - nbytesFirstChunk;
850 std::uint64_t *curChunkOffset = &chunkOffsets[0];
853 std::uint64_t chunkOffset;
857 const size_t bytesToRead = std::min<size_t>(fMaxKeySize, remainingBytes);
859 R__ASSERT(
static_cast<size_t>(bufCur -
reinterpret_cast<uint8_t *
>(buffer)) <= nbytes - bytesToRead);
861 auto nbytesRead = fRawFile->ReadAt(bufCur, bytesToRead, chunkOffset);
864 nread += bytesToRead;
865 bufCur += bytesToRead;
866 remainingBytes -= bytesToRead;
867 }
while (remainingBytes > 0);
880 RTFString strClass{kBlobClassName};
883 RTFKey keyHeader(
offset, RTFHeader::kBEGIN, strClass, strObject, strTitle,
len, nbytes);
887 unsigned char *writeBuffer = buffer;
888 memcpy(writeBuffer, &keyHeader, keyHeader.GetHeaderSize());
889 writeBuffer += keyHeader.GetHeaderSize();
890 memcpy(writeBuffer, &strClass, strClass.GetSize());
891 writeBuffer += strClass.GetSize();
892 memcpy(writeBuffer, &strObject, strObject.GetSize());
893 writeBuffer += strObject.GetSize();
894 memcpy(writeBuffer, &strTitle, strTitle.GetSize());
895 writeBuffer += strTitle.GetSize();
905 static_assert(kHeaderBlockSize % kBlockAlign == 0,
"invalid header block size");
906 if (bufferSize % kBlockAlign != 0)
907 throw RException(
R__FAIL(
"Buffer size not a multiple of alignment: " + std::to_string(bufferSize)));
908 fBlockSize = bufferSize;
910 std::align_val_t blockAlign{kBlockAlign};
911 fHeaderBlock =
static_cast<unsigned char *
>(::operator
new[](kHeaderBlockSize, blockAlign));
912 memset(fHeaderBlock, 0, kHeaderBlockSize);
913 fBlock =
static_cast<unsigned char *
>(::operator
new[](fBlockSize, blockAlign));
914 memset(fBlock, 0, fBlockSize);
922 std::align_val_t blockAlign{kBlockAlign};
924 ::operator
delete[](fHeaderBlock, blockAlign);
926 ::operator
delete[](fBlock, blockAlign);
930int FSeek64(FILE *stream, std::int64_t
offset,
int origin)
933 return fseeko64(stream,
offset, origin);
935 return fseek(stream,
offset, origin);
944 if (fBlockOffset == 0) {
945 std::size_t headerBlockSize = kHeaderBlockSize;
946 if (headerBlockSize > fFilePos) {
947 headerBlockSize = fFilePos;
949 memcpy(fBlock, fHeaderBlock, headerBlockSize);
952 std::size_t retval = FSeek64(fFile, fBlockOffset, SEEK_SET);
956 std::size_t lastBlockSize = fFilePos - fBlockOffset;
960 lastBlockSize += kBlockAlign - 1;
961 lastBlockSize = (lastBlockSize / kBlockAlign) * kBlockAlign;
964 retval = fwrite(fBlock, 1, lastBlockSize, fFile);
965 if (retval != lastBlockSize)
969 if (fBlockOffset > 0) {
970 retval = FSeek64(fFile, 0, SEEK_SET);
974 retval = fwrite(fHeaderBlock, 1, kHeaderBlockSize, fFile);
975 if (retval != RFileSimple::kHeaderBlockSize)
979 retval = fflush(fFile);
989 if ((
offset >= 0) && (
static_cast<std::uint64_t
>(
offset) != fFilePos)) {
994 if (fFilePos < kHeaderBlockSize) {
995 std::size_t headerBytes = nbytes;
996 if (fFilePos + headerBytes > kHeaderBlockSize) {
997 headerBytes = kHeaderBlockSize - fFilePos;
999 memcpy(fHeaderBlock + fFilePos, buffer, headerBytes);
1004 while (nbytes > 0) {
1005 std::uint64_t posInBlock = fFilePos % fBlockSize;
1006 std::uint64_t blockOffset = fFilePos - posInBlock;
1007 if (blockOffset != fBlockOffset) {
1009 retval = FSeek64(fFile, fBlockOffset, SEEK_SET);
1013 retval = fwrite(fBlock, 1, fBlockSize, fFile);
1014 if (retval != fBlockSize)
1018 memset(fBlock, 0, fBlockSize);
1021 fBlockOffset = blockOffset;
1022 std::size_t blockSize = nbytes;
1023 if (blockSize > fBlockSize - posInBlock) {
1024 blockSize = fBlockSize - posInBlock;
1026 memcpy(fBlock + posInBlock, buffer, blockSize);
1027 buffer =
static_cast<const unsigned char *
>(buffer) + blockSize;
1028 nbytes -= blockSize;
1029 fFilePos += blockSize;
1034 const void *buffer, std::size_t nbytes, std::size_t
len, std::int64_t
offset, std::uint64_t directoryOffset,
1035 const std::string &className,
const std::string &objectName,
const std::string &title)
1039 RTFString strClass{className};
1040 RTFString strObject{objectName};
1041 RTFString strTitle{title};
1043 RTFKey key(fKeyOffset, directoryOffset, strClass, strObject, strTitle,
len, nbytes);
1044 Write(&key, key.GetHeaderSize(), fKeyOffset);
1045 Write(&strClass, strClass.GetSize());
1046 Write(&strObject, strObject.GetSize());
1047 Write(&strTitle, strTitle.GetSize());
1048 auto offsetData = fFilePos;
1050 fKeyOffset = offsetData + nbytes;
1052 Write(buffer, nbytes);
1071 fKeyOffset = offsetData + nbytes;
1081 fDirectory->GetFile()->Seek(
offset);
1082 bool rv = fDirectory->GetFile()->WriteBuffer((
char *)(buffer), nbytes);
1091 std::uint64_t offsetKey;
1092 RKeyBlob keyBlob(fDirectory->GetFile());
1095 keyBlob.
Reserve(nbytes, &offsetKey);
1123std::unique_ptr<ROOT::Experimental::Internal::RNTupleFileWriter>
1128 std::string fileName(path);
1129 size_t idxDirSep = fileName.find_last_of(
"\\/");
1130 if (idxDirSep != std::string::npos) {
1131 fileName.erase(0, idxDirSep + 1);
1134 int flags = O_WRONLY | O_CREAT | O_TRUNC;
1137 flags |= O_LARGEFILE;
1142 int fd = open(std::string(path).c_str(), flags, 0666);
1143 FILE *fileStream = fdopen(fd,
"wb");
1146 FILE *fileStream = fopen64(std::string(path.data(), path.size()).c_str(),
"wb");
1148 FILE *fileStream = fopen(std::string(path.data(), path.size()).c_str(),
"wb");
1153 std::setvbuf(fileStream,
nullptr, _IONBF, 0);
1156 writer->fFileSimple.fFile = fileStream;
1159 writer->fFileName = fileName;
1162 switch (containerFormat) {
1163 case EContainerFormat::kTFile:
writer->WriteTFileSkeleton(defaultCompression);
break;
1164 case EContainerFormat::kBare:
1166 writer->WriteBareFileSkeleton(defaultCompression);
1168 default:
R__ASSERT(
false &&
"Internal error: unhandled container format");
1174std::unique_ptr<ROOT::Experimental::Internal::RNTupleFileWriter>
1176 std::uint64_t maxKeySize)
1180 throw RException(
R__FAIL(
"invalid attempt to add an RNTuple to a directory that is not backed by a file"));
1184 writer->fFileProper.fDirectory = &fileOrDirectory;
1191 fStreamerInfoMap.insert(streamerInfos.cbegin(), streamerInfos.cend());
1198 fFileProper.fDirectory->WriteObject(&fNTupleAnchor, fNTupleName.c_str());
1202 buf.
SetParent(fFileProper.fDirectory->GetFile());
1203 for (
auto [
_, info] : fStreamerInfoMap)
1206 fFileProper.fDirectory->GetFile()->Write();
1214 RTFNTuple ntupleOnDisk(fNTupleAnchor);
1216 std::uint64_t checksum = XXH3_64bits(ntupleOnDisk.GetPtrCkData(), ntupleOnDisk.GetSizeCkData());
1217 memcpy(fFileSimple.fHeaderBlock + fFileSimple.fControlBlock->fSeekNTuple, &ntupleOnDisk, ntupleOnDisk.GetSize());
1218 memcpy(fFileSimple.fHeaderBlock + fFileSimple.fControlBlock->fSeekNTuple + ntupleOnDisk.GetSize(), &checksum,
1220 fFileSimple.Flush();
1224 WriteTFileNTupleKey();
1225 WriteTFileKeysList();
1226 WriteTFileStreamerInfo();
1227 WriteTFileFreeList();
1230 memcpy(fFileSimple.fHeaderBlock, &fFileSimple.fControlBlock->fHeader, fFileSimple.fControlBlock->fHeader.GetSize());
1231 R__ASSERT(fFileSimple.fControlBlock->fSeekFileRecord + fFileSimple.fControlBlock->fFileRecord.GetSize() <
1232 RFileSimple::kHeaderBlockSize);
1233 memcpy(fFileSimple.fHeaderBlock + fFileSimple.fControlBlock->fSeekFileRecord,
1234 &fFileSimple.fControlBlock->fFileRecord, fFileSimple.fControlBlock->fFileRecord.GetSize());
1236 fFileSimple.Flush();
1241 auto writeKey = [
this](
const void *payload,
size_t nBytes,
size_t length) {
1243 WriteIntoReservedBlob(payload, nBytes,
offset);
1247 const std::uint64_t maxKeySize = fNTupleAnchor.fMaxKeySize;
1251 if (
static_cast<std::uint64_t
>(
len) >
static_cast<std::uint64_t
>(std::numeric_limits<std::uint32_t>::max()))
1254 if (nbytes <= maxKeySize) {
1256 return writeKey(
data, nbytes,
len);
1273 const size_t nbytesChunkOffsets = (nChunks - 1) *
sizeof(std::uint64_t);
1274 const size_t nbytesFirstChunk = maxKeySize - nbytesChunkOffsets;
1277 const uint8_t *chunkData =
reinterpret_cast<const uint8_t *
>(
data) + nbytesFirstChunk;
1278 size_t remainingBytes = nbytes - nbytesFirstChunk;
1280 const auto chunkOffsetsToWrite = MakeUninitArray<std::uint64_t>(nChunks - 1);
1281 std::uint64_t chunkOffsetIdx = 0;
1284 const size_t bytesNextChunk = std::min<size_t>(remainingBytes, maxKeySize);
1285 const std::uint64_t
offset = writeKey(chunkData, bytesNextChunk, bytesNextChunk);
1290 remainingBytes -= bytesNextChunk;
1291 chunkData += bytesNextChunk;
1293 }
while (remainingBytes > 0);
1296 const std::uint64_t firstOffset = ReserveBlob(maxKeySize, maxKeySize);
1297 WriteIntoReservedBlob(
data, nbytesFirstChunk, firstOffset);
1298 const std::uint64_t chunkOffsetsOffset = firstOffset + nbytesFirstChunk;
1299 WriteIntoReservedBlob(chunkOffsetsToWrite.get(), nbytesChunkOffsets, chunkOffsetsOffset);
1308 R__ASSERT(nbytes <= fNTupleAnchor.GetMaxKeySize());
1313 offset = fFileSimple.fKeyOffset;
1314 fFileSimple.fKeyOffset += nbytes;
1316 offset = fFileSimple.ReserveBlobKey(nbytes,
len, keyBuffer);
1319 offset = fFileProper.ReserveBlobKey(nbytes,
len, keyBuffer);
1328 fFileSimple.Write(buffer, nbytes,
offset);
1330 fFileProper.Write(buffer, nbytes,
offset);
1337 auto offset = WriteBlob(
data, nbytes, lenHeader);
1338 fNTupleAnchor.fLenHeader = lenHeader;
1339 fNTupleAnchor.fNBytesHeader = nbytes;
1340 fNTupleAnchor.fSeekHeader =
offset;
1347 auto offset = WriteBlob(
data, nbytes, lenFooter);
1348 fNTupleAnchor.fLenFooter = lenFooter;
1349 fNTupleAnchor.fNBytesFooter = nbytes;
1350 fNTupleAnchor.fSeekFooter =
offset;
1356 RBareFileHeader bareHeader;
1357 bareHeader.fCompress = defaultCompression;
1358 fFileSimple.Write(&bareHeader,
sizeof(bareHeader), 0);
1359 RTFString ntupleName{fNTupleName};
1360 fFileSimple.Write(&ntupleName, ntupleName.GetSize());
1363 RTFNTuple ntupleOnDisk;
1364 fFileSimple.fControlBlock->fSeekNTuple = fFileSimple.fFilePos;
1365 fFileSimple.Write(&ntupleOnDisk, ntupleOnDisk.GetSize());
1366 std::uint64_t checksum = 0;
1367 fFileSimple.Write(&checksum,
sizeof(checksum));
1368 fFileSimple.fKeyOffset = fFileSimple.fFilePos;
1378 TList streamerInfoList;
1379 for (
auto [
_, info] : fStreamerInfoMap) {
1380 streamerInfoList.
Add(info);
1389 RTFString strTList{
"TList"};
1390 RTFString strStreamerInfo{
"StreamerInfo"};
1391 RTFString strStreamerTitle{
"Doubly linked list"};
1392 fFileSimple.fControlBlock->fHeader.SetSeekInfo(fFileSimple.fKeyOffset);
1393 auto keyLen = RTFKey(fFileSimple.fControlBlock->fHeader.GetSeekInfo(), RTFHeader::kBEGIN, strTList, strStreamerInfo,
1394 strStreamerTitle, 0)
1400 assert(buffer.
Length() > keyLen);
1401 const auto bufPayload = buffer.
Buffer() + keyLen;
1402 const auto lenPayload = buffer.
Length() - keyLen;
1405 auto zipStreamerInfos = MakeUninitArray<unsigned char>(lenPayload);
1406 auto szZipStreamerInfos = compressor.
Zip(bufPayload, lenPayload, 1, zipStreamerInfos.get());
1408 fFileSimple.WriteKey(zipStreamerInfos.get(), szZipStreamerInfos, lenPayload,
1409 fFileSimple.fControlBlock->fHeader.GetSeekInfo(), RTFHeader::kBEGIN,
"TList",
"StreamerInfo",
1410 "Doubly linked list");
1411 fFileSimple.fControlBlock->fHeader.SetNbytesInfo(fFileSimple.fFilePos -
1412 fFileSimple.fControlBlock->fHeader.GetSeekInfo());
1418 RTFString strRNTupleClass{
"ROOT::RNTuple"};
1419 RTFString strRNTupleName{fNTupleName};
1420 RTFString strFileName{fFileName};
1422 RTFKey keyRNTuple(fFileSimple.fControlBlock->fSeekNTuple, RTFHeader::kBEGIN, strRNTupleClass, strRNTupleName,
1423 strEmpty, RTFNTuple::GetSizePlusChecksum());
1425 fFileSimple.fControlBlock->fFileRecord.SetSeekKeys(fFileSimple.fKeyOffset);
1426 RTFKeyList keyList{1};
1427 RTFKey keyKeyList(fFileSimple.fControlBlock->fFileRecord.GetSeekKeys(), RTFHeader::kBEGIN, strEmpty, strFileName,
1428 strEmpty, keyList.GetSize() + keyRNTuple.fKeyLen);
1429 fFileSimple.Write(&keyKeyList, keyKeyList.GetHeaderSize(), fFileSimple.fControlBlock->fFileRecord.GetSeekKeys());
1430 fFileSimple.Write(&strEmpty, strEmpty.GetSize());
1431 fFileSimple.Write(&strFileName, strFileName.GetSize());
1432 fFileSimple.Write(&strEmpty, strEmpty.GetSize());
1433 fFileSimple.Write(&keyList, keyList.GetSize());
1434 fFileSimple.Write(&keyRNTuple, keyRNTuple.GetHeaderSize());
1436 fFileSimple.Write(&strRNTupleClass, strRNTupleClass.GetSize());
1437 fFileSimple.Write(&strRNTupleName, strRNTupleName.GetSize());
1438 fFileSimple.Write(&strEmpty, strEmpty.GetSize());
1439 fFileSimple.fControlBlock->fFileRecord.fNBytesKeys =
1440 fFileSimple.fFilePos - fFileSimple.fControlBlock->fFileRecord.GetSeekKeys();
1441 fFileSimple.fKeyOffset = fFileSimple.fFilePos;
1446 fFileSimple.fControlBlock->fHeader.SetSeekFree(fFileSimple.fKeyOffset);
1448 RTFString strFileName{fFileName};
1449 RTFFreeEntry freeEntry;
1450 RTFKey keyFreeList(fFileSimple.fControlBlock->fHeader.GetSeekFree(), RTFHeader::kBEGIN, strEmpty, strFileName,
1451 strEmpty, freeEntry.GetSize());
1452 std::uint64_t firstFree = fFileSimple.fControlBlock->fHeader.GetSeekFree() + keyFreeList.GetSize();
1453 freeEntry.Set(firstFree, std::max(2000000000ULL, ((firstFree / 1000000000ULL) + 1) * 1000000000ULL));
1454 fFileSimple.WriteKey(&freeEntry, freeEntry.GetSize(), freeEntry.GetSize(),
1455 fFileSimple.fControlBlock->fHeader.GetSeekFree(), RTFHeader::kBEGIN,
"", fFileName,
"");
1456 fFileSimple.fControlBlock->fHeader.SetNbytesFree(fFileSimple.fFilePos -
1457 fFileSimple.fControlBlock->fHeader.GetSeekFree());
1458 fFileSimple.fControlBlock->fHeader.SetEnd(fFileSimple.fFilePos);
1463 RTFString strRNTupleClass{
"ROOT::RNTuple"};
1464 RTFString strRNTupleName{fNTupleName};
1467 RTFNTuple ntupleOnDisk(fNTupleAnchor);
1468 RUInt64BE checksum{XXH3_64bits(ntupleOnDisk.GetPtrCkData(), ntupleOnDisk.GetSizeCkData())};
1469 fFileSimple.fControlBlock->fSeekNTuple = fFileSimple.fKeyOffset;
1471 char keyBuf[RTFNTuple::GetSizePlusChecksum()];
1474 memcpy(keyBuf, &ntupleOnDisk,
sizeof(RTFNTuple));
1475 memcpy(keyBuf +
sizeof(RTFNTuple), &checksum,
sizeof(checksum));
1477 fFileSimple.WriteKey(keyBuf,
sizeof(keyBuf),
sizeof(keyBuf), fFileSimple.fControlBlock->fSeekNTuple,
1478 RTFHeader::kBEGIN,
"ROOT::RNTuple", fNTupleName,
"");
1483 RTFString strTFile{
"TFile"};
1484 RTFString strFileName{fFileName};
1487 fFileSimple.fControlBlock->fHeader = RTFHeader(defaultCompression);
1492 RTFKey keyRoot(RTFHeader::kBEGIN, 0, strTFile, strFileName, strEmpty,
1493 sizeof(RTFDirectory) + strFileName.GetSize() + strEmpty.GetSize() + uuid.GetSize());
1494 std::uint32_t nbytesName = keyRoot.fKeyLen + strFileName.GetSize() + 1;
1495 fFileSimple.fControlBlock->fFileRecord.fNBytesName = nbytesName;
1496 fFileSimple.fControlBlock->fHeader.SetNbytesName(nbytesName);
1498 fFileSimple.Write(&keyRoot, keyRoot.GetHeaderSize(), RTFHeader::kBEGIN);
1500 fFileSimple.Write(&strTFile, strTFile.GetSize());
1501 fFileSimple.Write(&strFileName, strFileName.GetSize());
1502 fFileSimple.Write(&strEmpty, strEmpty.GetSize());
1504 fFileSimple.Write(&strFileName, strFileName.GetSize());
1505 fFileSimple.Write(&strEmpty, strEmpty.GetSize());
1507 fFileSimple.fControlBlock->fSeekFileRecord = fFileSimple.fFilePos;
1508 fFileSimple.Write(&fFileSimple.fControlBlock->fFileRecord, fFileSimple.fControlBlock->fFileRecord.GetSize());
1509 fFileSimple.Write(&uuid, uuid.GetSize());
1512 RUInt32BE padding{0};
1513 for (
int i = 0; i < 3; ++i)
1514 fFileSimple.Write(&padding,
sizeof(padding));
1515 fFileSimple.fKeyOffset = fFileSimple.fFilePos;
#define R__FAIL(msg)
Short-hand to return an RResult<T> in an error state; the RError is implicitly converted into RResult...
static void PrepareBlobKey(std::int64_t offset, size_t nbytes, size_t len, unsigned char buffer[kBlobKeyLen])
Prepare a blob key in the provided buffer, which must provide space for kBlobKeyLen bytes.
static size_t ComputeNumChunks(size_t nbytes, size_t maxChunkSize)
static constexpr auto kBlobKeyLen
#define ROOT_VERSION_CODE
#define ClassDefInlineOverride(name, id)
#define R__ASSERT(e)
Checks condition e and reports a fatal error if it's false.
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
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 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 length
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
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
Binding & operator=(OUT(*fun)(void))
void ReadBuffer(char *&buffer) override
The RKeyBlob writes an invisible key into a TFile.
void Reserve(size_t nbytes, std::uint64_t *seekKey)
Register a new key for a data record of size nbytes.
std::uint64_t SearchInDirectory(std::uint64_t &offsetDir, std::string_view keyName, std::string_view typeName)
Searches for a key with the given name and type in the key index of the directory starting at offsetD...
RMiniFileReader()=default
RResult< RNTuple > GetNTupleBare(std::string_view ntupleName)
Used when the file container turns out to be a bare file.
RResult< RNTuple > GetNTuple(std::string_view ntupleName)
Extracts header and footer location for the RNTuple identified by ntupleName.
RResult< RNTuple > GetNTupleProper(std::string_view ntuplePath)
Used when the file turns out to be a TFile container.
void ReadBuffer(void *buffer, size_t nbytes, std::uint64_t offset)
Reads a given byte range from the file into the provided memory buffer.
Helper class to compress data blocks in the ROOT compression frame format.
size_t Zip(const void *from, size_t nbytes, int compression, Writer_t fnWriter)
Returns the size of the compressed data.
Helper class to uncompress data blocks in the ROOT compression frame format.
static void Unzip(const void *from, size_t nbytes, size_t dataLen, void *to)
The nbytes parameter provides the size ls of the from buffer.
Write RNTuple data blocks in a TFile or a bare file container.
RNTupleFileWriter(std::string_view name, std::uint64_t maxKeySize)
std::uint64_t WriteBlob(const void *data, size_t nbytes, size_t len)
Writes a new record as an RBlob key into the file.
std::uint64_t WriteNTupleFooter(const void *data, size_t nbytes, size_t lenFooter)
Writes the compressed footer and registeres its location; lenFooter is the size of the uncompressed f...
void WriteTFileKeysList()
Write the TList with the RNTuple key.
void UpdateStreamerInfos(const RNTupleSerializer::StreamerInfoMap_t &streamerInfos)
Ensures that the streamer info records passed as argument are written to the file.
void Commit()
Writes the RNTuple key to the file so that the header and footer keys can be found.
RFileSimple fFileSimple
For simple use cases, survives without libRIO dependency.
void WriteTFileNTupleKey()
The only key that will be visible in file->ls()
void WriteTFileFreeList()
Last record in the file.
EContainerFormat
For testing purposes, RNTuple data can be written into a bare file container instead of a ROOT file.
std::uint64_t ReserveBlob(size_t nbytes, size_t len, unsigned char keyBuffer[kBlobKeyLen]=nullptr)
Reserves a new record as an RBlob key in the file.
static std::unique_ptr< RNTupleFileWriter > Recreate(std::string_view ntupleName, std::string_view path, EContainerFormat containerFormat, const RNTupleWriteOptions &options)
Create or truncate the local file given by path with the new empty RNTuple identified by ntupleName.
static std::unique_ptr< RNTupleFileWriter > Append(std::string_view ntupleName, TDirectory &fileOrDirectory, std::uint64_t maxKeySize)
The directory parameter can also be a TFile object (TFile inherits from TDirectory).
void WriteTFileSkeleton(int defaultCompression)
For a TFile container written by a C file stream, write the header and TFile object.
void WriteBareFileSkeleton(int defaultCompression)
For a bare file, which is necessarily written by a C file stream, write file header.
void WriteTFileStreamerInfo()
Write the compressed streamer info record with the description of the RNTuple class.
static constexpr std::size_t kBlobKeyLen
The key length of a blob. It is always a big key (version > 1000) with class name RBlob.
std::uint64_t WriteNTupleHeader(const void *data, size_t nbytes, size_t lenHeader)
Writes the compressed header and registeres its location; lenHeader is the size of the uncompressed h...
RNTuple fNTupleAnchor
Header and footer location of the ntuple, written on Commit()
void WriteIntoReservedBlob(const void *buffer, size_t nbytes, std::int64_t offset)
Write into a reserved record; the caller is responsible for making sure that the written byte range i...
RNTupleSerializer::StreamerInfoMap_t fStreamerInfoMap
Set of streamer info records that should be written to the file.
static std::uint32_t SerializeUInt64(std::uint64_t val, void *buffer)
std::map< Int_t, TVirtualStreamerInfo * > StreamerInfoMap_t
static std::uint32_t DeserializeUInt64(const void *buffer, std::uint64_t &val)
Base class for all ROOT issued exceptions.
Common user-tunable settings for storing ntuples.
std::size_t GetWriteBufferSize() const
int GetCompression() const
bool GetUseDirectIO() const
std::uint64_t GetMaxKeySize() const
The class is used as a return type for operations that can fail; wraps a value of type T or an RError...
The RRawFile provides read-only access to local and remote files.
Representation of an RNTuple data set in a ROOT file.
std::uint64_t GetLenFooter() const
std::uint64_t GetSeekHeader() const
std::uint16_t GetVersionMajor() const
std::uint64_t GetNBytesFooter() const
std::uint64_t GetNBytesHeader() const
std::uint64_t fMaxKeySize
The maximum size for a TKey payload. Payloads bigger than this size will be written as multiple blobs...
std::uint16_t GetVersionMinor() const
std::uint16_t GetVersionPatch() const
std::uint64_t GetMaxKeySize() const
std::uint64_t GetLenHeader() const
std::uint64_t GetSeekFooter() const
std::uint16_t GetVersionEpoch() const
The concrete implementation of TBuffer for writing/reading to/from a ROOT file or socket.
void TagStreamerInfo(TVirtualStreamerInfo *info) override
Mark the classindex of the current file as using this TStreamerInfo.
void SetParent(TObject *parent)
Set parent owning this buffer.
void SetBufferOffset(Int_t offset=0)
TVirtualStreamerInfo * GetStreamerInfo(Int_t version=0, Bool_t isTransient=kFALSE) const
returns a pointer to the TVirtualStreamerInfo object for version If the object does not exist,...
Describe directory structure in memory.
virtual TFile * GetFile() const
A ROOT file is an on-disk file, usually with extension .root, that stores objects in a file-system-li...
Book space in a file, create I/O buffers, to fill them, (un)compress them.
Int_t Sizeof() const override
Return the size in bytes of the key header structure.
Int_t fVersion
Key version identifier.
Short_t fKeylen
Number of bytes for the key itself.
Long64_t fSeekKey
Location of object on file.
virtual void Create(Int_t nbytes, TFile *f=nullptr)
Create a TKey object of specified size.
TString fClassName
Object Class name.
void Streamer(TBuffer &) override
Stream all objects in the collection to or from the I/O buffer.
void Add(TObject *obj) override
This class defines a UUID (Universally Unique IDentifier), also known as GUIDs (Globally Unique IDent...
void FillBuffer(char *&buffer)
Stream UUID into output buffer.
RNTuple CreateAnchor(std::uint16_t versionEpoch, std::uint16_t versionMajor, std::uint16_t versionMinor, std::uint16_t versionPatch, std::uint64_t seekHeader, std::uint64_t nbytesHeader, std::uint64_t lenHeader, std::uint64_t seekFooter, std::uint64_t nbytesFooter, std::uint64_t lenFooter, std::uint64_t maxKeySize)
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
Helper templated class for swapping bytes; specializations for N={2,4,8} are provided below.
void Write(const void *buffer, size_t nbytes, std::int64_t offset)
Low-level writing using a TFile.
std::uint64_t ReserveBlobKey(size_t nbytes, size_t len, unsigned char keyBuffer[kBlobKeyLen]=nullptr)
Reserves an RBlob opaque key as data record and returns the offset of the record.
void AllocateBuffers(std::size_t bufferSize)
std::unique_ptr< ROOT::Experimental::Internal::RTFileControlBlock > fControlBlock
Keeps track of TFile control structures, which need to be updated on committing the data set.
void Write(const void *buffer, size_t nbytes, std::int64_t offset=-1)
Writes bytes in the open stream, either at fFilePos or at the given offset.
std::uint64_t ReserveBlobKey(std::size_t nbytes, std::size_t len, unsigned char keyBuffer[kBlobKeyLen]=nullptr)
Reserves an RBlob opaque key as data record and returns the offset of the record.
std::uint64_t WriteKey(const void *buffer, std::size_t nbytes, std::size_t len, std::int64_t offset=-1, std::uint64_t directoryOffset=100, const std::string &className="", const std::string &objectName="", const std::string &title="")
Writes a TKey including the data record, given by buffer, into fFile; returns the file offset to the ...
If a TFile container is written by a C stream (simple file), on dataset commit, the file header and t...
std::uint64_t fSeekNTuple
std::uint64_t fSeekFileRecord