Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RMiniFile.cxx
Go to the documentation of this file.
1/// \file RMiniFile.cxx
2/// \ingroup NTuple ROOT7
3/// \author Jakob Blomer <jblomer@cern.ch>
4/// \date 2019-12-22
5/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
6/// is welcome!
7
8/*************************************************************************
9 * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. *
10 * All rights reserved. *
11 * *
12 * For the licensing terms see $ROOTSYS/LICENSE. *
13 * For the list of contributors see $ROOTSYS/README/CREDITS. *
14 *************************************************************************/
15
16#include <ROOT/RConfig.hxx>
17
18#include "ROOT/RMiniFile.hxx"
19
20#include <ROOT/RRawFile.hxx>
21#include <ROOT/RNTuple.hxx> // For converting an anchor to an RNTuple object
22#include <ROOT/RNTupleZip.hxx>
23
24#include <TError.h>
25#include <TFile.h>
26#include <TKey.h>
27
28#include <algorithm>
29#include <cstdio>
30#include <cstring>
31#include <iostream>
32#include <string>
33#include <utility>
34#include <chrono>
35
36namespace {
37
38// The following types are used to read and write the TFile binary format
39
40/// Big-endian 16-bit unsigned integer
41class RUInt16BE {
42private:
43 std::uint16_t fValBE = 0;
44 static std::uint16_t Swap(std::uint16_t val) {
45 return (val & 0x00FF) << 8 | (val & 0xFF00) >> 8;
46 }
47public:
48 RUInt16BE() = default;
49 explicit RUInt16BE(const std::uint16_t val) : fValBE(Swap(val)) {}
50 operator std::uint16_t() const {
51 return Swap(fValBE);
52 }
53 RUInt16BE& operator =(const std::uint16_t val) {
54 fValBE = Swap(val);
55 return *this;
56 }
57};
58
59/// Big-endian 32-bit unsigned integer
60class RUInt32BE {
61private:
62 std::uint32_t fValBE = 0;
63 static std::uint32_t Swap(std::uint32_t val) {
64 auto x = (val & 0x0000FFFF) << 16 | (val & 0xFFFF0000) >> 16;
65 return (x & 0x00FF00FF) << 8 | (x & 0xFF00FF00) >> 8;
66 }
67public:
68 RUInt32BE() = default;
69 explicit RUInt32BE(const std::uint32_t val) : fValBE(Swap(val)) {}
70 operator std::uint32_t() const {
71 return Swap(fValBE);
72 }
73 RUInt32BE& operator =(const std::uint32_t val) {
74 fValBE = Swap(val);
75 return *this;
76 }
77};
78
79/// Big-endian 32-bit signed integer
80class RInt32BE {
81private:
82 std::int32_t fValBE = 0;
83 static std::int32_t Swap(std::int32_t val) {
84 auto x = (val & 0x0000FFFF) << 16 | (val & 0xFFFF0000) >> 16;
85 return (x & 0x00FF00FF) << 8 | (x & 0xFF00FF00) >> 8;
86 }
87public:
88 RInt32BE() = default;
89 explicit RInt32BE(const std::int32_t val) : fValBE(Swap(val)) {}
90 operator std::int32_t() const {
91 return Swap(fValBE);
92 }
93 RInt32BE& operator =(const std::int32_t val) {
94 fValBE = Swap(val);
95 return *this;
96 }
97};
98
99/// Big-endian 64-bit unsigned integer
100class RUInt64BE {
101private:
102 std::uint64_t fValBE = 0;
103 static std::uint64_t Swap(std::uint64_t val) {
104 auto x = (val & 0x00000000FFFFFFFF) << 32 | (val & 0xFFFFFFFF00000000) >> 32;
105 x = (x & 0x0000FFFF0000FFFF) << 16 | (x & 0xFFFF0000FFFF0000) >> 16;
106 return (x & 0x00FF00FF00FF00FF) << 8 | (x & 0xFF00FF00FF00FF00) >> 8;
107 }
108public:
109 RUInt64BE() = default;
110 explicit RUInt64BE(const std::uint64_t val) : fValBE(Swap(val)) {}
111 operator std::uint64_t() const {
112 return Swap(fValBE);
113 }
114 RUInt64BE& operator =(const std::uint64_t val) {
115 fValBE = Swap(val);
116 return *this;
117 }
118};
119
120constexpr std::int32_t ChecksumRNTupleClass() {
121 const char ident[] = "ROOT::Experimental::RNTuple"
122 "fChecksum"
123 "int"
124 "fVersion"
125 "unsigned int"
126 "fSize"
127 "unsigned int"
128 "fSeekHeader"
129 "unsigned long"
130 "fNBytesHeader"
131 "unsigned int"
132 "fLenHeader"
133 "unsigned int"
134 "fSeekFooter"
135 "unsigned long"
136 "fNBytesFooter"
137 "unsigned int"
138 "fLenFooter"
139 "unsigned int"
140 "fReserved"
141 "unsigned long";
142 std::int32_t id = 0;
143 for (unsigned i = 0; i < (sizeof(ident) - 1); i++)
144 id = static_cast<std::int32_t>(static_cast<std::int64_t>(id) * 3 + ident[i]);
145 return id;
146}
147
148
149#pragma pack(push, 1)
150/// A name (type, identifies, ...) in the TFile binary format
151struct RTFString {
152 char fLName{0};
153 char fData[255];
154 RTFString() = default;
155 RTFString(const std::string &str) {
156 R__ASSERT(str.length() < 256);
157 fLName = str.length();
158 memcpy(fData, str.data(), fLName);
159 }
160 char GetSize() const { return 1 + fLName; }
161};
162
163/// The timestamp format used in TFile; the default constructor initializes with the current time
164struct RTFDatetime {
165 RUInt32BE fDatetime;
166 RTFDatetime() {
167 auto now = std::chrono::system_clock::now();
168 auto tt = std::chrono::system_clock::to_time_t(now);
169 auto tm = *localtime(&tt);
170 fDatetime = (tm.tm_year + 1900 - 1995) << 26 | (tm.tm_mon + 1) << 22 | tm.tm_mday << 17 |
171 tm.tm_hour << 12 | tm.tm_min << 6 | tm.tm_sec;
172 }
173 explicit RTFDatetime(RUInt32BE val) : fDatetime(val) {}
174};
175
176/// The key part of a TFile record excluding the class, object, and title names
177struct RTFKey {
178 RInt32BE fNbytes{0};
179 RUInt16BE fVersion{4};
180 RUInt32BE fObjLen{0};
181 RTFDatetime fDatetime;
182 RUInt16BE fKeyLen{0};
183 RUInt16BE fCycle{1};
184 union {
185 struct {
186 RUInt32BE fSeekKey{0};
187 RUInt32BE fSeekPdir{0};
188 } fInfoShort;
189 struct {
190 RUInt64BE fSeekKey{0};
191 RUInt64BE fSeekPdir{0};
192 } fInfoLong;
193 };
194
195 std::uint32_t fKeyHeaderSize{18 + sizeof(fInfoShort)}; // not part of serialization
196
197 RTFKey() : fInfoShort() {}
198 RTFKey(std::uint64_t seekKey, std::uint64_t seekPdir,
199 const RTFString &clName, const RTFString &objName, const RTFString &titleName,
200 std::uint32_t szObjInMem, std::uint32_t szObjOnDisk = 0)
201 {
202 fObjLen = szObjInMem;
203 if ((seekKey > static_cast<unsigned int>(std::numeric_limits<std::int32_t>::max())) ||
204 (seekPdir > static_cast<unsigned int>(std::numeric_limits<std::int32_t>::max())))
205 {
206 fKeyHeaderSize = 18 + sizeof(fInfoLong);
207 fKeyLen = fKeyHeaderSize + clName.GetSize() + objName.GetSize() + titleName.GetSize();
208 fInfoLong.fSeekKey = seekKey;
209 fInfoLong.fSeekPdir = seekPdir;
210 fVersion = fVersion + 1000;
211 } else {
212 fKeyHeaderSize = 18 + sizeof(fInfoShort);
213 fKeyLen = fKeyHeaderSize + clName.GetSize() + objName.GetSize() + titleName.GetSize();
214 fInfoShort.fSeekKey = seekKey;
215 fInfoShort.fSeekPdir = seekPdir;
216 }
217 fNbytes = fKeyLen + ((szObjOnDisk == 0) ? szObjInMem : szObjOnDisk);
218 }
219
220 void MakeBigKey()
221 {
222 if (fVersion >= 1000)
223 return;
224 std::uint32_t seekKey = fInfoShort.fSeekKey;
225 std::uint32_t seekPdir = fInfoShort.fSeekPdir;
226 fInfoLong.fSeekKey = seekKey;
227 fInfoLong.fSeekPdir = seekPdir;
228 fKeyHeaderSize = fKeyHeaderSize + sizeof(fInfoLong) - sizeof(fInfoShort);
229 fNbytes = fNbytes + sizeof(fInfoLong) - sizeof(fInfoShort);
230 fVersion = fVersion + 1000;
231 }
232
233 std::uint32_t GetSize() const {
234 // Negative size indicates a gap in the file
235 if (fNbytes < 0)
236 return -fNbytes;
237 return fNbytes;
238 }
239
240 std::uint32_t GetHeaderSize() const {
241 if (fVersion >= 1000)
242 return 18 + sizeof(fInfoLong);
243 return 18 + sizeof(fInfoShort);
244 }
245
246 std::uint64_t GetSeekKey() const {
247 if (fVersion >= 1000)
248 return fInfoLong.fSeekKey;
249 return fInfoShort.fSeekKey;
250 }
251};
252
253/// The TFile global header
254struct RTFHeader {
255 char fMagic[4]{ 'r', 'o', 'o', 't' };
256 RUInt32BE fVersion{(ROOT_VERSION_CODE >> 16)*10000 +
257 ((ROOT_VERSION_CODE & 0xFF00) >> 8) * 100 +
258 (ROOT_VERSION_CODE & 0xFF)};
259 RUInt32BE fBEGIN{100};
260 union {
261 struct {
262 RUInt32BE fEND{0};
263 RUInt32BE fSeekFree{0};
264 RUInt32BE fNbytesFree{0};
265 RUInt32BE fNfree{1};
266 RUInt32BE fNbytesName{0};
267 unsigned char fUnits{4};
268 RUInt32BE fCompress{0};
269 RUInt32BE fSeekInfo{0};
270 RUInt32BE fNbytesInfo{0};
271 } fInfoShort;
272 struct {
273 RUInt64BE fEND{0};
274 RUInt64BE fSeekFree{0};
275 RUInt32BE fNbytesFree{0};
276 RUInt32BE fNfree{1};
277 RUInt32BE fNbytesName{0};
278 unsigned char fUnits{8};
279 RUInt32BE fCompress{0};
280 RUInt64BE fSeekInfo{0};
281 RUInt32BE fNbytesInfo{0};
282 } fInfoLong;
283 };
284
285 RTFHeader() : fInfoShort() {}
286 RTFHeader(int compression) : fInfoShort() {
287 fInfoShort.fCompress = compression;
288 }
289
290 void SetBigFile() {
291 if (fVersion >= 1000000)
292 return;
293
294 std::uint32_t end = fInfoShort.fEND;
295 std::uint32_t seekFree = fInfoShort.fSeekFree;
296 std::uint32_t nbytesFree = fInfoShort.fNbytesFree;
297 std::uint32_t nFree = fInfoShort.fNfree;
298 std::uint32_t nbytesName = fInfoShort.fNbytesName;
299 std::uint32_t compress = fInfoShort.fCompress;
300 std::uint32_t seekInfo = fInfoShort.fSeekInfo;
301 std::uint32_t nbytesInfo = fInfoShort.fNbytesInfo;
302 fInfoLong.fEND = end;
303 fInfoLong.fSeekFree = seekFree;
304 fInfoLong.fNbytesFree = nbytesFree;
305 fInfoLong.fNfree = nFree;
306 fInfoLong.fNbytesName = nbytesName;
307 fInfoLong.fUnits = 8;
308 fInfoLong.fCompress = compress;
309 fInfoLong.fSeekInfo = seekInfo;
310 fInfoLong.fNbytesInfo = nbytesInfo;
311 fVersion = fVersion + 1000000;
312 }
313
314 bool IsBigFile(std::uint64_t offset = 0) const {
315 return (fVersion >= 1000000) || (offset > static_cast<unsigned int>(std::numeric_limits<std::int32_t>::max()));
316 }
317
318 std::uint32_t GetSize() const {
319 std::uint32_t sizeHead = 4 + sizeof(fVersion) + sizeof(fBEGIN);
320 if (IsBigFile()) return sizeHead + sizeof(fInfoLong);
321 return sizeHead + sizeof(fInfoShort);
322 }
323
324 std::uint64_t GetEnd() const {
325 if (IsBigFile()) return fInfoLong.fEND;
326 return fInfoShort.fEND;
327 }
328
329 void SetEnd(std::uint64_t value) {
330 if (IsBigFile(value)) {
331 SetBigFile();
332 fInfoLong.fEND = value;
333 } else {
334 fInfoShort.fEND = value;
335 }
336 }
337
338 std::uint64_t GetSeekFree() const {
339 if (IsBigFile()) return fInfoLong.fSeekFree;
340 return fInfoShort.fSeekFree;
341 }
342
343 void SetSeekFree(std::uint64_t value) {
344 if (IsBigFile(value)) {
345 SetBigFile();
346 fInfoLong.fSeekFree = value;
347 } else {
348 fInfoShort.fSeekFree = value;
349 }
350 }
351
352 void SetNbytesFree(std::uint32_t value) {
353 if (IsBigFile()) {
354 fInfoLong.fNbytesFree = value;
355 } else {
356 fInfoShort.fNbytesFree = value;
357 }
358 }
359
360 void SetNbytesName(std::uint32_t value) {
361 if (IsBigFile()) {
362 fInfoLong.fNbytesName = value;
363 } else {
364 fInfoShort.fNbytesName = value;
365 }
366 }
367
368 std::uint64_t GetSeekInfo() const {
369 if (IsBigFile()) return fInfoLong.fSeekInfo;
370 return fInfoShort.fSeekInfo;
371 }
372
373 void SetSeekInfo(std::uint64_t value) {
374 if (IsBigFile(value)) {
375 SetBigFile();
376 fInfoLong.fSeekInfo = value;
377 } else {
378 fInfoShort.fSeekInfo = value;
379 }
380 }
381
382 void SetNbytesInfo(std::uint32_t value) {
383 if (IsBigFile()) {
384 fInfoLong.fNbytesInfo = value;
385 } else {
386 fInfoShort.fNbytesInfo = value;
387 }
388 }
389
390 void SetCompression(std::uint32_t value) {
391 if (IsBigFile()) {
392 fInfoLong.fCompress = value;
393 } else {
394 fInfoShort.fCompress = value;
395 }
396 }
397};
398
399
400/// A reference to an unused byte-range in a TFile
401struct RTFFreeEntry {
402 RUInt16BE fVersion{1};
403 union {
404 struct {
405 RUInt32BE fFirst{0};
406 RUInt32BE fLast{0};
407 } fInfoShort;
408 struct {
409 RUInt64BE fFirst{0};
410 RUInt64BE fLast{0};
411 } fInfoLong;
412 };
413
414 RTFFreeEntry() : fInfoShort() {}
415 void Set(std::uint64_t first, std::uint64_t last) {
416 if (last > static_cast<unsigned int>(std::numeric_limits<std::int32_t>::max())) {
417 fVersion = fVersion + 1000;
418 fInfoLong.fFirst = first;
419 fInfoLong.fLast = last;
420 } else {
421 fInfoShort.fFirst = first;
422 fInfoShort.fLast = last;
423 }
424 }
425 std::uint32_t GetSize() { return (fVersion >= 1000) ? 18 : 10; }
426};
427
428/// Streamer info for TObject
429struct RTFObject {
430 RUInt16BE fVersion{1};
431 RUInt32BE fUniqueID{0}; // unused
432 RUInt32BE fBits;
433 explicit RTFObject(std::uint32_t bits) : fBits(bits) {}
434};
435
436/// Streamer info for data member RNTuple::fChecksum
437struct RTFStreamerElementChecksum {
438 RUInt32BE fByteCount{0x40000000 | (sizeof(RTFStreamerElementChecksum) - sizeof(RUInt32BE))};
439 RUInt16BE fVersion{4};
440
441 RUInt32BE fByteCountNamed{0x40000000 | (sizeof(RUInt16BE) + sizeof(RTFObject) + 11)};
442 RUInt16BE fVersionNamed{1};
443 RTFObject fObjectNamed{0x02000000 | 0x01000000};
444 char fLName = 9;
445 char fName[9]{'f', 'C', 'h', 'e', 'c', 'k', 's', 'u', 'm'};
446 char fLTitle = 0;
447
448 RUInt32BE fType{3};
449 RUInt32BE fSize{4};
450 RUInt32BE fArrLength{0};
451 RUInt32BE fArrDim{0};
452 char fMaxIndex[20]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
453 char fLTypeName = 3;
454 char fTypeName[3]{'i', 'n', 't'};
455};
456
457/// Streamer info for data member RNTuple::fVersion
458struct RTFStreamerElementVersion {
459 RUInt32BE fByteCount{0x40000000 | (sizeof(RTFStreamerElementVersion) - sizeof(RUInt32BE))};
460 RUInt16BE fVersion{4};
461
462 RUInt32BE fByteCountNamed{0x40000000 | (sizeof(RUInt16BE) + sizeof(RTFObject) + 10)};
463 RUInt16BE fVersionNamed{1};
464 RTFObject fObjectNamed{0x02000000 | 0x01000000};
465 char fLName = 8;
466 char fName[8]{ 'f', 'V', 'e', 'r', 's', 'i', 'o', 'n' };
467 char fLTitle = 0;
468
469 RUInt32BE fType{13};
470 RUInt32BE fSize{4};
471 RUInt32BE fArrLength{0};
472 RUInt32BE fArrDim{0};
473 char fMaxIndex[20]{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
474 char fLTypeName = 12;
475 char fTypeName[12]{ 'u', 'n', 's', 'i', 'g', 'n', 'e', 'd', ' ', 'i', 'n', 't' };
476};
477
478/// Streamer info for data member RNTuple::fSize
479struct RTFStreamerElementSize {
480 RUInt32BE fByteCount{0x40000000 | (sizeof(RTFStreamerElementSize) - sizeof(RUInt32BE))};
481 RUInt16BE fVersion{4};
482
483 RUInt32BE fByteCountNamed{0x40000000 | (sizeof(RUInt16BE) + sizeof(RTFObject) + 7)};
484 RUInt16BE fVersionNamed{1};
485 RTFObject fObjectNamed{0x02000000 | 0x01000000};
486 char fLName = 5;
487 char fName[5]{ 'f', 'S', 'i', 'z', 'e' };
488 char fLTitle = 0;
489
490 RUInt32BE fType{13};
491 RUInt32BE fSize{4};
492 RUInt32BE fArrLength{0};
493 RUInt32BE fArrDim{0};
494 char fMaxIndex[20]{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
495 char fLTypeName = 12;
496 char fTypeName[12]{ 'u', 'n', 's', 'i', 'g', 'n', 'e', 'd', ' ', 'i', 'n', 't' };
497};
498
499/// Streamer info for data member RNTuple::fSeekHeader
500struct RTFStreamerElementSeekHeader {
501 RUInt32BE fByteCount{0x40000000 | (sizeof(RTFStreamerElementSeekHeader) - sizeof(RUInt32BE))};
502 RUInt16BE fVersion{4};
503
504 RUInt32BE fByteCountNamed{0x40000000 |
505 (sizeof(RUInt16BE) + sizeof(RTFObject) + 13)};
506 RUInt16BE fVersionNamed{1};
507 RTFObject fObjectNamed{0x02000000 | 0x01000000};
508 char fLName = 11;
509 char fName[11]{ 'f', 'S', 'e', 'e', 'k', 'H', 'e', 'a', 'd', 'e', 'r' };
510 char fLTitle = 0;
511
512 RUInt32BE fType{14};
513 RUInt32BE fSize{8};
514 RUInt32BE fArrLength{0};
515 RUInt32BE fArrDim{0};
516 char fMaxIndex[20]{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
517 char fLTypeName = 13;
518 char fTypeName[13]{ 'u', 'n', 's', 'i', 'g', 'n', 'e', 'd', ' ', 'l', 'o', 'n', 'g' };
519};
520
521/// Streamer info for data member RNTuple::fNbytesHeader
522struct RTFStreamerElementNBytesHeader {
523 RUInt32BE fByteCount{0x40000000 | (sizeof(RTFStreamerElementNBytesHeader) - sizeof(RUInt32BE))};
524 RUInt16BE fVersion{4};
525
526 RUInt32BE fByteCountNamed{0x40000000 |
527 (sizeof(RUInt16BE) + sizeof(RTFObject) + 15)};
528 RUInt16BE fVersionNamed{1};
529 RTFObject fObjectNamed{0x02000000 | 0x01000000};
530 char fLName = 13;
531 char fName[13]{ 'f', 'N', 'B', 'y', 't', 'e', 's', 'H', 'e', 'a', 'd', 'e', 'r' };
532 char fLTitle = 0;
533
534 RUInt32BE fType{13};
535 RUInt32BE fSize{4};
536 RUInt32BE fArrLength{0};
537 RUInt32BE fArrDim{0};
538 char fMaxIndex[20]{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
539 char fLTypeName = 12;
540 char fTypeName[12]{ 'u', 'n', 's', 'i', 'g', 'n', 'e', 'd', ' ', 'i', 'n', 't' };
541};
542
543/// Streamer info for data member RNTuple::fLenHeader
544struct RTFStreamerElementLenHeader {
545 RUInt32BE fByteCount{0x40000000 | (sizeof(RTFStreamerElementLenHeader) - sizeof(RUInt32BE))};
546 RUInt16BE fVersion{4};
547
548 RUInt32BE fByteCountNamed{0x40000000 |
549 (sizeof(RUInt16BE) + sizeof(RTFObject) + 12)};
550 RUInt16BE fVersionNamed{1};
551 RTFObject fObjectNamed{0x02000000 | 0x01000000};
552 char fLName = 10;
553 char fName[10]{ 'f', 'L', 'e', 'n', 'H', 'e', 'a', 'd', 'e', 'r' };
554 char fLTitle = 0;
555
556 RUInt32BE fType{13};
557 RUInt32BE fSize{4};
558 RUInt32BE fArrLength{0};
559 RUInt32BE fArrDim{0};
560 char fMaxIndex[20]{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
561 char fLTypeName = 12;
562 char fTypeName[12]{ 'u', 'n', 's', 'i', 'g', 'n', 'e', 'd', ' ', 'i', 'n', 't' };
563};
564
565/// Streamer info for data member RNTuple::fSeekFooter
566struct RTFStreamerElementSeekFooter {
567 RUInt32BE fByteCount{0x40000000 | (sizeof(RTFStreamerElementSeekFooter) - sizeof(RUInt32BE))};
568 RUInt16BE fVersion{4};
569
570 RUInt32BE fByteCountNamed{0x40000000 |
571 (sizeof(RUInt16BE) + sizeof(RTFObject) + 13)};
572 RUInt16BE fVersionNamed{1};
573 RTFObject fObjectNamed{0x02000000 | 0x01000000};
574 char fLName = 11;
575 char fName[11]{ 'f', 'S', 'e', 'e', 'k', 'F', 'o', 'o', 't', 'e', 'r' };
576 char fLTitle = 0;
577
578 RUInt32BE fType{14};
579 RUInt32BE fSize{8};
580 RUInt32BE fArrLength{0};
581 RUInt32BE fArrDim{0};
582 char fMaxIndex[20]{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
583 char fLTypeName = 13;
584 char fTypeName[13]{ 'u', 'n', 's', 'i', 'g', 'n', 'e', 'd', ' ', 'l', 'o', 'n', 'g' };
585};
586
587/// Streamer info for data member RNTuple::fNbytesFooter
588struct RTFStreamerElementNBytesFooter {
589 RUInt32BE fByteCount{0x40000000 | (sizeof(RTFStreamerElementNBytesFooter) - sizeof(RUInt32BE))};
590 RUInt16BE fVersion{4};
591
592 RUInt32BE fByteCountNamed{0x40000000 | (sizeof(RUInt16BE) + sizeof(RTFObject) + 15)};
593 RUInt16BE fVersionNamed{1};
594 RTFObject fObjectNamed{0x02000000 | 0x01000000};
595 char fLName = 13;
596 char fName[13]{ 'f', 'N', 'B', 'y', 't', 'e', 's', 'F', 'o', 'o', 't', 'e', 'r' };
597 char fLTitle = 0;
598
599 RUInt32BE fType{13};
600 RUInt32BE fSize{4};
601 RUInt32BE fArrLength{0};
602 RUInt32BE fArrDim{0};
603 char fMaxIndex[20]{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
604 char fLTypeName = 12;
605 char fTypeName[12]{ 'u', 'n', 's', 'i', 'g', 'n', 'e', 'd', ' ', 'i', 'n', 't' };
606};
607
608/// Streamer info for data member RNTuple::fLenFooter
609struct RTFStreamerElementLenFooter {
610 RUInt32BE fByteCount{0x40000000 | (sizeof(RTFStreamerElementLenFooter) - sizeof(RUInt32BE))};
611 RUInt16BE fVersion{4};
612
613 RUInt32BE fByteCountNamed{0x40000000 | (sizeof(RUInt16BE) + sizeof(RTFObject) + 12)};
614 RUInt16BE fVersionNamed{1};
615 RTFObject fObjectNamed{0x02000000 | 0x01000000};
616 char fLName = 10;
617 char fName[10]{ 'f', 'L', 'e', 'n', 'F', 'o', 'o', 't', 'e', 'r' };
618 char fLTitle = 0;
619
620 RUInt32BE fType{13};
621 RUInt32BE fSize{4};
622 RUInt32BE fArrLength{0};
623 RUInt32BE fArrDim{0};
624 char fMaxIndex[20]{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
625 char fLTypeName = 12;
626 char fTypeName[12]{ 'u', 'n', 's', 'i', 'g', 'n', 'e', 'd', ' ', 'i', 'n', 't' };
627};
628
629/// Streamer info for data member RNTuple::fReserved
630struct RTFStreamerElementReserved {
631 RUInt32BE fByteCount{0x40000000 | (sizeof(RTFStreamerElementReserved) - sizeof(RUInt32BE))};
632 RUInt16BE fVersion{4};
633
634 RUInt32BE fByteCountNamed{0x40000000 |
635 (sizeof(RUInt16BE) + sizeof(RTFObject) + 11)};
636 RUInt16BE fVersionNamed{1};
637 RTFObject fObjectNamed{0x02000000 | 0x01000000};
638 char fLName = 9;
639 char fName[9]{ 'f', 'R', 'e', 's', 'e', 'r', 'v', 'e', 'd' };
640 char fLTitle = 0;
641
642 RUInt32BE fType{14};
643 RUInt32BE fSize{8};
644 RUInt32BE fArrLength{0};
645 RUInt32BE fArrDim{0};
646 char fMaxIndex[20]{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
647 char fLTypeName = 13;
648 char fTypeName[13]{ 'u', 'n', 's', 'i', 'g', 'n', 'e', 'd', ' ', 'l', 'o', 'n', 'g' };
649};
650
651/// Streamer info frame for data member RNTuple::fChecksum
652struct RTFStreamerChecksum {
653 RUInt32BE fByteCount{0x40000000 | (sizeof(RTFStreamerChecksum) - sizeof(RUInt32BE))};
654 RUInt32BE fNewClassTag{0xffffffff};
655 char fClassName[19]{'T', 'S', 't', 'r', 'e', 'a', 'm', 'e', 'r', 'B', 'a', 's', 'i', 'c', 'T', 'y', 'p', 'e', '\0'};
656 RUInt32BE fByteCountRemaining{0x40000000 | (sizeof(RTFStreamerChecksum) - 2 * sizeof(RUInt32BE) -
657 19 /* strlen(fClassName) + 1 */ - sizeof(RUInt32BE))};
658 RUInt16BE fVersion{2};
659 RTFStreamerElementChecksum fStreamerElementChecksum;
660};
661
662/// Streamer info frame for data member RNTuple::fVersion
663struct RTFStreamerVersion {
664 RUInt32BE fByteCount{0x40000000 | (sizeof(RTFStreamerVersion) - sizeof(RUInt32BE))};
665 RUInt32BE fClassTag{0x80000000}; // Fix-up after construction, or'd with 0x80000000
666 RUInt32BE fByteCountRemaining{0x40000000 | (sizeof(RTFStreamerVersion) - 3 * sizeof(RUInt32BE))};
667 RUInt16BE fVersion{2};
668 RTFStreamerElementVersion fStreamerElementVersion;
669};
670
671/// Streamer info frame for data member RNTuple::fSize
672struct RTFStreamerSize {
673 RUInt32BE fByteCount{0x40000000 | (sizeof(RTFStreamerSize) - sizeof(RUInt32BE))};
674 RUInt32BE fClassTag{0x80000000}; // Fix-up after construction, or'd with 0x80000000
675 RUInt32BE fByteCountRemaining{0x40000000 | (sizeof(RTFStreamerSize) - 3 * sizeof(RUInt32BE))};
676 RUInt16BE fVersion{2};
677 RTFStreamerElementSize fStreamerElementSize;
678};
679
680/// Streamer info frame for data member RNTuple::fSeekHeader
681struct RTFStreamerSeekHeader {
682 RUInt32BE fByteCount{0x40000000 | (sizeof(RTFStreamerSeekHeader) - sizeof(RUInt32BE))};
683 RUInt32BE fClassTag{0x80000000}; // Fix-up after construction, or'd with 0x80000000
684 RUInt32BE fByteCountRemaining{0x40000000 | (sizeof(RTFStreamerSeekHeader) - 3 * sizeof(RUInt32BE))};
685 RUInt16BE fVersion{2};
686 RTFStreamerElementSeekHeader fStreamerElementSeekHeader;
687};
688
689/// Streamer info frame for data member RNTuple::fNbytesHeader
690struct RTFStreamerNBytesHeader {
691 RUInt32BE fByteCount{0x40000000 | (sizeof(RTFStreamerNBytesHeader) - sizeof(RUInt32BE))};
692 RUInt32BE fClassTag{0x80000000}; // Fix-up after construction, or'd with 0x80000000
693 RUInt32BE fByteCountRemaining{0x40000000 | (sizeof(RTFStreamerNBytesHeader) - 3 * sizeof(RUInt32BE))};
694 RUInt16BE fVersion{2};
695 RTFStreamerElementNBytesHeader fStreamerElementNBytesHeader;
696};
697
698/// Streamer info frame for data member RNTuple::fLenHeader
699struct RTFStreamerLenHeader {
700 RUInt32BE fByteCount{0x40000000 | (sizeof(RTFStreamerLenHeader) - sizeof(RUInt32BE))};
701 RUInt32BE fClassTag{0x80000000}; // Fix-up after construction, or'd with 0x80000000
702 RUInt32BE fByteCountRemaining{0x40000000 | (sizeof(RTFStreamerLenHeader) - 3 * sizeof(RUInt32BE))};
703 RUInt16BE fVersion{2};
704 RTFStreamerElementLenHeader fStreamerElementLenHeader;
705};
706
707/// Streamer info frame for data member RNTuple::fSeekFooter
708struct RTFStreamerSeekFooter {
709 RUInt32BE fByteCount{0x40000000 | (sizeof(RTFStreamerSeekFooter) - sizeof(RUInt32BE))};
710 RUInt32BE fClassTag{0x80000000}; // Fix-up after construction, or'd with 0x80000000
711 RUInt32BE fByteCountRemaining{0x40000000 | (sizeof(RTFStreamerSeekFooter) - 3 * sizeof(RUInt32BE))};
712 RUInt16BE fVersion{2};
713 RTFStreamerElementSeekFooter fStreamerElementSeekFooter;
714};
715
716/// Streamer info frame for data member RNTuple::fNBytesFooter
717struct RTFStreamerNBytesFooter {
718 RUInt32BE fByteCount{0x40000000 | (sizeof(RTFStreamerNBytesFooter) - sizeof(RUInt32BE))};
719 RUInt32BE fClassTag{0x80000000}; // Fix-up after construction, or'd with 0x80000000
720 RUInt32BE fByteCountRemaining{0x40000000 | (sizeof(RTFStreamerNBytesFooter) - 3 * sizeof(RUInt32BE))};
721 RUInt16BE fVersion{2};
722 RTFStreamerElementNBytesFooter fStreamerElementNBytesFooter;
723};
724
725/// Streamer info frame for data member RNTuple::fLenFooter
726struct RTFStreamerLenFooter {
727 RUInt32BE fByteCount{0x40000000 | (sizeof(RTFStreamerLenFooter) - sizeof(RUInt32BE))};
728 RUInt32BE fClassTag{0x80000000}; // Fix-up after construction, or'd with 0x80000000
729 RUInt32BE fByteCountRemaining{0x40000000 | (sizeof(RTFStreamerLenFooter) - 3 * sizeof(RUInt32BE))};
730 RUInt16BE fVersion{2};
731 RTFStreamerElementLenFooter fStreamerElementLenFooter;
732};
733
734/// Streamer info frame for data member RNTuple::fReserved
735struct RTFStreamerReserved {
736 RUInt32BE fByteCount{0x40000000 | (sizeof(RTFStreamerReserved) - sizeof(RUInt32BE))};
737 RUInt32BE fClassTag{0x80000000}; // Fix-up after construction, or'd with 0x80000000
738 RUInt32BE fByteCountRemaining{0x40000000 | (sizeof(RTFStreamerReserved) - 3 * sizeof(RUInt32BE))};
739 RUInt16BE fVersion{2};
740 RTFStreamerElementReserved fStreamerElementReserved;
741};
742
743/// Streamer info for class RNTuple
744struct RTFStreamerInfoObject {
745 RUInt32BE fByteCount{0x40000000 | (sizeof(RTFStreamerInfoObject) - sizeof(fByteCount))};
746 RUInt32BE fNewClassTag{0xffffffff};
747 char fClassName[14]{ 'T', 'S', 't', 'r', 'e', 'a', 'm', 'e', 'r', 'I', 'n', 'f', 'o', '\0' };
748 RUInt32BE fByteCountRemaining{0x40000000 |
749 (sizeof(RTFStreamerInfoObject) - 2 * sizeof(RUInt32BE) - 14 - sizeof(RUInt32BE))};
750 RUInt16BE fVersion{9};
751
752 RUInt32BE fByteCountNamed{0x40000000 |
753 (sizeof(RUInt16BE) + sizeof(RTFObject) + 29 /* strlen("ROOT::Experimental::RNTuple") + 2 */)};
754 RUInt16BE fVersionNamed{1};
755 RTFObject fObjectNamed{0x02000000 | 0x01000000 | 0x00010000};
756 char fLName = 27;
757 char fName[27]{ 'R', 'O', 'O', 'T', ':', ':',
758 'E', 'x', 'p', 'e', 'r', 'i', 'm', 'e', 'n', 't', 'a', 'l', ':', ':',
759 'R', 'N', 'T', 'u', 'p', 'l', 'e'};
760 char fLTitle = 0;
761
762 RInt32BE fChecksum{ChecksumRNTupleClass()};
763 RUInt32BE fVersionRNTuple{1};
764
765 RUInt32BE fByteCountObjArr{0x40000000 |
766 (sizeof(RUInt32BE) + 10 /* strlen(TObjArray) + 1 */ + sizeof(RUInt32BE) +
767 sizeof(RUInt16BE) + sizeof(RTFObject) + 1 + 2*sizeof(RUInt32BE) +
768 sizeof(fStreamers))};
769 RUInt32BE fNewClassTagObjArray{0xffffffff};
770 char fClassNameObjArray[10]{'T', 'O', 'b', 'j', 'A', 'r', 'r', 'a', 'y', '\0'};
771 RUInt32BE fByteCountObjArrRemaining{0x40000000 |
772 (sizeof(RUInt16BE) + sizeof(RTFObject) + 1 + 2*sizeof(RUInt32BE) +
773 sizeof(fStreamers))};
774 RUInt16BE fVersionObjArr{3};
775 RTFObject fObjectObjArr{0x02000000};
776 char fNameObjArr{0};
777
778 RUInt32BE fNObjects{10};
779 RUInt32BE fLowerBound{0};
780
781 struct {
782 RTFStreamerChecksum fStreamerChecksum;
783 RTFStreamerVersion fStreamerVersion;
784 RTFStreamerSize fStreamerSize;
785 RTFStreamerSeekHeader fStreamerSeekHeader;
786 RTFStreamerNBytesHeader fStreamerNBytesHeader;
787 RTFStreamerLenHeader fStreamerLenHeader;
788 RTFStreamerSeekFooter fStreamerSeekFooter;
789 RTFStreamerNBytesFooter fStreamerNBytesFooter;
790 RTFStreamerLenFooter fStreamerLenFooter;
791 RTFStreamerReserved fStreamerReserved;
792 } fStreamers;
793};
794
795/// The list of streamer info objects, for a new ntuple contains only the RNTuple class
796struct RTFStreamerInfoList {
797 RUInt32BE fByteCount{0x40000000 | (sizeof(RTFStreamerInfoList) - sizeof(fByteCount))};
798 RUInt16BE fVersion{5};
799 RTFObject fObject{0x02000000};
800 char fName{0};
801 RUInt32BE fNObjects{1};
802 RTFStreamerInfoObject fStreamerInfo;
803 char fEnd{0};
804
805 std::uint32_t GetSize() const { return sizeof(RTFStreamerInfoList); }
806};
807
808/// The header of the directory key index
809struct RTFKeyList {
810 RUInt32BE fNKeys;
811 std::uint32_t GetSize() const { return sizeof(RTFKeyList); }
812 explicit RTFKeyList(std::uint32_t nKeys) : fNKeys(nKeys) {}
813};
814
815/// A streamed TFile object
816struct RTFFile {
817 RUInt16BE fClassVersion{5};
818 RTFDatetime fDateC;
819 RTFDatetime fDateM;
820 RUInt32BE fNBytesKeys{0};
821 RUInt32BE fNBytesName{0};
822 // The version of the key has to tell whether offsets are 32bit or 64bit long
823 union {
824 struct {
825 RUInt32BE fSeekDir{100};
826 RUInt32BE fSeekParent{0};
827 RUInt32BE fSeekKeys{0};
828 } fInfoShort;
829 struct {
830 RUInt64BE fSeekDir{100};
831 RUInt64BE fSeekParent{0};
832 RUInt64BE fSeekKeys{0};
833 } fInfoLong;
834 };
835
836 RTFFile() : fInfoShort() {}
837
838 // In case of a short TFile record (<2G), 3 padding ints are written after the UUID
839 std::uint32_t GetSize() const
840 {
841 if (fClassVersion >= 1000)
842 return sizeof(RTFFile);
843 return 18 + sizeof(fInfoShort);
844 }
845
846 std::uint64_t GetSeekKeys() const
847 {
848 if (fClassVersion >= 1000)
849 return fInfoLong.fSeekKeys;
850 return fInfoShort.fSeekKeys;
851 }
852
853 void SetSeekKeys(std::uint64_t seekKeys)
854 {
855 if (seekKeys > static_cast<unsigned int>(std::numeric_limits<std::int32_t>::max())) {
856 std::uint32_t seekDir = fInfoShort.fSeekDir;
857 std::uint32_t seekParent = fInfoShort.fSeekParent;
858 fInfoLong.fSeekDir = seekDir;
859 fInfoLong.fSeekParent = seekParent;
860 fInfoLong.fSeekKeys = seekKeys;
861 fClassVersion = fClassVersion + 1000;
862 } else {
863 fInfoShort.fSeekKeys = seekKeys;
864 }
865 }
866};
867
868/// A zero UUID stored at the end of the TFile record
869struct RTFUUID {
870 RUInt16BE fVersionClass{1};
871 unsigned char fUUID[16] = {0};
872
873 RTFUUID() = default;
874 std::uint32_t GetSize() const { return sizeof(RTFUUID); }
875};
876
877/// A streamed RNTuple class
878struct RTFNTuple {
879 RUInt32BE fByteCount{0x40000000 | (sizeof(RTFNTuple) - sizeof(fByteCount))};
880 RUInt16BE fVersionClass{3};
881 RInt32BE fChecksum{ChecksumRNTupleClass()};
882 RUInt32BE fVersionInternal{0};
884 RUInt64BE fSeekHeader{0};
885 RUInt32BE fNBytesHeader{0};
886 RUInt32BE fLenHeader{0};
887 RUInt64BE fSeekFooter{0};
888 RUInt32BE fNBytesFooter{0};
889 RUInt32BE fLenFooter{0};
890 RUInt64BE fReserved{0};
891
892 RTFNTuple() = default;
893 explicit RTFNTuple(const ROOT::Experimental::Internal::RFileNTupleAnchor &inMemoryAnchor)
894 {
895 fVersionInternal = inMemoryAnchor.fVersion;
896 fSize = inMemoryAnchor.fSize;
897 fSeekHeader = inMemoryAnchor.fSeekHeader;
898 fNBytesHeader = inMemoryAnchor.fNBytesHeader;
899 fLenHeader = inMemoryAnchor.fLenHeader;
900 fSeekFooter = inMemoryAnchor.fSeekFooter;
901 fNBytesFooter = inMemoryAnchor.fNBytesFooter;
902 fLenFooter = inMemoryAnchor.fLenFooter;
903 fReserved = inMemoryAnchor.fReserved;
904 }
905 std::uint32_t GetSize() const { return sizeof(RTFNTuple); }
907 {
909 anchor.fChecksum = fChecksum;
910 anchor.fVersion = fVersionInternal;
911 anchor.fSize = fSize;
912 anchor.fSeekHeader = fSeekHeader;
913 anchor.fNBytesHeader = fNBytesHeader;
914 anchor.fLenHeader = fLenHeader;
915 anchor.fSeekFooter = fSeekFooter;
916 anchor.fNBytesFooter = fNBytesFooter;
917 anchor.fLenFooter = fLenFooter;
918 anchor.fReserved = fReserved;
919 return anchor;
920 }
921};
922
923/// The bare file global header
924struct RBareFileHeader {
925 char fMagic[7]{ 'r', 'n', 't', 'u', 'p', 'l', 'e' };
926 RUInt32BE fRootVersion{(ROOT_VERSION_CODE >> 16) * 10000 +
927 ((ROOT_VERSION_CODE & 0xFF00) >> 8) * 100 +
928 (ROOT_VERSION_CODE & 0xFF)};
929 RUInt32BE fFormatVersion{1};
930 RUInt32BE fCompress{0};
931 RTFNTuple fNTuple;
932 // followed by the ntuple name
933};
934#pragma pack(pop)
935
936/// The artifical class name shown for opaque RNTuple keys (see TBasket)
937static constexpr char const *kBlobClassName = "RBlob";
938/// The class name of the RNTuple anchor
939static constexpr char const *kNTupleClassName = "ROOT::Experimental::RNTuple";
940
941/// The RKeyBlob writes an invisible key into a TFile. That is, a key that is not indexed in the list of keys,
942/// like a TBasket.
943class RKeyBlob : public TKey {
944public:
945 explicit RKeyBlob(TFile *file) : TKey(file) {
946 fClassName = kBlobClassName;
947 fVersion += 1000;
948 fKeylen = Sizeof();
949 }
950
951 /// Register a new key for a data record of size nbytes
952 void Reserve(size_t nbytes, std::uint64_t *seekKey)
953 {
954 Create(nbytes);
955 *seekKey = fSeekKey;
956 }
957};
958
959} // anonymous namespace
960
961
962namespace ROOT {
963namespace Experimental {
964namespace Internal {
965/// If a TFile container is written by a C stream (simple file), on dataset commit, the file header
966/// and the TFile record need to be updated
968 RTFHeader fHeader;
969 RTFFile fFileRecord;
970 std::uint64_t fSeekNTuple{0}; // Remember the offset for the keys list
971 std::uint64_t fSeekFileRecord{0};
972};
973} // namespace ROOT
974} // namespace Experimental
975} // namespace Internal
976
977
979 : fRawFile(rawFile)
980{
981}
982
985{
986 char ident[4];
987 ReadBuffer(ident, 4, 0);
988 if (std::string(ident, 4) == "root")
989 return GetNTupleProper(ntupleName);
990 fIsBare = true;
991 return GetNTupleBare(ntupleName);
992}
993
996{
997 RTFHeader fileHeader;
998 ReadBuffer(&fileHeader, sizeof(fileHeader), 0);
999
1000 RTFKey key;
1001 RTFString name;
1002 ReadBuffer(&key, sizeof(key), fileHeader.fBEGIN);
1003 std::uint64_t offset = fileHeader.fBEGIN + key.fKeyLen;
1004 ReadBuffer(&name, 1, offset);
1005 offset += name.GetSize();
1006 ReadBuffer(&name, 1, offset);
1007 offset += name.GetSize();
1008 RTFFile file;
1009 ReadBuffer(&file, sizeof(file), offset);
1010
1011 RUInt32BE nKeys;
1012 offset = file.GetSeekKeys();
1013 ReadBuffer(&key, sizeof(key), offset);
1014 offset += key.fKeyLen;
1015 ReadBuffer(&nKeys, sizeof(nKeys), offset);
1016 offset += sizeof(nKeys);
1017 bool found = false;
1018 for (unsigned int i = 0; i < nKeys; ++i) {
1019 ReadBuffer(&key, sizeof(key), offset);
1020 auto offsetNextKey = offset + key.fKeyLen;
1021
1022 offset += key.GetHeaderSize();
1023 ReadBuffer(&name, 1, offset);
1024 ReadBuffer(&name, name.GetSize(), offset);
1025 if (std::string_view(name.fData, name.fLName) != kNTupleClassName) {
1026 offset = offsetNextKey;
1027 continue;
1028 }
1029 offset += name.GetSize();
1030 ReadBuffer(&name, 1, offset);
1031 ReadBuffer(&name, name.GetSize(), offset);
1032 if (std::string_view(name.fData, name.fLName) == ntupleName) {
1033 found = true;
1034 break;
1035 }
1036 offset = offsetNextKey;
1037 }
1038 if (!found) {
1039 return R__FAIL("no RNTuple named '" + std::string(ntupleName)
1040 + "' in file '" + fRawFile->GetUrl() + "'");
1041 }
1042
1043 ReadBuffer(&key, sizeof(key), key.GetSeekKey());
1044 offset = key.GetSeekKey() + key.fKeyLen;
1045 RTFNTuple ntuple;
1046 if (key.fObjLen > sizeof(ntuple)) {
1047 return R__FAIL("invalid anchor size: " + std::to_string(key.fObjLen) + " > " + std::to_string(sizeof(ntuple)));
1048 }
1049 ReadBuffer(&ntuple, key.fObjLen, offset);
1050 if (sizeof(ntuple) != key.fObjLen) {
1052 decompressor.Unzip(&ntuple, sizeof(ntuple), key.fObjLen);
1053 }
1054 return ntuple.ToAnchor();
1055}
1056
1059{
1060 RBareFileHeader fileHeader;
1061 ReadBuffer(&fileHeader, sizeof(fileHeader), 0);
1062 RTFString name;
1063 auto offset = sizeof(fileHeader);
1064 ReadBuffer(&name, 1, offset);
1065 ReadBuffer(&name, name.GetSize(), offset);
1066 std::string_view foundName(name.fData, name.fLName);
1067 if (foundName != ntupleName) {
1068 return R__FAIL("expected RNTuple named '" + std::string(ntupleName)
1069 + "' but instead found '" + std::string(foundName)
1070 + "' in file '" + fRawFile->GetUrl() + "'");
1071 }
1072 offset += name.GetSize();
1073
1074 RTFNTuple ntuple;
1075 ReadBuffer(&ntuple, sizeof(ntuple), offset);
1076 return ntuple.ToAnchor();
1077}
1078
1079
1080void ROOT::Experimental::Internal::RMiniFileReader::ReadBuffer(void *buffer, size_t nbytes, std::uint64_t offset)
1081{
1082 auto nread = fRawFile->ReadAt(buffer, nbytes, offset);
1083 R__ASSERT(nread == nbytes);
1084}
1085
1086
1087////////////////////////////////////////////////////////////////////////////////
1088
1089
1091{
1092 if (fFile)
1093 fclose(fFile);
1094}
1095
1096
1098 const void *buffer, size_t nbytes, std::int64_t offset)
1099{
1100 R__ASSERT(fFile);
1101 size_t retval;
1102 if ((offset >= 0) && (static_cast<std::uint64_t>(offset) != fFilePos)) {
1103#ifdef R__SEEK64
1104 retval = fseeko64(fFile, offset, SEEK_SET);
1105#else
1106 retval = fseek(fFile, offset, SEEK_SET);
1107#endif
1108 R__ASSERT(retval == 0);
1109 fFilePos = offset;
1110 }
1111 retval = fwrite(buffer, 1, nbytes, fFile);
1112 R__ASSERT(retval == nbytes);
1113 fFilePos += nbytes;
1114}
1115
1116
1118 const void *buffer, std::size_t nbytes, std::size_t len, std::int64_t offset,
1119 std::uint64_t directoryOffset,
1120 const std::string &className,
1121 const std::string &objectName,
1122 const std::string &title)
1123{
1124 if (offset < 0)
1125 offset = fFilePos;
1126 RTFString strClass{className};
1127 RTFString strObject{objectName};
1128 RTFString strTitle{title};
1129
1130 RTFKey key(offset, directoryOffset, strClass, strObject, strTitle, len, nbytes);
1131 Write(&key, key.fKeyHeaderSize, offset);
1132 Write(&strClass, strClass.GetSize());
1133 Write(&strObject, strObject.GetSize());
1134 Write(&strTitle, strTitle.GetSize());
1135 auto offsetData = fFilePos;
1136 if (buffer)
1137 Write(buffer, nbytes);
1138
1139 return offsetData;
1140}
1141
1142
1143////////////////////////////////////////////////////////////////////////////////
1144
1145
1147 const void *buffer, size_t nbytes, std::int64_t offset)
1148{
1149 R__ASSERT(fFile);
1150 fFile->Seek(offset);
1151 bool rv = fFile->WriteBuffer((char *)(buffer), nbytes);
1152 R__ASSERT(!rv);
1153}
1154
1155
1157 const void *buffer, size_t nbytes, size_t len)
1158{
1159 std::uint64_t offsetKey;
1160 RKeyBlob keyBlob(fFile);
1161 // Since it is unknown beforehand if offsetKey is beyond the 2GB limit or not,
1162 // RKeyBlob will always reserve space for a big key (version >= 1000)
1163 keyBlob.Reserve(nbytes, &offsetKey);
1164
1165 auto offset = offsetKey;
1166 RTFString strClass{kBlobClassName};
1167 RTFString strObject;
1168 RTFString strTitle;
1169 RTFKey keyHeader(offset, offset, strClass, strObject, strTitle, len, nbytes);
1170 // Follow the fact that RKeyBlob is a big key unconditionally (see above)
1171 keyHeader.MakeBigKey();
1172
1173 Write(&keyHeader, keyHeader.fKeyHeaderSize, offset);
1174 offset += keyHeader.fKeyHeaderSize;
1175 Write(&strClass, strClass.GetSize(), offset);
1176 offset += strClass.GetSize();
1177 Write(&strObject, strObject.GetSize(), offset);
1178 offset += strObject.GetSize();
1179 Write(&strTitle, strTitle.GetSize(), offset);
1180 offset += strTitle.GetSize();
1181 auto offsetData = offset;
1182 Write(buffer, nbytes, offset);
1183
1184 return offsetData;
1185}
1186
1187
1188////////////////////////////////////////////////////////////////////////////////
1189
1190
1192 : fNTupleName(name)
1193{
1194 fFileSimple.fControlBlock = std::make_unique<ROOT::Experimental::Internal::RTFileControlBlock>();
1195}
1196
1197
1199{
1200}
1201
1202
1204 std::string_view ntupleName, std::string_view path, int defaultCompression, ENTupleContainerFormat containerFormat)
1205{
1206 std::string fileName(path);
1207 size_t idxDirSep = fileName.find_last_of("\\/");
1208 if (idxDirSep != std::string::npos) {
1209 fileName.erase(0, idxDirSep + 1);
1210 }
1211#ifdef R__SEEK64
1212 FILE *fileStream = fopen64(std::string(path.data(), path.size()).c_str(), "wb");
1213#else
1214 FILE *fileStream = fopen(std::string(path.data(), path.size()).c_str(), "wb");
1215#endif
1216 R__ASSERT(fileStream);
1217
1218 auto writer = new RNTupleFileWriter(ntupleName);
1219 writer->fFileSimple.fFile = fileStream;
1220 writer->fFileName = fileName;
1221
1222 switch (containerFormat) {
1224 writer->WriteTFileSkeleton(defaultCompression);
1225 break;
1227 writer->fIsBare = true;
1228 writer->WriteBareFileSkeleton(defaultCompression);
1229 break;
1230 default:
1231 R__ASSERT(false && "Internal error: unhandled container format");
1232 }
1233
1234 return writer;
1235}
1236
1237
1239 std::string_view ntupleName, std::string_view path, std::unique_ptr<TFile> &file)
1240{
1241 file = std::unique_ptr<TFile>(TFile::Open(std::string(path.data(), path.size()).c_str(), "RECREATE"));
1242 R__ASSERT(file && !file->IsZombie());
1243
1244 auto writer = new RNTupleFileWriter(ntupleName);
1245 writer->fFileProper.fFile = file.get();
1246 return writer;
1247}
1248
1249
1251 std::string_view ntupleName, TFile &file)
1252{
1253 auto writer = new RNTupleFileWriter(ntupleName);
1254 writer->fFileProper.fFile = &file;
1255 return writer;
1256}
1257
1258
1260{
1261 if (fFileProper) {
1262 // Easy case, the ROOT file header and the RNTuple streaming is taken care of by TFile
1263 ROOT::Experimental::RNTuple ntuple(fNTupleAnchor);
1264 fFileProper.fFile->WriteObject(&ntuple, fNTupleName.c_str());
1265 fFileProper.fFile->Write();
1266 return;
1267 }
1268
1269 // Writing by C file stream: prepare the container format header and stream the RNTuple anchor object
1270 R__ASSERT(fFileSimple);
1271
1272 if (fIsBare) {
1273 RTFNTuple ntupleOnDisk(fNTupleAnchor);
1274 fFileSimple.Write(&ntupleOnDisk, ntupleOnDisk.GetSize(), fFileSimple.fControlBlock->fSeekNTuple);
1275 fflush(fFileSimple.fFile);
1276 return;
1277 }
1278
1279 WriteTFileNTupleKey();
1280 WriteTFileKeysList();
1281 WriteTFileStreamerInfo();
1282 WriteTFileFreeList();
1283
1284 // Update header and TFile record
1285 fFileSimple.Write(&fFileSimple.fControlBlock->fHeader, fFileSimple.fControlBlock->fHeader.GetSize(), 0);
1286 fFileSimple.Write(&fFileSimple.fControlBlock->fFileRecord, fFileSimple.fControlBlock->fFileRecord.GetSize(),
1287 fFileSimple.fControlBlock->fSeekFileRecord);
1288 fflush(fFileSimple.fFile);
1289}
1290
1291
1292std::uint64_t ROOT::Experimental::Internal::RNTupleFileWriter::WriteBlob(const void *data, size_t nbytes, size_t len)
1293{
1294 std::uint64_t offset;
1295 if (fFileSimple) {
1296 if (fIsBare) {
1297 offset = fFileSimple.fFilePos;
1298 fFileSimple.Write(data, nbytes);
1299 } else {
1300 offset = fFileSimple.WriteKey(data, nbytes, len, -1, 100, kBlobClassName);
1301 }
1302 } else {
1303 offset = fFileProper.WriteKey(data, nbytes, len);
1304 }
1305 return offset;
1306}
1307
1308
1310 const void *data, size_t nbytes, size_t lenHeader)
1311{
1312 auto offset = WriteBlob(data, nbytes, lenHeader);
1313 fNTupleAnchor.fLenHeader = lenHeader;
1314 fNTupleAnchor.fNBytesHeader = nbytes;
1315 fNTupleAnchor.fSeekHeader = offset;
1316 return offset;
1317}
1318
1319
1321 const void *data, size_t nbytes, size_t lenFooter)
1322{
1323 auto offset = WriteBlob(data, nbytes, lenFooter);
1324 fNTupleAnchor.fLenFooter = lenFooter;
1325 fNTupleAnchor.fNBytesFooter = nbytes;
1326 fNTupleAnchor.fSeekFooter = offset;
1327 return offset;
1328}
1329
1330
1332{
1333 RBareFileHeader bareHeader;
1334 bareHeader.fCompress = defaultCompression;
1335 fFileSimple.Write(&bareHeader, sizeof(bareHeader), 0);
1336 RTFString ntupleName{fNTupleName};
1337 fFileSimple.Write(&ntupleName, ntupleName.GetSize());
1338
1339 // Write zero-initialized ntuple to reserve the space; will be overwritten on commit
1340 RTFNTuple ntupleOnDisk;
1341 fFileSimple.fControlBlock->fSeekNTuple = fFileSimple.fFilePos;
1342 fFileSimple.Write(&ntupleOnDisk, ntupleOnDisk.GetSize());
1343}
1344
1346{
1347 RTFString strTList{"TList"};
1348 RTFString strStreamerInfo{"StreamerInfo"};
1349 RTFString strStreamerTitle{"Doubly linked list"};
1350
1351 fFileSimple.fControlBlock->fHeader.SetSeekInfo(fFileSimple.fFilePos);
1352 RTFKey keyStreamerInfo(
1353 fFileSimple.fControlBlock->fHeader.GetSeekInfo(), 100, strTList, strStreamerInfo, strStreamerTitle, 0);
1354 RTFStreamerInfoList streamerInfo;
1355 auto classTagOffset = keyStreamerInfo.fKeyLen + offsetof(struct RTFStreamerInfoList, fStreamerInfo) +
1356 offsetof(struct RTFStreamerInfoObject, fStreamers) +
1357 offsetof(struct RTFStreamerChecksum, fNewClassTag) + 2;
1358 streamerInfo.fStreamerInfo.fStreamers.fStreamerVersion.fClassTag = 0x80000000 | classTagOffset;
1359 streamerInfo.fStreamerInfo.fStreamers.fStreamerSize.fClassTag = 0x80000000 | classTagOffset;
1360 streamerInfo.fStreamerInfo.fStreamers.fStreamerSeekHeader.fClassTag = 0x80000000 | classTagOffset;
1361 streamerInfo.fStreamerInfo.fStreamers.fStreamerNBytesHeader.fClassTag = 0x80000000 | classTagOffset;
1362 streamerInfo.fStreamerInfo.fStreamers.fStreamerLenHeader.fClassTag = 0x80000000 | classTagOffset;
1363 streamerInfo.fStreamerInfo.fStreamers.fStreamerSeekFooter.fClassTag = 0x80000000 | classTagOffset;
1364 streamerInfo.fStreamerInfo.fStreamers.fStreamerNBytesFooter.fClassTag = 0x80000000 | classTagOffset;
1365 streamerInfo.fStreamerInfo.fStreamers.fStreamerLenFooter.fClassTag = 0x80000000 | classTagOffset;
1366 streamerInfo.fStreamerInfo.fStreamers.fStreamerReserved.fClassTag = 0x80000000 | classTagOffset;
1367 Detail::RNTupleCompressor compressor;
1368 auto szStreamerInfo = compressor.Zip(&streamerInfo, streamerInfo.GetSize(), 1);
1369 fFileSimple.WriteKey(compressor.GetZipBuffer(), szStreamerInfo, streamerInfo.GetSize(),
1370 fFileSimple.fControlBlock->fHeader.GetSeekInfo(), 100,
1371 "TList", "StreamerInfo", "Doubly linked list");
1372 fFileSimple.fControlBlock->fHeader.SetNbytesInfo(
1373 fFileSimple.fFilePos - fFileSimple.fControlBlock->fHeader.GetSeekInfo());
1374}
1375
1377{
1378 RTFString strEmpty;
1379 RTFString strRNTupleClass{"ROOT::Experimental::RNTuple"};
1380 RTFString strRNTupleName{fNTupleName};
1381 RTFString strFileName{fFileName};
1382
1383 RTFKey keyRNTuple(fFileSimple.fControlBlock->fSeekNTuple, 100, strRNTupleClass, strRNTupleName, strEmpty,
1384 RTFNTuple().GetSize());
1385
1386 fFileSimple.fControlBlock->fFileRecord.SetSeekKeys(fFileSimple.fFilePos);
1387 RTFKeyList keyList{1};
1388 RTFKey keyKeyList(fFileSimple.fControlBlock->fFileRecord.GetSeekKeys(), 100, strEmpty, strFileName, strEmpty,
1389 keyList.GetSize() + keyRNTuple.fKeyLen);
1390 fFileSimple.Write(&keyKeyList, keyKeyList.fKeyHeaderSize, fFileSimple.fControlBlock->fFileRecord.GetSeekKeys());
1391 fFileSimple.Write(&strEmpty, strEmpty.GetSize());
1392 fFileSimple.Write(&strFileName, strFileName.GetSize());
1393 fFileSimple.Write(&strEmpty, strEmpty.GetSize());
1394 fFileSimple.Write(&keyList, keyList.GetSize());
1395 fFileSimple.Write(&keyRNTuple, keyRNTuple.fKeyHeaderSize);
1396 fFileSimple.Write(&strRNTupleClass, strRNTupleClass.GetSize());
1397 fFileSimple.Write(&strRNTupleName, strRNTupleName.GetSize());
1398 fFileSimple.Write(&strEmpty, strEmpty.GetSize());
1399 fFileSimple.fControlBlock->fFileRecord.fNBytesKeys =
1400 fFileSimple.fFilePos - fFileSimple.fControlBlock->fFileRecord.GetSeekKeys();
1401}
1402
1404{
1405 fFileSimple.fControlBlock->fHeader.SetSeekFree(fFileSimple.fFilePos);
1406 RTFString strEmpty;
1407 RTFString strFileName{fFileName};
1408 RTFFreeEntry freeEntry;
1409 RTFKey keyFreeList(fFileSimple.fControlBlock->fHeader.GetSeekFree(), 100, strEmpty, strFileName, strEmpty,
1410 freeEntry.GetSize());
1411 std::uint64_t firstFree = fFileSimple.fControlBlock->fHeader.GetSeekFree() + keyFreeList.GetSize();
1412 freeEntry.Set(firstFree, std::max(2000000000ULL, ((firstFree / 1000000000ULL) + 1) * 1000000000ULL));
1413 fFileSimple.WriteKey(&freeEntry, freeEntry.GetSize(), freeEntry.GetSize(),
1414 fFileSimple.fControlBlock->fHeader.GetSeekFree(), 100, "", fFileName, "");
1415 fFileSimple.fControlBlock->fHeader.SetNbytesFree(fFileSimple.fFilePos -
1416 fFileSimple.fControlBlock->fHeader.GetSeekFree());
1417 fFileSimple.fControlBlock->fHeader.SetEnd(fFileSimple.fFilePos);
1418}
1419
1421{
1422 RTFString strRNTupleClass{"ROOT::Experimental::RNTuple"};
1423 RTFString strRNTupleName{fNTupleName};
1424 RTFString strEmpty;
1425
1426 RTFNTuple ntupleOnDisk(fNTupleAnchor);
1427 fFileSimple.fControlBlock->fSeekNTuple = fFileSimple.fFilePos;
1428 fFileSimple.WriteKey(&ntupleOnDisk, ntupleOnDisk.GetSize(), ntupleOnDisk.GetSize(),
1429 fFileSimple.fControlBlock->fSeekNTuple, 100, "ROOT::Experimental::RNTuple", fNTupleName, "");
1430}
1431
1433{
1434 RTFString strTFile{"TFile"};
1435 RTFString strFileName{fFileName};
1436 RTFString strEmpty;
1437
1438 fFileSimple.fControlBlock->fHeader = RTFHeader(defaultCompression);
1439
1440 RTFUUID uuid;
1441
1442 // First record of the file: the TFile object at offset 100
1443 RTFKey keyRoot(100, 0, strTFile, strFileName, strEmpty,
1444 sizeof(RTFFile) + strFileName.GetSize() + strEmpty.GetSize() + uuid.GetSize());
1445 std::uint32_t nbytesName = keyRoot.fKeyLen + strFileName.GetSize() + 1;
1446 fFileSimple.fControlBlock->fFileRecord.fNBytesName = nbytesName;
1447 fFileSimple.fControlBlock->fHeader.SetNbytesName(nbytesName);
1448
1449 fFileSimple.Write(&keyRoot, keyRoot.fKeyHeaderSize, 100);
1450 fFileSimple.Write(&strTFile, strTFile.GetSize());
1451 fFileSimple.Write(&strFileName, strFileName.GetSize());
1452 fFileSimple.Write(&strEmpty, strEmpty.GetSize());
1453 fFileSimple.Write(&strFileName, strFileName.GetSize());
1454 fFileSimple.Write(&strEmpty, strEmpty.GetSize());
1455 // Will be overwritten on commit
1456 fFileSimple.fControlBlock->fSeekFileRecord = fFileSimple.fFilePos;
1457 fFileSimple.Write(&fFileSimple.fControlBlock->fFileRecord, fFileSimple.fControlBlock->fFileRecord.GetSize());
1458 fFileSimple.Write(&uuid, uuid.GetSize());
1459
1460 // Padding bytes to allow the TFile record to grow for a big file
1461 RUInt32BE padding{0};
1462 for (int i = 0; i < 3; ++i)
1463 fFileSimple.Write(&padding, sizeof(padding));
1464}
size_t fSize
#define R__FAIL(msg)
Short-hand to return an RResult<T> in an error state; the RError is implicitly converted into RResult...
Definition RError.hxx:303
#define ROOT_VERSION_CODE
Definition RVersion.h:21
#define R__ASSERT(e)
Definition TError.h:117
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 id
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
char name[80]
Definition TGX11.cxx:110
Binding & operator=(OUT(*fun)(void))
void ReadBuffer(char *&buffer) override
T1 fFirst
Definition X11Events.mm:86
Helper class to compress data blocks in the ROOT compression frame format.
size_t Zip(const void *from, size_t nbytes, int compression, Writer_t fnWriter)
Returns the size of the compressed data.
Helper class to uncompress data blocks in the ROOT compression frame format.
void Unzip(const void *from, size_t nbytes, size_t dataLen, void *to)
The nbytes parameter provides the size ls of the from buffer.
RResult< RFileNTupleAnchor > GetNTupleProper(std::string_view ntupleName)
Used when the file turns out to be a TFile container.
RResult< RFileNTupleAnchor > GetNTuple(std::string_view ntupleName)
Extracts header and footer location for the RNTuple identified by ntupleName.
void ReadBuffer(void *buffer, size_t nbytes, std::uint64_t offset)
Reads a given byte range from the file into the provided memory buffer.
RResult< RFileNTupleAnchor > GetNTupleBare(std::string_view ntupleName)
Used when the file container turns out to be a bare file.
Write RNTuple data blocks in a TFile or a bare file container.
std::uint64_t WriteBlob(const void *data, size_t nbytes, size_t len)
Writes a new record as an RBlob key into the file.
std::uint64_t WriteNTupleFooter(const void *data, size_t nbytes, size_t lenFooter)
Writes the compressed footer and registeres its location; lenFooter is the size of the uncompressed f...
void WriteTFileKeysList()
Write the TList with the RNTuple key.
void Commit()
Writes the RNTuple key to the file so that the header and footer keys can be found.
RFileSimple fFileSimple
For simple use cases, survives without libRIO dependency.
static RNTupleFileWriter * Append(std::string_view ntupleName, TFile &file)
Add a new RNTuple identified by ntupleName to the existing TFile.
void WriteTFileNTupleKey()
The only key that will be visible in file->ls()
void WriteTFileFreeList()
Last record in the file.
static RNTupleFileWriter * Recreate(std::string_view ntupleName, std::string_view path, int defaultCompression, ENTupleContainerFormat containerFormat)
Create or truncate the local file given by path with the new empty RNTuple identified by ntupleName.
void WriteTFileSkeleton(int defaultCompression)
For a TFile container written by a C file stream, write the header and TFile object.
void WriteBareFileSkeleton(int defaultCompression)
For a bare file, which is necessarily written by a C file stream, write file header.
void WriteTFileStreamerInfo()
Write the compressed streamer info record with the description of the RNTuple class.
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...
Representation of an RNTuple data set in a ROOT file.
Definition RNTuple.hxx:496
The class is used as a return type for operations that can fail; wraps a value of type T or an RError...
Definition RError.hxx:207
The RRawFile provides read-only access to local and remote files.
Definition RRawFile.hxx:43
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format.
Definition TFile.h:51
static TFile * Open(const char *name, Option_t *option="", const char *ftitle="", Int_t compress=ROOT::RCompressionSetting::EDefaults::kUseCompiledDefault, Int_t netopt=0)
Create / open a file.
Definition TFile.cxx:4053
Book space in a file, create I/O buffers, to fill them, (un)compress them.
Definition TKey.h:28
Int_t Sizeof() const override
Return the size in bytes of the key header structure.
Definition TKey.cxx:1336
Long64_t fSeekKey
Location of object on file.
Definition TKey.h:45
virtual void Create(Int_t nbytes, TFile *f=nullptr)
Create a TKey object of specified size.
Definition TKey.cxx:459
struct void * fTypeName
Definition cppyy.h:9
#define Swap(a, b)
Definition geom.c:201
Double_t x[n]
Definition legend1.C:17
This file contains a specialised ROOT message handler to test for diagnostic in unit tests.
Definition file.py:1
Definition first.py:1
Entry point for an RNTuple in a ROOT file.
Definition RMiniFile.hxx:65
std::uint32_t fNBytesFooter
The size of the compressed ntuple footer.
Definition RMiniFile.hxx:82
std::int32_t fChecksum
The ROOT streamer info checksum.
Definition RMiniFile.hxx:68
std::uint64_t fSeekFooter
The file offset of the footer excluding the TKey part.
Definition RMiniFile.hxx:80
std::uint32_t fSize
Allows for skipping the struct.
Definition RMiniFile.hxx:72
std::uint32_t fNBytesHeader
The size of the compressed ntuple header.
Definition RMiniFile.hxx:76
std::uint32_t fLenFooter
The size of the uncompressed ntuple footer.
Definition RMiniFile.hxx:84
std::uint64_t fSeekHeader
The file offset of the header excluding the TKey part.
Definition RMiniFile.hxx:74
std::uint32_t fLenHeader
The size of the uncompressed ntuple header.
Definition RMiniFile.hxx:78
std::uint64_t fReserved
Currently unused, reserved for later use.
Definition RMiniFile.hxx:86
std::uint32_t fVersion
Allows for evolving the struct in future versions.
Definition RMiniFile.hxx:70
void Write(const void *buffer, size_t nbytes, std::int64_t offset)
Low-level writing using a TFile.
std::uint64_t WriteKey(const void *buffer, size_t nbytes, size_t len)
Writes an RBlob opaque key with the provided buffer as data record and returns the offset of the reco...
std::unique_ptr< ROOT::Experimental::Internal::RTFileControlBlock > fControlBlock
Keeps track of TFile control structures, which need to be updated on committing the data set.
void Write(const void *buffer, size_t nbytes, std::int64_t offset=-1)
Writes bytes in the open stream, either at fFilePos or at the given offset.
std::uint64_t WriteKey(const void *buffer, std::size_t nbytes, std::size_t len, std::int64_t offset=-1, std::uint64_t directoryOffset=100, const std::string &className="", const std::string &objectName="", const std::string &title="")
Writes a TKey including the data record, given by buffer, into fFile; returns the file offset to the ...
If a TFile container is written by a C stream (simple file), on dataset commit, the file header and t...
auto * tt
Definition textangle.C:16