49#ifndef R__LITTLE_ENDIAN
52#define R__LITTLE_ENDIAN 1
54#define R__LITTLE_ENDIAN 0
70 std::uint16_t fValBE = 0;
71 static std::uint16_t Swap(std::uint16_t val)
73#if R__LITTLE_ENDIAN == 1
74 return RByteSwap<
sizeof(val)>::bswap(val);
81 RUInt16BE() =
default;
82 explicit RUInt16BE(
const std::uint16_t val) : fValBE(Swap(val)) {}
83 operator std::uint16_t()
const {
return Swap(fValBE); }
84 RUInt16BE &
operator=(
const std::uint16_t val)
94 std::uint32_t fValBE = 0;
95 static std::uint32_t Swap(std::uint32_t val)
97#if R__LITTLE_ENDIAN == 1
98 return RByteSwap<
sizeof(val)>::bswap(val);
105 RUInt32BE() =
default;
106 explicit RUInt32BE(
const std::uint32_t val) : fValBE(Swap(val)) {}
107 operator std::uint32_t()
const {
return Swap(fValBE); }
108 RUInt32BE &
operator=(
const std::uint32_t val)
118 std::int32_t fValBE = 0;
119 static std::int32_t Swap(std::int32_t val)
121#if R__LITTLE_ENDIAN == 1
122 return RByteSwap<
sizeof(val)>::bswap(val);
129 RInt32BE() =
default;
130 explicit RInt32BE(
const std::int32_t val) : fValBE(Swap(val)) {}
131 operator std::int32_t()
const {
return Swap(fValBE); }
132 RInt32BE &
operator=(
const std::int32_t val)
142 std::uint64_t fValBE = 0;
143 static std::uint64_t Swap(std::uint64_t val)
145#if R__LITTLE_ENDIAN == 1
146 return RByteSwap<
sizeof(val)>::bswap(val);
153 RUInt64BE() =
default;
154 explicit RUInt64BE(
const std::uint64_t val) : fValBE(Swap(val)) {}
155 operator std::uint64_t()
const {
return Swap(fValBE); }
156 RUInt64BE &
operator=(
const std::uint64_t val)
166 unsigned char fLName{0};
168 RTFString() =
default;
169 RTFString(
const std::string &str)
174 fLName =
static_cast<unsigned char>(str.length());
175 memcpy(fData, str.data(), fLName);
177 std::size_t GetSize()
const
191 auto now = std::chrono::system_clock::now();
192 auto tt = std::chrono::system_clock::to_time_t(now);
193 auto tm = *localtime(&
tt);
194 fDatetime = (tm.tm_year + 1900 - 1995) << 26 | (tm.tm_mon + 1) << 22 | tm.tm_mday << 17 | tm.tm_hour << 12 |
195 tm.tm_min << 6 | tm.tm_sec;
197 explicit RTFDatetime(RUInt32BE val) : fDatetime(val) {}
202 static constexpr unsigned kBigKeyVersion = 1000;
205 RUInt16BE fVersion{4};
206 RUInt32BE fObjLen{0};
207 RTFDatetime fDatetime;
208 RUInt16BE fKeyLen{0};
212 RUInt32BE fSeekKey{0};
213 RUInt32BE fSeekPdir{0};
216 RUInt64BE fSeekKey{0};
217 RUInt64BE fSeekPdir{0};
221 RTFKey() : fInfoLong() {}
222 RTFKey(std::uint64_t seekKey, std::uint64_t seekPdir,
const RTFString &clName,
const RTFString &objName,
223 const RTFString &titleName, std::size_t szObjInMem, std::size_t szObjOnDisk = 0)
225 R__ASSERT(szObjInMem <= std::numeric_limits<std::uint32_t>::max());
226 R__ASSERT(szObjOnDisk <= std::numeric_limits<std::uint32_t>::max());
228 fVersion = fVersion + kBigKeyVersion;
229 fObjLen = szObjInMem;
230 fKeyLen =
static_cast<RUInt16BE
>(GetHeaderSize() + clName.GetSize() + objName.GetSize() + titleName.GetSize());
231 fInfoLong.fSeekKey = seekKey;
232 fInfoLong.fSeekPdir = seekPdir;
234 fNbytes = fKeyLen + ((szObjOnDisk == 0) ? szObjInMem : szObjOnDisk);
237 std::uint32_t GetSize()
const
245 std::uint32_t GetHeaderSize()
const
247 if (fVersion >= kBigKeyVersion)
248 return 18 +
sizeof(fInfoLong);
249 return 18 +
sizeof(fInfoShort);
252 std::uint64_t GetSeekKey()
const
254 if (fVersion >= kBigKeyVersion)
255 return fInfoLong.fSeekKey;
256 return fInfoShort.fSeekKey;
262 static constexpr unsigned kBEGIN = 100;
263 static constexpr unsigned kBigHeaderVersion = 1000000;
265 char fMagic[4]{
'r',
'o',
'o',
't'};
272 RUInt32BE fSeekFree{0};
273 RUInt32BE fNbytesFree{0};
275 RUInt32BE fNbytesName{0};
276 unsigned char fUnits{4};
277 RUInt32BE fCompress{0};
278 RUInt32BE fSeekInfo{0};
279 RUInt32BE fNbytesInfo{0};
283 RUInt64BE fSeekFree{0};
284 RUInt32BE fNbytesFree{0};
286 RUInt32BE fNbytesName{0};
287 unsigned char fUnits{8};
288 RUInt32BE fCompress{0};
289 RUInt64BE fSeekInfo{0};
290 RUInt32BE fNbytesInfo{0};
294 RTFHeader() : fInfoShort() {}
295 RTFHeader(
int compression) : fInfoShort() { fInfoShort.fCompress = compression; }
299 if (fVersion >= kBigHeaderVersion)
303 std::uint32_t end = fInfoShort.fEND;
304 std::uint32_t seekFree = fInfoShort.fSeekFree;
305 std::uint32_t nbytesFree = fInfoShort.fNbytesFree;
306 std::uint32_t nFree = fInfoShort.fNfree;
307 std::uint32_t nbytesName = fInfoShort.fNbytesName;
308 std::uint32_t compress = fInfoShort.fCompress;
309 std::uint32_t seekInfo = fInfoShort.fSeekInfo;
310 std::uint32_t nbytesInfo = fInfoShort.fNbytesInfo;
311 fInfoLong.fEND = end;
312 fInfoLong.fSeekFree = seekFree;
313 fInfoLong.fNbytesFree = nbytesFree;
314 fInfoLong.fNfree = nFree;
315 fInfoLong.fNbytesName = nbytesName;
316 fInfoLong.fUnits = 8;
317 fInfoLong.fCompress = compress;
318 fInfoLong.fSeekInfo = seekInfo;
319 fInfoLong.fNbytesInfo = nbytesInfo;
320 fVersion = fVersion + kBigHeaderVersion;
324 bool IsBigFile(std::uint64_t offset = 0)
const
326 return (fVersion >= kBigHeaderVersion) ||
327 (offset >
static_cast<unsigned int>(std::numeric_limits<std::int32_t>::max()));
330 std::uint32_t GetSize()
const
332 std::uint32_t sizeHead =
sizeof(fMagic) +
sizeof(fVersion) +
sizeof(fBEGIN);
334 return sizeHead +
sizeof(fInfoLong);
335 return sizeHead +
sizeof(fInfoShort);
338 std::uint64_t GetEnd()
const
341 return fInfoLong.fEND;
342 return fInfoShort.fEND;
345 void SetEnd(std::uint64_t value)
347 if (IsBigFile(value)) {
349 fInfoLong.fEND = value;
351 fInfoShort.fEND = value;
355 std::uint64_t GetSeekFree()
const
358 return fInfoLong.fSeekFree;
359 return fInfoShort.fSeekFree;
362 void SetSeekFree(std::uint64_t value)
364 if (IsBigFile(value)) {
366 fInfoLong.fSeekFree = value;
368 fInfoShort.fSeekFree = value;
372 void SetNbytesFree(std::uint32_t value)
375 fInfoLong.fNbytesFree = value;
377 fInfoShort.fNbytesFree = value;
381 void SetNbytesName(std::uint32_t value)
384 fInfoLong.fNbytesName = value;
386 fInfoShort.fNbytesName = value;
390 std::uint64_t GetSeekInfo()
const
393 return fInfoLong.fSeekInfo;
394 return fInfoShort.fSeekInfo;
397 void SetSeekInfo(std::uint64_t value)
399 if (IsBigFile(value)) {
401 fInfoLong.fSeekInfo = value;
403 fInfoShort.fSeekInfo = value;
407 std::uint64_t GetNbytesInfo()
const
410 return fInfoLong.fNbytesInfo;
411 return fInfoShort.fNbytesInfo;
414 void SetNbytesInfo(std::uint32_t value)
417 fInfoLong.fNbytesInfo = value;
419 fInfoShort.fNbytesInfo = value;
423 void SetCompression(std::uint32_t value)
426 fInfoLong.fCompress = value;
428 fInfoShort.fCompress = value;
435 static constexpr unsigned kBigFreeEntryVersion = 1000;
437 RUInt16BE fVersion{1};
449 RTFFreeEntry() : fInfoShort() {}
450 void Set(std::uint64_t first, std::uint64_t last)
452 if (last >
static_cast<unsigned int>(std::numeric_limits<std::int32_t>::max())) {
453 fVersion = fVersion + kBigFreeEntryVersion;
454 fInfoLong.fFirst = first;
455 fInfoLong.fLast = last;
457 fInfoShort.fFirst = first;
458 fInfoShort.fLast = last;
461 std::uint32_t GetSize() {
return (fVersion >= kBigFreeEntryVersion) ? 18 : 10; }
467 std::uint32_t GetSize()
const {
return sizeof(RTFKeyList); }
468 explicit RTFKeyList(std::uint32_t nKeys) : fNKeys(nKeys) {}
473 static constexpr unsigned kBigFileVersion = 1000;
475 RUInt16BE fClassVersion{5};
478 RUInt32BE fNBytesKeys{0};
479 RUInt32BE fNBytesName{0};
483 RUInt32BE fSeekDir{RTFHeader::kBEGIN};
484 RUInt32BE fSeekParent{0};
485 RUInt32BE fSeekKeys{0};
488 RUInt64BE fSeekDir{RTFHeader::kBEGIN};
489 RUInt64BE fSeekParent{0};
490 RUInt64BE fSeekKeys{0};
494 RTFDirectory() : fInfoShort() {}
497 std::uint32_t GetSize()
const
499 if (fClassVersion >= kBigFileVersion)
500 return sizeof(RTFDirectory);
501 return 18 +
sizeof(fInfoShort);
504 std::uint64_t GetSeekKeys()
const
506 if (fClassVersion >= kBigFileVersion)
507 return fInfoLong.fSeekKeys;
508 return fInfoShort.fSeekKeys;
511 void SetSeekKeys(std::uint64_t seekKeys)
513 if (seekKeys >
static_cast<unsigned int>(std::numeric_limits<std::int32_t>::max())) {
514 std::uint32_t seekDir = fInfoShort.fSeekDir;
515 std::uint32_t seekParent = fInfoShort.fSeekParent;
516 fInfoLong.fSeekDir = seekDir;
517 fInfoLong.fSeekParent = seekParent;
518 fInfoLong.fSeekKeys = seekKeys;
519 fClassVersion = fClassVersion + kBigFileVersion;
521 fInfoShort.fSeekKeys = seekKeys;
528 RUInt16BE fVersionClass{1};
529 unsigned char fUUID[16];
534 char *buffer =
reinterpret_cast<char *
>(
this);
536 assert(
reinterpret_cast<RTFUUID *
>(buffer) <= (
this + 1));
538 std::uint32_t GetSize()
const {
return sizeof(RTFUUID); }
547 RUInt32BE fByteCount{0x40000000 | (
sizeof(RTFNTuple) -
sizeof(fByteCount))};
548 RUInt16BE fVersionClass{2};
549 RUInt16BE fVersionEpoch{0};
550 RUInt16BE fVersionMajor{0};
551 RUInt16BE fVersionMinor{0};
552 RUInt16BE fVersionPatch{0};
553 RUInt64BE fSeekHeader{0};
554 RUInt64BE fNBytesHeader{0};
555 RUInt64BE fLenHeader{0};
556 RUInt64BE fSeekFooter{0};
557 RUInt64BE fNBytesFooter{0};
558 RUInt64BE fLenFooter{0};
559 RUInt64BE fMaxKeySize{0};
561 static constexpr std::uint32_t GetSizePlusChecksum() {
return sizeof(RTFNTuple) +
sizeof(std::uint64_t); }
563 RTFNTuple() =
default;
578 std::uint32_t GetSize()
const {
return sizeof(RTFNTuple); }
580 std::uint32_t GetOffsetCkData() {
return sizeof(fByteCount) +
sizeof(fVersionClass); }
581 std::uint32_t GetSizeCkData() {
return GetSize() - GetOffsetCkData(); }
582 unsigned char *GetPtrCkData() {
return reinterpret_cast<unsigned char *
>(
this) + GetOffsetCkData(); }
586struct RBareFileHeader {
587 char fMagic[7]{
'r',
'n',
't',
'u',
'p',
'l',
'e'};
590 RUInt32BE fFormatVersion{1};
591 RUInt32BE fCompress{0};
598constexpr char const *kBlobClassName =
"RBlob";
600constexpr char const *kNTupleClassName =
"ROOT::RNTuple";
631 void Reserve(
size_t nbytes, std::uint64_t *seekKey)
650 constexpr size_t kChunkOffsetSize =
sizeof(std::uint64_t);
652 assert(nbytes > maxChunkSize);
653 size_t nChunks = (nbytes + maxChunkSize - 1) / maxChunkSize;
655 size_t nbytesTail = nbytes % maxChunkSize;
656 size_t nbytesExtra = (nbytesTail > 0) * (maxChunkSize - nbytesTail);
657 size_t nbytesChunkOffsets = (nChunks - 1) * kChunkOffsetSize;
658 if (nbytesChunkOffsets > nbytesExtra) {
660 nbytesChunkOffsets += kChunkOffsetSize;
667 R__ASSERT(nbytesChunkOffsets <= maxChunkSize);
678 if (std::string(ident, 4) ==
"root")
687 std::string_view typeName)
689 RTFDirectory directory;
690 ReadBuffer(&directory,
sizeof(directory), offsetDir);
694 std::uint64_t offset = directory.GetSeekKeys();
696 offset += key.fKeyLen;
698 offset +=
sizeof(nKeys);
700 for (
unsigned int i = 0; i < nKeys; ++i) {
702 auto offsetNextKey = offset + key.fKeyLen;
704 offset += key.GetHeaderSize();
708 if (std::string_view(
name.fData,
name.fLName) != typeName) {
709 offset = offsetNextKey;
712 offset +=
name.GetSize();
715 if (std::string_view(
name.fData,
name.fLName) == keyName) {
716 return key.GetSeekKey();
718 offset = offsetNextKey;
727 RTFHeader fileHeader;
728 ReadBuffer(&fileHeader,
sizeof(fileHeader), 0);
730 const std::uint64_t seekKeyInfo = fileHeader.GetSeekInfo();
735 const std::uint64_t nbytesInfo = fileHeader.GetNbytesInfo() - key.fKeyLen;
736 const std::uint64_t seekInfo = seekKeyInfo + key.fKeyLen;
737 const std::uint32_t uncompLenInfo = key.fObjLen;
739 if (nbytesInfo == uncompLenInfo) {
741 ReadBuffer(streamerInfo.get(), nbytesInfo, seekInfo);
744 ReadBuffer(buffer.get(), nbytesInfo, seekInfo);
754 TList streamerInfoList;
771 RTFHeader fileHeader;
772 ReadBuffer(&fileHeader,
sizeof(fileHeader), 0);
776 ReadBuffer(&key,
sizeof(key), fileHeader.fBEGIN);
778 std::uint64_t offset = fileHeader.fBEGIN + key.fKeyLen;
781 offset +=
name.GetSize();
783 offset +=
name.GetSize();
786 std::string ntuplePathTail(ntuplePath);
787 if (!ntuplePathTail.empty() && ntuplePathTail[0] ==
'/')
788 ntuplePathTail = ntuplePathTail.substr(1);
789 auto pos = std::string::npos;
790 while ((
pos = ntuplePathTail.find(
'/')) != std::string::npos) {
791 auto directoryName = ntuplePathTail.substr(0,
pos);
792 ntuplePathTail.erase(0,
pos + 1);
796 return R__FAIL(
"no directory named '" + std::string(directoryName) +
"' in file '" +
fRawFile->GetUrl() +
"'");
799 offset = key.GetSeekKey() + key.fKeyLen;
802 auto ntupleName = ntuplePathTail;
806 return R__FAIL(
"no RNTuple named '" + std::string(ntupleName) +
"' in file '" +
fRawFile->GetUrl() +
"'");
810 offset = key.GetSeekKey() + key.fKeyLen;
813 constexpr size_t kMinNTupleSize = 78;
814 static_assert(kMinNTupleSize == RTFNTuple::GetSizePlusChecksum());
815 if (key.fObjLen < kMinNTupleSize) {
816 return R__FAIL(
"invalid anchor size: " + std::to_string(key.fObjLen) +
" < " + std::to_string(
sizeof(RTFNTuple)));
819 const auto objNbytes = key.GetSize() - key.fKeyLen;
825 std::uint64_t compSize,
826 std::uint64_t uncompLen)
831 RTFNTuple *ntuple =
new (bufAnchor.get()) RTFNTuple;
833 if (compSize != uncompLen) {
836 ReadBuffer(unzipBuf.get(), compSize, payloadOffset);
845 const auto lenCkData = uncompLen - ntuple->GetOffsetCkData() -
sizeof(uint64_t);
846 const auto ckCalc = XXH3_64bits(ntuple->GetPtrCkData(), lenCkData);
849 RUInt64BE *ckOnDiskPtr =
reinterpret_cast<RUInt64BE *
>(bufAnchor.get() + uncompLen -
sizeof(uint64_t));
850 ckOnDisk =
static_cast<uint64_t
>(*ckOnDiskPtr);
851 if (ckCalc != ckOnDisk) {
852 return R__FAIL(
"RNTuple anchor checksum mismatch");
855 return CreateAnchor(ntuple->fVersionEpoch, ntuple->fVersionMajor, ntuple->fVersionMinor, ntuple->fVersionPatch,
856 ntuple->fSeekHeader, ntuple->fNBytesHeader, ntuple->fLenHeader, ntuple->fSeekFooter,
857 ntuple->fNBytesFooter, ntuple->fLenFooter, ntuple->fMaxKeySize);
862 RBareFileHeader fileHeader;
863 ReadBuffer(&fileHeader,
sizeof(fileHeader), 0);
865 auto offset =
sizeof(fileHeader);
868 std::string_view foundName(
name.fData,
name.fLName);
869 if (foundName != ntupleName) {
870 return R__FAIL(
"expected RNTuple named '" + std::string(ntupleName) +
"' but instead found '" +
871 std::string(foundName) +
"' in file '" +
fRawFile->GetUrl() +
"'");
873 offset +=
name.GetSize();
877 std::uint64_t onDiskChecksum;
878 ReadBuffer(&onDiskChecksum,
sizeof(onDiskChecksum), offset +
sizeof(ntuple));
879 auto checksum = XXH3_64bits(ntuple.GetPtrCkData(), ntuple.GetSizeCkData());
880 if (checksum !=
static_cast<uint64_t
>(onDiskChecksum))
881 return R__FAIL(
"RNTuple bare file: anchor checksum mismatch");
883 return CreateAnchor(ntuple.fVersionEpoch, ntuple.fVersionMajor, ntuple.fVersionMinor, ntuple.fVersionPatch,
884 ntuple.fSeekHeader, ntuple.fNBytesHeader, ntuple.fLenHeader, ntuple.fSeekFooter,
885 ntuple.fNBytesFooter, ntuple.fLenFooter, ntuple.fMaxKeySize);
895 const auto ByteReadErr = [](std::size_t expected, std::size_t nread) {
896 return R__FAIL(
"invalid read (expected bytes: " + std::to_string(expected) +
", read: " + std::to_string(nread) +
903 nread =
fRawFile->ReadAt(buffer, nbytes, offset);
907 const size_t nbytesChunkOffsets = (nChunks - 1) *
sizeof(std::uint64_t);
908 const size_t nbytesFirstChunk =
fMaxKeySize - nbytesChunkOffsets;
909 uint8_t *bufCur =
reinterpret_cast<uint8_t *
>(buffer);
919 bufCur += nbytesFirstChunk;
920 nread -= nbytesChunkOffsets;
923 memcpy(chunkOffsets.get(), bufCur, nbytesChunkOffsets);
925 size_t remainingBytes = nbytes - nbytesFirstChunk;
926 std::uint64_t *curChunkOffset = &chunkOffsets[0];
929 std::uint64_t chunkOffset;
933 const size_t bytesToRead = std::min<size_t>(
fMaxKeySize, remainingBytes);
935 R__ASSERT(
static_cast<size_t>(bufCur -
reinterpret_cast<uint8_t *
>(buffer)) <= nbytes - bytesToRead);
937 auto nbytesRead =
fRawFile->ReadAt(bufCur, bytesToRead, chunkOffset);
938 if (nbytesRead != bytesToRead)
939 return ByteReadErr(bytesToRead, nbytesRead);
941 nread += bytesToRead;
942 bufCur += bytesToRead;
943 remainingBytes -= bytesToRead;
944 }
while (remainingBytes > 0);
948 return ByteReadErr(nbytes, nread);
960 RTFString strClass{kBlobClassName};
963 RTFKey keyHeader(offset, RTFHeader::kBEGIN, strClass, strObject, strTitle, len, nbytes);
967 unsigned char *writeBuffer = buffer;
968 memcpy(writeBuffer, &keyHeader, keyHeader.GetHeaderSize());
969 writeBuffer += keyHeader.GetHeaderSize();
970 memcpy(writeBuffer, &strClass, strClass.GetSize());
971 writeBuffer += strClass.GetSize();
972 memcpy(writeBuffer, &strObject, strObject.GetSize());
973 writeBuffer += strObject.GetSize();
974 memcpy(writeBuffer, &strTitle, strTitle.GetSize());
975 writeBuffer += strTitle.GetSize();
987 throw RException(
R__FAIL(
"Buffer size not a multiple of alignment: " + std::to_string(bufferSize)));
993 fBlock =
static_cast<unsigned char *
>(::operator
new[](
fBlockSize, blockAlign));
1006 ::operator
delete[](
fBlock, blockAlign);
1010int FSeek64(FILE *stream, std::int64_t offset,
int origin)
1013 return fseeko64(stream, offset, origin);
1015 return fseek(stream, offset, origin);
1045 if (retval != lastBlockSize)
1050 retval = FSeek64(
fFile, 0, SEEK_SET);
1059 retval = fflush(
fFile);
1068 if ((offset >= 0) && (
static_cast<std::uint64_t
>(offset) !=
fFilePos)) {
1074 std::size_t headerBytes = nbytes;
1083 while (nbytes > 0) {
1085 std::uint64_t blockOffset =
fFilePos - posInBlock;
1101 std::size_t blockSize = nbytes;
1105 memcpy(
fBlock + posInBlock, buffer, blockSize);
1106 buffer =
static_cast<const unsigned char *
>(buffer) + blockSize;
1107 nbytes -= blockSize;
1114 std::int64_t offset, std::uint64_t directoryOffset,
1115 const std::string &className,
const std::string &objectName,
1116 const std::string &title)
1120 RTFString strClass{className};
1121 RTFString strObject{objectName};
1122 RTFString strTitle{title};
1124 RTFKey key(
fKeyOffset, directoryOffset, strClass, strObject, strTitle, len, nbytes);
1126 Write(&strClass, strClass.GetSize());
1127 Write(&strObject, strObject.GetSize());
1128 Write(&strTitle, strTitle.GetSize());
1133 Write(buffer, nbytes);
1158template <
typename T>
1160 std::size_t len,
unsigned char keyBuffer[
kBlobKeyLen])
1162 std::uint64_t offsetKey;
1166 keyBlob.
Reserve(nbytes, &offsetKey);
1173 caller.Write(localKeyBuffer,
kBlobKeyLen, offsetKey);
1191 bool rv =
fDirectory->GetFile()->WriteBuffer((
char *)(buffer), nbytes);
1209 bool rv = file->WriteBuffer((
char *)(buffer), nbytes);
1228 fileSimple.
fControlBlock = std::make_unique<ROOT::Internal::RTFileControlBlock>();
1236std::unique_ptr<ROOT::Internal::RNTupleFileWriter>
1240 std::string fileName(path);
1241 size_t idxDirSep = fileName.find_last_of(
"\\/");
1242 if (idxDirSep != std::string::npos) {
1243 fileName.erase(0, idxDirSep + 1);
1246 int flags = O_WRONLY | O_CREAT | O_TRUNC;
1249 flags |= O_LARGEFILE;
1254 int fd = open(std::string(path).c_str(), flags, 0666);
1256 throw RException(
R__FAIL(std::string(
"open failed for file \"") + std::string(path) +
"\": " + strerror(errno)));
1258 FILE *fileStream = fdopen(fd,
"wb");
1261 FILE *fileStream = fopen64(std::string(path.data(), path.size()).c_str(),
"wb");
1263 FILE *fileStream = fopen(std::string(path.data(), path.size()).c_str(),
"wb");
1267 throw RException(
R__FAIL(std::string(
"open failed for file \"") + std::string(path) +
"\": " + strerror(errno)));
1270 std::setvbuf(fileStream,
nullptr, _IONBF, 0);
1275 fileSimple.
fFile = fileStream;
1278 writer->fFileName = fileName;
1281 switch (containerFormat) {
1285 writer->WriteBareFileSkeleton(defaultCompression);
1287 default:
R__ASSERT(
false &&
"Internal error: unhandled container format");
1293std::unique_ptr<ROOT::Internal::RNTupleFileWriter>
1295 std::uint64_t maxKeySize,
bool hidden)
1299 throw RException(
R__FAIL(
"invalid attempt to add an RNTuple to a directory that is not backed by a file"));
1308std::unique_ptr<ROOT::Internal::RNTupleFileWriter>
1310 std::string_view ntupleDir, std::uint64_t maxKeySize)
1314 rfile.
fFile = &file;
1315 R__ASSERT(ntupleDir.empty() || ntupleDir[ntupleDir.size() - 1] ==
'/');
1316 rfile.fDir = ntupleDir;
1320std::unique_ptr<ROOT::Internal::RNTupleFileWriter>
1323 if (
auto *file = std::get_if<RImplTFile>(&
fFile)) {
1348 const auto WriteStreamerInfoToFile = [&](
TFile *file) {
1358 anchorInfo.
fLength = RTFNTuple{}.GetSize() +
sizeof(std::uint64_t);
1361 if (
auto fileProper = std::get_if<RImplTFile>(&
fFile)) {
1364 WriteStreamerInfoToFile(fileProper->fDirectory->GetFile());
1365 auto key =
static_cast<TKey *
>(fileProper->fDirectory->GetListOfKeys()->FindObject(
fNTupleName.c_str()));
1371 fileProper->fDirectory->GetFile()->Write();
1376 fileProper->fDirectory->GetListOfKeys()->Remove(key);
1378 }
else if (
auto fileRFile = std::get_if<RImplRFile>(&
fFile)) {
1382 auto key = fileRFile->fFile->GetKeyInfo(
fNTupleName);
1386 fileRFile->fFile->Flush();
1389 auto &fileSimple = std::get<RImplSimple>(
fFile);
1396 std::uint64_t checksum = XXH3_64bits(ntupleOnDisk.GetPtrCkData(), ntupleOnDisk.GetSizeCkData());
1397 memcpy(fileSimple.fHeaderBlock + fileSimple.fControlBlock->fSeekNTuple, &ntupleOnDisk, ntupleOnDisk.GetSize());
1398 memcpy(fileSimple.fHeaderBlock + fileSimple.fControlBlock->fSeekNTuple + ntupleOnDisk.GetSize(), &checksum,
1410 memcpy(fileSimple.fHeaderBlock, &fileSimple.fControlBlock->fHeader,
1411 fileSimple.fControlBlock->fHeader.GetSize());
1412 R__ASSERT(fileSimple.fControlBlock->fSeekFileRecord + fileSimple.fControlBlock->fFileRecord.GetSize() <
1414 memcpy(fileSimple.fHeaderBlock + fileSimple.fControlBlock->fSeekFileRecord,
1415 &fileSimple.fControlBlock->fFileRecord, fileSimple.fControlBlock->fFileRecord.GetSize());
1428 auto writeKey = [
this](
const void *payload,
size_t nBytes,
size_t length) {
1429 std::uint64_t offset =
ReserveBlob(nBytes, length);
1438 if (
static_cast<std::uint64_t
>(len) >
static_cast<std::uint64_t
>(std::numeric_limits<std::uint32_t>::max()))
1441 if (nbytes <= maxKeySize) {
1443 return writeKey(data, nbytes, len);
1460 const size_t nbytesChunkOffsets = (nChunks - 1) *
sizeof(std::uint64_t);
1461 const size_t nbytesFirstChunk = maxKeySize - nbytesChunkOffsets;
1464 const uint8_t *chunkData =
reinterpret_cast<const uint8_t *
>(data) + nbytesFirstChunk;
1465 size_t remainingBytes = nbytes - nbytesFirstChunk;
1468 std::uint64_t chunkOffsetIdx = 0;
1471 const size_t bytesNextChunk = std::min<size_t>(remainingBytes, maxKeySize);
1472 const std::uint64_t offset = writeKey(chunkData, bytesNextChunk, bytesNextChunk);
1477 remainingBytes -= bytesNextChunk;
1478 chunkData += bytesNextChunk;
1480 }
while (remainingBytes > 0);
1483 const std::uint64_t firstOffset =
ReserveBlob(maxKeySize, maxKeySize);
1485 const std::uint64_t chunkOffsetsOffset = firstOffset + nbytesFirstChunk;
1497 std::uint64_t offset;
1498 if (
auto *fileSimple = std::get_if<RImplSimple>(&
fFile)) {
1500 offset = fileSimple->fKeyOffset;
1501 fileSimple->fKeyOffset += nbytes;
1503 offset = fileSimple->ReserveBlobKey(nbytes, len, keyBuffer);
1505 }
else if (
auto *fileProper = std::get_if<RImplTFile>(&
fFile)) {
1506 offset = fileProper->ReserveBlobKey(nbytes, len, keyBuffer);
1508 auto &fileRFile = std::get<RImplRFile>(
fFile);
1509 offset = fileRFile.ReserveBlobKey(nbytes, len, keyBuffer);
1516 if (
auto *fileSimple = std::get_if<RImplSimple>(&
fFile)) {
1517 fileSimple->Write(buffer, nbytes, offset);
1518 }
else if (
auto *fileProper = std::get_if<RImplTFile>(&
fFile)) {
1519 fileProper->Write(buffer, nbytes, offset);
1521 auto &fileRFile = std::get<RImplRFile>(
fFile);
1522 fileRFile.Write(buffer, nbytes, offset);
1528 auto offset =
WriteBlob(data, nbytes, lenHeader);
1537 auto offset =
WriteBlob(data, nbytes, lenFooter);
1546 RBareFileHeader bareHeader;
1547 bareHeader.fCompress = defaultCompression;
1548 auto &fileSimple = std::get<RImplSimple>(
fFile);
1549 fileSimple.Write(&bareHeader,
sizeof(bareHeader), 0);
1551 fileSimple.Write(&ntupleName, ntupleName.GetSize());
1554 RTFNTuple ntupleOnDisk;
1555 fileSimple.fControlBlock->fSeekNTuple = fileSimple.fFilePos;
1556 fileSimple.Write(&ntupleOnDisk, ntupleOnDisk.GetSize());
1557 std::uint64_t checksum = 0;
1558 fileSimple.Write(&checksum,
sizeof(checksum));
1559 fileSimple.fKeyOffset = fileSimple.fFilePos;
1569 TList streamerInfoList;
1571 streamerInfoList.
Add(info);
1580 RTFString strTList{
"TList"};
1581 RTFString strStreamerInfo{
"StreamerInfo"};
1582 RTFString strStreamerTitle{
"Doubly linked list"};
1583 auto &fileSimple = std::get<RImplSimple>(
fFile);
1584 fileSimple.fControlBlock->fHeader.SetSeekInfo(fileSimple.fKeyOffset);
1585 auto keyLen = RTFKey(fileSimple.fControlBlock->fHeader.GetSeekInfo(), RTFHeader::kBEGIN, strTList, strStreamerInfo,
1586 strStreamerTitle, 0)
1592 assert(buffer.
Length() > keyLen);
1593 const auto bufPayload = buffer.
Buffer() + keyLen;
1594 const auto lenPayload = buffer.
Length() - keyLen;
1597 auto szZipStreamerInfos =
RNTupleCompressor::Zip(bufPayload, lenPayload, compression, zipStreamerInfos.get());
1599 fileSimple.WriteKey(zipStreamerInfos.get(), szZipStreamerInfos, lenPayload,
1600 fileSimple.fControlBlock->fHeader.GetSeekInfo(), RTFHeader::kBEGIN,
"TList",
"StreamerInfo",
1601 "Doubly linked list");
1602 fileSimple.fControlBlock->fHeader.SetNbytesInfo(fileSimple.fFilePos -
1603 fileSimple.fControlBlock->fHeader.GetSeekInfo());
1609 RTFString strRNTupleClass{
"ROOT::RNTuple"};
1613 auto &fileSimple = std::get<RImplSimple>(
fFile);
1614 RTFKey keyRNTuple(fileSimple.fControlBlock->fSeekNTuple, RTFHeader::kBEGIN, strRNTupleClass, strRNTupleName,
1615 strEmpty, RTFNTuple::GetSizePlusChecksum(), anchorSize);
1617 fileSimple.fControlBlock->fFileRecord.SetSeekKeys(fileSimple.fKeyOffset);
1618 RTFKeyList keyList{1};
1619 RTFKey keyKeyList(fileSimple.fControlBlock->fFileRecord.GetSeekKeys(), RTFHeader::kBEGIN, strEmpty, strFileName,
1620 strEmpty, keyList.GetSize() + keyRNTuple.fKeyLen);
1621 fileSimple.Write(&keyKeyList, keyKeyList.GetHeaderSize(), fileSimple.fControlBlock->fFileRecord.GetSeekKeys());
1622 fileSimple.Write(&strEmpty, strEmpty.GetSize());
1623 fileSimple.Write(&strFileName, strFileName.GetSize());
1624 fileSimple.Write(&strEmpty, strEmpty.GetSize());
1625 fileSimple.Write(&keyList, keyList.GetSize());
1626 fileSimple.Write(&keyRNTuple, keyRNTuple.GetHeaderSize());
1628 fileSimple.Write(&strRNTupleClass, strRNTupleClass.GetSize());
1629 fileSimple.Write(&strRNTupleName, strRNTupleName.GetSize());
1630 fileSimple.Write(&strEmpty, strEmpty.GetSize());
1631 fileSimple.fControlBlock->fFileRecord.fNBytesKeys =
1632 fileSimple.fFilePos - fileSimple.fControlBlock->fFileRecord.GetSeekKeys();
1633 fileSimple.fKeyOffset = fileSimple.fFilePos;
1638 auto &fileSimple = std::get<RImplSimple>(
fFile);
1639 fileSimple.fControlBlock->fHeader.SetSeekFree(fileSimple.fKeyOffset);
1642 RTFFreeEntry freeEntry;
1643 RTFKey keyFreeList(fileSimple.fControlBlock->fHeader.GetSeekFree(), RTFHeader::kBEGIN, strEmpty, strFileName,
1644 strEmpty, freeEntry.GetSize());
1645 std::uint64_t firstFree = fileSimple.fControlBlock->fHeader.GetSeekFree() + keyFreeList.GetSize();
1646 freeEntry.Set(firstFree, std::max(2000000000ULL, ((firstFree / 1000000000ULL) + 1) * 1000000000ULL));
1647 fileSimple.WriteKey(&freeEntry, freeEntry.GetSize(), freeEntry.GetSize(),
1648 fileSimple.fControlBlock->fHeader.GetSeekFree(), RTFHeader::kBEGIN,
"",
fFileName,
"");
1649 fileSimple.fControlBlock->fHeader.SetNbytesFree(fileSimple.fFilePos -
1650 fileSimple.fControlBlock->fHeader.GetSeekFree());
1651 fileSimple.fControlBlock->fHeader.SetEnd(fileSimple.fFilePos);
1656 RTFString strRNTupleClass{
"ROOT::RNTuple"};
1661 RUInt64BE checksum{XXH3_64bits(ntupleOnDisk.GetPtrCkData(), ntupleOnDisk.GetSizeCkData())};
1662 auto &fileSimple = std::get<RImplSimple>(
fFile);
1663 fileSimple.fControlBlock->fSeekNTuple = fileSimple.fKeyOffset;
1665 char keyBuf[RTFNTuple::GetSizePlusChecksum()];
1668 memcpy(keyBuf, &ntupleOnDisk,
sizeof(RTFNTuple));
1669 memcpy(keyBuf +
sizeof(RTFNTuple), &checksum,
sizeof(checksum));
1671 const auto sizeAnchor =
sizeof(RTFNTuple) +
sizeof(checksum);
1672 char zipAnchor[RTFNTuple::GetSizePlusChecksum()];
1675 fileSimple.WriteKey(zipAnchor, szZipAnchor,
sizeof(keyBuf), fileSimple.fControlBlock->fSeekNTuple, RTFHeader::kBEGIN,
1682 RTFString strTFile{
"TFile"};
1686 auto &fileSimple = std::get<RImplSimple>(
fFile);
1687 fileSimple.fControlBlock->fHeader = RTFHeader(defaultCompression);
1692 RTFKey keyRoot(RTFHeader::kBEGIN, 0, strTFile, strFileName, strEmpty,
1693 sizeof(RTFDirectory) + strFileName.GetSize() + strEmpty.GetSize() + uuid.GetSize());
1694 std::uint32_t nbytesName = keyRoot.fKeyLen + strFileName.GetSize() + 1;
1695 fileSimple.fControlBlock->fFileRecord.fNBytesName = nbytesName;
1696 fileSimple.fControlBlock->fHeader.SetNbytesName(nbytesName);
1698 fileSimple.Write(&keyRoot, keyRoot.GetHeaderSize(), RTFHeader::kBEGIN);
1700 fileSimple.Write(&strTFile, strTFile.GetSize());
1701 fileSimple.Write(&strFileName, strFileName.GetSize());
1702 fileSimple.Write(&strEmpty, strEmpty.GetSize());
1704 fileSimple.Write(&strFileName, strFileName.GetSize());
1705 fileSimple.Write(&strEmpty, strEmpty.GetSize());
1707 fileSimple.fControlBlock->fSeekFileRecord = fileSimple.fFilePos;
1708 fileSimple.Write(&fileSimple.fControlBlock->fFileRecord, fileSimple.fControlBlock->fFileRecord.GetSize());
1709 fileSimple.Write(&uuid, uuid.GetSize());
1712 RUInt32BE padding{0};
1713 for (
int i = 0; i < 3; ++i)
1714 fileSimple.Write(&padding,
sizeof(padding));
1715 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...
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.
Binding & operator=(OUT(*fun)(void))
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