50#ifndef R__LITTLE_ENDIAN
53#define R__LITTLE_ENDIAN 1
55#define R__LITTLE_ENDIAN 0
71 std::uint16_t fValBE = 0;
72 static std::uint16_t Swap(std::uint16_t val)
74#if R__LITTLE_ENDIAN == 1
75 return RByteSwap<
sizeof(val)>::bswap(val);
82 RUInt16BE() =
default;
83 explicit RUInt16BE(
const std::uint16_t val) : fValBE(Swap(val)) {}
84 operator std::uint16_t()
const {
return Swap(fValBE); }
85 RUInt16BE &
operator=(
const std::uint16_t val)
95 std::uint32_t fValBE = 0;
96 static std::uint32_t Swap(std::uint32_t val)
98#if R__LITTLE_ENDIAN == 1
99 return RByteSwap<
sizeof(val)>::bswap(val);
106 RUInt32BE() =
default;
107 explicit RUInt32BE(
const std::uint32_t val) : fValBE(Swap(val)) {}
108 operator std::uint32_t()
const {
return Swap(fValBE); }
109 RUInt32BE &
operator=(
const std::uint32_t val)
119 std::int32_t fValBE = 0;
120 static std::int32_t Swap(std::int32_t val)
122#if R__LITTLE_ENDIAN == 1
123 return RByteSwap<
sizeof(val)>::bswap(val);
130 RInt32BE() =
default;
131 explicit RInt32BE(
const std::int32_t val) : fValBE(Swap(val)) {}
132 operator std::int32_t()
const {
return Swap(fValBE); }
133 RInt32BE &
operator=(
const std::int32_t val)
143 std::uint64_t fValBE = 0;
144 static std::uint64_t Swap(std::uint64_t val)
146#if R__LITTLE_ENDIAN == 1
147 return RByteSwap<
sizeof(val)>::bswap(val);
154 RUInt64BE() =
default;
155 explicit RUInt64BE(
const std::uint64_t val) : fValBE(Swap(val)) {}
156 operator std::uint64_t()
const {
return Swap(fValBE); }
157 RUInt64BE &
operator=(
const std::uint64_t val)
167 unsigned char fLName{0};
169 RTFString() =
default;
170 RTFString(
const std::string &str)
175 fLName =
static_cast<unsigned char>(str.length());
176 memcpy(fData, str.data(), fLName);
178 std::size_t GetSize()
const
192 auto now = std::chrono::system_clock::now();
193 auto tt = std::chrono::system_clock::to_time_t(now);
194 auto tm = *localtime(&
tt);
195 fDatetime = (tm.tm_year + 1900 - 1995) << 26 | (tm.tm_mon + 1) << 22 | tm.tm_mday << 17 | tm.tm_hour << 12 |
196 tm.tm_min << 6 | tm.tm_sec;
198 explicit RTFDatetime(RUInt32BE val) : fDatetime(val) {}
203 static constexpr unsigned kBigKeyVersion = 1000;
206 RUInt16BE fVersion{4};
207 RUInt32BE fObjLen{0};
208 RTFDatetime fDatetime;
209 RUInt16BE fKeyLen{0};
213 RUInt32BE fSeekKey{0};
214 RUInt32BE fSeekPdir{0};
217 RUInt64BE fSeekKey{0};
218 RUInt64BE fSeekPdir{0};
222 RTFKey() : fInfoLong() {}
223 RTFKey(std::uint64_t seekKey, std::uint64_t seekPdir,
const RTFString &clName,
const RTFString &objName,
224 const RTFString &titleName, std::size_t szObjInMem, std::size_t szObjOnDisk = 0)
226 R__ASSERT(szObjInMem <= std::numeric_limits<std::uint32_t>::max());
227 R__ASSERT(szObjOnDisk <= std::numeric_limits<std::uint32_t>::max());
229 fVersion = fVersion + kBigKeyVersion;
230 fObjLen = szObjInMem;
231 fKeyLen =
static_cast<RUInt16BE
>(GetHeaderSize() + clName.GetSize() + objName.GetSize() + titleName.GetSize());
232 fInfoLong.fSeekKey = seekKey;
233 fInfoLong.fSeekPdir = seekPdir;
235 fNbytes = fKeyLen + ((szObjOnDisk == 0) ? szObjInMem : szObjOnDisk);
238 std::uint32_t GetSize()
const
246 std::uint32_t GetHeaderSize()
const
248 if (fVersion >= kBigKeyVersion)
249 return 18 +
sizeof(fInfoLong);
250 return 18 +
sizeof(fInfoShort);
253 std::uint64_t GetSeekKey()
const
255 if (fVersion >= kBigKeyVersion)
256 return fInfoLong.fSeekKey;
257 return fInfoShort.fSeekKey;
263 static constexpr unsigned kBEGIN = 100;
264 static constexpr unsigned kBigHeaderVersion = 1000000;
266 char fMagic[4]{
'r',
'o',
'o',
't'};
273 RUInt32BE fSeekFree{0};
274 RUInt32BE fNbytesFree{0};
276 RUInt32BE fNbytesName{0};
277 unsigned char fUnits{4};
278 RUInt32BE fCompress{0};
279 RUInt32BE fSeekInfo{0};
280 RUInt32BE fNbytesInfo{0};
284 RUInt64BE fSeekFree{0};
285 RUInt32BE fNbytesFree{0};
287 RUInt32BE fNbytesName{0};
288 unsigned char fUnits{8};
289 RUInt32BE fCompress{0};
290 RUInt64BE fSeekInfo{0};
291 RUInt32BE fNbytesInfo{0};
295 RTFHeader() : fInfoShort() {}
296 RTFHeader(
int compression) : fInfoShort() { fInfoShort.fCompress = compression; }
300 if (fVersion >= kBigHeaderVersion)
304 std::uint32_t end = fInfoShort.fEND;
305 std::uint32_t seekFree = fInfoShort.fSeekFree;
306 std::uint32_t nbytesFree = fInfoShort.fNbytesFree;
307 std::uint32_t nFree = fInfoShort.fNfree;
308 std::uint32_t nbytesName = fInfoShort.fNbytesName;
309 std::uint32_t compress = fInfoShort.fCompress;
310 std::uint32_t seekInfo = fInfoShort.fSeekInfo;
311 std::uint32_t nbytesInfo = fInfoShort.fNbytesInfo;
312 fInfoLong.fEND = end;
313 fInfoLong.fSeekFree = seekFree;
314 fInfoLong.fNbytesFree = nbytesFree;
315 fInfoLong.fNfree = nFree;
316 fInfoLong.fNbytesName = nbytesName;
317 fInfoLong.fUnits = 8;
318 fInfoLong.fCompress = compress;
319 fInfoLong.fSeekInfo = seekInfo;
320 fInfoLong.fNbytesInfo = nbytesInfo;
321 fVersion = fVersion + kBigHeaderVersion;
325 bool IsBigFile(std::uint64_t
offset = 0)
const
327 return (fVersion >= kBigHeaderVersion) ||
328 (
offset >
static_cast<unsigned int>(std::numeric_limits<std::int32_t>::max()));
331 std::uint32_t GetSize()
const
333 std::uint32_t sizeHead =
sizeof(fMagic) +
sizeof(fVersion) +
sizeof(fBEGIN);
335 return sizeHead +
sizeof(fInfoLong);
336 return sizeHead +
sizeof(fInfoShort);
339 std::uint64_t GetEnd()
const
342 return fInfoLong.fEND;
343 return fInfoShort.fEND;
346 void SetEnd(std::uint64_t
value)
348 if (IsBigFile(
value)) {
350 fInfoLong.fEND =
value;
352 fInfoShort.fEND =
value;
356 std::uint64_t GetSeekFree()
const
359 return fInfoLong.fSeekFree;
360 return fInfoShort.fSeekFree;
363 void SetSeekFree(std::uint64_t
value)
365 if (IsBigFile(
value)) {
367 fInfoLong.fSeekFree =
value;
369 fInfoShort.fSeekFree =
value;
373 void SetNbytesFree(std::uint32_t
value)
376 fInfoLong.fNbytesFree =
value;
378 fInfoShort.fNbytesFree =
value;
382 void SetNbytesName(std::uint32_t
value)
385 fInfoLong.fNbytesName =
value;
387 fInfoShort.fNbytesName =
value;
391 std::uint64_t GetSeekInfo()
const
394 return fInfoLong.fSeekInfo;
395 return fInfoShort.fSeekInfo;
398 void SetSeekInfo(std::uint64_t
value)
400 if (IsBigFile(
value)) {
402 fInfoLong.fSeekInfo =
value;
404 fInfoShort.fSeekInfo =
value;
408 std::uint64_t GetNbytesInfo()
const
411 return fInfoLong.fNbytesInfo;
412 return fInfoShort.fNbytesInfo;
415 void SetNbytesInfo(std::uint32_t
value)
418 fInfoLong.fNbytesInfo =
value;
420 fInfoShort.fNbytesInfo =
value;
424 void SetCompression(std::uint32_t
value)
427 fInfoLong.fCompress =
value;
429 fInfoShort.fCompress =
value;
436 static constexpr unsigned kBigFreeEntryVersion = 1000;
438 RUInt16BE fVersion{1};
450 RTFFreeEntry() : fInfoShort() {}
451 void Set(std::uint64_t first, std::uint64_t last)
453 if (last >
static_cast<unsigned int>(std::numeric_limits<std::int32_t>::max())) {
454 fVersion = fVersion + kBigFreeEntryVersion;
455 fInfoLong.fFirst = first;
456 fInfoLong.fLast = last;
458 fInfoShort.fFirst = first;
459 fInfoShort.fLast = last;
462 std::uint32_t GetSize() {
return (fVersion >= kBigFreeEntryVersion) ? 18 : 10; }
468 std::uint32_t GetSize()
const {
return sizeof(RTFKeyList); }
469 explicit RTFKeyList(std::uint32_t nKeys) : fNKeys(nKeys) {}
474 static constexpr unsigned kBigFileVersion = 1000;
476 RUInt16BE fClassVersion{5};
479 RUInt32BE fNBytesKeys{0};
480 RUInt32BE fNBytesName{0};
484 RUInt32BE fSeekDir{RTFHeader::kBEGIN};
485 RUInt32BE fSeekParent{0};
486 RUInt32BE fSeekKeys{0};
489 RUInt64BE fSeekDir{RTFHeader::kBEGIN};
490 RUInt64BE fSeekParent{0};
491 RUInt64BE fSeekKeys{0};
495 RTFDirectory() : fInfoShort() {}
498 std::uint32_t GetSize()
const
500 if (fClassVersion >= kBigFileVersion)
501 return sizeof(RTFDirectory);
502 return 18 +
sizeof(fInfoShort);
505 std::uint64_t GetSeekKeys()
const
507 if (fClassVersion >= kBigFileVersion)
508 return fInfoLong.fSeekKeys;
509 return fInfoShort.fSeekKeys;
512 void SetSeekKeys(std::uint64_t seekKeys)
514 if (seekKeys >
static_cast<unsigned int>(std::numeric_limits<std::int32_t>::max())) {
515 std::uint32_t seekDir = fInfoShort.fSeekDir;
516 std::uint32_t seekParent = fInfoShort.fSeekParent;
517 fInfoLong.fSeekDir = seekDir;
518 fInfoLong.fSeekParent = seekParent;
519 fInfoLong.fSeekKeys = seekKeys;
520 fClassVersion = fClassVersion + kBigFileVersion;
522 fInfoShort.fSeekKeys = seekKeys;
529 RUInt16BE fVersionClass{1};
530 unsigned char fUUID[16];
535 char *buffer =
reinterpret_cast<char *
>(
this);
537 assert(
reinterpret_cast<RTFUUID *
>(buffer) <= (
this + 1));
539 std::uint32_t GetSize()
const {
return sizeof(RTFUUID); }
548 RUInt32BE fByteCount{0x40000000 | (
sizeof(RTFNTuple) -
sizeof(fByteCount))};
549 RUInt16BE fVersionClass{2};
550 RUInt16BE fVersionEpoch{0};
551 RUInt16BE fVersionMajor{0};
552 RUInt16BE fVersionMinor{0};
553 RUInt16BE fVersionPatch{0};
554 RUInt64BE fSeekHeader{0};
555 RUInt64BE fNBytesHeader{0};
556 RUInt64BE fLenHeader{0};
557 RUInt64BE fSeekFooter{0};
558 RUInt64BE fNBytesFooter{0};
559 RUInt64BE fLenFooter{0};
560 RUInt64BE fMaxKeySize{0};
562 static constexpr std::uint32_t GetSizePlusChecksum() {
return sizeof(RTFNTuple) +
sizeof(std::uint64_t); }
564 RTFNTuple() =
default;
579 std::uint32_t GetSize()
const {
return sizeof(RTFNTuple); }
581 std::uint32_t GetOffsetCkData() {
return sizeof(fByteCount) +
sizeof(fVersionClass); }
582 std::uint32_t GetSizeCkData() {
return GetSize() - GetOffsetCkData(); }
583 unsigned char *GetPtrCkData() {
return reinterpret_cast<unsigned char *
>(
this) + GetOffsetCkData(); }
587struct RBareFileHeader {
588 char fMagic[7]{
'r',
'n',
't',
'u',
'p',
'l',
'e'};
591 RUInt32BE fFormatVersion{1};
592 RUInt32BE fCompress{0};
599constexpr char const *kBlobClassName =
"RBlob";
601constexpr char const *kNTupleClassName =
"ROOT::RNTuple";
632 void Reserve(
size_t nbytes, std::uint64_t *seekKey)
651 constexpr size_t kChunkOffsetSize =
sizeof(std::uint64_t);
653 assert(nbytes > maxChunkSize);
654 size_t nChunks = (nbytes + maxChunkSize - 1) / maxChunkSize;
656 size_t nbytesTail = nbytes % maxChunkSize;
657 size_t nbytesExtra = (nbytesTail > 0) * (maxChunkSize - nbytesTail);
658 size_t nbytesChunkOffsets = (nChunks - 1) * kChunkOffsetSize;
659 if (nbytesChunkOffsets > nbytesExtra) {
661 nbytesChunkOffsets += kChunkOffsetSize;
668 R__ASSERT(nbytesChunkOffsets <= maxChunkSize);
679 if (std::string(ident, 4) ==
"root")
688 std::string_view typeName)
690 RTFDirectory directory;
691 ReadBuffer(&directory,
sizeof(directory), offsetDir);
695 std::uint64_t
offset = directory.GetSeekKeys();
701 for (
unsigned int i = 0; i < nKeys; ++i) {
703 auto offsetNextKey =
offset + key.fKeyLen;
705 offset += key.GetHeaderSize();
709 if (std::string_view(
name.fData,
name.fLName) != typeName) {
716 if (std::string_view(
name.fData,
name.fLName) == keyName) {
717 return key.GetSeekKey();
728 RTFHeader fileHeader;
729 ReadBuffer(&fileHeader,
sizeof(fileHeader), 0);
731 const std::uint64_t seekKeyInfo = fileHeader.GetSeekInfo();
736 const std::uint64_t nbytesInfo = fileHeader.GetNbytesInfo() - key.fKeyLen;
737 const std::uint64_t seekInfo = seekKeyInfo + key.fKeyLen;
738 const std::uint32_t uncompLenInfo = key.fObjLen;
740 if (nbytesInfo == uncompLenInfo) {
742 ReadBuffer(streamerInfo.get(), nbytesInfo, seekInfo);
745 ReadBuffer(buffer.get(), nbytesInfo, seekInfo);
755 TList streamerInfoList;
772 RTFHeader fileHeader;
773 ReadBuffer(&fileHeader,
sizeof(fileHeader), 0);
777 ReadBuffer(&key,
sizeof(key), fileHeader.fBEGIN);
779 std::uint64_t
offset = fileHeader.fBEGIN + key.fKeyLen;
787 std::string ntuplePathTail(ntuplePath);
788 if (!ntuplePathTail.empty() && ntuplePathTail[0] ==
'/')
789 ntuplePathTail = ntuplePathTail.substr(1);
790 auto pos = std::string::npos;
791 while ((pos = ntuplePathTail.find(
'/')) != std::string::npos) {
792 auto directoryName = ntuplePathTail.substr(0, pos);
793 ntuplePathTail.erase(0, pos + 1);
797 return R__FAIL(
"no directory named '" + std::string(directoryName) +
"' in file '" +
fRawFile->GetUrl() +
"'");
800 offset = key.GetSeekKey() + key.fKeyLen;
803 auto ntupleName = ntuplePathTail;
807 return R__FAIL(
"no RNTuple named '" + std::string(ntupleName) +
"' in file '" +
fRawFile->GetUrl() +
"'");
811 offset = key.GetSeekKey() + key.fKeyLen;
814 constexpr size_t kMinNTupleSize = 78;
815 static_assert(kMinNTupleSize == RTFNTuple::GetSizePlusChecksum());
816 if (key.fObjLen < kMinNTupleSize) {
817 return R__FAIL(
"invalid anchor size: " + std::to_string(key.fObjLen) +
" < " + std::to_string(
sizeof(RTFNTuple)));
820 const auto objNbytes = key.GetSize() - key.fKeyLen;
826 std::uint64_t compSize,
827 std::uint64_t uncompLen)
832 RTFNTuple *ntuple =
new (bufAnchor.get()) RTFNTuple;
834 if (compSize != uncompLen) {
837 ReadBuffer(unzipBuf.get(), compSize, payloadOffset);
846 const auto lenCkData = uncompLen - ntuple->GetOffsetCkData() -
sizeof(uint64_t);
847 const auto ckCalc = XXH3_64bits(ntuple->GetPtrCkData(), lenCkData);
850 RUInt64BE *ckOnDiskPtr =
reinterpret_cast<RUInt64BE *
>(bufAnchor.get() + uncompLen -
sizeof(uint64_t));
851 ckOnDisk =
static_cast<uint64_t
>(*ckOnDiskPtr);
852 if (ckCalc != ckOnDisk) {
853 return R__FAIL(
"RNTuple anchor checksum mismatch");
856 return CreateAnchor(ntuple->fVersionEpoch, ntuple->fVersionMajor, ntuple->fVersionMinor, ntuple->fVersionPatch,
857 ntuple->fSeekHeader, ntuple->fNBytesHeader, ntuple->fLenHeader, ntuple->fSeekFooter,
858 ntuple->fNBytesFooter, ntuple->fLenFooter, ntuple->fMaxKeySize);
863 RBareFileHeader fileHeader;
864 ReadBuffer(&fileHeader,
sizeof(fileHeader), 0);
866 auto offset =
sizeof(fileHeader);
869 std::string_view foundName(
name.fData,
name.fLName);
870 if (foundName != ntupleName) {
871 return R__FAIL(
"expected RNTuple named '" + std::string(ntupleName) +
"' but instead found '" +
872 std::string(foundName) +
"' in file '" +
fRawFile->GetUrl() +
"'");
878 std::uint64_t onDiskChecksum;
879 ReadBuffer(&onDiskChecksum,
sizeof(onDiskChecksum),
offset +
sizeof(ntuple));
880 auto checksum = XXH3_64bits(ntuple.GetPtrCkData(), ntuple.GetSizeCkData());
881 if (checksum !=
static_cast<uint64_t
>(onDiskChecksum))
882 return R__FAIL(
"RNTuple bare file: anchor checksum mismatch");
884 return CreateAnchor(ntuple.fVersionEpoch, ntuple.fVersionMajor, ntuple.fVersionMinor, ntuple.fVersionPatch,
885 ntuple.fSeekHeader, ntuple.fNBytesHeader, ntuple.fLenHeader, ntuple.fSeekFooter,
886 ntuple.fNBytesFooter, ntuple.fLenFooter, ntuple.fMaxKeySize);
896 const auto ByteReadErr = [](std::size_t expected, std::size_t nread) {
897 return R__FAIL(
"invalid read (expected bytes: " + std::to_string(expected) +
", read: " + std::to_string(nread) +
908 const size_t nbytesChunkOffsets = (nChunks - 1) *
sizeof(std::uint64_t);
909 const size_t nbytesFirstChunk =
fMaxKeySize - nbytesChunkOffsets;
910 uint8_t *bufCur =
reinterpret_cast<uint8_t *
>(buffer);
920 bufCur += nbytesFirstChunk;
921 nread -= nbytesChunkOffsets;
924 memcpy(chunkOffsets.get(), bufCur, nbytesChunkOffsets);
926 size_t remainingBytes = nbytes - nbytesFirstChunk;
927 std::uint64_t *curChunkOffset = &chunkOffsets[0];
930 std::uint64_t chunkOffset;
934 const size_t bytesToRead = std::min<size_t>(
fMaxKeySize, remainingBytes);
936 R__ASSERT(
static_cast<size_t>(bufCur -
reinterpret_cast<uint8_t *
>(buffer)) <= nbytes - bytesToRead);
938 auto nbytesRead =
fRawFile->ReadAt(bufCur, bytesToRead, chunkOffset);
939 if (nbytesRead != bytesToRead)
940 return ByteReadErr(bytesToRead, nbytesRead);
942 nread += bytesToRead;
943 bufCur += bytesToRead;
944 remainingBytes -= bytesToRead;
945 }
while (remainingBytes > 0);
949 return ByteReadErr(nbytes, nread);
961 RTFString strClass{kBlobClassName};
964 RTFKey keyHeader(
offset, RTFHeader::kBEGIN, strClass, strObject, strTitle,
len, nbytes);
968 unsigned char *writeBuffer = buffer;
969 memcpy(writeBuffer, &keyHeader, keyHeader.GetHeaderSize());
970 writeBuffer += keyHeader.GetHeaderSize();
971 memcpy(writeBuffer, &strClass, strClass.GetSize());
972 writeBuffer += strClass.GetSize();
973 memcpy(writeBuffer, &strObject, strObject.GetSize());
974 writeBuffer += strObject.GetSize();
975 memcpy(writeBuffer, &strTitle, strTitle.GetSize());
976 writeBuffer += strTitle.GetSize();
988 throw RException(
R__FAIL(
"Buffer size not a multiple of alignment: " + std::to_string(bufferSize)));
994 fBlock =
static_cast<unsigned char *
>(::operator
new[](
fBlockSize, blockAlign));
1007 ::operator
delete[](
fBlock, blockAlign);
1011int FSeek64(FILE *stream, std::int64_t
offset,
int origin)
1014 return fseeko64(stream,
offset, origin);
1016 return fseek(stream,
offset, origin);
1046 if (retval != lastBlockSize)
1051 retval = FSeek64(
fFile, 0, SEEK_SET);
1060 retval = fflush(
fFile);
1075 std::size_t headerBytes = nbytes;
1084 while (nbytes > 0) {
1086 std::uint64_t blockOffset =
fFilePos - posInBlock;
1102 std::size_t blockSize = nbytes;
1106 memcpy(
fBlock + posInBlock, buffer, blockSize);
1107 buffer =
static_cast<const unsigned char *
>(buffer) + blockSize;
1108 nbytes -= blockSize;
1115 std::int64_t
offset, std::uint64_t directoryOffset,
1116 const std::string &className,
const std::string &objectName,
1117 const std::string &title)
1121 RTFString strClass{className};
1122 RTFString strObject{objectName};
1123 RTFString strTitle{title};
1125 RTFKey key(
fKeyOffset, directoryOffset, strClass, strObject, strTitle,
len, nbytes);
1127 Write(&strClass, strClass.GetSize());
1128 Write(&strObject, strObject.GetSize());
1129 Write(&strTitle, strTitle.GetSize());
1134 Write(buffer, nbytes);
1159template <
typename T>
1163 std::uint64_t offsetKey;
1167 keyBlob.
Reserve(nbytes, &offsetKey);
1174 caller.Write(localKeyBuffer,
kBlobKeyLen, offsetKey);
1192 bool rv =
fDirectory->GetFile()->WriteBuffer((
char *)(buffer), nbytes);
1210 bool rv = file->WriteBuffer((
char *)(buffer), nbytes);
1229 fileSimple.
fControlBlock = std::make_unique<ROOT::Internal::RTFileControlBlock>();
1237std::unique_ptr<ROOT::Internal::RNTupleFileWriter>
1241 std::string fileName(path);
1242 size_t idxDirSep = fileName.find_last_of(
"\\/");
1243 if (idxDirSep != std::string::npos) {
1244 fileName.erase(0, idxDirSep + 1);
1247 int flags = O_WRONLY | O_CREAT | O_TRUNC;
1250 flags |= O_LARGEFILE;
1255 int fd = open(std::string(path).c_str(), flags, 0666);
1257 throw RException(
R__FAIL(std::string(
"open failed for file \"") + std::string(path) +
"\": " + strerror(errno)));
1259 FILE *fileStream = fdopen(fd,
"wb");
1262 FILE *fileStream = fopen64(std::string(path.data(), path.size()).c_str(),
"wb");
1264 FILE *fileStream = fopen(std::string(path.data(), path.size()).c_str(),
"wb");
1268 throw RException(
R__FAIL(std::string(
"open failed for file \"") + std::string(path) +
"\": " + strerror(errno)));
1271 std::setvbuf(fileStream,
nullptr, _IONBF, 0);
1276 fileSimple.
fFile = fileStream;
1279 writer->fFileName = fileName;
1282 switch (containerFormat) {
1286 writer->WriteBareFileSkeleton(defaultCompression);
1288 default:
R__ASSERT(
false &&
"Internal error: unhandled container format");
1294std::unique_ptr<ROOT::Internal::RNTupleFileWriter>
1296 std::uint64_t maxKeySize,
bool hidden)
1300 throw RException(
R__FAIL(
"invalid attempt to add an RNTuple to a directory that is not backed by a file"));
1309std::unique_ptr<ROOT::Internal::RNTupleFileWriter>
1311 std::string_view ntupleDir, std::uint64_t maxKeySize)
1315 rfile.
fFile = &file;
1316 R__ASSERT(ntupleDir.empty() || ntupleDir[ntupleDir.size() - 1] ==
'/');
1317 rfile.fDir = ntupleDir;
1321std::unique_ptr<ROOT::Internal::RNTupleFileWriter>
1324 if (
auto *file = std::get_if<RImplTFile>(&
fFile)) {
1349 const auto WriteStreamerInfoToFile = [&](
TFile *file) {
1359 anchorInfo.
fLength = RTFNTuple{}.GetSize() +
sizeof(std::uint64_t);
1362 if (
auto fileProper = std::get_if<RImplTFile>(&
fFile)) {
1365 WriteStreamerInfoToFile(fileProper->fDirectory->GetFile());
1366 auto key =
static_cast<TKey *
>(fileProper->fDirectory->GetListOfKeys()->FindObject(
fNTupleName.c_str()));
1372 fileProper->fDirectory->GetFile()->Write();
1377 fileProper->fDirectory->GetListOfKeys()->Remove(key);
1379 }
else if (
auto fileRFile = std::get_if<RImplRFile>(&
fFile)) {
1383 auto key = fileRFile->fFile->GetKeyInfo(
fNTupleName);
1387 fileRFile->fFile->Flush();
1390 auto &fileSimple = std::get<RImplSimple>(
fFile);
1397 std::uint64_t checksum = XXH3_64bits(ntupleOnDisk.GetPtrCkData(), ntupleOnDisk.GetSizeCkData());
1398 memcpy(fileSimple.fHeaderBlock + fileSimple.fControlBlock->fSeekNTuple, &ntupleOnDisk, ntupleOnDisk.GetSize());
1399 memcpy(fileSimple.fHeaderBlock + fileSimple.fControlBlock->fSeekNTuple + ntupleOnDisk.GetSize(), &checksum,
1411 memcpy(fileSimple.fHeaderBlock, &fileSimple.fControlBlock->fHeader,
1412 fileSimple.fControlBlock->fHeader.GetSize());
1413 R__ASSERT(fileSimple.fControlBlock->fSeekFileRecord + fileSimple.fControlBlock->fFileRecord.GetSize() <
1415 memcpy(fileSimple.fHeaderBlock + fileSimple.fControlBlock->fSeekFileRecord,
1416 &fileSimple.fControlBlock->fFileRecord, fileSimple.fControlBlock->fFileRecord.GetSize());
1429 auto writeKey = [
this](
const void *payload,
size_t nBytes,
size_t length) {
1439 if (
static_cast<std::uint64_t
>(
len) >
static_cast<std::uint64_t
>(std::numeric_limits<std::uint32_t>::max()))
1442 if (nbytes <= maxKeySize) {
1444 return writeKey(
data, nbytes,
len);
1461 const size_t nbytesChunkOffsets = (nChunks - 1) *
sizeof(std::uint64_t);
1462 const size_t nbytesFirstChunk = maxKeySize - nbytesChunkOffsets;
1465 const uint8_t *chunkData =
reinterpret_cast<const uint8_t *
>(
data) + nbytesFirstChunk;
1466 size_t remainingBytes = nbytes - nbytesFirstChunk;
1469 std::uint64_t chunkOffsetIdx = 0;
1472 const size_t bytesNextChunk = std::min<size_t>(remainingBytes, maxKeySize);
1473 const std::uint64_t
offset = writeKey(chunkData, bytesNextChunk, bytesNextChunk);
1478 remainingBytes -= bytesNextChunk;
1479 chunkData += bytesNextChunk;
1481 }
while (remainingBytes > 0);
1484 const std::uint64_t firstOffset =
ReserveBlob(maxKeySize, maxKeySize);
1486 const std::uint64_t chunkOffsetsOffset = firstOffset + nbytesFirstChunk;
1499 if (
auto *fileSimple = std::get_if<RImplSimple>(&
fFile)) {
1501 offset = fileSimple->fKeyOffset;
1502 fileSimple->fKeyOffset += nbytes;
1504 offset = fileSimple->ReserveBlobKey(nbytes,
len, keyBuffer);
1506 }
else if (
auto *fileProper = std::get_if<RImplTFile>(&
fFile)) {
1507 offset = fileProper->ReserveBlobKey(nbytes,
len, keyBuffer);
1509 auto &fileRFile = std::get<RImplRFile>(
fFile);
1510 offset = fileRFile.ReserveBlobKey(nbytes,
len, keyBuffer);
1517 if (
auto *fileSimple = std::get_if<RImplSimple>(&
fFile)) {
1518 fileSimple->Write(buffer, nbytes,
offset);
1519 }
else if (
auto *fileProper = std::get_if<RImplTFile>(&
fFile)) {
1520 fileProper->Write(buffer, nbytes,
offset);
1522 auto &fileRFile = std::get<RImplRFile>(
fFile);
1523 fileRFile.Write(buffer, nbytes,
offset);
1547 RBareFileHeader bareHeader;
1548 bareHeader.fCompress = defaultCompression;
1549 auto &fileSimple = std::get<RImplSimple>(
fFile);
1550 fileSimple.Write(&bareHeader,
sizeof(bareHeader), 0);
1552 fileSimple.Write(&ntupleName, ntupleName.GetSize());
1555 RTFNTuple ntupleOnDisk;
1556 fileSimple.fControlBlock->fSeekNTuple = fileSimple.fFilePos;
1557 fileSimple.Write(&ntupleOnDisk, ntupleOnDisk.GetSize());
1558 std::uint64_t checksum = 0;
1559 fileSimple.Write(&checksum,
sizeof(checksum));
1560 fileSimple.fKeyOffset = fileSimple.fFilePos;
1570 TList streamerInfoList;
1572 streamerInfoList.
Add(info);
1581 RTFString strTList{
"TList"};
1582 RTFString strStreamerInfo{
"StreamerInfo"};
1583 RTFString strStreamerTitle{
"Doubly linked list"};
1584 auto &fileSimple = std::get<RImplSimple>(
fFile);
1585 fileSimple.fControlBlock->fHeader.SetSeekInfo(fileSimple.fKeyOffset);
1586 auto keyLen = RTFKey(fileSimple.fControlBlock->fHeader.GetSeekInfo(), RTFHeader::kBEGIN, strTList, strStreamerInfo,
1587 strStreamerTitle, 0)
1593 assert(buffer.
Length() > keyLen);
1594 const auto bufPayload = buffer.
Buffer() + keyLen;
1595 const auto lenPayload = buffer.
Length() - keyLen;
1598 auto szZipStreamerInfos =
RNTupleCompressor::Zip(bufPayload, lenPayload, compression, zipStreamerInfos.get());
1600 fileSimple.WriteKey(zipStreamerInfos.get(), szZipStreamerInfos, lenPayload,
1601 fileSimple.fControlBlock->fHeader.GetSeekInfo(), RTFHeader::kBEGIN,
"TList",
"StreamerInfo",
1602 "Doubly linked list");
1603 fileSimple.fControlBlock->fHeader.SetNbytesInfo(fileSimple.fFilePos -
1604 fileSimple.fControlBlock->fHeader.GetSeekInfo());
1610 RTFString strRNTupleClass{
"ROOT::RNTuple"};
1614 auto &fileSimple = std::get<RImplSimple>(
fFile);
1615 RTFKey keyRNTuple(fileSimple.fControlBlock->fSeekNTuple, RTFHeader::kBEGIN, strRNTupleClass, strRNTupleName,
1616 strEmpty, RTFNTuple::GetSizePlusChecksum(), anchorSize);
1618 fileSimple.fControlBlock->fFileRecord.SetSeekKeys(fileSimple.fKeyOffset);
1619 RTFKeyList keyList{1};
1620 RTFKey keyKeyList(fileSimple.fControlBlock->fFileRecord.GetSeekKeys(), RTFHeader::kBEGIN, strEmpty, strFileName,
1621 strEmpty, keyList.GetSize() + keyRNTuple.fKeyLen);
1622 fileSimple.Write(&keyKeyList, keyKeyList.GetHeaderSize(), fileSimple.fControlBlock->fFileRecord.GetSeekKeys());
1623 fileSimple.Write(&strEmpty, strEmpty.GetSize());
1624 fileSimple.Write(&strFileName, strFileName.GetSize());
1625 fileSimple.Write(&strEmpty, strEmpty.GetSize());
1626 fileSimple.Write(&keyList, keyList.GetSize());
1627 fileSimple.Write(&keyRNTuple, keyRNTuple.GetHeaderSize());
1629 fileSimple.Write(&strRNTupleClass, strRNTupleClass.GetSize());
1630 fileSimple.Write(&strRNTupleName, strRNTupleName.GetSize());
1631 fileSimple.Write(&strEmpty, strEmpty.GetSize());
1632 fileSimple.fControlBlock->fFileRecord.fNBytesKeys =
1633 fileSimple.fFilePos - fileSimple.fControlBlock->fFileRecord.GetSeekKeys();
1634 fileSimple.fKeyOffset = fileSimple.fFilePos;
1639 auto &fileSimple = std::get<RImplSimple>(
fFile);
1640 fileSimple.fControlBlock->fHeader.SetSeekFree(fileSimple.fKeyOffset);
1643 RTFFreeEntry freeEntry;
1644 RTFKey keyFreeList(fileSimple.fControlBlock->fHeader.GetSeekFree(), RTFHeader::kBEGIN, strEmpty, strFileName,
1645 strEmpty, freeEntry.GetSize());
1646 std::uint64_t firstFree = fileSimple.fControlBlock->fHeader.GetSeekFree() + keyFreeList.GetSize();
1647 freeEntry.Set(firstFree, std::max(2000000000ULL, ((firstFree / 1000000000ULL) + 1) * 1000000000ULL));
1648 fileSimple.WriteKey(&freeEntry, freeEntry.GetSize(), freeEntry.GetSize(),
1649 fileSimple.fControlBlock->fHeader.GetSeekFree(), RTFHeader::kBEGIN,
"",
fFileName,
"");
1650 fileSimple.fControlBlock->fHeader.SetNbytesFree(fileSimple.fFilePos -
1651 fileSimple.fControlBlock->fHeader.GetSeekFree());
1652 fileSimple.fControlBlock->fHeader.SetEnd(fileSimple.fFilePos);
1657 RTFString strRNTupleClass{
"ROOT::RNTuple"};
1662 RUInt64BE checksum{XXH3_64bits(ntupleOnDisk.GetPtrCkData(), ntupleOnDisk.GetSizeCkData())};
1663 auto &fileSimple = std::get<RImplSimple>(
fFile);
1664 fileSimple.fControlBlock->fSeekNTuple = fileSimple.fKeyOffset;
1666 char keyBuf[RTFNTuple::GetSizePlusChecksum()];
1669 memcpy(keyBuf, &ntupleOnDisk,
sizeof(RTFNTuple));
1670 memcpy(keyBuf +
sizeof(RTFNTuple), &checksum,
sizeof(checksum));
1672 const auto sizeAnchor =
sizeof(RTFNTuple) +
sizeof(checksum);
1673 char zipAnchor[RTFNTuple::GetSizePlusChecksum()];
1676 fileSimple.WriteKey(zipAnchor, szZipAnchor,
sizeof(keyBuf), fileSimple.fControlBlock->fSeekNTuple, RTFHeader::kBEGIN,
1683 RTFString strTFile{
"TFile"};
1687 auto &fileSimple = std::get<RImplSimple>(
fFile);
1688 fileSimple.fControlBlock->fHeader = RTFHeader(defaultCompression);
1693 RTFKey keyRoot(RTFHeader::kBEGIN, 0, strTFile, strFileName, strEmpty,
1694 sizeof(RTFDirectory) + strFileName.GetSize() + strEmpty.GetSize() + uuid.GetSize());
1695 std::uint32_t nbytesName = keyRoot.fKeyLen + strFileName.GetSize() + 1;
1696 fileSimple.fControlBlock->fFileRecord.fNBytesName = nbytesName;
1697 fileSimple.fControlBlock->fHeader.SetNbytesName(nbytesName);
1699 fileSimple.Write(&keyRoot, keyRoot.GetHeaderSize(), RTFHeader::kBEGIN);
1701 fileSimple.Write(&strTFile, strTFile.GetSize());
1702 fileSimple.Write(&strFileName, strFileName.GetSize());
1703 fileSimple.Write(&strEmpty, strEmpty.GetSize());
1705 fileSimple.Write(&strFileName, strFileName.GetSize());
1706 fileSimple.Write(&strEmpty, strEmpty.GetSize());
1708 fileSimple.fControlBlock->fSeekFileRecord = fileSimple.fFilePos;
1709 fileSimple.Write(&fileSimple.fControlBlock->fFileRecord, fileSimple.fControlBlock->fFileRecord.GetSize());
1710 fileSimple.Write(&uuid, uuid.GetSize());
1713 RUInt32BE padding{0};
1714 for (
int i = 0; i < 3; ++i)
1715 fileSimple.Write(&padding,
sizeof(padding));
1716 fileSimple.fKeyOffset = fileSimple.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...
RInterface & operator=(const RInterface &)=default
Copy-assignment operator for RInterface.
static size_t ComputeNumChunks(size_t nbytes, size_t maxChunkSize)
#define ROOT_VERSION_CODE
int Int_t
Signed integer 4 bytes (int)
#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()
Attempts to load the streamer info from the file.
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...
ROOT::Internal::RRawFile * fRawFile
The raw file used to read byte ranges.
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.
bool fIsBare
Indicates whether the file is a TFile container or an RNTuple bare file.
std::uint64_t fMaxKeySize
If fMaxKeySize > 0 and ReadBuffer attempts to read nbytes > maxKeySize, it will assume the blob being...
Helper class to compress data blocks in the ROOT compression frame format.
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.
Helper class to uncompress data blocks in the ROOT compression frame format.
static void Unzip(const void *from, size_t nbytes, size_t dataLen, void *to)
The nbytes parameter provides the size ls of the from buffer.
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.
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.
std::uint64_t WriteTFileNTupleKey(int compression)
The only key that will be visible in file->ls() Returns the size on disk of the anchor object.
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...
std::string fFileName
The file name without parent directory; only required when writing with a C file stream.
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)
void Seek(std::uint64_t offset)
Seek a simple writer to offset.
bool fIsBare
A simple file can either be written as TFile container or as NTuple bare file.
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.
A helper class for serializing and deserialization of the RNTuple binary format.
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.
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::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.
TKey(const TKey &)=delete
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)
std::unique_ptr< T[]> MakeUninitArray(std::size_t size)
Make an array of default-initialized elements.
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)
bool fDirectIO
Whether the C file stream has been opened with Direct I/O, introducing alignment requirements.
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 ...
unsigned char * fHeaderBlock
std::uint64_t fBlockOffset
static constexpr int kBlockAlign
Direct I/O requires that all buffers and write lengths are aligned.
std::unique_ptr< ROOT::Internal::RTFileControlBlock > fControlBlock
Keeps track of TFile control structures, which need to be updated on committing the data set.
void Write(const void *buffer, size_t nbytes, std::int64_t offset=-1)
Writes bytes in the open stream, either at fFilePos or at the given offset.
static constexpr std::size_t kHeaderBlockSize
During commit, WriteTFileKeysList() updates fNBytesKeys and fSeekKeys of the RTFFile located at fSeek...
std::uint64_t fFilePos
Keeps track of the seek offset.
FILE * fFile
For the simplest cases, a C file stream can be used for writing.
std::uint64_t ReserveBlobKey(std::size_t nbytes, std::size_t len, unsigned char keyBuffer[kBlobKeyLen]=nullptr)
Reserves an RBlob opaque key as data record and returns the offset of the record.
std::uint64_t fKeyOffset
Keeps track of the next key offset.
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