Logo ROOT  
Reference Guide
RNTupleDescriptor.cxx
Go to the documentation of this file.
1/// \file RNTupleDescriptor.cxx
2/// \ingroup NTuple ROOT7
3/// \author Jakob Blomer <jblomer@cern.ch>
4/// \date 2018-10-04
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/RError.hxx>
17#include <ROOT/RField.hxx>
19#include <ROOT/RNTupleModel.hxx>
20#include <ROOT/RNTupleUtil.hxx>
21#include <ROOT/RStringView.hxx>
22
23#include <RZip.h>
24#include <TError.h>
25
26#include <algorithm>
27#include <cstdint>
28#include <iostream>
29#include <utility>
30
31namespace {
32
33/// The machine-independent serialization of meta-data wraps the header and footer as well as sub structures in
34/// frames. The frame layout is
35///
36/// -----------------------------------------------------------
37/// | TYPE | DESCRIPTION |
38/// |----------------------------------------------------------
39/// | std::uint16_t | Version used to write the frame |
40/// | std::uint16_t | Minimum version for reading the frame |
41/// | std::uint32_t | Length of the frame incl. preamble |
42/// -----------------------------------------------------------
43///
44/// In addition, the header and footer store a 4 byte CRC32 checksum of the frame immediately after the frame.
45/// The footer also repeats the frame size just before the CRC32 checksum. That means, one can read the last 8 bytes
46/// to determine the footer length, and the first 8 bytes to determine the header length.
47///
48/// Within the frames, integers of different lengths are stored in a machine-independent representation. Strings and
49/// vectors store the number of items followed by the items. Time stamps are stored in number of seconds since the
50/// UNIX epoch.
51
53
54std::uint32_t SerializeClusterSize(ROOT::Experimental::ClusterSize_t val, void *buffer)
55{
56 return SerializeUInt32(val, buffer);
57}
58
59std::uint32_t DeserializeClusterSize(const void *buffer, ROOT::Experimental::ClusterSize_t *val)
60{
61 std::uint32_t size;
62 auto nbytes = DeserializeUInt32(buffer, &size);
63 *val = size;
64 return nbytes;
65}
66
67std::uint32_t SerializeLocator(const ROOT::Experimental::RClusterDescriptor::RLocator &val, void *buffer)
68{
69 // In order to keep the meta-data small, we don't wrap the locator in a frame
70 if (buffer != nullptr) {
71 auto pos = reinterpret_cast<unsigned char *>(buffer);
72 pos += SerializeInt64(val.fPosition, pos);
73 pos += SerializeUInt32(val.fBytesOnStorage, pos);
74 pos += SerializeString(val.fUrl, pos);
75 }
76 return SerializeString(val.fUrl, nullptr) + 12;
77}
78
79std::uint32_t DeserializeLocator(const void *buffer, ROOT::Experimental::RClusterDescriptor::RLocator *val)
80{
81 auto bytes = reinterpret_cast<const unsigned char *>(buffer);
82 bytes += DeserializeInt64(bytes, &val->fPosition);
83 bytes += DeserializeUInt32(bytes, &val->fBytesOnStorage);
84 bytes += DeserializeString(bytes, &val->fUrl);
85 return SerializeString(val->fUrl, nullptr) + 12;
86}
87
88std::uint32_t SerializeFrame(std::uint16_t protocolVersionCurrent, std::uint16_t protocolVersionMin, void *buffer,
89 void **ptrSize)
90{
91 if (buffer != nullptr) {
92 auto pos = reinterpret_cast<unsigned char *>(buffer);
93 pos += SerializeUInt16(protocolVersionCurrent, pos); // The protocol version used to write the structure
94 pos += SerializeUInt16(protocolVersionMin, pos); // The minimum protocol version required to read the data
95 *ptrSize = pos;
96 pos += SerializeUInt32(0, pos); // placeholder for the size of the frame
97 }
98 return 8;
99}
100
101std::uint32_t DeserializeFrame(std::uint16_t protocolVersion, const void *buffer, std::uint32_t *size)
102{
103 auto bytes = reinterpret_cast<const unsigned char *>(buffer);
104 std::uint16_t protocolVersionAtWrite;
105 std::uint16_t protocolVersionMinRequired;
106 bytes += DeserializeUInt16(bytes, &protocolVersionAtWrite);
107 bytes += DeserializeUInt16(bytes, &protocolVersionMinRequired);
108 if (protocolVersion < protocolVersionMinRequired) {
109 throw ROOT::Experimental::RException(R__FAIL("RNTuple version too new (version "
110 + std::to_string(protocolVersionMinRequired)
111 + "), version <= " + std::to_string(protocolVersion) + " required"));
112 }
113 bytes += DeserializeUInt32(bytes, size);
114 return 8;
115}
116
117std::uint32_t SerializeVersion(const ROOT::Experimental::RNTupleVersion &val, void *buffer)
118{
119 auto base = reinterpret_cast<unsigned char *>((buffer != nullptr) ? buffer : 0);
120 auto pos = base;
121 void** where = (buffer == nullptr) ? &buffer : reinterpret_cast<void**>(&pos);
122
123 void *ptrSize = nullptr;
124 pos += SerializeFrame(0, 0, *where, &ptrSize);
125
126 pos += SerializeUInt32(val.GetVersionUse(), *where);
127 pos += SerializeUInt32(val.GetVersionMin(), *where);
128 pos += SerializeUInt64(val.GetFlags(), *where);
129
130 auto size = pos - base;
131 SerializeUInt32(size, ptrSize);
132 return size;
133}
134
135std::uint32_t DeserializeVersion(const void *buffer, ROOT::Experimental::RNTupleVersion *version)
136{
137 auto bytes = reinterpret_cast<const unsigned char *>(buffer);
138 std::uint32_t frameSize;
139 bytes += DeserializeFrame(0, bytes, &frameSize);
140
141 std::uint32_t versionUse;
142 std::uint32_t versionMin;
143 std::uint64_t flags;
144 bytes += DeserializeUInt32(bytes, &versionUse);
145 bytes += DeserializeUInt32(bytes, &versionMin);
146 bytes += DeserializeUInt64(bytes, &flags);
147 *version = ROOT::Experimental::RNTupleVersion(versionUse, versionMin, flags);
148
149 return frameSize;
150}
151
152std::uint32_t SerializeUuid(const ROOT::Experimental::RNTupleUuid &val, void *buffer)
153{
154 auto base = reinterpret_cast<unsigned char *>((buffer != nullptr) ? buffer : 0);
155 auto pos = base;
156 void** where = (buffer == nullptr) ? &buffer : reinterpret_cast<void**>(&pos);
157
158 void *ptrSize = nullptr;
159 pos += SerializeFrame(0, 0, *where, &ptrSize);
160
161 pos += SerializeString(val, *where);
162
163 auto size = pos - base;
164 SerializeUInt32(size, ptrSize);
165 return size;
166}
167
168std::uint32_t DeserializeUuid(const void *buffer, ROOT::Experimental::RNTupleUuid *uuid)
169{
170 auto bytes = reinterpret_cast<const unsigned char *>(buffer);
171 std::uint32_t frameSize;
172 bytes += DeserializeFrame(0, bytes, &frameSize);
173
174 bytes += DeserializeString(bytes, uuid);
175
176 return frameSize;
177}
178
179std::uint32_t SerializeColumnModel(const ROOT::Experimental::RColumnModel &val, void *buffer)
180{
181 auto base = reinterpret_cast<unsigned char *>((buffer != nullptr) ? buffer : 0);
182 auto pos = base;
183 void** where = (buffer == nullptr) ? &buffer : reinterpret_cast<void**>(&pos);
184
185 void *ptrSize = nullptr;
186 pos += SerializeFrame(0, 0, *where, &ptrSize);
187
188 pos += SerializeInt32(static_cast<int>(val.GetType()), *where);
189 pos += SerializeInt32(static_cast<int>(val.GetIsSorted()), *where);
190
191 auto size = pos - base;
192 SerializeUInt32(size, ptrSize);
193 return size;
194}
195
196std::uint32_t DeserializeColumnModel(const void *buffer, ROOT::Experimental::RColumnModel *columnModel)
197{
198 auto bytes = reinterpret_cast<const unsigned char *>(buffer);
199 std::uint32_t frameSize;
200 bytes += DeserializeFrame(0, bytes, &frameSize);
201
202 std::int32_t type;
203 std::int32_t isSorted;
204 bytes += DeserializeInt32(bytes, &type);
205 bytes += DeserializeInt32(bytes, &isSorted);
206 *columnModel = ROOT::Experimental::RColumnModel(static_cast<ROOT::Experimental::EColumnType>(type), isSorted);
207
208 return frameSize;
209}
210
211std::uint32_t SerializeTimeStamp(const std::chrono::system_clock::time_point &val, void *buffer)
212{
213 return SerializeInt64(std::chrono::system_clock::to_time_t(val), buffer);
214}
215
216std::uint32_t DeserializeTimeStamp(const void *buffer, std::chrono::system_clock::time_point *timeStamp)
217{
218 std::int64_t secSinceUnixEpoch;
219 auto size = DeserializeInt64(buffer, &secSinceUnixEpoch);
220 *timeStamp = std::chrono::system_clock::from_time_t(secSinceUnixEpoch);
221 return size;
222}
223
224std::uint32_t SerializeColumnRange(const ROOT::Experimental::RClusterDescriptor::RColumnRange &val, void *buffer)
225{
226 // To keep the cluster footers small, we don't put a frame around individual column ranges.
227 if (buffer != nullptr) {
228 auto pos = reinterpret_cast<unsigned char *>(buffer);
229 // The column id is stored in SerializeFooter() for the column range and the page range altogether
230 pos += SerializeUInt64(val.fFirstElementIndex, pos);
231 pos += SerializeClusterSize(val.fNElements, pos);
232 pos += SerializeInt64(val.fCompressionSettings, pos);
233 }
234 return 20;
235}
236
237std::uint32_t DeserializeColumnRange(const void *buffer,
239{
240 auto bytes = reinterpret_cast<const unsigned char *>(buffer);
241 // The column id is set elsewhere (see AddClustersFromFooter())
242 bytes += DeserializeUInt64(bytes, &columnRange->fFirstElementIndex);
243 bytes += DeserializeClusterSize(bytes, &columnRange->fNElements);
244 bytes += DeserializeInt64(bytes, &columnRange->fCompressionSettings);
245 return 20;
246}
247
248std::uint32_t SerializePageInfo(const ROOT::Experimental::RClusterDescriptor::RPageRange::RPageInfo &val, void *buffer)
249{
250 // To keep the cluster footers small, we don't put a frame around individual page infos.
251 if (buffer != nullptr) {
252 auto pos = reinterpret_cast<unsigned char *>(buffer);
253 // The column id is stored in SerializeFooter() for the column range and the page range altogether
254 pos += SerializeClusterSize(val.fNElements, pos);
255 pos += SerializeLocator(val.fLocator, pos);
256 }
257 return 4 + SerializeLocator(val.fLocator, nullptr);
258}
259
260std::uint32_t DeserializePageInfo(const void *buffer,
262{
263 auto base = reinterpret_cast<const unsigned char *>(buffer);
264 auto bytes = base;
265 // The column id is set elsewhere (see AddClustersFromFooter())
266 bytes += DeserializeClusterSize(bytes, &pageInfo->fNElements);
267 bytes += DeserializeLocator(bytes, &pageInfo->fLocator);
268 return bytes - base;
269}
270
271std::uint32_t SerializeCrc32(const unsigned char *data, std::uint32_t length, void *buffer)
272{
273 auto checksum = R__crc32(0, nullptr, 0);
274 if (buffer != nullptr) {
275 checksum = R__crc32(checksum, data, length);
276 SerializeUInt32(checksum, buffer);
277 }
278 return 4;
279}
280
281void VerifyCrc32(const unsigned char *data, std::uint32_t length)
282{
283 auto checksumReal = R__crc32(0, nullptr, 0);
284 checksumReal = R__crc32(checksumReal, data, length);
285 std::uint32_t checksumFound;
286 DeserializeUInt32(data + length, &checksumFound);
287 R__ASSERT(checksumFound == checksumReal);
288}
289
290std::uint32_t SerializeField(const ROOT::Experimental::RFieldDescriptor &val, void *buffer)
291{
292 auto base = reinterpret_cast<unsigned char *>((buffer != nullptr) ? buffer : 0);
293 auto pos = base;
294 void** where = (buffer == nullptr) ? &buffer : reinterpret_cast<void**>(&pos);
295
296 void *ptrSize = nullptr;
299
300 pos += SerializeUInt64(val.GetId(), *where);
301 pos += SerializeVersion(val.GetFieldVersion(), *where);
302 pos += SerializeVersion(val.GetTypeVersion(), *where);
303 pos += SerializeString(val.GetFieldName(), *where);
304 pos += SerializeString(val.GetFieldDescription(), *where);
305 pos += SerializeString(val.GetTypeName(), *where);
306 pos += SerializeUInt64(val.GetNRepetitions(), *where);
307 pos += SerializeUInt32(static_cast<int>(val.GetStructure()), *where);
308 pos += SerializeUInt64(val.GetParentId(), *where);
309 pos += SerializeUInt32(val.GetLinkIds().size(), *where);
310 for (const auto& l : val.GetLinkIds())
311 pos += SerializeUInt64(l, *where);
312
313 auto size = pos - base;
314 SerializeUInt32(size, ptrSize);
315 return size;
316}
317
318std::uint32_t SerializeColumn(const ROOT::Experimental::RColumnDescriptor &val, void *buffer)
319{
320 auto base = reinterpret_cast<unsigned char *>((buffer != nullptr) ? buffer : 0);
321 auto pos = base;
322 void** where = (buffer == nullptr) ? &buffer : reinterpret_cast<void**>(&pos);
323
324 void *ptrSize = nullptr;
327
328 pos += SerializeUInt64(val.GetId(), *where);
329 pos += SerializeVersion(val.GetVersion(), *where);
330 pos += SerializeColumnModel(val.GetModel(), *where);
331 pos += SerializeUInt64(val.GetFieldId(), *where);
332 pos += SerializeUInt32(val.GetIndex(), *where);
333
334 auto size = pos - base;
335 SerializeUInt32(size, ptrSize);
336 return size;
337}
338
339std::uint32_t SerializeClusterSummary(const ROOT::Experimental::RClusterDescriptor &val, void *buffer)
340{
341 auto base = reinterpret_cast<unsigned char *>((buffer != nullptr) ? buffer : 0);
342 auto pos = base;
343 void** where = (buffer == nullptr) ? &buffer : reinterpret_cast<void**>(&pos);
344
345 void *ptrSize = nullptr;
348
349 pos += SerializeUInt64(val.GetId(), *where);
350 pos += SerializeVersion(val.GetVersion(), *where);
351 pos += SerializeUInt64(val.GetFirstEntryIndex(), *where);
352 pos += SerializeUInt64(val.GetNEntries(), *where);
353 pos += SerializeLocator(val.GetLocator(), *where);
354
355 auto size = pos - base;
356 SerializeUInt32(size, ptrSize);
357 return size;
358}
359
360} // anonymous namespace
361
362
363////////////////////////////////////////////////////////////////////////////////
364
365
367{
368 return fFieldId == other.fFieldId &&
369 fFieldVersion == other.fFieldVersion &&
370 fTypeVersion == other.fTypeVersion &&
371 fFieldName == other.fFieldName &&
373 fTypeName == other.fTypeName &&
374 fNRepetitions == other.fNRepetitions &&
375 fStructure == other.fStructure &&
376 fParentId == other.fParentId &&
377 fLinkIds == other.fLinkIds;
378}
379
382{
383 RFieldDescriptor clone;
384 clone.fFieldId = fFieldId;
385 clone.fFieldVersion = fFieldVersion;
386 clone.fTypeVersion = fTypeVersion;
387 clone.fFieldName = fFieldName;
388 clone.fFieldDescription = fFieldDescription;
389 clone.fTypeName = fTypeName;
390 clone.fNRepetitions = fNRepetitions;
391 clone.fStructure = fStructure;
392 clone.fParentId = fParentId;
393 clone.fLinkIds = fLinkIds;
394 return clone;
395}
396
397std::unique_ptr<ROOT::Experimental::Detail::RFieldBase>
399{
400 if (GetTypeName().empty() && GetStructure() == ENTupleStructure::kCollection) {
401 // For untyped collections, we have no class available to collect all the sub fields.
402 // Therefore, we create an untyped record field as an artifical binder for the collection items.
403 std::vector<std::unique_ptr<Detail::RFieldBase>> memberFields;
404 for (auto id : fLinkIds) {
405 const auto &memberDesc = ntplDesc.GetFieldDescriptor(id);
406 memberFields.emplace_back(memberDesc.CreateField(ntplDesc));
407 }
408 auto recordField = std::make_unique<RRecordField>("_0", memberFields);
409 auto collectionField = std::make_unique<RVectorField>(GetFieldName(), std::move(recordField));
410 collectionField->SetOnDiskId(fFieldId);
411 return collectionField;
412 }
413
414 auto field = Detail::RFieldBase::Create(GetFieldName(), GetTypeName()).Unwrap();
415 field->SetOnDiskId(fFieldId);
416 for (auto &f : *field)
417 f.SetOnDiskId(ntplDesc.FindFieldId(f.GetName(), f.GetParent()->GetOnDiskId()));
418 return field;
419}
420
421
422////////////////////////////////////////////////////////////////////////////////
423
424
426{
427 return fColumnId == other.fColumnId &&
428 fVersion == other.fVersion &&
429 fModel == other.fModel &&
430 fFieldId == other.fFieldId &&
431 fIndex == other.fIndex;
432}
433
434
435////////////////////////////////////////////////////////////////////////////////
436
437
440{
441 // TODO(jblomer): binary search
442 RPageInfo pageInfo;
443 decltype(idxInCluster) firstInPage = 0;
444 NTupleSize_t pageNo = 0;
445 for (const auto &pi : fPageInfos) {
446 if (firstInPage + pi.fNElements > idxInCluster) {
447 pageInfo = pi;
448 break;
449 }
450 firstInPage += pi.fNElements;
451 ++pageNo;
452 }
453 R__ASSERT(firstInPage <= idxInCluster);
454 R__ASSERT((firstInPage + pageInfo.fNElements) > idxInCluster);
455 return RPageInfoExtended{pageInfo, firstInPage, pageNo};
456}
457
458
460{
461 return fClusterId == other.fClusterId &&
462 fVersion == other.fVersion &&
463 fFirstEntryIndex == other.fFirstEntryIndex &&
464 fNEntries == other.fNEntries &&
465 fLocator == other.fLocator &&
466 fColumnRanges == other.fColumnRanges &&
467 fPageRanges == other.fPageRanges;
468}
469
470
471std::unordered_set<ROOT::Experimental::DescriptorId_t> ROOT::Experimental::RClusterDescriptor::GetColumnIds() const
472{
473 std::unordered_set<DescriptorId_t> result;
474 for (const auto &x : fColumnRanges)
475 result.emplace(x.first);
476 return result;
477}
478
479
481{
482 return fColumnRanges.find(columnId) != fColumnRanges.end();
483}
484
485
487{
488 std::uint64_t nbytes = 0;
489 for (const auto &pr : fPageRanges) {
490 for (const auto &pi : pr.second.fPageInfos) {
491 nbytes += pi.fLocator.fBytesOnStorage;
492 }
493 }
494 return nbytes;
495}
496
497
498////////////////////////////////////////////////////////////////////////////////
499
500
502{
503 return fName == other.fName &&
504 fDescription == other.fDescription &&
505 fAuthor == other.fAuthor &&
506 fCustodian == other.fCustodian &&
507 fTimeStampData == other.fTimeStampData &&
508 fTimeStampWritten == other.fTimeStampWritten &&
509 fVersion == other.fVersion &&
510 fOwnUuid == other.fOwnUuid &&
511 fGroupUuid == other.fGroupUuid &&
512 fFieldDescriptors == other.fFieldDescriptors &&
513 fColumnDescriptors == other.fColumnDescriptors &&
514 fClusterDescriptors == other.fClusterDescriptors;
515}
516
517
519{
520 auto base = reinterpret_cast<unsigned char *>((buffer != nullptr) ? buffer : 0);
521 auto pos = base;
522 void** where = (buffer == nullptr) ? &buffer : reinterpret_cast<void**>(&pos);
523
524 void *ptrSize = nullptr;
525 pos += SerializeFrame(
527 pos += SerializeUInt64(0, *where); // reserved; can be at some point used, e.g., for compression flags
528
529 pos += SerializeString(fName, *where);
530 pos += SerializeString(fDescription, *where);
531 pos += SerializeString(fAuthor, *where);
532 pos += SerializeString(fCustodian, *where);
533 pos += SerializeTimeStamp(fTimeStampData, *where);
534 pos += SerializeTimeStamp(fTimeStampWritten, *where);
535 pos += SerializeVersion(fVersion, *where);
536 pos += SerializeUuid(fOwnUuid, *where);
537 pos += SerializeUuid(fGroupUuid, *where);
538 pos += SerializeUInt32(fFieldDescriptors.size(), *where);
539 for (const auto& f : fFieldDescriptors) {
540 pos += SerializeField(f.second, *where);
541 }
542 pos += SerializeUInt32(fColumnDescriptors.size(), *where);
543 for (const auto& c : fColumnDescriptors) {
544 pos += SerializeColumn(c.second, *where);
545 }
546
547 std::uint32_t size = pos - base;
548 SerializeUInt32(size, ptrSize);
549 size += SerializeCrc32(base, size, *where);
550
551 return size;
552}
553
555{
556 auto base = reinterpret_cast<unsigned char *>((buffer != nullptr) ? buffer : 0);
557 auto pos = base;
558 void** where = (buffer == nullptr) ? &buffer : reinterpret_cast<void**>(&pos);
559
560 void *ptrSize = nullptr;
561 pos += SerializeFrame(
563 pos += SerializeUInt64(0, *where); // reserved; can be at some point used, e.g., for compression flags
564
565 pos += SerializeUInt64(fClusterDescriptors.size(), *where);
566 for (const auto& cluster : fClusterDescriptors) {
567 pos += SerializeUuid(fOwnUuid, *where); // in order to verify that header and footer belong together
568 pos += SerializeClusterSummary(cluster.second, *where);
569
570 pos += SerializeUInt32(fColumnDescriptors.size(), *where);
571 for (const auto& column : fColumnDescriptors) {
572 auto columnId = column.first;
573 pos += SerializeUInt64(columnId, *where);
574
575 const auto &columnRange = cluster.second.GetColumnRange(columnId);
576 R__ASSERT(columnRange.fColumnId == columnId);
577 pos += SerializeColumnRange(columnRange, *where);
578
579 const auto &pageRange = cluster.second.GetPageRange(columnId);
580 R__ASSERT(pageRange.fColumnId == columnId);
581 auto nPages = pageRange.fPageInfos.size();
582 pos += SerializeUInt32(nPages, *where);
583 for (unsigned int i = 0; i < nPages; ++i) {
584 pos += SerializePageInfo(pageRange.fPageInfos[i], *where);
585 }
586 }
587 }
588
589 // The next 16 bytes make the ntuple's postscript
590 pos += SerializeUInt16(kFrameVersionCurrent, *where);
591 pos += SerializeUInt16(kFrameVersionMin, *where);
592 // Add the CRC32 bytes to the header and footer sizes
593 pos += SerializeUInt32(GetHeaderSize(), *where);
594 std::uint32_t size = pos - base + 4;
595 pos += SerializeUInt32(size + 4, *where);
596 size += SerializeCrc32(base, size, *where);
597
598 return size;
599}
600
601
603 const void *postscript, std::uint32_t &szHeader, std::uint32_t &szFooter)
604{
605 auto pos = reinterpret_cast<const unsigned char *>(postscript);
606 std::uint16_t dummy;
607 pos += DeserializeUInt16(pos, &dummy);
608 pos += DeserializeUInt16(pos, &dummy);
609 pos += DeserializeUInt32(pos, &szHeader);
610 pos += DeserializeUInt32(pos, &szFooter);
611}
612
613
615{
616 NTupleSize_t result = 0;
617 for (const auto &cd : fClusterDescriptors) {
618 result = std::max(result, cd.second.GetFirstEntryIndex() + cd.second.GetNEntries());
619 }
620 return result;
621}
622
624{
625 NTupleSize_t result = 0;
626 for (const auto &cd : fClusterDescriptors) {
627 if (!cd.second.ContainsColumn(columnId))
628 continue;
629 auto columnRange = cd.second.GetColumnRange(columnId);
630 result = std::max(result, columnRange.fFirstElementIndex + columnRange.fNElements);
631 }
632 return result;
633}
634
635
638{
639 std::string leafName(fieldName);
640 auto posDot = leafName.find_last_of('.');
641 if (posDot != std::string::npos) {
642 auto parentName = leafName.substr(0, posDot);
643 leafName = leafName.substr(posDot + 1);
644 parentId = FindFieldId(parentName, parentId);
645 }
646 for (const auto &fd : fFieldDescriptors) {
647 if (fd.second.GetParentId() == parentId && fd.second.GetFieldName() == leafName)
648 return fd.second.GetId();
649 }
651}
652
653
655{
656 if (fieldId == kInvalidDescriptorId)
657 return "";
658
659 const auto &fieldDescriptor = fFieldDescriptors.at(fieldId);
660 auto prefix = GetQualifiedFieldName(fieldDescriptor.GetParentId());
661 if (prefix.empty())
662 return fieldDescriptor.GetFieldName();
663 return prefix + "." + fieldDescriptor.GetFieldName();
664}
665
666
669{
670 return FindFieldId("", kInvalidDescriptorId);
671}
672
673
676{
677 return FindFieldId(fieldName, GetFieldZeroId());
678}
679
680
683{
684 for (const auto &cd : fColumnDescriptors) {
685 if (cd.second.GetFieldId() == fieldId && cd.second.GetIndex() == columnIndex)
686 return cd.second.GetId();
687 }
689}
690
691
694{
695 // TODO(jblomer): binary search?
696 for (const auto &cd : fClusterDescriptors) {
697 if (!cd.second.ContainsColumn(columnId))
698 continue;
699 auto columnRange = cd.second.GetColumnRange(columnId);
700 if (columnRange.Contains(index))
701 return cd.second.GetId();
702 }
704}
705
706
707// TODO(jblomer): fix for cases of sharded clasters
710{
711 const auto &clusterDesc = GetClusterDescriptor(clusterId);
712 auto firstEntryInNextCluster = clusterDesc.GetFirstEntryIndex() + clusterDesc.GetNEntries();
713 // TODO(jblomer): binary search?
714 for (const auto &cd : fClusterDescriptors) {
715 if (cd.second.GetFirstEntryIndex() == firstEntryInNextCluster)
716 return cd.second.GetId();
717 }
719}
720
721
722// TODO(jblomer): fix for cases of sharded clasters
725{
726 const auto &clusterDesc = GetClusterDescriptor(clusterId);
727 // TODO(jblomer): binary search?
728 for (const auto &cd : fClusterDescriptors) {
729 if (cd.second.GetFirstEntryIndex() + cd.second.GetNEntries() == clusterDesc.GetFirstEntryIndex())
730 return cd.second.GetId();
731 }
733}
734
735
736std::unique_ptr<ROOT::Experimental::RNTupleModel> ROOT::Experimental::RNTupleDescriptor::GenerateModel() const
737{
738 auto model = std::make_unique<RNTupleModel>();
739 model->GetFieldZero()->SetOnDiskId(GetFieldZeroId());
740 for (const auto &topDesc : GetTopLevelFields())
741 model->AddField(topDesc.CreateField(*this));
742 return model;
743}
744
745
746////////////////////////////////////////////////////////////////////////////////
747
748
751 // Reuse field name validity check
752 auto validName = Detail::RFieldBase::EnsureValidFieldName(fDescriptor.GetName());
753 if (!validName) {
754 return R__FORWARD_ERROR(validName);
755 }
756 // open-ended list of invariant checks
757 for (const auto& key_val: fDescriptor.fFieldDescriptors) {
758 const auto& id = key_val.first;
759 const auto& desc = key_val.second;
760 // parent not properly set
761 if (id != DescriptorId_t(0) && desc.GetParentId() == kInvalidDescriptorId) {
762 return R__FAIL("field with id '" + std::to_string(id) + "' has an invalid parent id");
763 }
764 }
765 return RResult<void>::Success();
766}
767
769{
770 RNTupleDescriptor result;
771 std::swap(result, fDescriptor);
772 return result;
773}
774
776{
777 auto pos = reinterpret_cast<unsigned char *>(headerBuffer);
778 auto base = pos;
779
780 std::uint32_t frameSize;
781 pos += DeserializeFrame(RNTupleDescriptor::kFrameVersionCurrent, base, &frameSize);
782 VerifyCrc32(base, frameSize);
783 std::uint64_t reserved;
784 pos += DeserializeUInt64(pos, &reserved);
785
786 pos += DeserializeString(pos, &fDescriptor.fName);
787 pos += DeserializeString(pos, &fDescriptor.fDescription);
788 pos += DeserializeString(pos, &fDescriptor.fAuthor);
789 pos += DeserializeString(pos, &fDescriptor.fCustodian);
790 pos += DeserializeTimeStamp(pos, &fDescriptor.fTimeStampData);
791 pos += DeserializeTimeStamp(pos, &fDescriptor.fTimeStampWritten);
792 pos += DeserializeVersion(pos, &fDescriptor.fVersion);
793 pos += DeserializeUuid(pos, &fDescriptor.fOwnUuid);
794 pos += DeserializeUuid(pos, &fDescriptor.fGroupUuid);
795
796 std::uint32_t nFields;
797 pos += DeserializeUInt32(pos, &nFields);
798 for (std::uint32_t i = 0; i < nFields; ++i) {
799 auto fieldBase = pos;
800 pos += DeserializeFrame(RFieldDescriptor::kFrameVersionCurrent, fieldBase, &frameSize);
801
803 pos += DeserializeUInt64(pos, &f.fFieldId);
804 pos += DeserializeVersion(pos, &f.fFieldVersion);
805 pos += DeserializeVersion(pos, &f.fTypeVersion);
806 pos += DeserializeString(pos, &f.fFieldName);
807 pos += DeserializeString(pos, &f.fFieldDescription);
808 pos += DeserializeString(pos, &f.fTypeName);
809 pos += DeserializeUInt64(pos, &f.fNRepetitions);
810 std::int32_t structure;
811 pos += DeserializeInt32(pos, &structure);
812 f.fStructure = static_cast<ENTupleStructure>(structure);
813 pos += DeserializeUInt64(pos, &f.fParentId);
814
815 std::uint32_t nLinks;
816 pos += DeserializeUInt32(pos, &nLinks);
817 f.fLinkIds.resize(nLinks);
818 for (std::uint32_t j = 0; j < nLinks; ++j) {
819 pos += DeserializeUInt64(pos, &f.fLinkIds[j]);
820 }
821
822 pos = fieldBase + frameSize;
823 fDescriptor.fFieldDescriptors.emplace(f.fFieldId, std::move(f));
824 }
825
826 std::uint32_t nColumns;
827 pos += DeserializeUInt32(pos, &nColumns);
828 for (std::uint32_t i = 0; i < nColumns; ++i) {
829 auto columnBase = pos;
830 pos += DeserializeFrame(RColumnDescriptor::kFrameVersionCurrent, columnBase, &frameSize);
831
833 pos += DeserializeUInt64(pos, &c.fColumnId);
834 pos += DeserializeVersion(pos, &c.fVersion);
835 pos += DeserializeColumnModel(pos, &c.fModel);
836 pos += DeserializeUInt64(pos, &c.fFieldId);
837 pos += DeserializeUInt32(pos, &c.fIndex);
838
839 pos = columnBase + frameSize;
840 fDescriptor.fColumnDescriptors.emplace(c.fColumnId, std::move(c));
841 }
842}
843
845 auto pos = reinterpret_cast<unsigned char *>(footerBuffer);
846 auto base = pos;
847
848 std::uint32_t frameSize;
849 pos += DeserializeFrame(RNTupleDescriptor::kFrameVersionCurrent, pos, &frameSize);
850 VerifyCrc32(base, frameSize);
851 std::uint64_t reserved;
852 pos += DeserializeUInt64(pos, &reserved);
853
854 std::uint64_t nClusters;
855 pos += DeserializeUInt64(pos, &nClusters);
856 for (std::uint64_t i = 0; i < nClusters; ++i) {
857 RNTupleUuid uuid;
858 pos += DeserializeUuid(pos, &uuid);
859 R__ASSERT(uuid == fDescriptor.fOwnUuid);
860 auto clusterBase = pos;
861 pos += DeserializeFrame(RClusterDescriptor::kFrameVersionCurrent, clusterBase, &frameSize);
862
863 std::uint64_t clusterId;
864 RNTupleVersion version;
865 std::uint64_t firstEntry;
866 std::uint64_t nEntries;
867 pos += DeserializeUInt64(pos, &clusterId);
868 pos += DeserializeVersion(pos, &version);
869 pos += DeserializeUInt64(pos, &firstEntry);
870 pos += DeserializeUInt64(pos, &nEntries);
871 AddCluster(clusterId, version, firstEntry, ROOT::Experimental::ClusterSize_t(nEntries));
873 pos += DeserializeLocator(pos, &locator);
874 SetClusterLocator(clusterId, locator);
875
876 pos = clusterBase + frameSize;
877
878 std::uint32_t nColumns;
879 pos += DeserializeUInt32(pos, &nColumns);
880 for (std::uint32_t j = 0; j < nColumns; ++j) {
881 uint64_t columnId;
882 pos += DeserializeUInt64(pos, &columnId);
883
885 columnRange.fColumnId = columnId;
886 pos += DeserializeColumnRange(pos, &columnRange);
887 AddClusterColumnRange(clusterId, columnRange);
888
890 pageRange.fColumnId = columnId;
891 std::uint32_t nPages;
892 pos += DeserializeUInt32(pos, &nPages);
893 for (unsigned int k = 0; k < nPages; ++k) {
895 pos += DeserializePageInfo(pos, &pageInfo);
896 pageRange.fPageInfos.emplace_back(pageInfo);
897 }
898 AddClusterPageRange(clusterId, std::move(pageRange));
899 }
900 }
901}
902
904 const std::string_view name, const std::string_view description, const std::string_view author,
905 const RNTupleVersion &version, const RNTupleUuid &uuid)
906{
907 fDescriptor.fName = std::string(name);
908 fDescriptor.fDescription = std::string(description);
909 fDescriptor.fAuthor = std::string(author);
910 fDescriptor.fVersion = version;
911 fDescriptor.fOwnUuid = uuid;
912 fDescriptor.fGroupUuid = uuid;
913}
914
916 const RFieldDescriptor& fieldDesc) : fField(fieldDesc.Clone())
917{
919 fField.fLinkIds = {};
920}
921
924 RDanglingFieldDescriptor fieldDesc;
925 fieldDesc.FieldVersion(field.GetFieldVersion())
927 .FieldName(field.GetName())
929 .TypeName(field.GetType())
930 .Structure(field.GetStructure())
932 return fieldDesc;
933}
934
937 if (fField.GetId() == kInvalidDescriptorId) {
938 return R__FAIL("invalid field id");
939 }
940 if (fField.GetStructure() == ENTupleStructure::kInvalid) {
941 return R__FAIL("invalid field structure");
942 }
943 // FieldZero is usually named "" and would be a false positive here
944 if (fField.GetId() != DescriptorId_t(0)) {
945 auto validName = Detail::RFieldBase::EnsureValidFieldName(fField.GetFieldName());
946 if (!validName) {
947 return R__FORWARD_ERROR(validName);
948 }
949 }
950 return fField.Clone();
951}
952
954 fDescriptor.fFieldDescriptors.emplace(fieldDesc.GetId(), fieldDesc.Clone());
955}
956
959{
960 if (linkId == DescriptorId_t(0)) {
961 return R__FAIL("cannot make FieldZero a child field");
962 }
963 if (fDescriptor.fFieldDescriptors.count(fieldId) == 0) {
964 return R__FAIL("field with id '" + std::to_string(fieldId) + "' doesn't exist in NTuple");
965 }
966 if (fDescriptor.fFieldDescriptors.count(linkId) == 0) {
967 return R__FAIL("child field with id '" + std::to_string(linkId) + "' doesn't exist in NTuple");
968 }
969 // fail if field already has a valid parent
970 auto parentId = fDescriptor.fFieldDescriptors.at(linkId).GetParentId();
971 if (parentId != kInvalidDescriptorId) {
972 return R__FAIL("field '" + std::to_string(linkId) + "' already has a parent ('" +
973 std::to_string(parentId) + ")");
974 }
975 if (fieldId == linkId) {
976 return R__FAIL("cannot make field '" + std::to_string(fieldId) + "' a child of itself");
977 }
978 fDescriptor.fFieldDescriptors.at(linkId).fParentId = fieldId;
979 fDescriptor.fFieldDescriptors.at(fieldId).fLinkIds.push_back(linkId);
980 return RResult<void>::Success();
981}
982
984 DescriptorId_t columnId, DescriptorId_t fieldId, const RNTupleVersion &version, const RColumnModel &model,
985 std::uint32_t index)
986{
988 c.fColumnId = columnId;
989 c.fFieldId = fieldId;
990 c.fVersion = version;
991 c.fModel = model;
992 c.fIndex = index;
993 fDescriptor.fColumnDescriptors.emplace(columnId, std::move(c));
994}
995
997 DescriptorId_t clusterId, RNTupleVersion version, NTupleSize_t firstEntryIndex, ClusterSize_t nEntries)
998{
1000 c.fClusterId = clusterId;
1001 c.fVersion = version;
1002 c.fFirstEntryIndex = firstEntryIndex;
1003 c.fNEntries = nEntries;
1004 fDescriptor.fClusterDescriptors.emplace(clusterId, std::move(c));
1005}
1006
1009{
1010 fDescriptor.fClusterDescriptors[clusterId].fLocator = locator;
1011}
1012
1014 DescriptorId_t clusterId, const RClusterDescriptor::RColumnRange &columnRange)
1015{
1016 fDescriptor.fClusterDescriptors[clusterId].fColumnRanges[columnRange.fColumnId] = columnRange;
1017}
1018
1020 DescriptorId_t clusterId, RClusterDescriptor::RPageRange &&pageRange)
1021{
1022 fDescriptor.fClusterDescriptors[clusterId].fPageRanges.emplace(pageRange.fColumnId, std::move(pageRange));
1023}
1024
1026{
1027 fDescriptor.fName = "";
1028 fDescriptor.fVersion = RNTupleVersion();
1029 fDescriptor.fFieldDescriptors.clear();
1030 fDescriptor.fColumnDescriptors.clear();
1031 fDescriptor.fClusterDescriptors.clear();
1032}
#define R__FORWARD_ERROR(res)
Short-hand to return an RResult<T> in an error state (i.e. after checking)
Definition: RError.hxx:295
#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:291
#define f(i)
Definition: RSha256.hxx:104
#define c(i)
Definition: RSha256.hxx:101
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
#define R__ASSERT(e)
Definition: TError.h:118
char name[80]
Definition: TGX11.cxx:110
int type
Definition: TGX11.cxx:121
@ kCollection
Definition: TStructNode.h:21
@ kInvalid
Definition: TSystem.h:79
std::string GetDescription() const
Get the field's description.
Definition: RField.hxx:244
std::size_t GetNRepetitions() const
Definition: RField.hxx:238
virtual RNTupleVersion GetTypeVersion() const
Indicates an evolution of the C++ type itself.
Definition: RField.hxx:258
static RResult< void > EnsureValidFieldName(std::string_view fieldName)
Check whether a given string is a valid field name.
Definition: RField.cxx:214
static RResult< std::unique_ptr< RFieldBase > > Create(const std::string &fieldName, const std::string &typeName)
Factory method to resurrect a field from the stored on-disk type information.
Definition: RField.cxx:131
virtual RNTupleVersion GetFieldVersion() const
Indicates an evolution of the mapping scheme from C++ type to columns.
Definition: RField.hxx:256
ENTupleStructure GetStructure() const
Definition: RField.hxx:237
The available trivial, native content types of a column.
Meta-data for a set of ntuple clusters.
std::unordered_map< DescriptorId_t, RPageRange > fPageRanges
RNTupleVersion fVersion
Future versions of the cluster descriptor might add more meta-data, e.g. a semantic checksum.
bool ContainsColumn(DescriptorId_t columnId) const
RLocator fLocator
For pre-fetching / caching an entire contiguous cluster.
static constexpr std::uint16_t kFrameVersionMin
NTupleSize_t fFirstEntryIndex
Clusters can be swapped by adjusting the entry offsets.
std::unordered_set< DescriptorId_t > GetColumnIds() const
std::unordered_map< DescriptorId_t, RColumnRange > fColumnRanges
bool operator==(const RClusterDescriptor &other) const
static constexpr std::uint16_t kFrameVersionCurrent
In order to handle changes to the serialization routine in future ntuple versions.
Meta-data stored for every column of an ntuple.
static constexpr std::uint16_t kFrameVersionCurrent
In order to handle changes to the serialization routine in future ntuple versions.
DescriptorId_t fFieldId
Every column belongs to one and only one field.
RColumnModel fModel
Contains the column type and whether it is sorted.
static constexpr std::uint16_t kFrameVersionMin
RNTupleVersion fVersion
Versions can change, e.g., when new column types are added.
std::uint32_t fIndex
A field can be serialized into several columns, which are numbered from zero to $n$.
bool operator==(const RColumnDescriptor &other) const
Holds the static meta-data of a column in a tree.
A helper class for piece-wise construction of an RFieldDescriptor.
RDanglingFieldDescriptor & TypeVersion(const RNTupleVersion &typeVersion)
RDanglingFieldDescriptor & FieldVersion(const RNTupleVersion &fieldVersion)
RDanglingFieldDescriptor & Structure(const ENTupleStructure &structure)
RResult< RFieldDescriptor > MakeDescriptor() const
Attempt to make a field descriptor.
static RDanglingFieldDescriptor FromField(const Detail::RFieldBase &field)
Make a new RDanglingFieldDescriptor based off a live NTuple field.
RDanglingFieldDescriptor & NRepetitions(std::uint64_t nRepetitions)
RDanglingFieldDescriptor & FieldName(const std::string &fieldName)
RDanglingFieldDescriptor & TypeName(const std::string &typeName)
RDanglingFieldDescriptor()=default
Make an empty dangling field descriptor.
RDanglingFieldDescriptor & FieldDescription(const std::string &fieldDescription)
Base class for all ROOT issued exceptions.
Definition: RError.hxx:114
Meta-data stored for every field of an ntuple.
std::vector< DescriptorId_t > fLinkIds
The pointers in the other direction from parent to children.
RNTupleVersion fFieldVersion
The version of the C++-type-to-column translation mechanics.
std::unique_ptr< Detail::RFieldBase > CreateField(const RNTupleDescriptor &ntplDesc) const
In general, we create a field simply from the C++ type name.
std::string fFieldDescription
Free text set by the user.
static constexpr std::uint16_t kFrameVersionMin
std::string fFieldName
The leaf name, not including parent fields.
const std::vector< DescriptorId_t > & GetLinkIds() const
DescriptorId_t fParentId
Establishes sub field relationships, such as classes and collections.
RNTupleVersion fTypeVersion
The version of the C++ type itself.
RFieldDescriptor Clone() const
Get a copy of the descriptor.
bool operator==(const RFieldDescriptor &other) const
ENTupleStructure fStructure
The structural information carried by this field in the data model tree.
std::string fTypeName
The C++ type that was used when writing the field.
std::uint64_t fNRepetitions
The number of elements per entry for fixed-size arrays.
static constexpr std::uint16_t kFrameVersionCurrent
In order to handle changes to the serialization routine in future ntuple versions.
RResult< void > EnsureValidDescriptor() const
Checks whether invariants hold:
void AddCluster(DescriptorId_t clusterId, RNTupleVersion version, NTupleSize_t firstEntryIndex, ClusterSize_t nEntries)
RResult< void > AddFieldLink(DescriptorId_t fieldId, DescriptorId_t linkId)
void AddColumn(DescriptorId_t columnId, DescriptorId_t fieldId, const RNTupleVersion &version, const RColumnModel &model, std::uint32_t index)
void SetClusterLocator(DescriptorId_t clusterId, RClusterDescriptor::RLocator locator)
void Reset()
Clears so-far stored clusters, fields, and columns and return to a pristine ntuple descriptor.
void AddClusterColumnRange(DescriptorId_t clusterId, const RClusterDescriptor::RColumnRange &columnRange)
void SetNTuple(const std::string_view name, const std::string_view description, const std::string_view author, const RNTupleVersion &version, const RNTupleUuid &uuid)
void AddClusterPageRange(DescriptorId_t clusterId, RClusterDescriptor::RPageRange &&pageRange)
void AddField(const RFieldDescriptor &fieldDesc)
The on-storage meta-data of an ntuple.
std::unordered_map< DescriptorId_t, RClusterDescriptor > fClusterDescriptors
May contain only a subset of all the available clusters, e.g.
RNTupleUuid fGroupUuid
Column sets that are created as derived sets from existing NTuples share the same group id.
std::unique_ptr< RNTupleModel > GenerateModel() const
Re-create the C++ model from the stored meta-data.
std::chrono::system_clock::time_point fTimeStampWritten
The time stamp of writing the data to storage, which gets updated when re-written.
DescriptorId_t FindNextClusterId(DescriptorId_t clusterId) const
std::uint32_t SerializeHeader(void *buffer) const
We deliberately do not use ROOT's built-in serialization in order to allow for use of RNTuple's witho...
DescriptorId_t FindPrevClusterId(DescriptorId_t clusterId) const
DescriptorId_t GetFieldZeroId() const
Returns the logical parent of all top-level NTuple data fields.
std::unordered_map< DescriptorId_t, RColumnDescriptor > fColumnDescriptors
std::string fName
The ntuple name needs to be unique in a given storage location (file)
std::uint32_t SerializeFooter(void *buffer) const
Serializes cluster meta data. Returns the number of bytes and fills buffer if it is not nullptr.
std::string fAuthor
The origin of the data.
std::unordered_map< DescriptorId_t, RFieldDescriptor > fFieldDescriptors
static constexpr std::uint16_t kFrameVersionMin
RNTupleVersion fVersion
The version evolves with the ntuple summary meta-data.
bool operator==(const RNTupleDescriptor &other) const
std::string GetQualifiedFieldName(DescriptorId_t fieldId) const
Walks up the parents of the field ID and returns a field name of the form a.b.c.d In case of invalid ...
DescriptorId_t FindFieldId(std::string_view fieldName, DescriptorId_t parentId) const
const RFieldDescriptor & GetFieldDescriptor(DescriptorId_t fieldId) const
std::string fCustodian
The current responsible for storing the data.
DescriptorId_t FindColumnId(DescriptorId_t fieldId, std::uint32_t columnIndex) const
NTupleSize_t GetNElements(DescriptorId_t columnId) const
static void LocateMetadata(const void *postscript, std::uint32_t &szHeader, std::uint32_t &szFooter)
Given kNBytesPostscript bytes, extract the header and footer lengths in bytes.
std::string fDescription
Free text from the user.
static constexpr std::uint16_t kFrameVersionCurrent
In order to handle changes to the serialization routine in future ntuple versions.
RNTupleUuid fOwnUuid
Every NTuple gets a unique identifier.
std::chrono::system_clock::time_point fTimeStampData
The time stamp of the ntuple data (immutable)
DescriptorId_t FindClusterId(DescriptorId_t columnId, NTupleSize_t index) const
For forward and backward compatibility, attach version information to the consitituents of the file f...
std::uint32_t GetVersionUse() const
NTupleFlags_t GetFlags() const
std::uint32_t GetVersionMin() const
RResult<void> has no data member and no Inspect() method but instead a Success() factory method.
Definition: RError.hxx:257
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:195
struct void * fTypeName
Definition: cppyy.h:9
Double_t x[n]
Definition: legend1.C:17
basic_string_view< char > string_view
Machine-independent serialization functions for fundamental types.
Definition: RNTupleUtil.hxx:36
std::uint32_t DeserializeInt64(const void *buffer, std::int64_t *val)
Definition: RNTupleUtil.cxx:58
std::uint32_t DeserializeUInt16(const void *buffer, std::uint16_t *val)
std::uint32_t SerializeInt64(std::int64_t val, void *buffer)
Definition: RNTupleUtil.cxx:37
std::uint32_t SerializeUInt32(std::uint32_t val, void *buffer)
Definition: RNTupleUtil.cxx:85
std::uint32_t SerializeInt32(std::int32_t val, void *buffer)
Definition: RNTupleUtil.cxx:73
std::uint32_t SerializeUInt16(std::uint16_t val, void *buffer)
std::uint32_t DeserializeUInt64(const void *buffer, std::uint64_t *val)
Definition: RNTupleUtil.cxx:68
std::uint32_t SerializeUInt64(std::uint64_t val, void *buffer)
Definition: RNTupleUtil.cxx:53
std::uint32_t DeserializeString(const void *buffer, std::string *val)
std::uint32_t DeserializeInt32(const void *buffer, std::int32_t *val)
Definition: RNTupleUtil.cxx:90
std::uint32_t DeserializeUInt32(const void *buffer, std::uint32_t *val)
Definition: RNTupleUtil.cxx:98
std::uint32_t SerializeString(const std::string &val, void *buffer)
void swap(RDirectoryEntry &e1, RDirectoryEntry &e2) noexcept
std::uint64_t NTupleSize_t
Integer type long enough to hold the maximum number of entries in a column.
Definition: RNTupleUtil.hxx:77
ENTupleStructure
The fields in the ntuple model tree can carry different structural information about the type system.
Definition: RNTupleUtil.hxx:67
std::uint64_t DescriptorId_t
Distriniguishes elements of the same type within a descriptor, e.g. different fields.
std::string RNTupleUuid
Every NTuple is identified by a UUID. TODO(jblomer): should this be a TUUID?
constexpr DescriptorId_t kInvalidDescriptorId
static constexpr double pi
The window of element indexes of a particular column in a particular cluster.
std::int64_t fCompressionSettings
The usual format for ROOT compression settings (see Compression.h).
NTupleSize_t fFirstElementIndex
A 64bit element index.
ClusterSize_t fNElements
A 32bit value for the number of column elements in the cluster.
Generic information about the physical location of data.
We do not need to store the element size / uncompressed page size because we know to which column the...
RLocator fLocator
The meaning of fLocator depends on the storage backend.
ClusterSize_t fNElements
The sum of the elements of all the pages must match the corresponding fNElements field in fColumnRang...
Records the parition of data into pages for a particular column in a particular cluster.
RPageInfoExtended Find(RClusterSize::ValueType idxInCluster) const
Find the page in the RPageRange that contains the given element. The element must exist.
Wrap the 32bit integer in a struct in order to avoid template specialization clash with std::uint32_t...
Definition: RNTupleUtil.hxx:80
auto * l
Definition: textangle.C:4