49#ifndef R__LITTLE_ENDIAN
52#define R__LITTLE_ENDIAN 1
54#define R__LITTLE_ENDIAN 0
65 std::uint16_t fValBE = 0;
66 static std::uint16_t Swap(std::uint16_t val)
68#if R__LITTLE_ENDIAN == 1
69 return RByteSwap<
sizeof(val)>::bswap(val);
76 RUInt16BE() =
default;
77 explicit RUInt16BE(
const std::uint16_t val) : fValBE(Swap(val)) {}
78 operator std::uint16_t()
const {
return Swap(fValBE); }
79 RUInt16BE &operator=(
const std::uint16_t val)
89 std::uint32_t fValBE = 0;
90 static std::uint32_t Swap(std::uint32_t val)
92#if R__LITTLE_ENDIAN == 1
93 return RByteSwap<
sizeof(val)>::bswap(val);
100 RUInt32BE() =
default;
101 explicit RUInt32BE(
const std::uint32_t val) : fValBE(Swap(val)) {}
102 operator std::uint32_t()
const {
return Swap(fValBE); }
103 RUInt32BE &operator=(
const std::uint32_t val)
113 std::int32_t fValBE = 0;
114 static std::int32_t Swap(std::int32_t val)
116#if R__LITTLE_ENDIAN == 1
117 return RByteSwap<
sizeof(val)>::bswap(val);
124 RInt32BE() =
default;
125 explicit RInt32BE(
const std::int32_t val) : fValBE(Swap(val)) {}
126 operator std::int32_t()
const {
return Swap(fValBE); }
127 RInt32BE &operator=(
const std::int32_t val)
137 std::uint64_t fValBE = 0;
138 static std::uint64_t Swap(std::uint64_t val)
140#if R__LITTLE_ENDIAN == 1
141 return RByteSwap<
sizeof(val)>::bswap(val);
148 RUInt64BE() =
default;
149 explicit RUInt64BE(
const std::uint64_t val) : fValBE(Swap(val)) {}
150 operator std::uint64_t()
const {
return Swap(fValBE); }
151 RUInt64BE &operator=(
const std::uint64_t val)
161 unsigned char fLName{0};
163 RTFString() =
default;
164 RTFString(
const std::string &str)
169 fLName =
static_cast<unsigned char>(str.length());
170 memcpy(fData, str.data(), fLName);
172 std::size_t GetSize()
const
186 auto now = std::chrono::system_clock::now();
187 auto tt = std::chrono::system_clock::to_time_t(now);
188 auto tm = *localtime(&
tt);
189 fDatetime = (tm.tm_year + 1900 - 1995) << 26 | (tm.tm_mon + 1) << 22 | tm.tm_mday << 17 | tm.tm_hour << 12 |
190 tm.tm_min << 6 | tm.tm_sec;
192 explicit RTFDatetime(RUInt32BE val) : fDatetime(val) {}
197 static constexpr unsigned kBigKeyVersion = 1000;
200 RUInt16BE fVersion{4};
201 RUInt32BE fObjLen{0};
202 RTFDatetime fDatetime;
203 RUInt16BE fKeyLen{0};
207 RUInt32BE fSeekKey{0};
208 RUInt32BE fSeekPdir{0};
211 RUInt64BE fSeekKey{0};
212 RUInt64BE fSeekPdir{0};
216 RTFKey() : fInfoLong() {}
217 RTFKey(std::uint64_t seekKey, std::uint64_t seekPdir,
const RTFString &clName,
const RTFString &objName,
218 const RTFString &titleName, std::size_t szObjInMem, std::size_t szObjOnDisk = 0)
220 R__ASSERT(szObjInMem <= std::numeric_limits<std::uint32_t>::max());
221 R__ASSERT(szObjOnDisk <= std::numeric_limits<std::uint32_t>::max());
223 fVersion = fVersion + kBigKeyVersion;
224 fObjLen = szObjInMem;
225 fKeyLen =
static_cast<RUInt16BE
>(GetHeaderSize() + clName.GetSize() + objName.GetSize() + titleName.GetSize());
226 fInfoLong.fSeekKey = seekKey;
227 fInfoLong.fSeekPdir = seekPdir;
229 fNbytes = fKeyLen + ((szObjOnDisk == 0) ? szObjInMem : szObjOnDisk);
232 std::uint32_t GetSize()
const
240 std::uint32_t GetHeaderSize()
const
242 if (fVersion >= kBigKeyVersion)
243 return 18 +
sizeof(fInfoLong);
244 return 18 +
sizeof(fInfoShort);
247 std::uint64_t GetSeekKey()
const
249 if (fVersion >= kBigKeyVersion)
250 return fInfoLong.fSeekKey;
251 return fInfoShort.fSeekKey;
257 static constexpr unsigned kBEGIN = 100;
258 static constexpr unsigned kBigHeaderVersion = 1000000;
260 char fMagic[4]{
'r',
'o',
'o',
't'};
267 RUInt32BE fSeekFree{0};
268 RUInt32BE fNbytesFree{0};
270 RUInt32BE fNbytesName{0};
271 unsigned char fUnits{4};
272 RUInt32BE fCompress{0};
273 RUInt32BE fSeekInfo{0};
274 RUInt32BE fNbytesInfo{0};
278 RUInt64BE fSeekFree{0};
279 RUInt32BE fNbytesFree{0};
281 RUInt32BE fNbytesName{0};
282 unsigned char fUnits{8};
283 RUInt32BE fCompress{0};
284 RUInt64BE fSeekInfo{0};
285 RUInt32BE fNbytesInfo{0};
289 RTFHeader() : fInfoShort() {}
290 RTFHeader(
int compression) : fInfoShort() { fInfoShort.fCompress = compression; }
294 if (fVersion >= kBigHeaderVersion)
298 std::uint32_t end = fInfoShort.fEND;
299 std::uint32_t seekFree = fInfoShort.fSeekFree;
300 std::uint32_t nbytesFree = fInfoShort.fNbytesFree;
301 std::uint32_t nFree = fInfoShort.fNfree;
302 std::uint32_t nbytesName = fInfoShort.fNbytesName;
303 std::uint32_t compress = fInfoShort.fCompress;
304 std::uint32_t seekInfo = fInfoShort.fSeekInfo;
305 std::uint32_t nbytesInfo = fInfoShort.fNbytesInfo;
306 fInfoLong.fEND = end;
307 fInfoLong.fSeekFree = seekFree;
308 fInfoLong.fNbytesFree = nbytesFree;
309 fInfoLong.fNfree = nFree;
310 fInfoLong.fNbytesName = nbytesName;
311 fInfoLong.fUnits = 8;
312 fInfoLong.fCompress = compress;
313 fInfoLong.fSeekInfo = seekInfo;
314 fInfoLong.fNbytesInfo = nbytesInfo;
315 fVersion = fVersion + kBigHeaderVersion;
319 bool IsBigFile(std::uint64_t
offset = 0)
const
321 return (fVersion >= kBigHeaderVersion) ||
322 (
offset >
static_cast<unsigned int>(std::numeric_limits<std::int32_t>::max()));
325 std::uint32_t GetSize()
const
327 std::uint32_t sizeHead =
sizeof(fMagic) +
sizeof(fVersion) +
sizeof(fBEGIN);
329 return sizeHead +
sizeof(fInfoLong);
330 return sizeHead +
sizeof(fInfoShort);
333 std::uint64_t GetEnd()
const
336 return fInfoLong.fEND;
337 return fInfoShort.fEND;
340 void SetEnd(std::uint64_t
value)
342 if (IsBigFile(
value)) {
344 fInfoLong.fEND =
value;
346 fInfoShort.fEND =
value;
350 std::uint64_t GetSeekFree()
const
353 return fInfoLong.fSeekFree;
354 return fInfoShort.fSeekFree;
357 void SetSeekFree(std::uint64_t
value)
359 if (IsBigFile(
value)) {
361 fInfoLong.fSeekFree =
value;
363 fInfoShort.fSeekFree =
value;
367 void SetNbytesFree(std::uint32_t
value)
370 fInfoLong.fNbytesFree =
value;
372 fInfoShort.fNbytesFree =
value;
376 void SetNbytesName(std::uint32_t
value)
379 fInfoLong.fNbytesName =
value;
381 fInfoShort.fNbytesName =
value;
385 std::uint64_t GetSeekInfo()
const
388 return fInfoLong.fSeekInfo;
389 return fInfoShort.fSeekInfo;
392 void SetSeekInfo(std::uint64_t
value)
394 if (IsBigFile(
value)) {
396 fInfoLong.fSeekInfo =
value;
398 fInfoShort.fSeekInfo =
value;
402 std::uint64_t GetNbytesInfo()
const
405 return fInfoLong.fNbytesInfo;
406 return fInfoShort.fNbytesInfo;
409 void SetNbytesInfo(std::uint32_t
value)
412 fInfoLong.fNbytesInfo =
value;
414 fInfoShort.fNbytesInfo =
value;
418 void SetCompression(std::uint32_t
value)
421 fInfoLong.fCompress =
value;
423 fInfoShort.fCompress =
value;
430 static constexpr unsigned kBigFreeEntryVersion = 1000;
432 RUInt16BE fVersion{1};
444 RTFFreeEntry() : fInfoShort() {}
445 void Set(std::uint64_t first, std::uint64_t last)
447 if (last >
static_cast<unsigned int>(std::numeric_limits<std::int32_t>::max())) {
448 fVersion = fVersion + kBigFreeEntryVersion;
449 fInfoLong.fFirst = first;
450 fInfoLong.fLast = last;
452 fInfoShort.fFirst = first;
453 fInfoShort.fLast = last;
456 std::uint32_t GetSize() {
return (fVersion >= kBigFreeEntryVersion) ? 18 : 10; }
462 std::uint32_t GetSize()
const {
return sizeof(RTFKeyList); }
463 explicit RTFKeyList(std::uint32_t nKeys) : fNKeys(nKeys) {}
468 static constexpr unsigned kBigFileVersion = 1000;
470 RUInt16BE fClassVersion{5};
473 RUInt32BE fNBytesKeys{0};
474 RUInt32BE fNBytesName{0};
478 RUInt32BE fSeekDir{RTFHeader::kBEGIN};
479 RUInt32BE fSeekParent{0};
480 RUInt32BE fSeekKeys{0};
483 RUInt64BE fSeekDir{RTFHeader::kBEGIN};
484 RUInt64BE fSeekParent{0};
485 RUInt64BE fSeekKeys{0};
489 RTFDirectory() : fInfoShort() {}
492 std::uint32_t GetSize()
const
494 if (fClassVersion >= kBigFileVersion)
495 return sizeof(RTFDirectory);
496 return 18 +
sizeof(fInfoShort);
499 std::uint64_t GetSeekKeys()
const
501 if (fClassVersion >= kBigFileVersion)
502 return fInfoLong.fSeekKeys;
503 return fInfoShort.fSeekKeys;
506 void SetSeekKeys(std::uint64_t seekKeys)
508 if (seekKeys >
static_cast<unsigned int>(std::numeric_limits<std::int32_t>::max())) {
509 std::uint32_t seekDir = fInfoShort.fSeekDir;
510 std::uint32_t seekParent = fInfoShort.fSeekParent;
511 fInfoLong.fSeekDir = seekDir;
512 fInfoLong.fSeekParent = seekParent;
513 fInfoLong.fSeekKeys = seekKeys;
514 fClassVersion = fClassVersion + kBigFileVersion;
516 fInfoShort.fSeekKeys = seekKeys;
523 RUInt16BE fVersionClass{1};
524 unsigned char fUUID[16];
529 char *buffer =
reinterpret_cast<char *
>(
this);
531 assert(
reinterpret_cast<RTFUUID *
>(buffer) <= (
this + 1));
533 std::uint32_t GetSize()
const {
return sizeof(RTFUUID); }
542 RUInt32BE fByteCount{0x40000000 | (
sizeof(RTFNTuple) -
sizeof(fByteCount))};
543 RUInt16BE fVersionClass{2};
544 RUInt16BE fVersionEpoch{0};
545 RUInt16BE fVersionMajor{0};
546 RUInt16BE fVersionMinor{0};
547 RUInt16BE fVersionPatch{0};
548 RUInt64BE fSeekHeader{0};
549 RUInt64BE fNBytesHeader{0};
550 RUInt64BE fLenHeader{0};
551 RUInt64BE fSeekFooter{0};
552 RUInt64BE fNBytesFooter{0};
553 RUInt64BE fLenFooter{0};
554 RUInt64BE fMaxKeySize{0};
556 static constexpr std::uint32_t GetSizePlusChecksum() {
return sizeof(RTFNTuple) +
sizeof(std::uint64_t); }
558 RTFNTuple() =
default;
573 std::uint32_t GetSize()
const {
return sizeof(RTFNTuple); }
575 std::uint32_t GetOffsetCkData() {
return sizeof(fByteCount) +
sizeof(fVersionClass); }
576 std::uint32_t GetSizeCkData() {
return GetSize() - GetOffsetCkData(); }
577 unsigned char *GetPtrCkData() {
return reinterpret_cast<unsigned char *
>(
this) + GetOffsetCkData(); }
581struct RBareFileHeader {
582 char fMagic[7]{
'r',
'n',
't',
'u',
'p',
'l',
'e'};
585 RUInt32BE fFormatVersion{1};
586 RUInt32BE fCompress{0};
593constexpr char const *kBlobClassName =
"RBlob";
595constexpr char const *kNTupleClassName =
"ROOT::RNTuple";
626 void Reserve(
size_t nbytes, std::uint64_t *seekKey)
645 constexpr size_t kChunkOffsetSize =
sizeof(std::uint64_t);
647 assert(nbytes > maxChunkSize);
648 size_t nChunks = (nbytes + maxChunkSize - 1) / maxChunkSize;
650 size_t nbytesTail = nbytes % maxChunkSize;
651 size_t nbytesExtra = (nbytesTail > 0) * (maxChunkSize - nbytesTail);
652 size_t nbytesChunkOffsets = (nChunks - 1) * kChunkOffsetSize;
653 if (nbytesChunkOffsets > nbytesExtra) {
655 nbytesChunkOffsets += kChunkOffsetSize;
662 R__ASSERT(nbytesChunkOffsets <= maxChunkSize);
673 if (std::string(ident, 4) ==
"root")
674 return GetNTupleProper(ntupleName);
676 return GetNTupleBare(ntupleName);
682 std::string_view typeName)
684 RTFDirectory directory;
685 ReadBuffer(&directory,
sizeof(directory), offsetDir);
689 std::uint64_t
offset = directory.GetSeekKeys();
695 for (
unsigned int i = 0; i < nKeys; ++i) {
697 auto offsetNextKey =
offset + key.fKeyLen;
699 offset += key.GetHeaderSize();
703 if (std::string_view(
name.fData,
name.fLName) != typeName) {
710 if (std::string_view(
name.fData,
name.fLName) == keyName) {
711 return key.GetSeekKey();
728 R__ASSERT(fNbytesKeyAndInfo >= key.fKeyLen);
729 const std::uint64_t nbytesInfo = fNbytesKeyAndInfo - key.fKeyLen;
730 const std::uint64_t seekInfo = fSeekKeyInfo + key.fKeyLen;
731 const std::uint32_t uncompLenInfo = key.fObjLen;
732 auto streamerInfo = MakeUninitArray<char>(uncompLenInfo);
733 if (nbytesInfo == uncompLenInfo) {
735 ReadBuffer(streamerInfo.get(), nbytesInfo, seekInfo);
737 auto buffer = MakeUninitArray<std::byte>(nbytesInfo);
738 ReadBuffer(buffer.get(), nbytesInfo, seekInfo);
748 TList streamerInfoList;
765 RTFHeader fileHeader;
766 ReadBuffer(&fileHeader,
sizeof(fileHeader), 0);
768 fSeekKeyInfo = fileHeader.GetSeekInfo();
769 fNbytesKeyAndInfo = fileHeader.GetNbytesInfo();
773 ReadBuffer(&key,
sizeof(key), fileHeader.fBEGIN);
775 std::uint64_t
offset = fileHeader.fBEGIN + key.fKeyLen;
783 std::string ntuplePathTail(ntuplePath);
784 if (!ntuplePathTail.empty() && ntuplePathTail[0] ==
'/')
785 ntuplePathTail = ntuplePathTail.substr(1);
786 auto pos = std::string::npos;
787 while ((pos = ntuplePathTail.find(
'/')) != std::string::npos) {
788 auto directoryName = ntuplePathTail.substr(0, pos);
789 ntuplePathTail.erase(0, pos + 1);
791 offset = SearchInDirectory(
offset, directoryName,
"TDirectory");
793 return R__FAIL(
"no directory named '" + std::string(directoryName) +
"' in file '" + fRawFile->GetUrl() +
"'");
796 offset = key.GetSeekKey() + key.fKeyLen;
799 auto ntupleName = ntuplePathTail;
801 offset = SearchInDirectory(
offset, ntupleName, kNTupleClassName);
803 return R__FAIL(
"no RNTuple named '" + std::string(ntupleName) +
"' in file '" + fRawFile->GetUrl() +
"'");
807 offset = key.GetSeekKey() + key.fKeyLen;
810 constexpr size_t kMinNTupleSize = 78;
811 static_assert(kMinNTupleSize == RTFNTuple::GetSizePlusChecksum());
812 if (key.fObjLen < kMinNTupleSize) {
813 return R__FAIL(
"invalid anchor size: " + std::to_string(key.fObjLen) +
" < " + std::to_string(
sizeof(RTFNTuple)));
816 const auto objNbytes = key.GetSize() - key.fKeyLen;
817 auto res = GetNTupleProperAtOffset(
offset, objNbytes, key.fObjLen);
823 std::uint64_t compSize,
824 std::uint64_t uncompLen)
828 auto bufAnchor = MakeUninitArray<unsigned char>(std::max<size_t>(uncompLen,
sizeof(RTFNTuple)));
829 RTFNTuple *ntuple =
new (bufAnchor.get()) RTFNTuple;
831 if (compSize != uncompLen) {
833 auto unzipBuf = MakeUninitArray<unsigned char>(std::max<size_t>(uncompLen,
sizeof(RTFNTuple)));
834 ReadBuffer(unzipBuf.get(), compSize, payloadOffset);
843 const auto lenCkData = uncompLen - ntuple->GetOffsetCkData() -
sizeof(uint64_t);
844 const auto ckCalc = XXH3_64bits(ntuple->GetPtrCkData(), lenCkData);
847 RUInt64BE *ckOnDiskPtr =
reinterpret_cast<RUInt64BE *
>(bufAnchor.get() + uncompLen -
sizeof(uint64_t));
848 ckOnDisk =
static_cast<uint64_t
>(*ckOnDiskPtr);
849 if (ckCalc != ckOnDisk) {
850 return R__FAIL(
"RNTuple anchor checksum mismatch");
853 return CreateAnchor(ntuple->fVersionEpoch, ntuple->fVersionMajor, ntuple->fVersionMinor, ntuple->fVersionPatch,
854 ntuple->fSeekHeader, ntuple->fNBytesHeader, ntuple->fLenHeader, ntuple->fSeekFooter,
855 ntuple->fNBytesFooter, ntuple->fLenFooter, ntuple->fMaxKeySize);
860 RBareFileHeader fileHeader;
861 ReadBuffer(&fileHeader,
sizeof(fileHeader), 0);
863 auto offset =
sizeof(fileHeader);
866 std::string_view foundName(
name.fData,
name.fLName);
867 if (foundName != ntupleName) {
868 return R__FAIL(
"expected RNTuple named '" + std::string(ntupleName) +
"' but instead found '" +
869 std::string(foundName) +
"' in file '" + fRawFile->GetUrl() +
"'");
875 std::uint64_t onDiskChecksum;
876 ReadBuffer(&onDiskChecksum,
sizeof(onDiskChecksum),
offset +
sizeof(ntuple));
877 auto checksum = XXH3_64bits(ntuple.GetPtrCkData(), ntuple.GetSizeCkData());
878 if (checksum !=
static_cast<uint64_t
>(onDiskChecksum))
879 return R__FAIL(
"RNTuple bare file: anchor checksum mismatch");
881 return CreateAnchor(ntuple.fVersionEpoch, ntuple.fVersionMajor, ntuple.fVersionMinor, ntuple.fVersionPatch,
882 ntuple.fSeekHeader, ntuple.fNBytesHeader, ntuple.fLenHeader, ntuple.fSeekFooter,
883 ntuple.fNBytesFooter, ntuple.fLenFooter, ntuple.fMaxKeySize);
888 TryReadBuffer(buffer, nbytes,
offset).ThrowOnError();
893 const auto ByteReadErr = [](std::size_t expected, std::size_t nread) {
894 return R__FAIL(
"invalid read (expected bytes: " + std::to_string(expected) +
", read: " + std::to_string(nread) +
899 if (fMaxKeySize == 0 || nbytes <= fMaxKeySize) {
901 nread = fRawFile->ReadAt(buffer, nbytes,
offset);
905 const size_t nbytesChunkOffsets = (nChunks - 1) *
sizeof(std::uint64_t);
906 const size_t nbytesFirstChunk = fMaxKeySize - nbytesChunkOffsets;
907 uint8_t *bufCur =
reinterpret_cast<uint8_t *
>(buffer);
910 nread = fRawFile->ReadAt(bufCur, fMaxKeySize,
offset);
911 if (nread != fMaxKeySize)
912 return ByteReadErr(fMaxKeySize, nread);
917 bufCur += nbytesFirstChunk;
918 nread -= nbytesChunkOffsets;
920 const auto chunkOffsets = MakeUninitArray<std::uint64_t>(nChunks - 1);
921 memcpy(chunkOffsets.get(), bufCur, nbytesChunkOffsets);
923 size_t remainingBytes = nbytes - nbytesFirstChunk;
924 std::uint64_t *curChunkOffset = &chunkOffsets[0];
927 std::uint64_t chunkOffset;
931 const size_t bytesToRead = std::min<size_t>(fMaxKeySize, remainingBytes);
933 R__ASSERT(
static_cast<size_t>(bufCur -
reinterpret_cast<uint8_t *
>(buffer)) <= nbytes - bytesToRead);
935 auto nbytesRead = fRawFile->ReadAt(bufCur, bytesToRead, chunkOffset);
936 if (nbytesRead != bytesToRead)
937 return ByteReadErr(bytesToRead, nbytesRead);
939 nread += bytesToRead;
940 bufCur += bytesToRead;
941 remainingBytes -= bytesToRead;
942 }
while (remainingBytes > 0);
946 return ByteReadErr(nbytes, nread);
956 unsigned char buffer[kBlobKeyLen])
958 RTFString strClass{kBlobClassName};
961 RTFKey keyHeader(
offset, RTFHeader::kBEGIN, strClass, strObject, strTitle,
len, nbytes);
962 R__ASSERT(keyHeader.fKeyLen == kBlobKeyLen);
965 unsigned char *writeBuffer = buffer;
966 memcpy(writeBuffer, &keyHeader, keyHeader.GetHeaderSize());
967 writeBuffer += keyHeader.GetHeaderSize();
968 memcpy(writeBuffer, &strClass, strClass.GetSize());
969 writeBuffer += strClass.GetSize();
970 memcpy(writeBuffer, &strObject, strObject.GetSize());
971 writeBuffer += strObject.GetSize();
972 memcpy(writeBuffer, &strTitle, strTitle.GetSize());
973 writeBuffer += strTitle.GetSize();
974 R__ASSERT(writeBuffer == buffer + kBlobKeyLen);
983 static_assert(kHeaderBlockSize % kBlockAlign == 0,
"invalid header block size");
984 if (bufferSize % kBlockAlign != 0)
985 throw RException(
R__FAIL(
"Buffer size not a multiple of alignment: " + std::to_string(bufferSize)));
989 fShared = std::make_shared<RSharedData>(
nullptr);
991 fShared->fBlockSize = bufferSize;
992 fShared->fControlBlock = std::make_unique<ROOT::Internal::RTFileControlBlock>();
994 std::align_val_t blockAlign{kBlockAlign};
995 fShared->fHeaderBlock =
static_cast<unsigned char *
>(::operator
new[](kHeaderBlockSize, blockAlign));
996 memset(fShared->fHeaderBlock, 0, kHeaderBlockSize);
997 fShared->fBlock =
static_cast<unsigned char *
>(::operator
new[](fShared->fBlockSize, blockAlign));
998 memset(fShared->fBlock, 0, fShared->fBlockSize);
1010 ::operator
delete[](fHeaderBlock, blockAlign);
1012 ::operator
delete[](fBlock, blockAlign);
1016int FSeek64(FILE *stream, std::int64_t
offset,
int origin)
1019 return fseeko64(stream,
offset, origin);
1021 return fseek(stream,
offset, origin);
1032 if (shared.fBlockOffset == 0) {
1034 if (headerBlockSize > shared.fFilePos) {
1035 headerBlockSize = shared.fFilePos;
1037 memcpy(shared.fBlock, shared.fHeaderBlock, headerBlockSize);
1040 std::size_t retval = FSeek64(shared.fFile, shared.fBlockOffset, SEEK_SET);
1044 std::size_t lastBlockSize = shared.fFilePos - shared.fBlockOffset;
1045 R__ASSERT(lastBlockSize <= shared.fBlockSize);
1046 if (shared.fDirectIO) {
1050 R__ASSERT(lastBlockSize <= shared.fBlockSize);
1052 retval = fwrite(shared.fBlock, 1, lastBlockSize, shared.fFile);
1053 if (retval != lastBlockSize)
1057 if (shared.fBlockOffset > 0) {
1058 retval = FSeek64(shared.fFile, 0, SEEK_SET);
1067 retval = fflush(shared.fFile);
1078 if ((
offset >= 0) && (
static_cast<std::uint64_t
>(
offset) != shared.fFilePos)) {
1079 shared.fFilePos =
offset;
1084 std::size_t headerBytes = nbytes;
1088 memcpy(shared.fHeaderBlock + shared.fFilePos, buffer, headerBytes);
1091 R__ASSERT(shared.fFilePos >= shared.fBlockOffset);
1093 while (nbytes > 0) {
1094 std::uint64_t posInBlock = shared.fFilePos % shared.fBlockSize;
1095 std::uint64_t blockOffset = shared.fFilePos - posInBlock;
1096 if (blockOffset != shared.fBlockOffset) {
1098 retval = FSeek64(shared.fFile, shared.fBlockOffset, SEEK_SET);
1102 retval = fwrite(shared.fBlock, 1, shared.fBlockSize, shared.fFile);
1103 if (retval != shared.fBlockSize)
1107 memset(shared.fBlock, 0, shared.fBlockSize);
1110 shared.fBlockOffset = blockOffset;
1111 std::size_t blockSize = nbytes;
1112 if (blockSize > shared.fBlockSize - posInBlock) {
1113 blockSize = shared.fBlockSize - posInBlock;
1115 memcpy(shared.fBlock + posInBlock, buffer, blockSize);
1116 buffer =
static_cast<const unsigned char *
>(buffer) + blockSize;
1117 nbytes -= blockSize;
1118 shared.fFilePos += blockSize;
1124 std::int64_t
offset, std::uint64_t directoryOffset,
1125 const std::string &className,
const std::string &objectName,
1126 const std::string &title)
1131 shared.fKeyOffset =
offset;
1132 RTFString strClass{className};
1133 RTFString strObject{objectName};
1134 RTFString strTitle{title};
1136 RTFKey key(shared.fKeyOffset, directoryOffset, strClass, strObject, strTitle,
len, nbytes);
1137 Write(&key, key.GetHeaderSize(), shared.fKeyOffset);
1138 Write(&strClass, strClass.GetSize());
1139 Write(&strObject, strObject.GetSize());
1140 Write(&strTitle, strTitle.GetSize());
1141 auto offsetData = shared.fFilePos;
1143 shared.fKeyOffset = offsetData + nbytes;
1145 Write(buffer, nbytes);
1163 auto offsetData = shared.fKeyOffset +
kBlobKeyLen;
1165 shared.fKeyOffset = offsetData + nbytes;
1172template <
typename T>
1176 std::uint64_t offsetKey;
1180 keyBlob.
Reserve(nbytes, &offsetKey);
1187 caller.Write(localKeyBuffer,
kBlobKeyLen, offsetKey);
1204 fDirectory->GetFile()->Seek(
offset);
1205 bool rv = fDirectory->GetFile()->WriteBuffer((
char *)(buffer), nbytes);
1223 bool rv = file->WriteBuffer((
char *)(buffer), nbytes);
1249std::unique_ptr<ROOT::Internal::RNTupleFileWriter>
1253 std::string fileName(path);
1254 size_t idxDirSep = fileName.find_last_of(
"\\/");
1255 if (idxDirSep != std::string::npos) {
1256 fileName.erase(0, idxDirSep + 1);
1259 int flags = O_WRONLY | O_CREAT | O_TRUNC;
1262 flags |= O_LARGEFILE;
1267 int fd = open(std::string(path).c_str(), flags, 0666);
1269 throw RException(
R__FAIL(std::string(
"open failed for file \"") + std::string(path) +
"\": " + strerror(errno)));
1271 FILE *fileStream = fdopen(fd,
"wb");
1274 FILE *fileStream = fopen64(std::string(path.data(), path.size()).c_str(),
"wb");
1276 FILE *fileStream = fopen(std::string(path.data(), path.size()).c_str(),
"wb");
1280 throw RException(
R__FAIL(std::string(
"open failed for file \"") + std::string(path) +
"\": " + strerror(errno)));
1283 std::setvbuf(fileStream,
nullptr, _IONBF, 0);
1285 auto writer = std::unique_ptr<RNTupleFileWriter>(
1289 fileSimple.
fShared->fFile = fileStream;
1291 writer->fFileName = fileName;
1294 switch (containerFormat) {
1295 case EContainerFormat::kTFile:
writer->WriteTFileSkeleton(defaultCompression);
break;
1296 case EContainerFormat::kBare:
1298 writer->WriteBareFileSkeleton(defaultCompression);
1300 default:
R__ASSERT(
false &&
"Internal error: unhandled container format");
1306std::unique_ptr<ROOT::Internal::RNTupleFileWriter>
1308 std::uint64_t maxKeySize,
bool hidden)
1312 throw RException(
R__FAIL(
"invalid attempt to add an RNTuple to a directory that is not backed by a file"));
1321std::unique_ptr<ROOT::Internal::RNTupleFileWriter>
1323 std::string_view ntupleDir, std::uint64_t maxKeySize)
1327 rfile.
fFile = &file;
1328 R__ASSERT(ntupleDir.empty() || ntupleDir[ntupleDir.size() - 1] ==
'/');
1329 rfile.fDir = ntupleDir;
1333std::unique_ptr<ROOT::Internal::RNTupleFileWriter>
1336 if (
auto *tfile = std::get_if<RImplTFile>(&fFile)) {
1337 return Append(ntupleName, *tfile->fDirectory, fNTupleAnchor.fMaxKeySize,
true);
1338 }
else if (
auto *file = std::get_if<RImplSimple>(&fFile)) {
1342 auto writer = std::unique_ptr<RNTupleFileWriter>(
1344 auto &clonedFile = std::get<RImplSimple>(
writer->fFile);
1345 clonedFile.fShared = file->fShared;
1354 RImplSimple *fileSimple = std::get_if<RImplSimple>(&fFile);
1365 fStreamerInfoMap.insert(streamerInfos.cbegin(), streamerInfos.cend());
1370 const auto WriteStreamerInfoToFile = [&](
TFile *file) {
1374 for (
auto [
_, info] : fStreamerInfoMap)
1380 anchorInfo.
fLength = RTFNTuple{}.GetSize() +
sizeof(std::uint64_t);
1383 if (
auto fileProper = std::get_if<RImplTFile>(&fFile)) {
1385 fileProper->fDirectory->WriteObject(&fNTupleAnchor, fNTupleName.c_str());
1386 WriteStreamerInfoToFile(fileProper->fDirectory->GetFile());
1387 auto key =
static_cast<TKey *
>(fileProper->fDirectory->GetListOfKeys()->FindObject(fNTupleName.c_str()));
1393 fileProper->fDirectory->GetFile()->Write();
1398 fileProper->fDirectory->GetListOfKeys()->Remove(key);
1400 }
else if (
auto fileRFile = std::get_if<RImplRFile>(&fFile)) {
1402 fileRFile->fFile->Put(fileRFile->fDir + fNTupleName, fNTupleAnchor);
1404 auto key = fileRFile->fFile->GetKeyInfo(fNTupleName);
1408 fileRFile->fFile->Flush();
1411 auto &fileSimple = std::get<RImplSimple>(fFile);
1412 auto &shared = *fileSimple.fShared;
1415 RTFNTuple ntupleOnDisk(fNTupleAnchor);
1418 std::uint64_t checksum = XXH3_64bits(ntupleOnDisk.GetPtrCkData(), ntupleOnDisk.GetSizeCkData());
1419 memcpy(shared.fHeaderBlock + shared.fControlBlock->fSeekNTuple, &ntupleOnDisk, ntupleOnDisk.GetSize());
1420 memcpy(shared.fHeaderBlock + shared.fControlBlock->fSeekNTuple + ntupleOnDisk.GetSize(), &checksum,
1427 anchorInfo = WriteTFileNTupleKey(compression);
1430 WriteTFileStreamerInfo(compression);
1431 WriteTFileFreeList();
1434 memcpy(shared.fHeaderBlock, &shared.fControlBlock->fHeader, shared.fControlBlock->fHeader.GetSize());
1435 R__ASSERT(shared.fControlBlock->fSeekFileRecord + shared.fControlBlock->fFileRecord.GetSize() <
1436 RImplSimple::kHeaderBlockSize);
1437 memcpy(shared.fHeaderBlock + shared.fControlBlock->fSeekFileRecord, &shared.fControlBlock->fFileRecord,
1438 shared.fControlBlock->fFileRecord.GetSize());
1450 auto writeKey = [
this](
const void *payload,
size_t nBytes,
size_t length) {
1452 WriteIntoReservedBlob(payload, nBytes,
offset);
1456 const std::uint64_t maxKeySize = fNTupleAnchor.fMaxKeySize;
1460 if (
static_cast<std::uint64_t
>(
len) >
static_cast<std::uint64_t
>(std::numeric_limits<std::uint32_t>::max()))
1463 if (nbytes <= maxKeySize) {
1465 return writeKey(
data, nbytes,
len);
1482 const size_t nbytesChunkOffsets = (nChunks - 1) *
sizeof(std::uint64_t);
1483 const size_t nbytesFirstChunk = maxKeySize - nbytesChunkOffsets;
1486 const uint8_t *chunkData =
reinterpret_cast<const uint8_t *
>(
data) + nbytesFirstChunk;
1487 size_t remainingBytes = nbytes - nbytesFirstChunk;
1489 const auto chunkOffsetsToWrite = MakeUninitArray<std::uint64_t>(nChunks - 1);
1490 std::uint64_t chunkOffsetIdx = 0;
1493 const size_t bytesNextChunk = std::min<size_t>(remainingBytes, maxKeySize);
1494 const std::uint64_t
offset = writeKey(chunkData, bytesNextChunk, bytesNextChunk);
1499 remainingBytes -= bytesNextChunk;
1500 chunkData += bytesNextChunk;
1502 }
while (remainingBytes > 0);
1505 const std::uint64_t firstOffset = ReserveBlob(maxKeySize, maxKeySize);
1506 WriteIntoReservedBlob(
data, nbytesFirstChunk, firstOffset);
1507 const std::uint64_t chunkOffsetsOffset = firstOffset + nbytesFirstChunk;
1508 WriteIntoReservedBlob(chunkOffsetsToWrite.get(), nbytesChunkOffsets, chunkOffsetsOffset);
1517 R__ASSERT(nbytes <= fNTupleAnchor.GetMaxKeySize());
1520 if (
auto *fileSimple = std::get_if<RImplSimple>(&fFile)) {
1522 offset = fileSimple->fShared->fKeyOffset;
1523 fileSimple->fShared->fKeyOffset += nbytes;
1525 offset = fileSimple->ReserveBlobKey(nbytes,
len, keyBuffer);
1527 }
else if (
auto *fileProper = std::get_if<RImplTFile>(&fFile)) {
1528 offset = fileProper->ReserveBlobKey(nbytes,
len, keyBuffer);
1530 auto &fileRFile = std::get<RImplRFile>(fFile);
1531 offset = fileRFile.ReserveBlobKey(nbytes,
len, keyBuffer);
1538 if (
auto *fileSimple = std::get_if<RImplSimple>(&fFile)) {
1539 fileSimple->Write(buffer, nbytes,
offset);
1540 }
else if (
auto *fileProper = std::get_if<RImplTFile>(&fFile)) {
1541 fileProper->Write(buffer, nbytes,
offset);
1543 auto &fileRFile = std::get<RImplRFile>(fFile);
1544 fileRFile.Write(buffer, nbytes,
offset);
1550 auto offset = WriteBlob(
data, nbytes, lenHeader);
1551 fNTupleAnchor.fLenHeader = lenHeader;
1552 fNTupleAnchor.fNBytesHeader = nbytes;
1553 fNTupleAnchor.fSeekHeader =
offset;
1559 auto offset = WriteBlob(
data, nbytes, lenFooter);
1560 fNTupleAnchor.fLenFooter = lenFooter;
1561 fNTupleAnchor.fNBytesFooter = nbytes;
1562 fNTupleAnchor.fSeekFooter =
offset;
1568 RBareFileHeader bareHeader;
1569 bareHeader.fCompress = defaultCompression;
1570 auto &fileSimple = std::get<RImplSimple>(fFile);
1571 fileSimple.Write(&bareHeader,
sizeof(bareHeader), 0);
1572 RTFString ntupleName{fNTupleName};
1573 fileSimple.Write(&ntupleName, ntupleName.GetSize());
1576 RTFNTuple ntupleOnDisk;
1577 fileSimple.fShared->fControlBlock->fSeekNTuple = fileSimple.fShared->fFilePos;
1578 fileSimple.Write(&ntupleOnDisk, ntupleOnDisk.GetSize());
1579 std::uint64_t checksum = 0;
1580 fileSimple.Write(&checksum,
sizeof(checksum));
1581 fileSimple.fShared->fKeyOffset = fileSimple.fShared->fFilePos;
1591 TList streamerInfoList;
1592 for (
auto [
_, info] : fStreamerInfoMap) {
1593 streamerInfoList.
Add(info);
1602 RTFString strTList{
"TList"};
1603 RTFString strStreamerInfo{
"StreamerInfo"};
1604 RTFString strStreamerTitle{
"Doubly linked list"};
1605 auto &fileSimple = std::get<RImplSimple>(fFile);
1606 fileSimple.fShared->fControlBlock->fHeader.SetSeekInfo(fileSimple.fShared->fKeyOffset);
1607 auto keyLen = RTFKey(fileSimple.fShared->fControlBlock->fHeader.GetSeekInfo(), RTFHeader::kBEGIN, strTList,
1608 strStreamerInfo, strStreamerTitle, 0)
1614 assert(buffer.
Length() > keyLen);
1615 const auto bufPayload = buffer.
Buffer() + keyLen;
1616 const auto lenPayload = buffer.
Length() - keyLen;
1618 auto zipStreamerInfos = MakeUninitArray<unsigned char>(lenPayload);
1619 auto szZipStreamerInfos =
RNTupleCompressor::Zip(bufPayload, lenPayload, compression, zipStreamerInfos.get());
1621 fileSimple.WriteKey(zipStreamerInfos.get(), szZipStreamerInfos, lenPayload,
1622 fileSimple.fShared->fControlBlock->fHeader.GetSeekInfo(), RTFHeader::kBEGIN,
"TList",
1623 "StreamerInfo",
"Doubly linked list");
1624 fileSimple.fShared->fControlBlock->fHeader.SetNbytesInfo(fileSimple.fShared->fFilePos -
1625 fileSimple.fShared->fControlBlock->fHeader.GetSeekInfo());
1631 RTFString strRNTupleClass{
"ROOT::RNTuple"};
1632 RTFString strRNTupleName{fNTupleName};
1633 RTFString strFileName{fFileName};
1635 auto &fileSimple = std::get<RImplSimple>(fFile);
1636 RTFKey keyRNTuple(fileSimple.fShared->fControlBlock->fSeekNTuple, RTFHeader::kBEGIN, strRNTupleClass, strRNTupleName,
1637 strEmpty, RTFNTuple::GetSizePlusChecksum(), anchorSize);
1639 auto &fileShared = *fileSimple.fShared;
1640 fileSimple.fShared->fControlBlock->fFileRecord.SetSeekKeys(fileShared.fKeyOffset);
1641 RTFKeyList keyList{1};
1642 RTFKey keyKeyList(fileSimple.fShared->fControlBlock->fFileRecord.GetSeekKeys(), RTFHeader::kBEGIN, strEmpty,
1643 strFileName, strEmpty, keyList.GetSize() + keyRNTuple.fKeyLen);
1644 fileSimple.Write(&keyKeyList, keyKeyList.GetHeaderSize(),
1645 fileSimple.fShared->fControlBlock->fFileRecord.GetSeekKeys());
1646 fileSimple.Write(&strEmpty, strEmpty.GetSize());
1647 fileSimple.Write(&strFileName, strFileName.GetSize());
1648 fileSimple.Write(&strEmpty, strEmpty.GetSize());
1649 fileSimple.Write(&keyList, keyList.GetSize());
1650 fileSimple.Write(&keyRNTuple, keyRNTuple.GetHeaderSize());
1652 fileSimple.Write(&strRNTupleClass, strRNTupleClass.GetSize());
1653 fileSimple.Write(&strRNTupleName, strRNTupleName.GetSize());
1654 fileSimple.Write(&strEmpty, strEmpty.GetSize());
1655 fileSimple.fShared->fControlBlock->fFileRecord.fNBytesKeys =
1656 fileShared.fFilePos - fileSimple.fShared->fControlBlock->fFileRecord.GetSeekKeys();
1657 fileShared.fKeyOffset = fileShared.fFilePos;
1662 auto &fileSimple = std::get<RImplSimple>(fFile);
1663 auto &fileShared = *fileSimple.fShared;
1664 fileSimple.fShared->fControlBlock->fHeader.SetSeekFree(fileShared.fKeyOffset);
1666 RTFString strFileName{fFileName};
1667 RTFFreeEntry freeEntry;
1668 RTFKey keyFreeList(fileSimple.fShared->fControlBlock->fHeader.GetSeekFree(), RTFHeader::kBEGIN, strEmpty,
1669 strFileName, strEmpty, freeEntry.GetSize());
1670 std::uint64_t firstFree = fileSimple.fShared->fControlBlock->fHeader.GetSeekFree() + keyFreeList.GetSize();
1671 freeEntry.Set(firstFree, std::max(2000000000ULL, ((firstFree / 1000000000ULL) + 1) * 1000000000ULL));
1672 fileSimple.WriteKey(&freeEntry, freeEntry.GetSize(), freeEntry.GetSize(),
1673 fileSimple.fShared->fControlBlock->fHeader.GetSeekFree(), RTFHeader::kBEGIN,
"", fFileName,
"");
1674 fileSimple.fShared->fControlBlock->fHeader.SetNbytesFree(fileShared.fFilePos -
1675 fileSimple.fShared->fControlBlock->fHeader.GetSeekFree());
1676 fileSimple.fShared->fControlBlock->fHeader.SetEnd(fileShared.fFilePos);
1681 RTFString strRNTupleClass{
"ROOT::RNTuple"};
1682 RTFString strRNTupleName{fNTupleName};
1685 RTFNTuple ntupleOnDisk(fNTupleAnchor);
1686 RUInt64BE checksum{XXH3_64bits(ntupleOnDisk.GetPtrCkData(), ntupleOnDisk.GetSizeCkData())};
1687 auto &fileSimple = std::get<RImplSimple>(fFile);
1688 fileSimple.fShared->fControlBlock->fSeekNTuple = fileSimple.fShared->fKeyOffset;
1690 char keyBuf[RTFNTuple::GetSizePlusChecksum()];
1693 memcpy(keyBuf, &ntupleOnDisk,
sizeof(RTFNTuple));
1694 memcpy(keyBuf +
sizeof(RTFNTuple), &checksum,
sizeof(checksum));
1696 const auto sizeAnchor =
sizeof(RTFNTuple) +
sizeof(checksum);
1697 char zipAnchor[RTFNTuple::GetSizePlusChecksum()];
1702 fileSimple.WriteKey(zipAnchor, szZipAnchor,
sizeof(keyBuf), fileSimple.fShared->fControlBlock->fSeekNTuple,
1703 RTFHeader::kBEGIN,
"ROOT::RNTuple", fNTupleName,
"");
1705 assert(szZipAnchor < std::numeric_limits<
decltype(anchorLink.
fLength)>::max());
1706 anchorLink.
fLength =
sizeof(keyBuf);
1714 RTFString strTFile{
"TFile"};
1715 RTFString strFileName{fFileName};
1718 auto &fileSimple = std::get<RImplSimple>(fFile);
1719 fileSimple.fShared->fControlBlock->fHeader = RTFHeader(defaultCompression);
1724 RTFKey keyRoot(RTFHeader::kBEGIN, 0, strTFile, strFileName, strEmpty,
1725 sizeof(RTFDirectory) + strFileName.GetSize() + strEmpty.GetSize() + uuid.GetSize());
1726 std::uint32_t nbytesName = keyRoot.fKeyLen + strFileName.GetSize() + 1;
1727 fileSimple.fShared->fControlBlock->fFileRecord.fNBytesName = nbytesName;
1728 fileSimple.fShared->fControlBlock->fHeader.SetNbytesName(nbytesName);
1730 fileSimple.Write(&keyRoot, keyRoot.GetHeaderSize(), RTFHeader::kBEGIN);
1732 fileSimple.Write(&strTFile, strTFile.GetSize());
1733 fileSimple.Write(&strFileName, strFileName.GetSize());
1734 fileSimple.Write(&strEmpty, strEmpty.GetSize());
1736 fileSimple.Write(&strFileName, strFileName.GetSize());
1737 fileSimple.Write(&strEmpty, strEmpty.GetSize());
1739 fileSimple.fShared->fControlBlock->fSeekFileRecord = fileSimple.fShared->fFilePos;
1740 fileSimple.Write(&fileSimple.fShared->fControlBlock->fFileRecord,
1741 fileSimple.fShared->fControlBlock->fFileRecord.GetSize());
1742 fileSimple.Write(&uuid, uuid.GetSize());
1745 RUInt32BE padding{0};
1746 for (
int i = 0; i < 3; ++i)
1747 fileSimple.Write(&padding,
sizeof(padding));
1748 fileSimple.fShared->fKeyOffset = fileSimple.fShared->fFilePos;
T ReadBuffer(TBufferFile *buf)
One of the template functions used to read objects from messages.
#define R__FAIL(msg)
Short-hand to return an RResult<T> in an error state; the RError is implicitly converted into RResult...
static size_t ComputeNumChunks(size_t nbytes, size_t maxChunkSize)
#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
An interface to read from, or write to, a ROOT file, as well as performing other common operations.
The RKeyBlob writes an invisible key into a TFile.
bool WasAllocatedInAFreeSlot() const
void Reserve(size_t nbytes, std::uint64_t *seekKey)
Register a new key for a data record of size nbytes.
void ReadBuffer(void *buffer, size_t nbytes, std::uint64_t offset)
Reads a given byte range from the file into the provided memory buffer.
RMiniFileReader()=default
void LoadStreamerInfo()
Load the streamer info from the file into the global list of streamer infos.
RResult< RNTuple > GetNTupleProperAtOffset(std::uint64_t payloadOffset, std::uint64_t compSize, std::uint64_t uncompLen)
Loads an RNTuple anchor from a TFile at the given file offset (unzipping it if necessary).
RResult< RNTuple > GetNTupleBare(std::string_view ntupleName)
Used when the file container turns out to be a bare file.
ROOT::RResult< void > TryReadBuffer(void *buffer, size_t nbytes, std::uint64_t offset)
Like ReadBuffer but returns a RResult instead of throwing.
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...
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.
static std::size_t Zip(const void *from, std::size_t nbytes, int compression, void *to)
Returns the size of the compressed data, written into the provided output buffer.
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.
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.
ROOT::Internal::RNTupleLink WriteTFileNTupleKey(int compression)
The only key that will be visible in file->ls() Returns the link to the RNTuple anchor.
void WriteTFileStreamerInfo(int compression)
Write the compressed streamer info record with the description of the RNTuple class.
std::string fNTupleName
The identifier of the RNTuple; A single writer object can only write a single RNTuple but multiple wr...
void WriteTFileKeysList(std::uint64_t anchorSize)
Write the TList with the RNTuple key.
void WriteBareFileSkeleton(int defaultCompression)
For a bare file, which is necessarily written by a C file stream, write file header.
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...
static std::uint64_t ReserveBlobKey(T &caller, TFile &file, std::size_t nbytes, std::size_t len, unsigned char keyBuffer[kBlobKeyLen])
static std::unique_ptr< RNTupleFileWriter > Append(std::string_view ntupleName, TDirectory &fileOrDirectory, std::uint64_t maxKeySize, bool isHidden)
The directory parameter can also be a TFile object (TFile inherits from TDirectory).
void WriteTFileFreeList()
Last record in the file.
std::unique_ptr< RNTupleFileWriter > CloneAsHidden(std::string_view ntupleName) const
Creates a new RNTupleFileWriter with the same underlying TDirectory as this but writing to a differen...
void WriteTFileSkeleton(int defaultCompression)
For a TFile container written by a C file stream, write the header and TFile object.
RNTupleFileWriter(std::string_view name, std::uint64_t maxKeySize, bool isHidden)
Private constructor used by all factory methods.
void Seek(std::uint64_t offset)
Seek a simple writer to offset.
ROOT::Internal::RNTupleSerializer::StreamerInfoMap_t fStreamerInfoMap
Set of streamer info records that should be written to the file.
std::uint64_t WriteBlob(const void *data, size_t nbytes, size_t len)
Writes a new record as an RBlob key into the file.
static std::unique_ptr< RNTupleFileWriter > Recreate(std::string_view ntupleName, std::string_view path, EContainerFormat containerFormat, const ROOT::RNTupleWriteOptions &options)
Create or truncate the local file given by path with the new empty RNTuple identified by ntupleName.
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...
static constexpr std::size_t kBlobKeyLen
The key length of a blob. It is always a big key (version > 1000) with class name RBlob.
RNTupleLink Commit(int compression=RCompressionSetting::EDefaults::kUseGeneralPurpose)
Writes the RNTuple key to the file so that the header and footer keys can be found.
static void PrepareBlobKey(std::int64_t offset, size_t nbytes, size_t len, unsigned char buffer[kBlobKeyLen])
Prepares buffer for a new record as an RBlob key at offset.
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...
bool fIsHidden
True if this RNTuple's anchor must be stored as a hidden key (this is the case e.g....
void UpdateStreamerInfos(const ROOT::Internal::RNTupleSerializer::StreamerInfoMap_t &streamerInfos)
Ensures that the streamer info records passed as argument are written to the file.
RNTuple fNTupleAnchor
Header and footer location of the ntuple, written on Commit()
EContainerFormat
For testing purposes, RNTuple data can be written into a bare file container instead of a ROOT file.
std::map< Int_t, TVirtualStreamerInfo * > StreamerInfoMap_t
static std::uint32_t DeserializeUInt64(const void *buffer, std::uint64_t &val)
static std::uint32_t SerializeUInt64(std::uint64_t val, void *buffer)
The RRawFile provides read-only access to local and remote files.
Base class for all ROOT issued exceptions.
std::uint64_t GetNBytesOnStorage() const
void SetType(ELocatorType type)
void SetPosition(std::uint64_t position)
void SetNBytesOnStorage(std::uint64_t nBytesOnStorage)
Common user-tunable settings for storing RNTuples.
std::size_t GetWriteBufferSize() const
std::uint64_t GetMaxKeySize() const
bool GetUseDirectIO() const
std::uint32_t GetCompression() const
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 class is used as a return type for operations that can fail; wraps a value of type T or an RError...
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 SetBufferDisplacement() override
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 file, usually with extension .root, that stores data and code in the form of serialized objects in ...
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.
Int_t fLeft
Number of bytes left in current segment.
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.
virtual char * GetBuffer() const
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
virtual TObjLink * FirstLink() const
Wrapper around a TObject so it can be stored in a TList.
TObject * GetObject() const
Describes a persistent version of a class.
void BuildCheck(TFile *file=nullptr, Bool_t load=kTRUE) override
Check if built and consistent with the class dictionary.
This class defines a UUID (Universally Unique IDentifier), also known as GUIDs (Globally Unique IDent...
static TUUID UUIDv4()
Create a UUID version 4 (variant 1) UUID according to RFC 4122.
void FillBuffer(char *&buffer)
Stream UUID into output buffer.
TFile * GetRFileTFile(RFile &rfile)
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)
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.
ROOT::Experimental::RFile * fFile
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::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 ...
static constexpr int kBlockAlign
Direct I/O requires that all buffers and write lengths are aligned.
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.
static constexpr std::size_t kHeaderBlockSize
During commit, WriteTFileKeysList() updates fNBytesKeys and fSeekKeys of the RTFFile located at fSeek...
std::shared_ptr< RSharedData > fShared
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.
TDirectory * fDirectory
A sub directory in fFile or nullptr if the data is stored in the root directory of the file.
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.
std::uint32_t fLength
Uncompressed length of the anchor, including the checksum.
If a TFile container is written by a C stream (simple file), on dataset commit, the file header and t...
std::uint64_t fSeekFileRecord
std::uint64_t fSeekNTuple