Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RNTupleDescriptor.hxx
Go to the documentation of this file.
1/// \file ROOT/RNTupleDescriptor.hxx
2/// \ingroup NTuple
3/// \author Jakob Blomer <jblomer@cern.ch>
4/// \author Javier Lopez-Gomez <javier.lopez.gomez@cern.ch>
5/// \date 2018-07-19
6
7/*************************************************************************
8 * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. *
9 * All rights reserved. *
10 * *
11 * For the licensing terms see $ROOTSYS/LICENSE. *
12 * For the list of contributors see $ROOTSYS/README/CREDITS. *
13 *************************************************************************/
14
15#ifndef ROOT_RNTupleDescriptor
16#define ROOT_RNTupleDescriptor
17
19#include <ROOT/RError.hxx>
21#include <ROOT/RNTupleTypes.hxx>
22#include <ROOT/RSpan.hxx>
23
24#include <TError.h>
25
26#include <algorithm>
27#include <chrono>
28#include <cmath>
29#include <functional>
30#include <iterator>
31#include <map>
32#include <memory>
33#include <optional>
34#include <ostream>
35#include <vector>
36#include <set>
37#include <string>
38#include <string_view>
39#include <unordered_map>
40#include <unordered_set>
41
42namespace ROOT {
43
44class RFieldBase;
45class RNTupleModel;
46
47namespace Internal {
48class RColumnElementBase;
49}
50
51class RNTupleDescriptor;
52class RFieldDescriptor;
53
54namespace Internal {
55class RColumnDescriptorBuilder;
56class RClusterDescriptorBuilder;
57class RClusterGroupDescriptorBuilder;
58class RExtraTypeInfoDescriptorBuilder;
59class RFieldDescriptorBuilder;
60class RNTupleDescriptorBuilder;
61
62RNTupleDescriptor CloneDescriptorSchema(const RNTupleDescriptor &desc);
67
68std::vector<ROOT::Internal::RNTupleClusterBoundaries> GetClusterBoundaries(const RNTupleDescriptor &desc);
69
71} // namespace Internal
72
73namespace Experimental {
74
75// clang-format off
76/**
77\class ROOT::Experimental::RNTupleAttrSetDescriptor
78\ingroup NTuple
79\brief Metadata stored for every Attribute Set linked to an RNTuple.
80*/
81// clang-format on
84
85 std::uint16_t fSchemaVersionMajor = 0;
86 std::uint16_t fSchemaVersionMinor = 0;
87 std::uint32_t fAnchorLength = 0; ///< uncompressed size of the linked anchor
88 // The locator of the AttributeSet anchor.
89 // In case of kTypeFile, it points to the beginning of the Anchor's payload.
90 // NOTE: Only kTypeFile is supported at the moment.
92 std::string fName;
93
94public:
100
101 bool operator==(const RNTupleAttrSetDescriptor &other) const;
102 bool operator!=(const RNTupleAttrSetDescriptor &other) const { return !(*this == other); }
103
104 const std::string &GetName() const { return fName; }
105 std::uint16_t GetSchemaVersionMajor() const { return fSchemaVersionMajor; }
106 std::uint16_t GetSchemaVersionMinor() const { return fSchemaVersionMinor; }
107 std::uint32_t GetAnchorLength() const { return fAnchorLength; }
109
111};
112
113class RNTupleAttrSetDescriptorIterable;
114
115} // namespace Experimental
116
117// clang-format off
118/**
119\class ROOT::RFieldDescriptor
120\ingroup NTuple
121\brief Metadata stored for every field of an RNTuple
122*/
123// clang-format on
128
129private:
131 /// The version of the C++-type-to-column translation mechanics
132 std::uint32_t fFieldVersion = 0;
133 /// The version of the C++ type itself
134 std::uint32_t fTypeVersion = 0;
135 /// The leaf name, not including parent fields
136 std::string fFieldName;
137 /// Free text set by the user
138 std::string fFieldDescription;
139 /// The C++ type that was used when writing the field
140 std::string fTypeName;
141 /// A typedef or using directive that resolved to the type name during field creation
142 std::string fTypeAlias;
143 /// The number of elements per entry for fixed-size arrays
144 std::uint64_t fNRepetitions = 0;
145 /// The structural information carried by this field in the data model tree
147 /// Establishes sub field relationships, such as classes and collections
149 /// For projected fields, the source field ID
151 /// The pointers in the other direction from parent to children. They are serialized, too, to keep the
152 /// order of sub fields.
153 std::vector<ROOT::DescriptorId_t> fLinkIds;
154 /// The number of columns in the column representations of the field. The column cardinality helps to navigate the
155 /// list of logical column ids. For example, the second column of the third column representation is
156 /// fLogicalColumnIds[2 * fColumnCardinality + 1]
157 std::uint32_t fColumnCardinality = 0;
158 /// The ordered list of columns attached to this field: first by representation index then by column index.
159 std::vector<ROOT::DescriptorId_t> fLogicalColumnIds;
160 /// For custom classes, we store the ROOT TClass reported checksum to facilitate the use of I/O rules that
161 /// identify types by their checksum
162 std::optional<std::uint32_t> fTypeChecksum;
163 /// Indicates if this is a collection that should be represented in memory by a SoA layout.
164 bool fIsSoACollection = false;
165
166public:
167 RFieldDescriptor() = default;
172
173 bool operator==(const RFieldDescriptor &other) const;
174 /// Get a copy of the descriptor
175 RFieldDescriptor Clone() const;
176
177 /// In general, we create a field simply from the C++ type name. For untyped fields, however, we potentially need
178 /// access to sub fields, which is provided by the RNTupleDescriptor argument.
179 std::unique_ptr<ROOT::RFieldBase>
180 CreateField(const RNTupleDescriptor &ntplDesc, const ROOT::RCreateFieldOptions &options = {}) const;
181
183 std::uint32_t GetFieldVersion() const { return fFieldVersion; }
184 std::uint32_t GetTypeVersion() const { return fTypeVersion; }
185 const std::string &GetFieldName() const { return fFieldName; }
186 const std::string &GetFieldDescription() const { return fFieldDescription; }
187 const std::string &GetTypeName() const { return fTypeName; }
188 const std::string &GetTypeAlias() const { return fTypeAlias; }
189 std::uint64_t GetNRepetitions() const { return fNRepetitions; }
193 const std::vector<ROOT::DescriptorId_t> &GetLinkIds() const { return fLinkIds; }
194 const std::vector<ROOT::DescriptorId_t> &GetLogicalColumnIds() const { return fLogicalColumnIds; }
195 std::uint32_t GetColumnCardinality() const { return fColumnCardinality; }
196 std::optional<std::uint32_t> GetTypeChecksum() const { return fTypeChecksum; }
198 bool IsSoACollection() const { return fIsSoACollection; }
199
200 bool IsCustomClass() const R__DEPRECATED(6, 42, "removed from public interface");
201 bool IsCustomEnum(const RNTupleDescriptor &desc) const R__DEPRECATED(6, 42, "removed from public interface");
202 bool IsStdAtomic() const R__DEPRECATED(6, 42, "removed from public interface");
203};
204
205// clang-format off
206/**
207\class ROOT::RColumnDescriptor
208\ingroup NTuple
209\brief Metadata stored for every column of an RNTuple
210*/
211// clang-format on
215
216public:
217 struct RValueRange {
218 double fMin = 0, fMax = 0;
219
220 RValueRange() = default;
221 RValueRange(double min, double max) : fMin(min), fMax(max) {}
222 RValueRange(std::pair<double, double> range) : fMin(range.first), fMax(range.second) {}
223
224 bool operator==(RValueRange other) const { return fMin == other.fMin && fMax == other.fMax; }
225 bool operator!=(RValueRange other) const { return !(*this == other); }
226 };
227
228private:
229 /// The actual column identifier, which is the link to the corresponding field
231 /// Usually identical to the logical column ID, except for alias columns where it references the shadowed column
233 /// Every column belongs to one and only one field
235 /// The absolute value specifies the index for the first stored element for this column.
236 /// For deferred columns the absolute value is larger than zero.
237 /// Negative values specify a suppressed and deferred column.
238 std::int64_t fFirstElementIndex = 0U;
239 /// A field can be serialized into several columns, which are numbered from zero to $n$
240 std::uint32_t fIndex = 0;
241 /// A field may use multiple column representations, which are numbered from zero to $m$.
242 /// Every representation has the same number of columns.
243 std::uint16_t fRepresentationIndex = 0;
244 /// The size in bits of elements of this column. Most columns have the size fixed by their type
245 /// but low-precision float columns have variable bit widths.
246 std::uint16_t fBitsOnStorage = 0;
247 /// The on-disk column type
249 /// Optional value range (used e.g. by quantized real fields)
250 std::optional<RValueRange> fValueRange;
251
252public:
253 RColumnDescriptor() = default;
258
259 bool operator==(const RColumnDescriptor &other) const;
260 /// Get a copy of the descriptor
261 RColumnDescriptor Clone() const;
262
263 ROOT::DescriptorId_t GetLogicalId() const { return fLogicalColumnId; }
264 ROOT::DescriptorId_t GetPhysicalId() const { return fPhysicalColumnId; }
266 std::uint32_t GetIndex() const { return fIndex; }
267 std::uint16_t GetRepresentationIndex() const { return fRepresentationIndex; }
268 std::uint64_t GetFirstElementIndex() const { return std::abs(fFirstElementIndex); }
269 std::uint16_t GetBitsOnStorage() const { return fBitsOnStorage; }
270 ROOT::ENTupleColumnType GetType() const { return fType; }
271 std::optional<RValueRange> GetValueRange() const { return fValueRange; }
272 bool IsAliasColumn() const { return fPhysicalColumnId != fLogicalColumnId; }
273 bool IsDeferredColumn() const { return fFirstElementIndex != 0; }
274 bool IsSuppressedDeferredColumn() const { return fFirstElementIndex < 0; }
275};
276
277// clang-format off
278/**
279\class ROOT::RClusterDescriptor
280\ingroup NTuple
281\brief Metadata for RNTuple clusters
282
283The cluster descriptor is built in two phases. In a first phase, the descriptor has only an ID.
284In a second phase, the event range, column group, page locations and column ranges are added.
285Both phases are populated by the RClusterDescriptorBuilder.
286Clusters span across all available columns in the RNTuple.
287*/
288// clang-format on
291
292public:
293 // clang-format off
294 /**
295 \class ROOT::RClusterDescriptor::RColumnRange
296 \ingroup NTuple
297 \brief The window of element indexes of a particular column in a particular cluster
298 */
299 // clang-format on
302 /// The global index of the first column element in the cluster
304 /// The number of column elements in the cluster
306 /// The usual format for ROOT compression settings (see Compression.h).
307 /// The pages of a particular column in a particular cluster are all compressed with the same settings.
308 /// If unset, the compression settings are undefined (deferred columns, suppressed columns).
309 std::optional<std::uint32_t> fCompressionSettings;
310 /// Suppressed columns have an empty page range and unknown compression settings.
311 /// Their element index range, however, is aligned with the corresponding column of the
312 /// primary column representation (see Section "Suppressed Columns" in the specification)
313 bool fIsSuppressed = false;
314
315 // TODO(jblomer): we perhaps want to store summary information, such as average, min/max, etc.
316 // Should this be done on the field level?
317
318 public:
319 RColumnRange() = default;
320
322 ROOT::NTupleSize_t nElements, std::optional<std::uint32_t> compressionSettings,
323 bool suppressed = false)
324 : fPhysicalColumnId(physicalColumnId),
325 fFirstElementIndex(firstElementIndex),
326 fNElements(nElements),
327 fCompressionSettings(compressionSettings),
328 fIsSuppressed(suppressed)
329 {
330 }
331
332 ROOT::DescriptorId_t GetPhysicalColumnId() const { return fPhysicalColumnId; }
333 void SetPhysicalColumnId(ROOT::DescriptorId_t id) { fPhysicalColumnId = id; }
334
335 ROOT::NTupleSize_t GetFirstElementIndex() const { return fFirstElementIndex; }
336 void SetFirstElementIndex(ROOT::NTupleSize_t idx) { fFirstElementIndex = idx; }
337 void IncrementFirstElementIndex(ROOT::NTupleSize_t by) { fFirstElementIndex += by; }
338
339 ROOT::NTupleSize_t GetNElements() const { return fNElements; }
340 void SetNElements(ROOT::NTupleSize_t n) { fNElements = n; }
342
343 std::optional<std::uint32_t> GetCompressionSettings() const { return fCompressionSettings; }
344 void SetCompressionSettings(std::optional<std::uint32_t> comp) { fCompressionSettings = comp; }
345
346 bool IsSuppressed() const { return fIsSuppressed; }
347 void SetIsSuppressed(bool suppressed) { fIsSuppressed = suppressed; }
348
349 bool operator==(const RColumnRange &other) const
350 {
351 return fPhysicalColumnId == other.fPhysicalColumnId && fFirstElementIndex == other.fFirstElementIndex &&
352 fNElements == other.fNElements && fCompressionSettings == other.fCompressionSettings &&
353 fIsSuppressed == other.fIsSuppressed;
354 }
355
357 {
358 return (fFirstElementIndex <= index && (fFirstElementIndex + fNElements) > index);
359 }
360 };
361
362 // clang-format off
363 /**
364 \class ROOT::RClusterDescriptor::RPageInfo
365 \ingroup NTuple
366 \brief Information about a single page in the context of a cluster's page range.
367 */
368 // clang-format on
369 // NOTE: We do not need to store the element size / uncompressed page size because we know to which column
370 // the page belongs
371 struct RPageInfo {
372 private:
373 /// The meaning of `fLocator` depends on the storage backend.
375 /// The sum of the elements of all the pages must match the corresponding `fNElements` field in `fColumnRanges`
376 std::uint32_t fNElements = std::uint32_t(-1);
377 /// If true, the 8 bytes following the serialized page are an xxhash of the on-disk page data
378 bool fHasChecksum = false;
379
380 public:
381 RPageInfo() = default;
383 : fLocator(locator), fNElements(nElements), fHasChecksum(hasChecksum)
384 {
385 }
386
387 bool operator==(const RPageInfo &other) const
388 {
389 return fLocator == other.fLocator && fNElements == other.fNElements;
390 }
391
392 const RNTupleLocator &GetLocator() const { return fLocator; }
393 RNTupleLocator &GetLocator() { return fLocator; }
394 void SetLocator(const RNTupleLocator &locator) { fLocator = locator; }
395
396 std::uint32_t GetNElements() const { return fNElements; }
397 void SetNElements(std::uint32_t n) { fNElements = n; }
398
399 bool HasChecksum() const { return fHasChecksum; }
400 void SetHasChecksum(bool hasChecksum) { fHasChecksum = hasChecksum; }
401 };
402
403 // clang-format off
404 /**
405 \class ROOT::RClusterDescriptor::RPageInfoExtended
406 \ingroup NTuple
407 \brief Additional information about a page in an in-memory RPageRange.
408
409 Used by RPageRange::Find() to return information relative to the RPageRange. This information is not stored on disk
410 and we don't need to keep it in memory because it can be easily recomputed.
411 */
412 // clang-format on
414 private:
415 /// Index (in cluster) of the first element in page.
416 ROOT::NTupleSize_t fFirstElementIndex = 0;
417 /// Page number in the corresponding RPageRange.
418 ROOT::NTupleSize_t fPageNumber = 0;
419
420 public:
421 RPageInfoExtended() = default;
426
427 ROOT::NTupleSize_t GetFirstElementIndex() const { return fFirstElementIndex; }
429
430 ROOT::NTupleSize_t GetPageNumber() const { return fPageNumber; }
432 };
433
434 // clang-format off
435 /**
436 \class ROOT::RClusterDescriptor::RPageRange
437 \ingroup NTuple
438 \brief Records the partition of data into pages for a particular column in a particular cluster
439 */
440 // clang-format on
443
444 private:
445 /// \brief Extend this RPageRange to fit the given RColumnRange.
446 ///
447 /// To do so, prepend as many synthetic RPageInfos as needed to cover the range in `columnRange`.
448 /// RPageInfos are constructed to contain as many elements of type `element` given a page size
449 /// limit of `pageSize` (in bytes); the locator for the referenced pages is `kTypePageZero`.
450 /// This function is used to make up RPageRanges for clusters that contain deferred columns.
451 /// \return The number of column elements covered by the synthesized RPageInfos
452 std::size_t ExtendToFitColumnRange(const RColumnRange &columnRange,
454
455 std::vector<RPageInfo> fPageInfos;
456
457 /// Has the same length than fPageInfos and stores the sum of the number of elements of all the pages
458 /// up to and including a given index. Used for binary search in Find().
459 /// This vector is only created if fPageInfos has at least kLargeRangeThreshold elements.
460 std::unique_ptr<std::vector<ROOT::NTupleSize_t>> fCumulativeNElements;
461
463
464 public:
465 /// Create the fCumulativeNElements only when its needed, i.e. when there are many pages to search through.
466 static constexpr std::size_t kLargeRangeThreshold = 10;
467
468 RPageRange() = default;
469 RPageRange(const RPageRange &other) = delete;
473
475 {
476 RPageRange clone;
477 clone.fPhysicalColumnId = fPhysicalColumnId;
478 clone.fPageInfos = fPageInfos;
479 if (fCumulativeNElements) {
480 clone.fCumulativeNElements = std::make_unique<std::vector<ROOT::NTupleSize_t>>(*fCumulativeNElements);
481 }
482 return clone;
483 }
484
485 /// Find the page in the RPageRange that contains the given element. The element must exist.
487
488 ROOT::DescriptorId_t GetPhysicalColumnId() const { return fPhysicalColumnId; }
489 void SetPhysicalColumnId(ROOT::DescriptorId_t id) { fPhysicalColumnId = id; }
490
491 const std::vector<RPageInfo> &GetPageInfos() const { return fPageInfos; }
492 std::vector<RPageInfo> &GetPageInfos() { return fPageInfos; }
493
494 bool operator==(const RPageRange &other) const
495 {
496 return fPhysicalColumnId == other.fPhysicalColumnId && fPageInfos == other.fPageInfos;
497 }
498 };
499
500private:
502 /// Clusters can be swapped by adjusting the entry offsets of the cluster and all ranges
505
506 std::unordered_map<ROOT::DescriptorId_t, RColumnRange> fColumnRanges;
507 std::unordered_map<ROOT::DescriptorId_t, RPageRange> fPageRanges;
508
509public:
511
517
518 RClusterDescriptor Clone() const;
519
520 bool operator==(const RClusterDescriptor &other) const;
521
522 ROOT::DescriptorId_t GetId() const { return fClusterId; }
523 ROOT::NTupleSize_t GetFirstEntryIndex() const { return fFirstEntryIndex; }
524 ROOT::NTupleSize_t GetNEntries() const { return fNEntries; }
525 const RColumnRange &GetColumnRange(ROOT::DescriptorId_t physicalId) const { return fColumnRanges.at(physicalId); }
526 const RPageRange &GetPageRange(ROOT::DescriptorId_t physicalId) const { return fPageRanges.at(physicalId); }
527 /// Returns an iterator over pairs { columnId, columnRange }. The iteration order is unspecified.
528 RColumnRangeIterable GetColumnRangeIterable() const;
530 {
531 return fColumnRanges.find(physicalId) != fColumnRanges.end();
532 }
533 std::uint64_t GetNBytesOnStorage() const;
534};
535
537private:
539
540public:
542 private:
543 using Iter_t = std::unordered_map<ROOT::DescriptorId_t, RColumnRange>::const_iterator;
544 /// The wrapped map iterator
546
547 public:
548 using iterator_category = std::forward_iterator_tag;
551 using difference_type = std::ptrdiff_t;
552 using pointer = const RColumnRange *;
553 using reference = const RColumnRange &;
554
555 RIterator(Iter_t iter) : fIter(iter) {}
556 iterator &operator++() /* prefix */
557 {
558 ++fIter;
559 return *this;
560 }
561 iterator operator++(int) /* postfix */
562 {
563 auto old = *this;
564 operator++();
565 return old;
566 }
567 reference operator*() const { return fIter->second; }
568 pointer operator->() const { return &fIter->second; }
569 bool operator!=(const iterator &rh) const { return fIter != rh.fIter; }
570 bool operator==(const iterator &rh) const { return fIter == rh.fIter; }
571 };
572
573 explicit RColumnRangeIterable(const RClusterDescriptor &desc) : fDesc(desc) {}
574
575 RIterator begin() { return RIterator{fDesc.fColumnRanges.cbegin()}; }
576 RIterator end() { return RIterator{fDesc.fColumnRanges.cend()}; }
577 size_t size() { return fDesc.fColumnRanges.size(); }
578};
579
580// clang-format off
581/**
582\class ROOT::RClusterGroupDescriptor
583\ingroup NTuple
584\brief Clusters are bundled in cluster groups.
585
586Very large RNTuples can contain multiple cluster groups to organize cluster metadata.
587Every RNTuple has at least one cluster group. The clusters in a cluster group are ordered
588corresponding to their first entry number.
589*/
590// clang-format on
593
594private:
596 /// The cluster IDs can be empty if the corresponding page list is not loaded.
597 /// Otherwise, cluster ids are sorted by first entry number.
598 std::vector<ROOT::DescriptorId_t> fClusterIds;
599 /// The page list that corresponds to the cluster group
601 /// Uncompressed size of the page list
602 std::uint64_t fPageListLength = 0;
603 /// The minimum first entry number of the clusters in the cluster group
604 std::uint64_t fMinEntry = 0;
605 /// Number of entries that are (partially for sharded clusters) covered by this cluster group.
606 std::uint64_t fEntrySpan = 0;
607 /// Number of clusters is always known even if the cluster IDs are not (yet) populated
608 std::uint32_t fNClusters = 0;
609
610public:
616
617 RClusterGroupDescriptor Clone() const;
618 /// Creates a clone without the cluster IDs
619 RClusterGroupDescriptor CloneSummary() const;
620
621 bool operator==(const RClusterGroupDescriptor &other) const;
622
623 ROOT::DescriptorId_t GetId() const { return fClusterGroupId; }
624 std::uint32_t GetNClusters() const { return fNClusters; }
625 RNTupleLocator GetPageListLocator() const { return fPageListLocator; }
626 std::uint64_t GetPageListLength() const { return fPageListLength; }
627 const std::vector<ROOT::DescriptorId_t> &GetClusterIds() const { return fClusterIds; }
628 std::uint64_t GetMinEntry() const { return fMinEntry; }
629 std::uint64_t GetEntrySpan() const { return fEntrySpan; }
630 /// A cluster group is loaded in two stages. Stage one loads only the summary information.
631 /// Stage two loads the list of cluster IDs.
632 bool HasClusterDetails() const { return !fClusterIds.empty(); }
633};
634
635/// Used in RExtraTypeInfoDescriptor
637 kInvalid,
639};
640
641// clang-format off
642/**
643\class ROOT::RExtraTypeInfoDescriptor
644\ingroup NTuple
645\brief Field specific extra type information from the header / extenstion header
646
647Currently only used by streamer fields to store RNTuple-wide list of streamer info records.
648*/
649// clang-format on
652
653private:
654 /// Specifies the meaning of the extra information
655 EExtraTypeInfoIds fContentId = EExtraTypeInfoIds::kInvalid;
656 /// Type version the extra type information is bound to
657 std::uint32_t fTypeVersion = 0;
658 /// The type name the extra information refers to; empty for RNTuple-wide extra information
659 std::string fTypeName;
660 /// The content format depends on the content ID and may be binary
661 std::string fContent;
662
663public:
669
670 bool operator==(const RExtraTypeInfoDescriptor &other) const;
671
672 RExtraTypeInfoDescriptor Clone() const;
673
674 EExtraTypeInfoIds GetContentId() const { return fContentId; }
675 std::uint32_t GetTypeVersion() const { return fTypeVersion; }
676 const std::string &GetTypeName() const { return fTypeName; }
677 const std::string &GetContent() const { return fContent; }
678};
679
680namespace Internal {
681// Used by the RNTupleReader to activate/deactivate entries. Needs to adapt when we have sharded clusters.
683} // namespace Internal
684
685// clang-format off
686/**
687\class ROOT::RNTupleDescriptor
688\ingroup NTuple
689\brief The on-storage metadata of an RNTuple
690
691Represents the on-disk (on storage) information about an RNTuple. The metadata consists of a header, a footer, and
692potentially multiple page lists.
693The header carries the RNTuple schema, i.e. the fields and the associated columns and their relationships.
694The footer carries information about one or several cluster groups and links to their page lists.
695For every cluster group, a page list envelope stores cluster summaries and page locations.
696For every cluster, it stores for every column the range of element indexes as well as a list of pages and page
697locations.
698
699The descriptor provides machine-independent (de-)serialization of headers and footers, and it provides lookup routines
700for RNTuple objects (pages, clusters, ...). It is supposed to be usable by all RPageStorage implementations.
701
702The serialization does not use standard ROOT streamers in order to not let it depend on libCore. The serialization uses
703the concept of envelopes and frames: header, footer, and page list envelopes have a preamble with a type ID and length.
704Substructures are serialized in frames and have a size and number of items (for list frames). This allows for forward
705and backward compatibility when the metadata evolves.
706*/
707// clang-format on
710 friend RNTupleDescriptor Internal::CloneDescriptorSchema(const RNTupleDescriptor &desc);
711 friend DescriptorId_t Internal::CallFindClusterIdOn(const RNTupleDescriptor &desc, NTupleSize_t entryIdx);
712
713public:
714 class RHeaderExtension;
715
716private:
717 /// The RNTuple name needs to be unique in a given storage location (file)
718 std::string fName;
719 /// Free text from the user
720 std::string fDescription;
721
722 ROOT::DescriptorId_t fFieldZeroId = ROOT::kInvalidDescriptorId; ///< Set by the descriptor builder
723
724 std::uint64_t fNPhysicalColumns = 0; ///< Updated by the descriptor builder when columns are added
725
726 std::set<unsigned int> fFeatureFlags;
727 std::unordered_map<ROOT::DescriptorId_t, RFieldDescriptor> fFieldDescriptors;
728 std::unordered_map<ROOT::DescriptorId_t, RColumnDescriptor> fColumnDescriptors;
729
730 std::vector<RExtraTypeInfoDescriptor> fExtraTypeInfoDescriptors;
731 std::unique_ptr<RHeaderExtension> fHeaderExtension;
732
733 //// All fields above are part of the schema and are cloned when creating a new descriptor from a given one
734 //// (see CloneSchema())
735
736 std::uint16_t fVersionEpoch = 0; ///< Set by the descriptor builder when deserialized
737 std::uint16_t fVersionMajor = 0; ///< Set by the descriptor builder when deserialized
738 std::uint16_t fVersionMinor = 0; ///< Set by the descriptor builder when deserialized
739 std::uint16_t fVersionPatch = 0; ///< Set by the descriptor builder when deserialized
740
741 std::uint64_t fOnDiskHeaderSize = 0; ///< Set by the descriptor builder when deserialized
742 std::uint64_t fOnDiskHeaderXxHash3 = 0; ///< Set by the descriptor builder when deserialized
743 std::uint64_t fOnDiskFooterSize = 0; ///< Like fOnDiskHeaderSize, contains both cluster summaries and page locations
744
745 std::uint64_t fNEntries = 0; ///< Updated by the descriptor builder when the cluster groups are added
746 std::uint64_t fNClusters = 0; ///< Updated by the descriptor builder when the cluster groups are added
747
748 /// \brief The generation of the descriptor
749 ///
750 /// Once constructed by an RNTupleDescriptorBuilder, the descriptor is mostly immutable except for the set of
751 /// active page locations. During the lifetime of the descriptor, page location information for clusters
752 /// can be added or removed. When this happens, the generation should be increased, so that users of the
753 /// descriptor know that the information changed. The generation is increased, e.g., by the page source's
754 /// exclusive lock guard around the descriptor. It is used, e.g., by the descriptor cache in RNTupleReader.
755 std::uint64_t fGeneration = 0;
756
757 std::unordered_map<ROOT::DescriptorId_t, RClusterGroupDescriptor> fClusterGroupDescriptors;
758 /// References cluster groups sorted by entry range and thus allows for binary search.
759 /// Note that this list is empty during the descriptor building process and will only be
760 /// created when the final descriptor is extracted from the builder.
761 std::vector<ROOT::DescriptorId_t> fSortedClusterGroupIds;
762 /// Potentially a subset of all the available clusters
763 std::unordered_map<ROOT::DescriptorId_t, RClusterDescriptor> fClusterDescriptors;
764 /// List of AttributeSets linked to this RNTuple
765 std::vector<Experimental::RNTupleAttrSetDescriptor> fAttributeSets;
766
767 // We don't expose this publicly because when we add sharded clusters, this interface does not make sense anymore
769
770 /// Creates a descriptor containing only the schema information about this RNTuple, i.e. all the information needed
771 /// to create a new RNTuple with the same schema as this one but not necessarily the same clustering. This is used
772 /// when merging two RNTuples.
773 RNTupleDescriptor CloneSchema() const;
774
775 /// ROOT v6.34, with spec versions before 1.0.0.1, did not properly renormalize the type name.
776 /// This function returns true if this descriptor has a version prior to 1.0.0.1 and may therefore contain such
777 /// fields. This is only valid to call after SetVersion() or SetVersionForWriting() has been called on this
778 /// descriptor.
779 bool FieldTypeNamesMayNeedFixup() const;
780
781public:
782 /// All known feature flags.
783 /// Note that the flag values represent the bit _index_, not the already-bitshifted integer.
785 /// Signals that the RNTuple contains at least one deferred column that is part of a collection and was extended
786 /// (i.e. it appears in the footer). This can happen when merging two RNTuples that have the same collection field
787 /// backed by columns with different encoding, e.g. a vector<float> whose elements are represented by SplitReal32
788 /// in the first ntuple and by Real32 in the second.
789 /// Added in version 1.1.0.0 of the binary format.
790 kFeatureFlag_NestedDeferredColumns = 0,
791 // Insert new feature flags here, with contiguous values. If at any point a "hole" appears in the valid feature
792 // flags values, the check in RNTupleSerialize must be updated.
793
794 // End of regular feature flags
796
797 /// Reserved for forward-compatibility testing
798 kFeatureFlag_Test = 137
799 };
800
801 class RColumnDescriptorIterable;
802 class RFieldDescriptorIterable;
803 class RClusterGroupDescriptorIterable;
804 class RClusterDescriptorIterable;
805 class RExtraTypeInfoDescriptorIterable;
807
808 /// Modifiers passed to CreateModel()
810 private:
811 /// If set to true, projected fields will be reconstructed as such. This will prevent the model to be used
812 /// with an RNTupleReader, but it is useful, e.g., to accurately merge data.
813 bool fReconstructProjections = false;
814 /// By default, creating a model will fail if any of the reconstructed fields contains an unknown column type
815 /// or an unknown field structural role.
816 /// If this option is enabled, the model will be created and all fields containing unknown data (directly
817 /// or indirectly) will be skipped instead.
818 bool fForwardCompatible = false;
819 /// If true, the model will be created without a default entry (bare model).
820 bool fCreateBare = false;
821 /// If true, fields with a user defined type that have no available dictionaries will be reconstructed
822 /// as record fields from the on-disk information; otherwise, they will cause an error.
823 bool fEmulateUnknownTypes = false;
824
825 public:
826 RCreateModelOptions() {} // Work around compiler bug, see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88165
827
828 void SetReconstructProjections(bool v) { fReconstructProjections = v; }
829 bool GetReconstructProjections() const { return fReconstructProjections; }
830
831 void SetForwardCompatible(bool v) { fForwardCompatible = v; }
832 bool GetForwardCompatible() const { return fForwardCompatible; }
833
834 void SetCreateBare(bool v) { fCreateBare = v; }
835 bool GetCreateBare() const { return fCreateBare; }
836
837 void SetEmulateUnknownTypes(bool v) { fEmulateUnknownTypes = v; }
838 bool GetEmulateUnknownTypes() const { return fEmulateUnknownTypes; }
839 };
840
841 RNTupleDescriptor() = default;
846
847 RNTupleDescriptor Clone() const;
848
849 bool operator==(const RNTupleDescriptor &other) const;
850
851 std::uint64_t GetOnDiskHeaderXxHash3() const { return fOnDiskHeaderXxHash3; }
852 std::uint64_t GetOnDiskHeaderSize() const { return fOnDiskHeaderSize; }
853 std::uint64_t GetOnDiskFooterSize() const { return fOnDiskFooterSize; }
854 /// \see ROOT::RNTuple::GetCurrentVersion()
855 std::uint64_t GetVersion() const
856 {
857 return (static_cast<std::uint64_t>(fVersionEpoch) << 48) | (static_cast<std::uint64_t>(fVersionMajor) << 32) |
858 (static_cast<std::uint64_t>(fVersionMinor) << 16) | (static_cast<std::uint64_t>(fVersionPatch));
859 }
860
862 {
863 return fFieldDescriptors.at(fieldId);
864 }
866 {
867 return fColumnDescriptors.at(columnId);
868 }
870 {
871 return fClusterGroupDescriptors.at(clusterGroupId);
872 }
874 {
875 return fClusterDescriptors.at(clusterId);
876 }
877
878 RFieldDescriptorIterable GetFieldIterable(const RFieldDescriptor &fieldDesc) const;
879 RFieldDescriptorIterable
880 GetFieldIterable(const RFieldDescriptor &fieldDesc,
881 const std::function<bool(ROOT::DescriptorId_t, ROOT::DescriptorId_t)> &comparator) const;
882 RFieldDescriptorIterable GetFieldIterable(ROOT::DescriptorId_t fieldId) const;
883 RFieldDescriptorIterable
884 GetFieldIterable(ROOT::DescriptorId_t fieldId,
885 const std::function<bool(ROOT::DescriptorId_t, ROOT::DescriptorId_t)> &comparator) const;
886
887 RFieldDescriptorIterable GetTopLevelFields() const;
888 RFieldDescriptorIterable
889 GetTopLevelFields(const std::function<bool(ROOT::DescriptorId_t, ROOT::DescriptorId_t)> &comparator) const;
890
891 RColumnDescriptorIterable GetColumnIterable() const;
892 RColumnDescriptorIterable GetColumnIterable(const RFieldDescriptor &fieldDesc) const;
893 RColumnDescriptorIterable GetColumnIterable(ROOT::DescriptorId_t fieldId) const;
894
895 RClusterGroupDescriptorIterable GetClusterGroupIterable() const;
896
897 RClusterDescriptorIterable GetClusterIterable() const;
898
899 RExtraTypeInfoDescriptorIterable GetExtraTypeInfoIterable() const;
900
902
903 const std::string &GetName() const { return fName; }
904 const std::string &GetDescription() const { return fDescription; }
905
906 std::size_t GetNFields() const { return fFieldDescriptors.size(); }
907 std::size_t GetNLogicalColumns() const { return fColumnDescriptors.size(); }
908 std::size_t GetNPhysicalColumns() const { return fNPhysicalColumns; }
909 std::size_t GetNClusterGroups() const { return fClusterGroupDescriptors.size(); }
910 std::size_t GetNClusters() const { return fNClusters; }
911 std::size_t GetNActiveClusters() const { return fClusterDescriptors.size(); }
912 std::size_t GetNExtraTypeInfos() const { return fExtraTypeInfoDescriptors.size(); }
913 std::size_t GetNAttributeSets() const { return fAttributeSets.size(); }
914
915 /// We know the number of entries from adding the cluster summaries
916 ROOT::NTupleSize_t GetNEntries() const { return fNEntries; }
918
919 /// Returns the logical parent of all top-level RNTuple data fields.
920 ROOT::DescriptorId_t GetFieldZeroId() const { return fFieldZeroId; }
921 const RFieldDescriptor &GetFieldZero() const { return GetFieldDescriptor(GetFieldZeroId()); }
922 ROOT::DescriptorId_t FindFieldId(std::string_view fieldName, ROOT::DescriptorId_t parentId) const;
923 /// Searches for a top-level field
924 ROOT::DescriptorId_t FindFieldId(std::string_view fieldName) const;
925 ROOT::DescriptorId_t FindLogicalColumnId(ROOT::DescriptorId_t fieldId, std::uint32_t columnIndex,
926 std::uint16_t representationIndex) const;
927 ROOT::DescriptorId_t FindPhysicalColumnId(ROOT::DescriptorId_t fieldId, std::uint32_t columnIndex,
928 std::uint16_t representationIndex) const;
930 ROOT::DescriptorId_t FindNextClusterId(ROOT::DescriptorId_t clusterId) const;
931 ROOT::DescriptorId_t FindPrevClusterId(ROOT::DescriptorId_t clusterId) const;
932
933 /// Walks up the parents of the field ID and returns a field name of the form a.b.c.d
934 /// In case of invalid field ID, an empty string is returned.
935 std::string GetQualifiedFieldName(ROOT::DescriptorId_t fieldId) const;
936
937 /// Adjust the type name of the passed RFieldDescriptor for comparison with another renormalized type name.
938 std::string GetTypeNameForComparison(const RFieldDescriptor &fieldDesc) const;
939
940 bool HasFeature(unsigned int flag) const { return fFeatureFlags.count(flag) > 0; }
941 std::vector<std::uint64_t> GetFeatureFlags() const;
942
943 /// Return header extension information; if the descriptor does not have a header extension, return `nullptr`
944 const RHeaderExtension *GetHeaderExtension() const { return fHeaderExtension.get(); }
945
946 /// Methods to load and drop cluster group details (cluster IDs and page locations)
948 AddClusterGroupDetails(ROOT::DescriptorId_t clusterGroupId, std::vector<RClusterDescriptor> &clusterDescs);
949 RResult<void> DropClusterGroupDetails(ROOT::DescriptorId_t clusterGroupId);
950
951 std::uint64_t GetGeneration() const { return fGeneration; }
952 void IncGeneration() { fGeneration++; }
953
954 /// Re-create the C++ model from the stored metadata
955 std::unique_ptr<ROOT::RNTupleModel> CreateModel(const RCreateModelOptions &options = RCreateModelOptions()) const;
956 void PrintInfo(std::ostream &output) const;
957};
958
959// clang-format off
960/**
961\class ROOT::RNTupleDescriptor::RColumnDescriptorIterable
962\ingroup NTuple
963\brief Used to loop over a field's associated columns
964*/
965// clang-format on
967private:
968 /// The associated RNTuple for this range.
970 /// The descriptor ids of the columns ordered by field, representation, and column index
971 std::vector<ROOT::DescriptorId_t> fColumns = {};
972
973public:
975 private:
976 /// The enclosing range's RNTuple.
978 /// The enclosing range's descriptor id list.
979 const std::vector<ROOT::DescriptorId_t> &fColumns;
980 std::size_t fIndex = 0;
981
982 public:
983 using iterator_category = std::forward_iterator_tag;
986 using difference_type = std::ptrdiff_t;
987 using pointer = const RColumnDescriptor *;
989
990 RIterator(const RNTupleDescriptor &ntuple, const std::vector<ROOT::DescriptorId_t> &columns, std::size_t index)
991 : fNTuple(ntuple), fColumns(columns), fIndex(index)
992 {
993 }
994 iterator &operator++() /* prefix */
995 {
996 ++fIndex;
997 return *this;
998 }
999 iterator operator++(int) /* postfix */
1000 {
1001 auto old = *this;
1002 operator++();
1003 return old;
1004 }
1005 reference operator*() const { return fNTuple.GetColumnDescriptor(fColumns.at(fIndex)); }
1006 pointer operator->() const { return &fNTuple.GetColumnDescriptor(fColumns.at(fIndex)); }
1007 bool operator!=(const iterator &rh) const { return fIndex != rh.fIndex; }
1008 bool operator==(const iterator &rh) const { return fIndex == rh.fIndex; }
1009 };
1010
1013
1014 RIterator begin() { return RIterator(fNTuple, fColumns, 0); }
1015 RIterator end() { return RIterator(fNTuple, fColumns, fColumns.size()); }
1016 size_t size() { return fColumns.size(); }
1017};
1018
1019// clang-format off
1020/**
1021\class ROOT::RNTupleDescriptor::RFieldDescriptorIterable
1022\ingroup NTuple
1023\brief Used to loop over a field's child fields
1024*/
1025// clang-format on
1027private:
1028 /// The associated RNTuple for this range.
1030 /// The descriptor IDs of the child fields. These may be sorted using
1031 /// a comparison function.
1032 std::vector<ROOT::DescriptorId_t> fFieldChildren = {};
1033
1034public:
1036 private:
1037 /// The enclosing range's RNTuple.
1039 /// The enclosing range's descriptor id list.
1040 const std::vector<ROOT::DescriptorId_t> &fFieldChildren;
1041 std::size_t fIndex = 0;
1042
1043 public:
1044 using iterator_category = std::forward_iterator_tag;
1047 using difference_type = std::ptrdiff_t;
1048 using pointer = const RFieldDescriptor *;
1050
1051 RIterator(const RNTupleDescriptor &ntuple, const std::vector<ROOT::DescriptorId_t> &fieldChildren,
1052 std::size_t index)
1053 : fNTuple(ntuple), fFieldChildren(fieldChildren), fIndex(index)
1054 {
1055 }
1056 iterator &operator++() /* prefix */
1057 {
1058 ++fIndex;
1059 return *this;
1060 }
1061 iterator operator++(int) /* postfix */
1062 {
1063 auto old = *this;
1064 operator++();
1065 return old;
1066 }
1067 reference operator*() const { return fNTuple.GetFieldDescriptor(fFieldChildren.at(fIndex)); }
1068 pointer operator->() const { return &fNTuple.GetFieldDescriptor(fFieldChildren.at(fIndex)); }
1069 bool operator!=(const iterator &rh) const { return fIndex != rh.fIndex; }
1070 bool operator==(const iterator &rh) const { return fIndex == rh.fIndex; }
1071 };
1073 : fNTuple(ntuple), fFieldChildren(field.GetLinkIds())
1074 {
1075 }
1076 /// Sort the range using an arbitrary comparison function.
1078 const std::function<bool(ROOT::DescriptorId_t, ROOT::DescriptorId_t)> &comparator)
1079 : fNTuple(ntuple), fFieldChildren(field.GetLinkIds())
1080 {
1081 std::sort(fFieldChildren.begin(), fFieldChildren.end(), comparator);
1082 }
1083 RIterator begin() { return RIterator(fNTuple, fFieldChildren, 0); }
1084 RIterator end() { return RIterator(fNTuple, fFieldChildren, fFieldChildren.size()); }
1085};
1086
1087// clang-format off
1088/**
1089\class ROOT::RNTupleDescriptor::RClusterGroupDescriptorIterable
1090\ingroup NTuple
1091\brief Used to loop over all the cluster groups of an RNTuple (in unspecified order)
1092
1093Enumerate all cluster group IDs from the descriptor. No specific order can be assumed.
1094*/
1095// clang-format on
1097private:
1098 /// The associated RNTuple for this range.
1100
1101public:
1103 private:
1104 using Iter_t = std::unordered_map<ROOT::DescriptorId_t, RClusterGroupDescriptor>::const_iterator;
1105 /// The wrapped map iterator
1107
1108 public:
1109 using iterator_category = std::forward_iterator_tag;
1112 using difference_type = std::ptrdiff_t;
1115
1116 RIterator(Iter_t iter) : fIter(iter) {}
1117 iterator &operator++() /* prefix */
1118 {
1119 ++fIter;
1120 return *this;
1121 }
1122 iterator operator++(int) /* postfix */
1123 {
1124 auto old = *this;
1125 operator++();
1126 return old;
1127 }
1128 reference operator*() const { return fIter->second; }
1129 pointer operator->() const { return &fIter->second; }
1130 bool operator!=(const iterator &rh) const { return fIter != rh.fIter; }
1131 bool operator==(const iterator &rh) const { return fIter == rh.fIter; }
1132 };
1133
1135 RIterator begin() { return RIterator(fNTuple.fClusterGroupDescriptors.cbegin()); }
1136 RIterator end() { return RIterator(fNTuple.fClusterGroupDescriptors.cend()); }
1137};
1138
1139// clang-format off
1140/**
1141\class ROOT::RNTupleDescriptor::RClusterDescriptorIterable
1142\ingroup NTuple
1143\brief Used to loop over all the clusters of an RNTuple (in unspecified order)
1144
1145Enumerate all cluster IDs from all cluster descriptors. No specific order can be assumed, use
1146RNTupleDescriptor::FindNextClusterId() and RNTupleDescriptor::FindPrevClusterId() to traverse
1147clusters by entry number.
1148*/
1149// clang-format on
1151private:
1152 /// The associated RNTuple for this range.
1154
1155public:
1157 private:
1158 using Iter_t = std::unordered_map<ROOT::DescriptorId_t, RClusterDescriptor>::const_iterator;
1159 /// The wrapped map iterator
1161
1162 public:
1163 using iterator_category = std::forward_iterator_tag;
1166 using difference_type = std::ptrdiff_t;
1169
1170 RIterator(Iter_t iter) : fIter(iter) {}
1171 iterator &operator++() /* prefix */
1172 {
1173 ++fIter;
1174 return *this;
1175 }
1176 iterator operator++(int) /* postfix */
1177 {
1178 auto old = *this;
1179 operator++();
1180 return old;
1181 }
1182 reference operator*() const { return fIter->second; }
1183 pointer operator->() const { return &fIter->second; }
1184 bool operator!=(const iterator &rh) const { return fIter != rh.fIter; }
1185 bool operator==(const iterator &rh) const { return fIter == rh.fIter; }
1186 };
1187
1189 RIterator begin() { return RIterator(fNTuple.fClusterDescriptors.cbegin()); }
1190 RIterator end() { return RIterator(fNTuple.fClusterDescriptors.cend()); }
1191};
1192
1193// clang-format off
1194/**
1195\class ROOT::RNTupleDescriptor::RExtraTypeInfoDescriptorIterable
1196\ingroup NTuple
1197\brief Used to loop over all the extra type info record of an RNTuple (in unspecified order)
1198*/
1199// clang-format on
1201private:
1202 /// The associated RNTuple for this range.
1204
1205public:
1207 private:
1208 using Iter_t = std::vector<RExtraTypeInfoDescriptor>::const_iterator;
1209 /// The wrapped vector iterator
1211
1212 public:
1213 using iterator_category = std::forward_iterator_tag;
1216 using difference_type = std::ptrdiff_t;
1219
1220 RIterator(Iter_t iter) : fIter(iter) {}
1221 iterator &operator++() /* prefix */
1222 {
1223 ++fIter;
1224 return *this;
1225 }
1226 iterator operator++(int) /* postfix */
1227 {
1228 auto old = *this;
1229 operator++();
1230 return old;
1231 }
1232 reference operator*() const { return *fIter; }
1233 pointer operator->() const { return &*fIter; }
1234 bool operator!=(const iterator &rh) const { return fIter != rh.fIter; }
1235 bool operator==(const iterator &rh) const { return fIter == rh.fIter; }
1236 };
1237
1239 RIterator begin() { return RIterator(fNTuple.fExtraTypeInfoDescriptors.cbegin()); }
1240 RIterator end() { return RIterator(fNTuple.fExtraTypeInfoDescriptors.cend()); }
1241};
1242
1243namespace Experimental {
1244// clang-format off
1245/**
1246\class ROOT::Experimental::RNTupleAttrSetDescriptorIterable
1247\ingroup NTuple
1248\brief Used to loop over all the Attribute Sets linked to an RNTuple
1249*/
1250// clang-format on
1251// TODO: move this to RNTupleDescriptor::RNTupleAttrSetDescriptorIterable when it moves out of Experimental.
1253private:
1254 /// The associated RNTuple for this range.
1256
1257public:
1259 private:
1260 using Iter_t = std::vector<RNTupleAttrSetDescriptor>::const_iterator;
1261 /// The wrapped vector iterator
1263
1264 public:
1265 using iterator_category = std::forward_iterator_tag;
1268 using difference_type = std::ptrdiff_t;
1269 using pointer = const value_type *;
1270 using reference = const value_type &;
1271
1272 RIterator(Iter_t iter) : fIter(iter) {}
1273 iterator &operator++() /* prefix */
1274 {
1275 ++fIter;
1276 return *this;
1277 }
1278 iterator operator++(int) /* postfix */
1279 {
1280 auto old = *this;
1281 operator++();
1282 return old;
1283 }
1284 reference operator*() const { return *fIter; }
1285 pointer operator->() const { return &*fIter; }
1286 bool operator!=(const iterator &rh) const { return fIter != rh.fIter; }
1287 bool operator==(const iterator &rh) const { return fIter == rh.fIter; }
1288 };
1289
1291 RIterator begin() { return RIterator(fNTuple.fAttributeSets.cbegin()); }
1292 RIterator end() { return RIterator(fNTuple.fAttributeSets.cend()); }
1293};
1294} // namespace Experimental
1295
1296// clang-format off
1297/**
1298\class ROOT::RNTupleDescriptor::RHeaderExtension
1299\ingroup NTuple
1300\brief Summarizes information about fields and the corresponding columns that were added after the header has been serialized
1301*/
1302// clang-format on
1305
1306private:
1307 /// All field IDs of late model extensions, in the order of field addition. This is necessary to serialize the
1308 /// the fields in that order.
1309 std::vector<ROOT::DescriptorId_t> fFieldIdsOrder;
1310 /// All field IDs of late model extensions for efficient lookup. When a column gets added to the extension
1311 /// header, this enables us to determine if the column belongs to a field of the header extension of if it
1312 /// belongs to a field of the regular header that gets extended by additional column representations.
1313 std::unordered_set<ROOT::DescriptorId_t> fFieldIdsLookup;
1314 /// All logical column IDs of columns that extend, with additional column representations, fields of the regular
1315 /// header. During serialization, these columns are not picked up as columns of `fFieldIdsOrder`. But instead
1316 /// these columns need to be serialized in the extension header without re-serializing the field.
1317 std::vector<ROOT::DescriptorId_t> fExtendedColumnRepresentations;
1318 /// Number of logical and physical columns; updated by the descriptor builder when columns are added
1319 std::uint32_t fNLogicalColumns = 0;
1320 std::uint32_t fNPhysicalColumns = 0;
1321
1322 /// Marks `fieldDesc` as an extended field, i.e. a field that appears in the Header Extension (e.g. having been added
1323 /// through late model extension). Note that the field descriptor should also have been added to the RNTuple
1324 /// Descriptor alongside non-extended fields.
1326 {
1327 fFieldIdsOrder.emplace_back(fieldDesc.GetId());
1328 fFieldIdsLookup.insert(fieldDesc.GetId());
1329 }
1330
1331 /// Marks `columnDesc` as an extended column, i.e. a column that appears in the Header Extension (e.g. having been
1332 /// added through late model extension as an additional representation of an existing column). Note that the column
1333 /// descriptor should also have been added to the RNTuple Descriptor alongside non-extended columns.
1335 {
1336 fNLogicalColumns++;
1337 if (!columnDesc.IsAliasColumn())
1338 fNPhysicalColumns++;
1339 if (fFieldIdsLookup.count(columnDesc.GetFieldId()) == 0) {
1340 fExtendedColumnRepresentations.emplace_back(columnDesc.GetLogicalId());
1341 }
1342 }
1343
1344public:
1345 std::size_t GetNFields() const { return fFieldIdsOrder.size(); }
1346 std::size_t GetNLogicalColumns() const { return fNLogicalColumns; }
1347 std::size_t GetNPhysicalColumns() const { return fNPhysicalColumns; }
1348 const std::vector<ROOT::DescriptorId_t> &GetExtendedColumnRepresentations() const
1349 {
1350 return fExtendedColumnRepresentations;
1351 }
1352 /// Return a vector containing the IDs of the top-level fields defined in the extension header, in the order
1353 /// of their addition. Note that these fields are not necessarily top-level fields in the overall schema.
1354 /// If a nested field is extended, it will return the top-most field of the extended subtree.
1355 /// We cannot create this vector when building the fFields because at the time when AddExtendedField is called,
1356 /// the field is not yet linked into the schema tree.
1357 std::vector<ROOT::DescriptorId_t> GetTopMostFields(const RNTupleDescriptor &desc) const;
1358
1360 {
1361 return fFieldIdsLookup.find(fieldId) != fFieldIdsLookup.end();
1362 }
1364 {
1365 return std::find(fExtendedColumnRepresentations.begin(), fExtendedColumnRepresentations.end(), columnId) !=
1366 fExtendedColumnRepresentations.end();
1367 }
1368};
1369
1370namespace Experimental::Internal {
1373
1374public:
1376 {
1377 fDesc.fName = name;
1378 return *this;
1379 }
1381 {
1382 fDesc.fSchemaVersionMajor = major;
1383 fDesc.fSchemaVersionMinor = minor;
1384 return *this;
1385 }
1387 {
1388 fDesc.fAnchorLocator = loc;
1389 return *this;
1390 }
1392 {
1393 fDesc.fAnchorLength = length;
1394 return *this;
1395 }
1396
1397 /// Attempt to make an AttributeSet descriptor. This may fail if the builder
1398 /// was not given enough information to make a proper descriptor.
1400};
1401} // namespace Experimental::Internal
1402
1403namespace Internal {
1404
1405// clang-format off
1406/**
1407\class ROOT::Internal::RColumnDescriptorBuilder
1408\ingroup NTuple
1409\brief A helper class for piece-wise construction of an RColumnDescriptor
1410
1411Dangling column descriptors can become actual descriptors when added to an
1412RNTupleDescriptorBuilder instance and then linked to their fields.
1413*/
1414// clang-format on
1416private:
1418
1419public:
1420 /// Make an empty column descriptor builder.
1422
1434 {
1435 fColumn.fBitsOnStorage = bitsOnStorage;
1436 return *this;
1437 }
1439 {
1440 fColumn.fType = type;
1441 return *this;
1442 }
1444 {
1445 fColumn.fFieldId = fieldId;
1446 return *this;
1447 }
1449 {
1450 fColumn.fIndex = index;
1451 return *this;
1452 }
1454 {
1456 return *this;
1457 }
1459 {
1460 R__ASSERT(fColumn.fFirstElementIndex != 0);
1461 if (fColumn.fFirstElementIndex > 0)
1462 fColumn.fFirstElementIndex = -fColumn.fFirstElementIndex;
1463 return *this;
1464 }
1466 {
1468 return *this;
1469 }
1470 RColumnDescriptorBuilder &ValueRange(double min, double max)
1471 {
1472 fColumn.fValueRange = {min, max};
1473 return *this;
1474 }
1475 RColumnDescriptorBuilder &ValueRange(std::optional<RColumnDescriptor::RValueRange> valueRange)
1476 {
1477 fColumn.fValueRange = valueRange;
1478 return *this;
1479 }
1480 ROOT::DescriptorId_t GetFieldId() const { return fColumn.fFieldId; }
1482 /// Attempt to make a column descriptor. This may fail if the column
1483 /// was not given enough information to make a proper descriptor.
1484 RResult<RColumnDescriptor> MakeDescriptor() const;
1485};
1486
1487// clang-format off
1488/**
1489\class ROOT::Internal::RFieldDescriptorBuilder
1490\ingroup NTuple
1491\brief A helper class for piece-wise construction of an RFieldDescriptor
1492
1493Dangling field descriptors describe a single field in isolation. They are
1494missing the necessary relationship information (parent field, any child fields)
1495required to describe a real RNTuple field.
1496
1497Dangling field descriptors can only become actual descriptors when added to an
1498RNTupleDescriptorBuilder instance and then linked to other fields.
1499*/
1500// clang-format on
1502private:
1504
1505public:
1506 /// Make an empty dangling field descriptor.
1508
1509 /// Make a new RFieldDescriptorBuilder based off a live RNTuple field.
1510 static RFieldDescriptorBuilder FromField(const ROOT::RFieldBase &field);
1511
1513 {
1514 fField.fFieldId = fieldId;
1515 return *this;
1516 }
1518 {
1519 fField.fFieldVersion = fieldVersion;
1520 return *this;
1521 }
1523 {
1524 fField.fTypeVersion = typeVersion;
1525 return *this;
1526 }
1528 {
1529 fField.fParentId = id;
1530 return *this;
1531 }
1533 {
1534 fField.fProjectionSourceId = id;
1535 return *this;
1536 }
1538 {
1539 fField.fFieldName = fieldName;
1540 return *this;
1541 }
1543 {
1545 return *this;
1546 }
1547 RFieldDescriptorBuilder &TypeName(const std::string &typeName)
1548 {
1549 fField.fTypeName = typeName;
1550 return *this;
1551 }
1553 {
1554 fField.fTypeAlias = typeAlias;
1555 return *this;
1556 }
1558 {
1559 fField.fNRepetitions = nRepetitions;
1560 return *this;
1561 }
1563 {
1564 fField.fStructure = structure;
1565 return *this;
1566 }
1567 RFieldDescriptorBuilder &TypeChecksum(const std::optional<std::uint32_t> typeChecksum)
1568 {
1569 fField.fTypeChecksum = typeChecksum;
1570 return *this;
1571 }
1573 {
1574 fField.fIsSoACollection = val;
1575 return *this;
1576 }
1577 ROOT::DescriptorId_t GetParentId() const { return fField.fParentId; }
1578 /// Attempt to make a field descriptor. This may fail if the dangling field
1579 /// was not given enough information to make a proper descriptor.
1580 RResult<RFieldDescriptor> MakeDescriptor() const;
1581};
1582
1583// clang-format off
1584/**
1585\class ROOT::Internal::RClusterDescriptorBuilder
1586\ingroup NTuple
1587\brief A helper class for piece-wise construction of an RClusterDescriptor
1588
1589The cluster descriptor builder starts from a summary-only cluster descriptor and allows for the
1590piecewise addition of page locations.
1591*/
1592// clang-format on
1594private:
1596
1597public:
1599 {
1600 fCluster.fClusterId = clusterId;
1601 return *this;
1602 }
1603
1605 {
1607 return *this;
1608 }
1609
1611 {
1612 fCluster.fNEntries = nEntries;
1613 return *this;
1614 }
1615
1616 RResult<void> CommitColumnRange(ROOT::DescriptorId_t physicalId, std::uint64_t firstElementIndex,
1618
1619 /// Books the given column ID as being suppressed in this cluster. The correct first element index and number of
1620 /// elements need to be set by CommitSuppressedColumnRanges() once all the calls to CommitColumnRange() and
1621 /// MarkSuppressedColumnRange() took place.
1622 RResult<void> MarkSuppressedColumnRange(ROOT::DescriptorId_t physicalId);
1623
1624 /// Sets the first element index and number of elements for all the suppressed column ranges.
1625 /// The information is taken from the corresponding columns from the primary representation.
1626 /// Needs to be called when all the columns (suppressed and regular) where added.
1627 RResult<void> CommitSuppressedColumnRanges(const RNTupleDescriptor &desc);
1628
1629 /// Add column and page ranges for columns created during late model extension missing in this cluster. The locator
1630 /// type for the synthesized page ranges is `kTypePageZero`. All the page sources must be able to populate the
1631 /// 'zero' page from such locator. Any call to CommitColumnRange() and CommitSuppressedColumnRanges()
1632 /// should happen before calling this function.
1633 RClusterDescriptorBuilder &AddExtendedColumnRanges(const RNTupleDescriptor &desc);
1634
1639
1640 /// Move out the full cluster descriptor including page locations
1641 RResult<RClusterDescriptor> MoveDescriptor();
1642};
1643
1644// clang-format off
1645/**
1646\class ROOT::Internal::RClusterGroupDescriptorBuilder
1647\ingroup NTuple
1648\brief A helper class for piece-wise construction of an RClusterGroupDescriptor
1649*/
1650// clang-format on
1652private:
1654
1655public:
1658
1670 {
1671 fClusterGroup.fPageListLength = pageListLength;
1672 return *this;
1673 }
1675 {
1676 fClusterGroup.fMinEntry = minEntry;
1677 return *this;
1678 }
1680 {
1681 fClusterGroup.fEntrySpan = entrySpan;
1682 return *this;
1683 }
1685 {
1686 fClusterGroup.fNClusters = nClusters;
1687 return *this;
1688 }
1689 void AddSortedClusters(const std::vector<ROOT::DescriptorId_t> &clusterIds)
1690 {
1691 if (clusterIds.size() != fClusterGroup.GetNClusters())
1692 throw RException(R__FAIL("mismatch of number of clusters"));
1693 fClusterGroup.fClusterIds = clusterIds;
1694 }
1695
1696 RResult<RClusterGroupDescriptor> MoveDescriptor();
1697};
1698
1699// clang-format off
1700/**
1701\class ROOT::Internal::RExtraTypeInfoDescriptorBuilder
1702\ingroup NTuple
1703\brief A helper class for piece-wise construction of an RExtraTypeInfoDescriptor
1704*/
1705// clang-format on
1707private:
1709
1710public:
1712
1714 {
1715 fExtraTypeInfo.fContentId = contentId;
1716 return *this;
1717 }
1719 {
1720 fExtraTypeInfo.fTypeVersion = typeVersion;
1721 return *this;
1722 }
1723 RExtraTypeInfoDescriptorBuilder &TypeName(const std::string &typeName)
1724 {
1725 fExtraTypeInfo.fTypeName = typeName;
1726 return *this;
1727 }
1729 {
1730 fExtraTypeInfo.fContent = content;
1731 return *this;
1732 }
1733
1734 RResult<RExtraTypeInfoDescriptor> MoveDescriptor();
1735};
1736
1737// clang-format off
1738/**
1739\class ROOT::Internal::RNTupleDescriptorBuilder
1740\ingroup NTuple
1741\brief A helper class for piece-wise construction of an RNTupleDescriptor
1742
1743Used by RPageStorage implementations in order to construct the RNTupleDescriptor from the various header parts.
1744*/
1745// clang-format on
1747private:
1749 RResult<void> EnsureFieldExists(ROOT::DescriptorId_t fieldId) const;
1750
1751public:
1752 /// Checks whether invariants hold:
1753 /// * RNTuple epoch is valid
1754 /// * RNTuple name is valid
1755 /// * Fields have valid parents
1756 /// * Number of columns is constant across column representations
1757 RResult<void> EnsureValidDescriptor() const;
1758 const RNTupleDescriptor &GetDescriptor() const { return fDescriptor; }
1759 RNTupleDescriptor MoveDescriptor();
1760
1761 /// Copies the "schema" part of `descriptor` into the builder's descriptor.
1762 /// This resets the builder's descriptor.
1763 void SetSchemaFromExisting(const RNTupleDescriptor &descriptor);
1764
1765 void SetVersion(std::uint16_t versionEpoch, std::uint16_t versionMajor, std::uint16_t versionMinor,
1766 std::uint16_t versionPatch);
1767 void SetVersionForWriting();
1768
1769 void SetNTuple(const std::string_view name, const std::string_view description);
1770 void SetFeature(unsigned int flag);
1771
1772 void SetOnDiskHeaderXxHash3(std::uint64_t xxhash3) { fDescriptor.fOnDiskHeaderXxHash3 = xxhash3; }
1773 void SetOnDiskHeaderSize(std::uint64_t size) { fDescriptor.fOnDiskHeaderSize = size; }
1774 /// The real footer size also include the page list envelopes
1775 void AddToOnDiskFooterSize(std::uint64_t size) { fDescriptor.fOnDiskFooterSize += size; }
1776
1777 void AddField(const RFieldDescriptor &fieldDesc);
1780
1781 // The field that the column belongs to has to be already available. For fields with multiple columns,
1782 // the columns need to be added in order of the column index
1784
1787
1789 void ReplaceExtraTypeInfo(RExtraTypeInfoDescriptor &&extraTypeInfoDesc);
1790
1792
1793 /// Mark the beginning of the header extension; any fields and columns added after a call to this function are
1794 /// annotated as begin part of the header extension.
1795 void BeginHeaderExtension();
1796
1797 /// \brief Shift column IDs of alias columns by `offset`
1798 ///
1799 /// If the descriptor is constructed in pieces consisting of physical and alias columns
1800 /// (regular and projected fields), the natural column order would be
1801 /// - Physical and alias columns of piece one
1802 /// - Physical and alias columns of piece two
1803 /// - etc.
1804 /// What we want, however, are first all physical column IDs and then all alias column IDs.
1805 /// This method adds `offset` to the logical column IDs of all alias columns and fixes up the corresponding
1806 /// column IDs in the projected field descriptors. In this way, a new piece of physical and alias columns can
1807 /// first shift the existing alias columns by the number of new physical columns, resulting in the following order
1808 /// - Physical columns of piece one
1809 /// - Physical columns of piece two
1810 /// - ...
1811 // - Logical columns of piece one
1812 /// - Logical columns of piece two
1813 /// - ...
1814 void ShiftAliasColumns(std::uint32_t offset);
1815};
1816
1818{
1819 return desc.CloneSchema();
1820}
1821
1822/// Tells if the field describes a user-defined enum type.
1823/// The dictionary does not need to be available for this method.
1824/// Needs the full descriptor to look up sub fields.
1826
1827/// Tells if the field describes a std::atomic<T> type
1829
1830} // namespace Internal
1831
1832} // namespace ROOT
1833
1834#endif // ROOT_RNTupleDescriptor
#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:300
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
Bool_t operator==(const TDatime &d1, const TDatime &d2)
Definition TDatime.h:102
#define R__ASSERT(e)
Checks condition e and reports a fatal error if it's false.
Definition TError.h:125
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h length
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize id
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 type
char name[80]
Definition TGX11.cxx:145
The available trivial, native content types of a column.
RNTupleAttrSetDescriptorBuilder & AnchorLocator(const RNTupleLocator &loc)
RNTupleAttrSetDescriptorBuilder & SchemaVersion(std::uint16_t major, std::uint16_t minor)
RNTupleAttrSetDescriptorBuilder & Name(std::string_view name)
RNTupleAttrSetDescriptorBuilder & AnchorLength(std::uint32_t length)
std::vector< RNTupleAttrSetDescriptor >::const_iterator Iter_t
Used to loop over all the Attribute Sets linked to an RNTuple.
const RNTupleDescriptor & fNTuple
The associated RNTuple for this range.
RNTupleAttrSetDescriptorIterable(const RNTupleDescriptor &ntuple)
Metadata stored for every Attribute Set linked to an RNTuple.
RNTupleAttrSetDescriptor & operator=(const RNTupleAttrSetDescriptor &other)=delete
bool operator==(const RNTupleAttrSetDescriptor &other) const
std::uint32_t fAnchorLength
uncompressed size of the linked anchor
RNTupleAttrSetDescriptor(const RNTupleAttrSetDescriptor &other)=delete
RNTupleAttrSetDescriptor & operator=(RNTupleAttrSetDescriptor &&other)=default
const RNTupleLocator & GetAnchorLocator() const
bool operator!=(const RNTupleAttrSetDescriptor &other) const
RNTupleAttrSetDescriptor(RNTupleAttrSetDescriptor &&other)=default
A helper class for piece-wise construction of an RClusterDescriptor.
RClusterDescriptorBuilder & NEntries(std::uint64_t nEntries)
const RClusterDescriptor::RColumnRange & GetColumnRange(ROOT::DescriptorId_t physicalId)
RClusterDescriptorBuilder & ClusterId(ROOT::DescriptorId_t clusterId)
RClusterDescriptorBuilder & FirstEntryIndex(std::uint64_t firstEntryIndex)
A helper class for piece-wise construction of an RClusterGroupDescriptor.
RClusterGroupDescriptorBuilder & EntrySpan(std::uint64_t entrySpan)
RClusterGroupDescriptorBuilder & PageListLocator(const RNTupleLocator &pageListLocator)
RClusterGroupDescriptorBuilder & PageListLength(std::uint64_t pageListLength)
RClusterGroupDescriptorBuilder & MinEntry(std::uint64_t minEntry)
void AddSortedClusters(const std::vector< ROOT::DescriptorId_t > &clusterIds)
RClusterGroupDescriptorBuilder & ClusterGroupId(ROOT::DescriptorId_t clusterGroupId)
RClusterGroupDescriptorBuilder & NClusters(std::uint32_t nClusters)
A helper class for piece-wise construction of an RColumnDescriptor.
ROOT::DescriptorId_t GetRepresentationIndex() const
RColumnDescriptorBuilder & SetSuppressedDeferred()
RColumnDescriptorBuilder & LogicalColumnId(ROOT::DescriptorId_t logicalColumnId)
RColumnDescriptorBuilder & FieldId(ROOT::DescriptorId_t fieldId)
RColumnDescriptorBuilder & BitsOnStorage(std::uint16_t bitsOnStorage)
RColumnDescriptorBuilder & ValueRange(double min, double max)
RColumnDescriptorBuilder()=default
Make an empty column descriptor builder.
RColumnDescriptorBuilder & ValueRange(std::optional< RColumnDescriptor::RValueRange > valueRange)
RColumnDescriptorBuilder & Type(ROOT::ENTupleColumnType type)
RColumnDescriptorBuilder & PhysicalColumnId(ROOT::DescriptorId_t physicalColumnId)
RColumnDescriptorBuilder & FirstElementIndex(std::uint64_t firstElementIdx)
RColumnDescriptorBuilder & Index(std::uint32_t index)
RColumnDescriptorBuilder & RepresentationIndex(std::uint16_t representationIndex)
A column element encapsulates the translation between basic C++ types and their column representation...
A helper class for piece-wise construction of an RExtraTypeInfoDescriptor.
RExtraTypeInfoDescriptorBuilder & ContentId(EExtraTypeInfoIds contentId)
RExtraTypeInfoDescriptorBuilder & TypeName(const std::string &typeName)
RExtraTypeInfoDescriptorBuilder & Content(const std::string &content)
RExtraTypeInfoDescriptorBuilder & TypeVersion(std::uint32_t typeVersion)
A helper class for piece-wise construction of an RFieldDescriptor.
RFieldDescriptorBuilder & NRepetitions(std::uint64_t nRepetitions)
RFieldDescriptorBuilder & Structure(const ROOT::ENTupleStructure &structure)
RFieldDescriptorBuilder()=default
Make an empty dangling field descriptor.
RFieldDescriptorBuilder & TypeAlias(const std::string &typeAlias)
RFieldDescriptorBuilder & ProjectionSourceId(ROOT::DescriptorId_t id)
RFieldDescriptorBuilder & TypeVersion(std::uint32_t typeVersion)
RFieldDescriptorBuilder & IsSoACollection(bool val)
RFieldDescriptorBuilder & TypeChecksum(const std::optional< std::uint32_t > typeChecksum)
RFieldDescriptorBuilder & ParentId(ROOT::DescriptorId_t id)
RFieldDescriptorBuilder & FieldDescription(const std::string &fieldDescription)
RFieldDescriptorBuilder & FieldVersion(std::uint32_t fieldVersion)
RFieldDescriptorBuilder & FieldName(const std::string &fieldName)
RFieldDescriptorBuilder & FieldId(ROOT::DescriptorId_t fieldId)
RFieldDescriptorBuilder & TypeName(const std::string &typeName)
A helper class for piece-wise construction of an RNTupleDescriptor.
const RNTupleDescriptor & GetDescriptor() const
void SetOnDiskHeaderXxHash3(std::uint64_t xxhash3)
void AddToOnDiskFooterSize(std::uint64_t size)
The real footer size also include the page list envelopes.
std::unordered_map< ROOT::DescriptorId_t, RColumnRange >::const_iterator Iter_t
RColumnRangeIterable(const RClusterDescriptor &desc)
The window of element indexes of a particular column in a particular cluster.
void SetCompressionSettings(std::optional< std::uint32_t > comp)
void SetPhysicalColumnId(ROOT::DescriptorId_t id)
ROOT::DescriptorId_t GetPhysicalColumnId() const
bool operator==(const RColumnRange &other) const
void SetFirstElementIndex(ROOT::NTupleSize_t idx)
std::optional< std::uint32_t > GetCompressionSettings() const
std::optional< std::uint32_t > fCompressionSettings
The usual format for ROOT compression settings (see Compression.h).
ROOT::NTupleSize_t GetFirstElementIndex() const
RColumnRange(ROOT::DescriptorId_t physicalColumnId, ROOT::NTupleSize_t firstElementIndex, ROOT::NTupleSize_t nElements, std::optional< std::uint32_t > compressionSettings, bool suppressed=false)
void IncrementFirstElementIndex(ROOT::NTupleSize_t by)
bool Contains(ROOT::NTupleSize_t index) const
void IncrementNElements(ROOT::NTupleSize_t by)
Records the partition of data into pages for a particular column in a particular cluster.
RPageRange & operator=(const RPageRange &other)=delete
std::unique_ptr< std::vector< ROOT::NTupleSize_t > > fCumulativeNElements
Has the same length than fPageInfos and stores the sum of the number of elements of all the pages up ...
RPageRange(RPageRange &&other)=default
RPageRange(const RPageRange &other)=delete
const std::vector< RPageInfo > & GetPageInfos() const
bool operator==(const RPageRange &other) const
ROOT::DescriptorId_t GetPhysicalColumnId() const
void SetPhysicalColumnId(ROOT::DescriptorId_t id)
RPageRange & operator=(RPageRange &&other)=default
std::vector< RPageInfo > & GetPageInfos()
Metadata for RNTuple clusters.
ROOT::NTupleSize_t GetNEntries() const
ROOT::NTupleSize_t fFirstEntryIndex
Clusters can be swapped by adjusting the entry offsets of the cluster and all ranges.
RClusterDescriptor & operator=(const RClusterDescriptor &other)=delete
ROOT::DescriptorId_t GetId() const
const RPageRange & GetPageRange(ROOT::DescriptorId_t physicalId) const
RClusterDescriptor(RClusterDescriptor &&other)=default
std::unordered_map< ROOT::DescriptorId_t, RColumnRange > fColumnRanges
ROOT::DescriptorId_t fClusterId
bool ContainsColumn(ROOT::DescriptorId_t physicalId) const
RClusterDescriptor & operator=(RClusterDescriptor &&other)=default
const RColumnRange & GetColumnRange(ROOT::DescriptorId_t physicalId) const
ROOT::NTupleSize_t GetFirstEntryIndex() const
std::unordered_map< ROOT::DescriptorId_t, RPageRange > fPageRanges
RClusterDescriptor(const RClusterDescriptor &other)=delete
Clusters are bundled in cluster groups.
RNTupleLocator fPageListLocator
The page list that corresponds to the cluster group.
RClusterGroupDescriptor & operator=(const RClusterGroupDescriptor &other)=delete
std::vector< ROOT::DescriptorId_t > fClusterIds
The cluster IDs can be empty if the corresponding page list is not loaded.
ROOT::DescriptorId_t GetId() const
RClusterGroupDescriptor(RClusterGroupDescriptor &&other)=default
std::uint64_t fMinEntry
The minimum first entry number of the clusters in the cluster group.
bool HasClusterDetails() const
A cluster group is loaded in two stages.
std::uint32_t fNClusters
Number of clusters is always known even if the cluster IDs are not (yet) populated.
RClusterGroupDescriptor & operator=(RClusterGroupDescriptor &&other)=default
const std::vector< ROOT::DescriptorId_t > & GetClusterIds() const
std::uint64_t fPageListLength
Uncompressed size of the page list.
std::uint64_t GetPageListLength() const
RNTupleLocator GetPageListLocator() const
RClusterGroupDescriptor(const RClusterGroupDescriptor &other)=delete
std::uint64_t fEntrySpan
Number of entries that are (partially for sharded clusters) covered by this cluster group.
Metadata stored for every column of an RNTuple.
std::optional< RValueRange > GetValueRange() const
ROOT::DescriptorId_t fPhysicalColumnId
Usually identical to the logical column ID, except for alias columns where it references the shadowed...
ROOT::DescriptorId_t fLogicalColumnId
The actual column identifier, which is the link to the corresponding field.
RColumnDescriptor(const RColumnDescriptor &other)=delete
std::uint64_t GetFirstElementIndex() const
ROOT::DescriptorId_t fFieldId
Every column belongs to one and only one field.
std::int64_t fFirstElementIndex
The absolute value specifies the index for the first stored element for this column.
ROOT::DescriptorId_t GetFieldId() const
RColumnDescriptor(RColumnDescriptor &&other)=default
std::uint32_t fIndex
A field can be serialized into several columns, which are numbered from zero to $n$.
RColumnDescriptor & operator=(RColumnDescriptor &&other)=default
std::uint32_t GetIndex() const
std::uint16_t fBitsOnStorage
The size in bits of elements of this column.
std::uint16_t fRepresentationIndex
A field may use multiple column representations, which are numbered from zero to $m$.
ROOT::ENTupleColumnType fType
The on-disk column type.
ROOT::ENTupleColumnType GetType() const
ROOT::DescriptorId_t GetPhysicalId() const
std::uint16_t GetRepresentationIndex() const
std::optional< RValueRange > fValueRange
Optional value range (used e.g. by quantized real fields)
std::uint16_t GetBitsOnStorage() const
RColumnDescriptor & operator=(const RColumnDescriptor &other)=delete
ROOT::DescriptorId_t GetLogicalId() const
Base class for all ROOT issued exceptions.
Definition RError.hxx:79
Field specific extra type information from the header / extenstion header.
RExtraTypeInfoDescriptor & operator=(RExtraTypeInfoDescriptor &&other)=default
RExtraTypeInfoDescriptor & operator=(const RExtraTypeInfoDescriptor &other)=delete
RExtraTypeInfoDescriptor(const RExtraTypeInfoDescriptor &other)=delete
EExtraTypeInfoIds fContentId
Specifies the meaning of the extra information.
std::string fTypeName
The type name the extra information refers to; empty for RNTuple-wide extra information.
std::string fContent
The content format depends on the content ID and may be binary.
const std::string & GetContent() const
const std::string & GetTypeName() const
RExtraTypeInfoDescriptor(RExtraTypeInfoDescriptor &&other)=default
EExtraTypeInfoIds GetContentId() const
std::uint32_t fTypeVersion
Type version the extra type information is bound to.
A field translates read and write calls from/to underlying columns to/from tree values.
Metadata stored for every field of an RNTuple.
const std::string & GetTypeAlias() const
std::unique_ptr< ROOT::RFieldBase > CreateField(const RNTupleDescriptor &ntplDesc, const ROOT::RCreateFieldOptions &options={}) const
In general, we create a field simply from the C++ type name.
std::uint32_t fFieldVersion
The version of the C++-type-to-column translation mechanics.
ROOT::DescriptorId_t fFieldId
RFieldDescriptor Clone() const
Get a copy of the descriptor.
ROOT::DescriptorId_t GetId() const
std::uint64_t fNRepetitions
The number of elements per entry for fixed-size arrays.
std::uint32_t GetFieldVersion() const
const std::vector< ROOT::DescriptorId_t > & GetLogicalColumnIds() const
std::uint32_t fColumnCardinality
The number of columns in the column representations of the field.
ROOT::DescriptorId_t fProjectionSourceId
For projected fields, the source field ID.
bool IsCustomEnum(const RNTupleDescriptor &desc) const R__DEPRECATED(6
ROOT::ENTupleStructure GetStructure() const
bool operator==(const RFieldDescriptor &other) const
RFieldDescriptor(const RFieldDescriptor &other)=delete
bool IsCustomClass() const R__DEPRECATED(6
std::uint32_t GetColumnCardinality() const
bool IsStdAtomic() const R__DEPRECATED(6
std::string fFieldDescription
Free text set by the user.
RFieldDescriptor & operator=(const RFieldDescriptor &other)=delete
RFieldDescriptor & operator=(RFieldDescriptor &&other)=default
const std::vector< ROOT::DescriptorId_t > & GetLinkIds() const
ROOT::DescriptorId_t fParentId
Establishes sub field relationships, such as classes and collections.
ROOT::DescriptorId_t GetParentId() const
std::string fTypeAlias
A typedef or using directive that resolved to the type name during field creation.
ROOT::ENTupleStructure fStructure
The structural information carried by this field in the data model tree.
std::uint64_t GetNRepetitions() const
RFieldDescriptor(RFieldDescriptor &&other)=default
std::vector< ROOT::DescriptorId_t > fLinkIds
The pointers in the other direction from parent to children.
std::string fFieldName
The leaf name, not including parent fields.
const std::string & GetFieldDescription() const
std::optional< std::uint32_t > GetTypeChecksum() const
ROOT::DescriptorId_t GetProjectionSourceId() const
bool fIsSoACollection
Indicates if this is a collection that should be represented in memory by a SoA layout.
std::uint32_t fTypeVersion
The version of the C++ type itself.
std::string fTypeName
The C++ type that was used when writing the field.
std::uint32_t GetTypeVersion() const
const std::string & GetFieldName() const
std::vector< ROOT::DescriptorId_t > fLogicalColumnIds
The ordered list of columns attached to this field: first by representation index then by column inde...
const std::string & GetTypeName() const
std::optional< std::uint32_t > fTypeChecksum
For custom classes, we store the ROOT TClass reported checksum to facilitate the use of I/O rules tha...
std::unordered_map< ROOT::DescriptorId_t, RClusterDescriptor >::const_iterator Iter_t
Used to loop over all the clusters of an RNTuple (in unspecified order)
const RNTupleDescriptor & fNTuple
The associated RNTuple for this range.
RClusterDescriptorIterable(const RNTupleDescriptor &ntuple)
std::unordered_map< ROOT::DescriptorId_t, RClusterGroupDescriptor >::const_iterator Iter_t
Used to loop over all the cluster groups of an RNTuple (in unspecified order)
const RNTupleDescriptor & fNTuple
The associated RNTuple for this range.
const RNTupleDescriptor & fNTuple
The enclosing range's RNTuple.
const std::vector< ROOT::DescriptorId_t > & fColumns
The enclosing range's descriptor id list.
RIterator(const RNTupleDescriptor &ntuple, const std::vector< ROOT::DescriptorId_t > &columns, std::size_t index)
Used to loop over a field's associated columns.
const RNTupleDescriptor & fNTuple
The associated RNTuple for this range.
std::vector< RExtraTypeInfoDescriptor >::const_iterator Iter_t
Used to loop over all the extra type info record of an RNTuple (in unspecified order)
const RNTupleDescriptor & fNTuple
The associated RNTuple for this range.
RIterator(const RNTupleDescriptor &ntuple, const std::vector< ROOT::DescriptorId_t > &fieldChildren, std::size_t index)
const std::vector< ROOT::DescriptorId_t > & fFieldChildren
The enclosing range's descriptor id list.
const RNTupleDescriptor & fNTuple
The enclosing range's RNTuple.
Used to loop over a field's child fields.
const RNTupleDescriptor & fNTuple
The associated RNTuple for this range.
RFieldDescriptorIterable(const RNTupleDescriptor &ntuple, const RFieldDescriptor &field, const std::function< bool(ROOT::DescriptorId_t, ROOT::DescriptorId_t)> &comparator)
Sort the range using an arbitrary comparison function.
RFieldDescriptorIterable(const RNTupleDescriptor &ntuple, const RFieldDescriptor &field)
Summarizes information about fields and the corresponding columns that were added after the header ha...
const std::vector< ROOT::DescriptorId_t > & GetExtendedColumnRepresentations() const
std::unordered_set< ROOT::DescriptorId_t > fFieldIdsLookup
All field IDs of late model extensions for efficient lookup.
std::vector< ROOT::DescriptorId_t > fExtendedColumnRepresentations
All logical column IDs of columns that extend, with additional column representations,...
bool ContainsExtendedColumnRepresentation(ROOT::DescriptorId_t columnId) const
void MarkExtendedField(const RFieldDescriptor &fieldDesc)
Marks fieldDesc as an extended field, i.e.
std::vector< ROOT::DescriptorId_t > fFieldIdsOrder
All field IDs of late model extensions, in the order of field addition.
bool ContainsField(ROOT::DescriptorId_t fieldId) const
void MarkExtendedColumn(const RColumnDescriptor &columnDesc)
Marks columnDesc as an extended column, i.e.
The on-storage metadata of an RNTuple.
std::uint64_t GetGeneration() const
RNTupleDescriptor(RNTupleDescriptor &&other)=default
const RClusterGroupDescriptor & GetClusterGroupDescriptor(ROOT::DescriptorId_t clusterGroupId) const
const RColumnDescriptor & GetColumnDescriptor(ROOT::DescriptorId_t columnId) const
std::set< unsigned int > fFeatureFlags
std::unordered_map< ROOT::DescriptorId_t, RClusterGroupDescriptor > fClusterGroupDescriptors
const RFieldDescriptor & GetFieldDescriptor(ROOT::DescriptorId_t fieldId) const
RNTupleDescriptor & operator=(RNTupleDescriptor &&other)=default
std::vector< Experimental::RNTupleAttrSetDescriptor > fAttributeSets
List of AttributeSets linked to this RNTuple.
std::size_t GetNExtraTypeInfos() const
std::uint64_t GetOnDiskFooterSize() const
std::size_t GetNActiveClusters() const
const std::string & GetName() const
std::uint64_t fOnDiskFooterSize
Like fOnDiskHeaderSize, contains both cluster summaries and page locations.
ROOT::NTupleSize_t GetNEntries() const
We know the number of entries from adding the cluster summaries.
ROOT::DescriptorId_t GetFieldZeroId() const
Returns the logical parent of all top-level RNTuple data fields.
std::unordered_map< ROOT::DescriptorId_t, RClusterDescriptor > fClusterDescriptors
Potentially a subset of all the available clusters.
std::size_t GetNAttributeSets() const
std::size_t GetNClusters() const
std::size_t GetNPhysicalColumns() const
EFeatureFlags
All known feature flags.
const RHeaderExtension * GetHeaderExtension() const
Return header extension information; if the descriptor does not have a header extension,...
std::uint64_t GetVersion() const
std::uint64_t fOnDiskHeaderXxHash3
Set by the descriptor builder when deserialized.
const RClusterDescriptor & GetClusterDescriptor(ROOT::DescriptorId_t clusterId) const
std::string fName
The RNTuple name needs to be unique in a given storage location (file)
RNTupleDescriptor(const RNTupleDescriptor &other)=delete
std::uint64_t fOnDiskHeaderSize
Set by the descriptor builder when deserialized.
std::uint64_t GetOnDiskHeaderXxHash3() const
std::vector< ROOT::DescriptorId_t > fSortedClusterGroupIds
References cluster groups sorted by entry range and thus allows for binary search.
std::unordered_map< ROOT::DescriptorId_t, RColumnDescriptor > fColumnDescriptors
std::unordered_map< ROOT::DescriptorId_t, RFieldDescriptor > fFieldDescriptors
std::size_t GetNFields() const
bool HasFeature(unsigned int flag) const
std::uint64_t GetOnDiskHeaderSize() const
std::string fDescription
Free text from the user.
std::vector< RExtraTypeInfoDescriptor > fExtraTypeInfoDescriptors
std::size_t GetNLogicalColumns() const
RNTupleDescriptor & operator=(const RNTupleDescriptor &other)=delete
std::size_t GetNClusterGroups() const
RNTupleDescriptor CloneSchema() const
Creates a descriptor containing only the schema information about this RNTuple, i....
const std::string & GetDescription() const
std::unique_ptr< RHeaderExtension > fHeaderExtension
const RFieldDescriptor & GetFieldZero() const
Generic information about the physical location of data.
const Int_t n
Definition legend1.C:16
RNTupleDescriptor CloneDescriptorSchema(const RNTupleDescriptor &desc)
void FixupFieldTypeName(ROOT::RFieldDescriptor &fieldDesc)
bool IsCustomEnumFieldDesc(const RNTupleDescriptor &desc, const RFieldDescriptor &fieldDesc)
Tells if the field describes a user-defined enum type.
std::vector< ROOT::Internal::RNTupleClusterBoundaries > GetClusterBoundaries(const RNTupleDescriptor &desc)
Return the cluster boundaries for each cluster in this RNTuple.
bool IsStdAtomicFieldDesc(const RFieldDescriptor &fieldDesc)
Tells if the field describes a std::atomic<T> type.
EExtraTypeInfoIds
Used in RExtraTypeInfoDescriptor.
std::uint64_t DescriptorId_t
Distriniguishes elements of the same type within a descriptor, e.g. different fields.
constexpr NTupleSize_t kInvalidNTupleIndex
std::uint64_t NTupleSize_t
Integer type long enough to hold the maximum number of entries in a column.
constexpr DescriptorId_t kInvalidDescriptorId
ENTupleStructure
The fields in the RNTuple data model tree can carry different structural information about the type s...
Additional information about a page in an in-memory RPageRange.
RPageInfoExtended(const RPageInfo &pageInfo, ROOT::NTupleSize_t firstElementIndex, ROOT::NTupleSize_t pageNumber)
void SetFirstElementIndex(ROOT::NTupleSize_t firstInPage)
void SetPageNumber(ROOT::NTupleSize_t pageNumber)
Information about a single page in the context of a cluster's page range.
void SetLocator(const RNTupleLocator &locator)
bool operator==(const RPageInfo &other) const
const RNTupleLocator & GetLocator() const
RNTupleLocator fLocator
The meaning of fLocator depends on the storage backend.
RPageInfo(std::uint32_t nElements, const RNTupleLocator &locator, bool hasChecksum)
bool operator==(RValueRange other) const
RValueRange(std::pair< double, double > range)
bool operator!=(RValueRange other) const
static void output()