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)
826 if (compSize > uncompLen) {
827 return R__FAIL(
"Invalid size and length combination of anchor at offset " + std::to_string(payloadOffset) +
828 " (length: " + std::to_string(uncompLen) +
", bytes on disk: " + std::to_string(compSize) +
")");
833 auto bufAnchor = MakeUninitArray<unsigned char>(std::max<size_t>(uncompLen,
sizeof(RTFNTuple)));
834 RTFNTuple *ntuple =
new (bufAnchor.get()) RTFNTuple;
836 if (compSize < uncompLen) {
838 auto zipBuf = MakeUninitArray<unsigned char>(compSize);
839 ReadBuffer(zipBuf.get(), compSize, payloadOffset);
850 const auto lenCkData = uncompLen - ntuple->GetOffsetCkData() -
sizeof(uint64_t);
851 const auto ckCalc = XXH3_64bits(ntuple->GetPtrCkData(), lenCkData);
854 RUInt64BE *ckOnDiskPtr =
reinterpret_cast<RUInt64BE *
>(bufAnchor.get() + uncompLen -
sizeof(uint64_t));
855 ckOnDisk =
static_cast<uint64_t
>(*ckOnDiskPtr);
856 if (ckCalc != ckOnDisk) {
857 return R__FAIL(
"RNTuple anchor checksum mismatch");
860 return CreateAnchor(ntuple->fVersionEpoch, ntuple->fVersionMajor, ntuple->fVersionMinor, ntuple->fVersionPatch,
861 ntuple->fSeekHeader, ntuple->fNBytesHeader, ntuple->fLenHeader, ntuple->fSeekFooter,
862 ntuple->fNBytesFooter, ntuple->fLenFooter, ntuple->fMaxKeySize);
867 RBareFileHeader fileHeader;
868 ReadBuffer(&fileHeader,
sizeof(fileHeader), 0);
870 auto offset =
sizeof(fileHeader);
873 std::string_view foundName(
name.fData,
name.fLName);
874 if (foundName != ntupleName) {
875 return R__FAIL(
"expected RNTuple named '" + std::string(ntupleName) +
"' but instead found '" +
876 std::string(foundName) +
"' in file '" + fRawFile->GetUrl() +
"'");
882 std::uint64_t onDiskChecksum;
883 ReadBuffer(&onDiskChecksum,
sizeof(onDiskChecksum),
offset +
sizeof(ntuple));
884 auto checksum = XXH3_64bits(ntuple.GetPtrCkData(), ntuple.GetSizeCkData());
885 if (checksum !=
static_cast<uint64_t
>(onDiskChecksum))
886 return R__FAIL(
"RNTuple bare file: anchor checksum mismatch");
888 return CreateAnchor(ntuple.fVersionEpoch, ntuple.fVersionMajor, ntuple.fVersionMinor, ntuple.fVersionPatch,
889 ntuple.fSeekHeader, ntuple.fNBytesHeader, ntuple.fLenHeader, ntuple.fSeekFooter,
890 ntuple.fNBytesFooter, ntuple.fLenFooter, ntuple.fMaxKeySize);
895 TryReadBuffer(buffer, nbytes,
offset).ThrowOnError();
900 const auto ByteReadErr = [](std::size_t expected, std::size_t nread) {
901 return R__FAIL(
"invalid read (expected bytes: " + std::to_string(expected) +
", read: " + std::to_string(nread) +
906 if (fMaxKeySize == 0 || nbytes <= fMaxKeySize) {
908 nread = fRawFile->ReadAt(buffer, nbytes,
offset);
912 const size_t nbytesChunkOffsets = (nChunks - 1) *
sizeof(std::uint64_t);
913 const size_t nbytesFirstChunk = fMaxKeySize - nbytesChunkOffsets;
914 uint8_t *bufCur =
reinterpret_cast<uint8_t *
>(buffer);
917 nread = fRawFile->ReadAt(bufCur, fMaxKeySize,
offset);
918 if (nread != fMaxKeySize)
919 return ByteReadErr(fMaxKeySize, nread);
924 bufCur += nbytesFirstChunk;
925 nread -= nbytesChunkOffsets;
927 const auto chunkOffsets = MakeUninitArray<std::uint64_t>(nChunks - 1);
928 memcpy(chunkOffsets.get(), bufCur, nbytesChunkOffsets);
930 size_t remainingBytes = nbytes - nbytesFirstChunk;
931 std::uint64_t *curChunkOffset = &chunkOffsets[0];
934 std::uint64_t chunkOffset;
938 const size_t bytesToRead = std::min<size_t>(fMaxKeySize, remainingBytes);
940 R__ASSERT(
static_cast<size_t>(bufCur -
reinterpret_cast<uint8_t *
>(buffer)) <= nbytes - bytesToRead);
942 auto nbytesRead = fRawFile->ReadAt(bufCur, bytesToRead, chunkOffset);
943 if (nbytesRead != bytesToRead)
944 return ByteReadErr(bytesToRead, nbytesRead);
946 nread += bytesToRead;
947 bufCur += bytesToRead;
948 remainingBytes -= bytesToRead;
949 }
while (remainingBytes > 0);
953 return ByteReadErr(nbytes, nread);
963 unsigned char buffer[kBlobKeyLen])
965 RTFString strClass{kBlobClassName};
968 RTFKey keyHeader(
offset, RTFHeader::kBEGIN, strClass, strObject, strTitle,
len, nbytes);
969 R__ASSERT(keyHeader.fKeyLen == kBlobKeyLen);
972 unsigned char *writeBuffer = buffer;
973 memcpy(writeBuffer, &keyHeader, keyHeader.GetHeaderSize());
974 writeBuffer += keyHeader.GetHeaderSize();
975 memcpy(writeBuffer, &strClass, strClass.GetSize());
976 writeBuffer += strClass.GetSize();
977 memcpy(writeBuffer, &strObject, strObject.GetSize());
978 writeBuffer += strObject.GetSize();
979 memcpy(writeBuffer, &strTitle, strTitle.GetSize());
980 writeBuffer += strTitle.GetSize();
981 R__ASSERT(writeBuffer == buffer + kBlobKeyLen);
990 static_assert(kHeaderBlockSize % kBlockAlign == 0,
"invalid header block size");
991 if (bufferSize % kBlockAlign != 0)
992 throw RException(
R__FAIL(
"Buffer size not a multiple of alignment: " + std::to_string(bufferSize)));
996 fShared = std::make_shared<RSharedData>(
nullptr);
998 fShared->fBlockSize = bufferSize;
999 fShared->fControlBlock = std::make_unique<ROOT::Internal::RTFileControlBlock>();
1001 std::align_val_t blockAlign{kBlockAlign};
1002 fShared->fHeaderBlock =
static_cast<unsigned char *
>(::operator
new[](kHeaderBlockSize, blockAlign));
1003 memset(fShared->fHeaderBlock, 0, kHeaderBlockSize);
1004 fShared->fBlock =
static_cast<unsigned char *
>(::operator
new[](fShared->fBlockSize, blockAlign));
1005 memset(fShared->fBlock, 0, fShared->fBlockSize);
1017 ::operator
delete[](fHeaderBlock, blockAlign);
1019 ::operator
delete[](fBlock, blockAlign);
1023int FSeek64(FILE *stream, std::int64_t
offset,
int origin)
1026 return fseeko64(stream,
offset, origin);
1028 return fseek(stream,
offset, origin);
1039 if (shared.fBlockOffset == 0) {
1041 if (headerBlockSize > shared.fFilePos) {
1042 headerBlockSize = shared.fFilePos;
1044 memcpy(shared.fBlock, shared.fHeaderBlock, headerBlockSize);
1047 std::size_t retval = FSeek64(shared.fFile, shared.fBlockOffset, SEEK_SET);
1051 std::size_t lastBlockSize = shared.fFilePos - shared.fBlockOffset;
1052 R__ASSERT(lastBlockSize <= shared.fBlockSize);
1053 if (shared.fDirectIO) {
1057 R__ASSERT(lastBlockSize <= shared.fBlockSize);
1059 retval = fwrite(shared.fBlock, 1, lastBlockSize, shared.fFile);
1060 if (retval != lastBlockSize)
1064 if (shared.fBlockOffset > 0) {
1065 retval = FSeek64(shared.fFile, 0, SEEK_SET);
1074 retval = fflush(shared.fFile);
1085 if ((
offset >= 0) && (
static_cast<std::uint64_t
>(
offset) != shared.fFilePos)) {
1086 shared.fFilePos =
offset;
1091 std::size_t headerBytes = nbytes;
1095 memcpy(shared.fHeaderBlock + shared.fFilePos, buffer, headerBytes);
1098 R__ASSERT(shared.fFilePos >= shared.fBlockOffset);
1100 while (nbytes > 0) {
1101 std::uint64_t posInBlock = shared.fFilePos % shared.fBlockSize;
1102 std::uint64_t blockOffset = shared.fFilePos - posInBlock;
1103 if (blockOffset != shared.fBlockOffset) {
1105 retval = FSeek64(shared.fFile, shared.fBlockOffset, SEEK_SET);
1109 retval = fwrite(shared.fBlock, 1, shared.fBlockSize, shared.fFile);
1110 if (retval != shared.fBlockSize)
1114 memset(shared.fBlock, 0, shared.fBlockSize);
1117 shared.fBlockOffset = blockOffset;
1118 std::size_t blockSize = nbytes;
1119 if (blockSize > shared.fBlockSize - posInBlock) {
1120 blockSize = shared.fBlockSize - posInBlock;
1122 memcpy(shared.fBlock + posInBlock, buffer, blockSize);
1123 buffer =
static_cast<const unsigned char *
>(buffer) + blockSize;
1124 nbytes -= blockSize;
1125 shared.fFilePos += blockSize;
1131 std::int64_t
offset, std::uint64_t directoryOffset,
1132 const std::string &className,
const std::string &objectName,
1133 const std::string &title)
1138 shared.fKeyOffset =
offset;
1139 RTFString strClass{className};
1140 RTFString strObject{objectName};
1141 RTFString strTitle{title};
1143 RTFKey key(shared.fKeyOffset, directoryOffset, strClass, strObject, strTitle,
len, nbytes);
1144 Write(&key, key.GetHeaderSize(), shared.fKeyOffset);
1145 Write(&strClass, strClass.GetSize());
1146 Write(&strObject, strObject.GetSize());
1147 Write(&strTitle, strTitle.GetSize());
1148 auto offsetData = shared.fFilePos;
1150 shared.fKeyOffset = offsetData + nbytes;
1152 Write(buffer, nbytes);
1170 auto offsetData = shared.fKeyOffset +
kBlobKeyLen;
1172 shared.fKeyOffset = offsetData + nbytes;
1179template <
typename T>
1183 std::uint64_t offsetKey;
1187 keyBlob.
Reserve(nbytes, &offsetKey);
1194 caller.Write(localKeyBuffer,
kBlobKeyLen, offsetKey);
1211 fDirectory->GetFile()->Seek(
offset);
1212 bool rv = fDirectory->GetFile()->WriteBuffer((
char *)(buffer), nbytes);
1230 bool rv = file->WriteBuffer((
char *)(buffer), nbytes);
1256std::unique_ptr<ROOT::Internal::RNTupleFileWriter>
1260 std::string fileName(path);
1261 size_t idxDirSep = fileName.find_last_of(
"\\/");
1262 if (idxDirSep != std::string::npos) {
1263 fileName.erase(0, idxDirSep + 1);
1266 int flags = O_WRONLY | O_CREAT | O_TRUNC;
1269 flags |= O_LARGEFILE;
1274 int fd = open(std::string(path).c_str(), flags, 0666);
1276 throw RException(
R__FAIL(std::string(
"open failed for file \"") + std::string(path) +
"\": " + strerror(errno)));
1278 FILE *fileStream = fdopen(fd,
"wb");
1281 FILE *fileStream = fopen64(std::string(path.data(), path.size()).c_str(),
"wb");
1283 FILE *fileStream = fopen(std::string(path.data(), path.size()).c_str(),
"wb");
1287 throw RException(
R__FAIL(std::string(
"open failed for file \"") + std::string(path) +
"\": " + strerror(errno)));
1290 std::setvbuf(fileStream,
nullptr, _IONBF, 0);
1292 auto writer = std::unique_ptr<RNTupleFileWriter>(
1296 fileSimple.
fShared->fFile = fileStream;
1298 writer->fFileName = fileName;
1301 switch (containerFormat) {
1302 case EContainerFormat::kTFile:
writer->WriteTFileSkeleton(defaultCompression);
break;
1303 case EContainerFormat::kBare:
1305 writer->WriteBareFileSkeleton(defaultCompression);
1307 default:
R__ASSERT(
false &&
"Internal error: unhandled container format");
1313std::unique_ptr<ROOT::Internal::RNTupleFileWriter>
1315 std::uint64_t maxKeySize,
bool hidden)
1319 throw RException(
R__FAIL(
"invalid attempt to add an RNTuple to a directory that is not backed by a file"));
1328std::unique_ptr<ROOT::Internal::RNTupleFileWriter>
1330 std::uint64_t maxKeySize)
1334 rfile.
fFile = &file;
1335 R__ASSERT(ntupleDir.empty() || ntupleDir[ntupleDir.size() - 1] ==
'/');
1336 rfile.fDir = ntupleDir;
1340std::unique_ptr<ROOT::Internal::RNTupleFileWriter>
1343 if (
auto *tfile = std::get_if<RImplTFile>(&fFile)) {
1344 return Append(ntupleName, *tfile->fDirectory, fNTupleAnchor.fMaxKeySize,
true);
1345 }
else if (
auto *file = std::get_if<RImplSimple>(&fFile)) {
1349 auto writer = std::unique_ptr<RNTupleFileWriter>(
1351 auto &clonedFile = std::get<RImplSimple>(
writer->fFile);
1352 clonedFile.fShared = file->fShared;
1361 RImplSimple *fileSimple = std::get_if<RImplSimple>(&fFile);
1372 fStreamerInfoMap.insert(streamerInfos.cbegin(), streamerInfos.cend());
1377 const auto WriteStreamerInfoToFile = [&](
TFile *file) {
1381 for (
auto [
_, info] : fStreamerInfoMap)
1387 anchorInfo.
fLength = RTFNTuple{}.GetSize() +
sizeof(std::uint64_t);
1390 if (
auto fileProper = std::get_if<RImplTFile>(&fFile)) {
1392 fileProper->fDirectory->WriteObject(&fNTupleAnchor, fNTupleName.c_str());
1393 WriteStreamerInfoToFile(fileProper->fDirectory->GetFile());
1394 auto key =
static_cast<TKey *
>(fileProper->fDirectory->GetListOfKeys()->FindObject(fNTupleName.c_str()));
1400 fileProper->fDirectory->GetFile()->Write();
1405 fileProper->fDirectory->GetListOfKeys()->Remove(key);
1407 }
else if (
auto fileRFile = std::get_if<RImplRFile>(&fFile)) {
1409 fileRFile->fFile->Put(fileRFile->fDir + fNTupleName, fNTupleAnchor);
1411 auto key = fileRFile->fFile->GetKeyInfo(fNTupleName);
1415 fileRFile->fFile->Flush();
1418 auto &fileSimple = std::get<RImplSimple>(fFile);
1419 auto &shared = *fileSimple.fShared;
1422 RTFNTuple ntupleOnDisk(fNTupleAnchor);
1425 std::uint64_t checksum = XXH3_64bits(ntupleOnDisk.GetPtrCkData(), ntupleOnDisk.GetSizeCkData());
1426 memcpy(shared.fHeaderBlock + shared.fControlBlock->fSeekNTuple, &ntupleOnDisk, ntupleOnDisk.GetSize());
1427 memcpy(shared.fHeaderBlock + shared.fControlBlock->fSeekNTuple + ntupleOnDisk.GetSize(), &checksum,
1434 anchorInfo = WriteTFileNTupleKey(compression);
1437 WriteTFileStreamerInfo(compression);
1438 WriteTFileFreeList();
1441 memcpy(shared.fHeaderBlock, &shared.fControlBlock->fHeader, shared.fControlBlock->fHeader.GetSize());
1442 R__ASSERT(shared.fControlBlock->fSeekFileRecord + shared.fControlBlock->fFileRecord.GetSize() <
1443 RImplSimple::kHeaderBlockSize);
1444 memcpy(shared.fHeaderBlock + shared.fControlBlock->fSeekFileRecord, &shared.fControlBlock->fFileRecord,
1445 shared.fControlBlock->fFileRecord.GetSize());
1457 auto writeKey = [
this](
const void *payload,
size_t nBytes,
size_t length) {
1459 WriteIntoReservedBlob(payload, nBytes,
offset);
1463 const std::uint64_t maxKeySize = fNTupleAnchor.fMaxKeySize;
1467 if (
static_cast<std::uint64_t
>(
len) >
static_cast<std::uint64_t
>(std::numeric_limits<std::uint32_t>::max()))
1470 if (nbytes <= maxKeySize) {
1472 return writeKey(
data, nbytes,
len);
1489 const size_t nbytesChunkOffsets = (nChunks - 1) *
sizeof(std::uint64_t);
1490 const size_t nbytesFirstChunk = maxKeySize - nbytesChunkOffsets;
1493 const uint8_t *chunkData =
reinterpret_cast<const uint8_t *
>(
data) + nbytesFirstChunk;
1494 size_t remainingBytes = nbytes - nbytesFirstChunk;
1496 const auto chunkOffsetsToWrite = MakeUninitArray<std::uint64_t>(nChunks - 1);
1497 std::uint64_t chunkOffsetIdx = 0;
1500 const size_t bytesNextChunk = std::min<size_t>(remainingBytes, maxKeySize);
1501 const std::uint64_t
offset = writeKey(chunkData, bytesNextChunk, bytesNextChunk);
1506 remainingBytes -= bytesNextChunk;
1507 chunkData += bytesNextChunk;
1509 }
while (remainingBytes > 0);
1512 const std::uint64_t firstOffset = ReserveBlob(maxKeySize, maxKeySize);
1513 WriteIntoReservedBlob(
data, nbytesFirstChunk, firstOffset);
1514 const std::uint64_t chunkOffsetsOffset = firstOffset + nbytesFirstChunk;
1515 WriteIntoReservedBlob(chunkOffsetsToWrite.get(), nbytesChunkOffsets, chunkOffsetsOffset);
1524 R__ASSERT(nbytes <= fNTupleAnchor.GetMaxKeySize());
1527 if (
auto *fileSimple = std::get_if<RImplSimple>(&fFile)) {
1529 offset = fileSimple->fShared->fKeyOffset;
1530 fileSimple->fShared->fKeyOffset += nbytes;
1532 offset = fileSimple->ReserveBlobKey(nbytes,
len, keyBuffer);
1534 }
else if (
auto *fileProper = std::get_if<RImplTFile>(&fFile)) {
1535 offset = fileProper->ReserveBlobKey(nbytes,
len, keyBuffer);
1537 auto &fileRFile = std::get<RImplRFile>(fFile);
1538 offset = fileRFile.ReserveBlobKey(nbytes,
len, keyBuffer);
1545 if (
auto *fileSimple = std::get_if<RImplSimple>(&fFile)) {
1546 fileSimple->Write(buffer, nbytes,
offset);
1547 }
else if (
auto *fileProper = std::get_if<RImplTFile>(&fFile)) {
1548 fileProper->Write(buffer, nbytes,
offset);
1550 auto &fileRFile = std::get<RImplRFile>(fFile);
1551 fileRFile.Write(buffer, nbytes,
offset);
1557 auto offset = WriteBlob(
data, nbytes, lenHeader);
1558 fNTupleAnchor.fLenHeader = lenHeader;
1559 fNTupleAnchor.fNBytesHeader = nbytes;
1560 fNTupleAnchor.fSeekHeader =
offset;
1566 auto offset = WriteBlob(
data, nbytes, lenFooter);
1567 fNTupleAnchor.fLenFooter = lenFooter;
1568 fNTupleAnchor.fNBytesFooter = nbytes;
1569 fNTupleAnchor.fSeekFooter =
offset;
1575 RBareFileHeader bareHeader;
1576 bareHeader.fCompress = defaultCompression;
1577 auto &fileSimple = std::get<RImplSimple>(fFile);
1578 fileSimple.Write(&bareHeader,
sizeof(bareHeader), 0);
1579 RTFString ntupleName{fNTupleName};
1580 fileSimple.Write(&ntupleName, ntupleName.GetSize());
1583 RTFNTuple ntupleOnDisk;
1584 fileSimple.fShared->fControlBlock->fSeekNTuple = fileSimple.fShared->fFilePos;
1585 fileSimple.Write(&ntupleOnDisk, ntupleOnDisk.GetSize());
1586 std::uint64_t checksum = 0;
1587 fileSimple.Write(&checksum,
sizeof(checksum));
1588 fileSimple.fShared->fKeyOffset = fileSimple.fShared->fFilePos;
1598 TList streamerInfoList;
1599 for (
auto [
_, info] : fStreamerInfoMap) {
1600 streamerInfoList.
Add(info);
1609 RTFString strTList{
"TList"};
1610 RTFString strStreamerInfo{
"StreamerInfo"};
1611 RTFString strStreamerTitle{
"Doubly linked list"};
1612 auto &fileSimple = std::get<RImplSimple>(fFile);
1613 fileSimple.fShared->fControlBlock->fHeader.SetSeekInfo(fileSimple.fShared->fKeyOffset);
1614 auto keyLen = RTFKey(fileSimple.fShared->fControlBlock->fHeader.GetSeekInfo(), RTFHeader::kBEGIN, strTList,
1615 strStreamerInfo, strStreamerTitle, 0)
1621 assert(buffer.
Length() > keyLen);
1622 const auto bufPayload = buffer.
Buffer() + keyLen;
1623 const auto lenPayload = buffer.
Length() - keyLen;
1625 auto zipStreamerInfos = MakeUninitArray<unsigned char>(lenPayload);
1626 auto szZipStreamerInfos =
RNTupleCompressor::Zip(bufPayload, lenPayload, compression, zipStreamerInfos.get());
1628 fileSimple.WriteKey(zipStreamerInfos.get(), szZipStreamerInfos, lenPayload,
1629 fileSimple.fShared->fControlBlock->fHeader.GetSeekInfo(), RTFHeader::kBEGIN,
"TList",
1630 "StreamerInfo",
"Doubly linked list");
1631 fileSimple.fShared->fControlBlock->fHeader.SetNbytesInfo(fileSimple.fShared->fFilePos -
1632 fileSimple.fShared->fControlBlock->fHeader.GetSeekInfo());
1638 RTFString strRNTupleClass{
"ROOT::RNTuple"};
1639 RTFString strRNTupleName{fNTupleName};
1640 RTFString strFileName{fFileName};
1642 auto &fileSimple = std::get<RImplSimple>(fFile);
1643 RTFKey keyRNTuple(fileSimple.fShared->fControlBlock->fSeekNTuple, RTFHeader::kBEGIN, strRNTupleClass, strRNTupleName,
1644 strEmpty, RTFNTuple::GetSizePlusChecksum(), anchorSize);
1646 auto &fileShared = *fileSimple.fShared;
1647 fileSimple.fShared->fControlBlock->fFileRecord.SetSeekKeys(fileShared.fKeyOffset);
1648 RTFKeyList keyList{1};
1649 RTFKey keyKeyList(fileSimple.fShared->fControlBlock->fFileRecord.GetSeekKeys(), RTFHeader::kBEGIN, strEmpty,
1650 strFileName, strEmpty, keyList.GetSize() + keyRNTuple.fKeyLen);
1651 fileSimple.Write(&keyKeyList, keyKeyList.GetHeaderSize(),
1652 fileSimple.fShared->fControlBlock->fFileRecord.GetSeekKeys());
1653 fileSimple.Write(&strEmpty, strEmpty.GetSize());
1654 fileSimple.Write(&strFileName, strFileName.GetSize());
1655 fileSimple.Write(&strEmpty, strEmpty.GetSize());
1656 fileSimple.Write(&keyList, keyList.GetSize());
1657 fileSimple.Write(&keyRNTuple, keyRNTuple.GetHeaderSize());
1659 fileSimple.Write(&strRNTupleClass, strRNTupleClass.GetSize());
1660 fileSimple.Write(&strRNTupleName, strRNTupleName.GetSize());
1661 fileSimple.Write(&strEmpty, strEmpty.GetSize());
1662 fileSimple.fShared->fControlBlock->fFileRecord.fNBytesKeys =
1663 fileShared.fFilePos - fileSimple.fShared->fControlBlock->fFileRecord.GetSeekKeys();
1664 fileShared.fKeyOffset = fileShared.fFilePos;
1669 auto &fileSimple = std::get<RImplSimple>(fFile);
1670 auto &fileShared = *fileSimple.fShared;
1671 fileSimple.fShared->fControlBlock->fHeader.SetSeekFree(fileShared.fKeyOffset);
1673 RTFString strFileName{fFileName};
1674 RTFFreeEntry freeEntry;
1675 RTFKey keyFreeList(fileSimple.fShared->fControlBlock->fHeader.GetSeekFree(), RTFHeader::kBEGIN, strEmpty,
1676 strFileName, strEmpty, freeEntry.GetSize());
1677 std::uint64_t firstFree = fileSimple.fShared->fControlBlock->fHeader.GetSeekFree() + keyFreeList.GetSize();
1678 freeEntry.Set(firstFree, std::max(2000000000ULL, ((firstFree / 1000000000ULL) + 1) * 1000000000ULL));
1679 fileSimple.WriteKey(&freeEntry, freeEntry.GetSize(), freeEntry.GetSize(),
1680 fileSimple.fShared->fControlBlock->fHeader.GetSeekFree(), RTFHeader::kBEGIN,
"", fFileName,
"");
1681 fileSimple.fShared->fControlBlock->fHeader.SetNbytesFree(fileShared.fFilePos -
1682 fileSimple.fShared->fControlBlock->fHeader.GetSeekFree());
1683 fileSimple.fShared->fControlBlock->fHeader.SetEnd(fileShared.fFilePos);
1688 RTFString strRNTupleClass{
"ROOT::RNTuple"};
1689 RTFString strRNTupleName{fNTupleName};
1692 RTFNTuple ntupleOnDisk(fNTupleAnchor);
1693 RUInt64BE checksum{XXH3_64bits(ntupleOnDisk.GetPtrCkData(), ntupleOnDisk.GetSizeCkData())};
1694 auto &fileSimple = std::get<RImplSimple>(fFile);
1695 fileSimple.fShared->fControlBlock->fSeekNTuple = fileSimple.fShared->fKeyOffset;
1697 char keyBuf[RTFNTuple::GetSizePlusChecksum()];
1700 memcpy(keyBuf, &ntupleOnDisk,
sizeof(RTFNTuple));
1701 memcpy(keyBuf +
sizeof(RTFNTuple), &checksum,
sizeof(checksum));
1703 const auto sizeAnchor =
sizeof(RTFNTuple) +
sizeof(checksum);
1704 char zipAnchor[RTFNTuple::GetSizePlusChecksum()];
1709 fileSimple.WriteKey(zipAnchor, szZipAnchor,
sizeof(keyBuf), fileSimple.fShared->fControlBlock->fSeekNTuple,
1710 RTFHeader::kBEGIN,
"ROOT::RNTuple", fNTupleName,
"");
1712 assert(szZipAnchor < std::numeric_limits<
decltype(anchorLink.
fLength)>::max());
1713 anchorLink.
fLength =
sizeof(keyBuf);
1721 RTFString strTFile{
"TFile"};
1722 RTFString strFileName{fFileName};
1725 auto &fileSimple = std::get<RImplSimple>(fFile);
1726 fileSimple.fShared->fControlBlock->fHeader = RTFHeader(defaultCompression);
1731 RTFKey keyRoot(RTFHeader::kBEGIN, 0, strTFile, strFileName, strEmpty,
1732 sizeof(RTFDirectory) + strFileName.GetSize() + strEmpty.GetSize() + uuid.GetSize());
1733 std::uint32_t nbytesName = keyRoot.fKeyLen + strFileName.GetSize() + 1;
1734 fileSimple.fShared->fControlBlock->fFileRecord.fNBytesName = nbytesName;
1735 fileSimple.fShared->fControlBlock->fHeader.SetNbytesName(nbytesName);
1737 fileSimple.Write(&keyRoot, keyRoot.GetHeaderSize(), RTFHeader::kBEGIN);
1739 fileSimple.Write(&strTFile, strTFile.GetSize());
1740 fileSimple.Write(&strFileName, strFileName.GetSize());
1741 fileSimple.Write(&strEmpty, strEmpty.GetSize());
1743 fileSimple.Write(&strFileName, strFileName.GetSize());
1744 fileSimple.Write(&strEmpty, strEmpty.GetSize());
1746 fileSimple.fShared->fControlBlock->fSeekFileRecord = fileSimple.fShared->fFilePos;
1747 fileSimple.Write(&fileSimple.fShared->fControlBlock->fFileRecord,
1748 fileSimple.fShared->fControlBlock->fFileRecord.GetSize());
1749 fileSimple.Write(&uuid, uuid.GetSize());
1752 RUInt32BE padding{0};
1753 for (
int i = 0; i < 3; ++i)
1754 fileSimple.Write(&padding,
sizeof(padding));
1755 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
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.
An interface to read from, or write to, a ROOT file, as well as performing other common operations.
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.
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)
TFile * GetRFileTFile(RFile &rfile)
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::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