Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RNTupleDescriptor.hxx
Go to the documentation of this file.
1/// \file ROOT/RNTupleDescriptor.hxx
2/// \author Jakob Blomer <jblomer@cern.ch>
3/// \author Javier Lopez-Gomez <javier.lopez.gomez@cern.ch>
4/// \date 2018-07-19
5
6/*************************************************************************
7 * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. *
8 * All rights reserved. *
9 * *
10 * For the licensing terms see $ROOTSYS/LICENSE. *
11 * For the list of contributors see $ROOTSYS/README/CREDITS. *
12 *************************************************************************/
13
14#ifndef ROOT_RNTupleDescriptor
15#define ROOT_RNTupleDescriptor
16
18#include <ROOT/RError.hxx>
20#include <ROOT/RNTupleTypes.hxx>
21#include <ROOT/RNTupleUtils.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} // namespace Internal
70
71namespace Experimental {
72
73// clang-format off
74/**
75\class ROOT::Experimental::RNTupleAttrSetDescriptor
76\ingroup NTuple
77\brief Metadata stored for every Attribute Set linked to an RNTuple.
78*/
79// clang-format on
82
83 std::uint16_t fSchemaVersionMajor = 0;
84 std::uint16_t fSchemaVersionMinor = 0;
85 std::uint32_t fAnchorLength = 0; ///< uncompressed size of the linked anchor
86 // The locator of the AttributeSet anchor.
87 // In case of kTypeFile, it points to the beginning of the Anchor's payload.
88 // NOTE: Only kTypeFile is supported at the moment.
90 std::string fName;
91
92public:
98
99 bool operator==(const RNTupleAttrSetDescriptor &other) const;
100 bool operator!=(const RNTupleAttrSetDescriptor &other) const { return !(*this == other); }
101
102 const std::string &GetName() const { return fName; }
103 std::uint16_t GetSchemaVersionMajor() const { return fSchemaVersionMajor; }
104 std::uint16_t GetSchemaVersionMinor() const { return fSchemaVersionMinor; }
105 std::uint32_t GetAnchorLength() const { return fAnchorLength; }
107
109};
110
111class RNTupleAttrSetDescriptorIterable;
112
113} // namespace Experimental
114
115// clang-format off
116/**
117\class ROOT::RFieldDescriptor
118\ingroup NTuple
119\brief Metadata stored for every field of an RNTuple
120*/
121// clang-format on
125
126private:
127 static const std::string &GetEmptyString();
128
130 /// The version of the C++-type-to-column translation mechanics
131 std::uint32_t fFieldVersion = 0;
132 /// The version of the C++ type itself
133 std::uint32_t fTypeVersion = 0;
134 /// Optional string storage for a free-standing field descriptor. If possible, strings come from the surrounding
135 /// RNTupleDescriptor string pool and this member remains unset.
136 std::unique_ptr<Internal::RStringPool> fStringPool;
137 /// The leaf name, not including parent fields
138 const std::string *fFieldName = nullptr;
139 /// Free text set by the user
140 const std::string *fFieldDescription = nullptr;
141 /// The C++ type that was used when writing the field
142 const std::string *fTypeName = nullptr;
143 /// A typedef or using directive that resolved to the type name during field creation
144 const std::string *fTypeAlias = nullptr;
145 /// The number of elements per entry for fixed-size arrays
146 std::uint64_t fNRepetitions = 0;
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 ordered list of columns attached to this field: first by representation index then by column index.
155 std::vector<ROOT::DescriptorId_t> fLogicalColumnIds;
156 /// The number of columns in the column representations of the field. The column cardinality helps to navigate the
157 /// list of logical column ids. For example, the second column of the third column representation is
158 /// fLogicalColumnIds[2 * fColumnCardinality + 1]
159 std::uint32_t fColumnCardinality = 0;
160 /// The structural information carried by this field in the data model tree
162 /// For custom classes, we store the ROOT TClass reported checksum to facilitate the use of I/O rules that
163 /// identify types by their checksum
164 std::optional<std::uint32_t> fTypeChecksum;
165 /// Indicates if this is a collection that should be represented in memory by a SoA layout.
166 bool fIsSoACollection = false;
167
169
170public:
171 RFieldDescriptor() = default;
176
177 bool operator==(const RFieldDescriptor &other) const;
178 /// Get a copy of the descriptor
179 RFieldDescriptor Clone() const;
180
181 /// In general, we create a field simply from the C++ type name. For untyped fields, however, we potentially need
182 /// access to sub fields, which is provided by the RNTupleDescriptor argument.
183 std::unique_ptr<ROOT::RFieldBase>
184 CreateField(const RNTupleDescriptor &ntplDesc, const ROOT::RCreateFieldOptions &options = {}) const;
185
187 std::uint32_t GetFieldVersion() const { return fFieldVersion; }
188 std::uint32_t GetTypeVersion() const { return fTypeVersion; }
189 const std::string &GetFieldName() const { return fFieldName ? *fFieldName : GetEmptyString(); }
190 const std::string &GetFieldDescription() const { return fFieldDescription ? *fFieldDescription : GetEmptyString(); }
191 const std::string &GetTypeName() const { return fTypeName ? *fTypeName : GetEmptyString(); }
192 const std::string &GetTypeAlias() const { return fTypeAlias ? *fTypeAlias : GetEmptyString(); }
193 std::uint64_t GetNRepetitions() const { return fNRepetitions; }
197 const std::vector<ROOT::DescriptorId_t> &GetLinkIds() const { return fLinkIds; }
198 const std::vector<ROOT::DescriptorId_t> &GetLogicalColumnIds() const { return fLogicalColumnIds; }
199 std::uint32_t GetColumnCardinality() const { return fColumnCardinality; }
200 std::optional<std::uint32_t> GetTypeChecksum() const { return fTypeChecksum; }
202 bool IsSoACollection() const { return fIsSoACollection; }
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 /// Optional value range (used e.g. by quantized real fields)
240 std::unique_ptr<RValueRange> fValueRange;
241 /// A field can be serialized into several columns, which are numbered from zero to $n$
242 std::uint32_t fIndex = 0;
243 /// A field may use multiple column representations, which are numbered from zero to $m$.
244 /// Every representation has the same number of columns.
245 std::uint16_t fRepresentationIndex = 0;
246 /// The size in bits of elements of this column. Most columns have the size fixed by their type
247 /// but low-precision float columns have variable bit widths.
248 std::uint16_t fBitsOnStorage = 0;
249 /// The on-disk column type
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
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; }
272 bool IsDeferredColumn() const { return fFirstElementIndex != 0; }
274 std::optional<RValueRange> GetValueRange() const
275 {
276 if (fValueRange)
277 return *fValueRange;
278 return std::nullopt;
279 }
280};
281
282// clang-format off
283/**
284\class ROOT::RClusterDescriptor
285\ingroup NTuple
286\brief Metadata for RNTuple clusters
287
288The cluster descriptor is built in two phases. In a first phase, the descriptor has only an ID.
289In a second phase, the event range, column group, page locations and column ranges are added.
290Both phases are populated by the RClusterDescriptorBuilder.
291Clusters span across all available columns in the RNTuple.
292*/
293// clang-format on
296
297public:
298 // clang-format off
299 /**
300 \class ROOT::RClusterDescriptor::RColumnRange
301 \ingroup NTuple
302 \brief The window of element indexes of a particular column in a particular cluster
303 */
304 // clang-format on
307 /// The global index of the first column element in the cluster
309 /// The number of column elements in the cluster
311 /// The usual format for ROOT compression settings (see Compression.h).
312 /// The pages of a particular column in a particular cluster are all compressed with the same settings.
313 /// If unset, the compression settings are undefined (deferred columns, suppressed columns).
314 std::optional<std::uint32_t> fCompressionSettings;
315 /// Suppressed columns have an empty page range and unknown compression settings.
316 /// Their element index range, however, is aligned with the corresponding column of the
317 /// primary column representation (see Section "Suppressed Columns" in the specification)
318 bool fIsSuppressed = false;
319
320 // TODO(jblomer): we perhaps want to store summary information, such as average, min/max, etc.
321 // Should this be done on the field level?
322
323 public:
324 RColumnRange() = default;
325
336
339
343
347
348 std::optional<std::uint32_t> GetCompressionSettings() const { return fCompressionSettings; }
349 void SetCompressionSettings(std::optional<std::uint32_t> comp) { fCompressionSettings = comp; }
350
351 bool IsSuppressed() const { return fIsSuppressed; }
353
354 bool operator==(const RColumnRange &other) const
355 {
356 return fPhysicalColumnId == other.fPhysicalColumnId && fFirstElementIndex == other.fFirstElementIndex &&
357 fNElements == other.fNElements && fCompressionSettings == other.fCompressionSettings &&
358 fIsSuppressed == other.fIsSuppressed;
359 }
360
365 };
366
367 // clang-format off
368 /**
369 \class ROOT::RClusterDescriptor::RPageInfo
370 \ingroup NTuple
371 \brief Information about a single page in the context of a cluster's page range.
372 */
373 // clang-format on
374 // NOTE: We do not need to store the element size / uncompressed page size because we know to which column
375 // the page belongs
376 struct RPageInfo {
377 private:
378 /// The meaning of `fLocator` depends on the storage backend.
380 /// The sum of the elements of all the pages must match the corresponding `fNElements` field in `fColumnRanges`
381 std::uint32_t fNElements = std::uint32_t(-1);
382 /// If true, the 8 bytes following the serialized page are an xxhash of the on-disk page data
383 bool fHasChecksum = false;
384
385 public:
386 RPageInfo() = default;
391
392 bool operator==(const RPageInfo &other) const
393 {
394 return fLocator == other.fLocator && fNElements == other.fNElements;
395 }
396
397 const RNTupleLocator &GetLocator() const { return fLocator; }
400
401 std::uint32_t GetNElements() const { return fNElements; }
402 void SetNElements(std::uint32_t n) { fNElements = n; }
403
404 bool HasChecksum() const { return fHasChecksum; }
406 };
407
408 // clang-format off
409 /**
410 \class ROOT::RClusterDescriptor::RPageInfoExtended
411 \ingroup NTuple
412 \brief Additional information about a page in an in-memory RPageRange.
413
414 Used by RPageRange::Find() to return information relative to the RPageRange. This information is not stored on disk
415 and we don't need to keep it in memory because it can be easily recomputed.
416 */
417 // clang-format on
438
439 // clang-format off
440 /**
441 \class ROOT::RClusterDescriptor::RPageRange
442 \ingroup NTuple
443 \brief Records the partition of data into pages for a particular column in a particular cluster
444 */
445 // clang-format on
448
449 private:
450 /// \brief Extend this RPageRange to fit the given RColumnRange.
451 ///
452 /// To do so, prepend as many synthetic RPageInfos as needed to cover the range in `columnRange`.
453 /// RPageInfos are constructed to contain as many elements of type `element` given a page size
454 /// limit of `pageSize` (in bytes); the locator for the referenced pages is `kTypePageZero`.
455 /// This function is used to make up RPageRanges for clusters that contain deferred columns.
456 /// \return The number of column elements covered by the synthesized RPageInfos
459
460 std::vector<RPageInfo> fPageInfos;
461
462 /// Has the same length than fPageInfos and stores the sum of the number of elements of all the pages
463 /// up to and including a given index. Used for binary search in Find().
464 /// This vector is only created if fPageInfos has at least kLargeRangeThreshold elements.
465 std::unique_ptr<std::vector<ROOT::NTupleSize_t>> fCumulativeNElements;
466
468
469 public:
470 /// Create the fCumulativeNElements only when its needed, i.e. when there are many pages to search through.
471 static constexpr std::size_t kLargeRangeThreshold = 10;
472
473 RPageRange() = default;
474 RPageRange(const RPageRange &other) = delete;
478
480 {
481 RPageRange clone;
483 clone.fPageInfos = fPageInfos;
485 clone.fCumulativeNElements = std::make_unique<std::vector<ROOT::NTupleSize_t>>(*fCumulativeNElements);
486 }
487 return clone;
488 }
489
490 /// Find the page in the RPageRange that contains the given element. The element must exist.
492
495
496 const std::vector<RPageInfo> &GetPageInfos() const { return fPageInfos; }
497 std::vector<RPageInfo> &GetPageInfos() { return fPageInfos; }
498
499 bool operator==(const RPageRange &other) const
500 {
501 return fPhysicalColumnId == other.fPhysicalColumnId && fPageInfos == other.fPageInfos;
502 }
503 };
504
505private:
507 /// Clusters can be swapped by adjusting the entry offsets of the cluster and all ranges
510
511 std::unordered_map<ROOT::DescriptorId_t, RColumnRange> fColumnRanges;
512 std::unordered_map<ROOT::DescriptorId_t, RPageRange> fPageRanges;
513
514public:
516
522
524
525 bool operator==(const RClusterDescriptor &other) const;
526
532 /// Returns an iterator over pairs { columnId, columnRange }. The iteration order is unspecified.
533 RColumnRangeIterable GetColumnRangeIterable() const;
535 {
536 return fColumnRanges.find(physicalId) != fColumnRanges.end();
537 }
538 std::uint64_t GetNBytesOnStorage() const;
539};
540
542private:
544
545public:
547 private:
548 using Iter_t = std::unordered_map<ROOT::DescriptorId_t, RColumnRange>::const_iterator;
549 /// The wrapped map iterator
551
552 public:
553 using iterator_category = std::forward_iterator_tag;
556 using difference_type = std::ptrdiff_t;
557 using pointer = const RColumnRange *;
558 using reference = const RColumnRange &;
559
560 RIterator() = default;
561 explicit RIterator(Iter_t iter) : fIter(iter) {}
562 iterator &operator++() /* prefix */
563 {
564 ++fIter;
565 return *this;
566 }
567 iterator operator++(int) /* postfix */
568 {
569 auto old = *this;
570 operator++();
571 return old;
572 }
573 reference operator*() const { return fIter->second; }
574 pointer operator->() const { return &fIter->second; }
575 bool operator!=(const iterator &rh) const { return fIter != rh.fIter; }
576 bool operator==(const iterator &rh) const { return fIter == rh.fIter; }
577 };
578
580
581 RIterator begin() { return RIterator{fDesc.fColumnRanges.cbegin()}; }
582 RIterator end() { return RIterator{fDesc.fColumnRanges.cend()}; }
583 size_t size() { return fDesc.fColumnRanges.size(); }
584};
585
586// clang-format off
587/**
588\class ROOT::RClusterGroupDescriptor
589\ingroup NTuple
590\brief Clusters are bundled in cluster groups.
591
592Very large RNTuples can contain multiple cluster groups to organize cluster metadata.
593Every RNTuple has at least one cluster group. The clusters in a cluster group are ordered
594corresponding to their first entry number.
595*/
596// clang-format on
599
600private:
602 /// The cluster IDs can be empty if the corresponding page list is not loaded.
603 /// Otherwise, cluster ids are sorted by first entry number.
604 std::vector<ROOT::DescriptorId_t> fClusterIds;
605 /// The page list that corresponds to the cluster group
607 /// Uncompressed size of the page list
608 std::uint64_t fPageListLength = 0;
609 /// The minimum first entry number of the clusters in the cluster group
610 std::uint64_t fMinEntry = 0;
611 /// Number of entries that are (partially for sharded clusters) covered by this cluster group.
612 std::uint64_t fEntrySpan = 0;
613 /// Number of clusters is always known even if the cluster IDs are not (yet) populated
614 std::uint32_t fNClusters = 0;
615
616public:
622
624 /// Creates a clone without the cluster IDs
626
627 bool operator==(const RClusterGroupDescriptor &other) const;
628
630 std::uint32_t GetNClusters() const { return fNClusters; }
632 std::uint64_t GetPageListLength() const { return fPageListLength; }
633 const std::vector<ROOT::DescriptorId_t> &GetClusterIds() const { return fClusterIds; }
634 std::uint64_t GetMinEntry() const { return fMinEntry; }
635 std::uint64_t GetEntrySpan() const { return fEntrySpan; }
636 /// A cluster group is loaded in two stages. Stage one loads only the summary information.
637 /// Stage two loads the list of cluster IDs.
638 bool HasClusterDetails() const { return !fClusterIds.empty(); }
639};
640
641/// Used in RExtraTypeInfoDescriptor
643 kInvalid,
645};
646
647// clang-format off
648/**
649\class ROOT::RExtraTypeInfoDescriptor
650\ingroup NTuple
651\brief Field specific extra type information from the header / extenstion header
652
653Currently only used by streamer fields to store RNTuple-wide list of streamer info records.
654*/
655// clang-format on
658
659private:
660 /// Specifies the meaning of the extra information
662 /// Type version the extra type information is bound to
663 std::uint32_t fTypeVersion = 0;
664 /// The type name the extra information refers to; empty for RNTuple-wide extra information
665 std::string fTypeName;
666 /// The content format depends on the content ID and may be binary
667 std::string fContent;
668
669public:
675
676 bool operator==(const RExtraTypeInfoDescriptor &other) const;
677
679
681 std::uint32_t GetTypeVersion() const { return fTypeVersion; }
682 const std::string &GetTypeName() const { return fTypeName; }
683 const std::string &GetContent() const { return fContent; }
684};
685
686// clang-format off
687/**
688\class ROOT::RNTupleDescriptor
689\ingroup NTuple
690\brief The on-storage metadata of an RNTuple
691
692Represents the on-disk (on storage) information about an RNTuple. The metadata consists of a header, a footer, and
693potentially multiple page lists.
694The header carries the RNTuple schema, i.e. the fields and the associated columns and their relationships.
695The footer carries information about one or several cluster groups and links to their page lists.
696For every cluster group, a page list envelope stores cluster summaries and page locations.
697For every cluster, it stores for every column the range of element indexes as well as a list of pages and page
698locations.
699
700The descriptor provides machine-independent (de-)serialization of headers and footers, and it provides lookup routines
701for RNTuple objects (pages, clusters, ...). It is supposed to be usable by all RPageStorage implementations.
702
703The serialization does not use standard ROOT streamers in order to not let it depend on libCore. The serialization uses
704the concept of envelopes and frames: header, footer, and page list envelopes have a preamble with a type ID and length.
705Substructures are serialized in frames and have a size and number of items (for list frames). This allows for forward
706and backward compatibility when the metadata evolves.
707*/
708// clang-format on
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
723
724 std::uint64_t fNPhysicalColumns = 0; ///< Updated by the descriptor builder when columns are added
725
726 /// Storage for all the field strings. Shared among descriptor clones.
727 std::shared_ptr<Internal::RStringPool> fStringPool;
728
729 std::set<unsigned int> fFeatureFlags; // needs to be ordered
730 std::unordered_map<ROOT::DescriptorId_t, RFieldDescriptor> fFieldDescriptors;
731 std::unordered_map<ROOT::DescriptorId_t, RColumnDescriptor> fColumnDescriptors;
732
733 std::vector<RExtraTypeInfoDescriptor> fExtraTypeInfoDescriptors;
734 std::unique_ptr<RHeaderExtension> fHeaderExtension;
735
736 //// All fields above are part of the schema and are cloned when creating a new descriptor from a given one
737 //// (see CloneSchema())
738
739 std::uint16_t fVersionEpoch = 0; ///< Set by the descriptor builder when deserialized
740 std::uint16_t fVersionMajor = 0; ///< Set by the descriptor builder when deserialized
741 std::uint16_t fVersionMinor = 0; ///< Set by the descriptor builder when deserialized
742 std::uint16_t fVersionPatch = 0; ///< Set by the descriptor builder when deserialized
743
744 std::uint64_t fOnDiskHeaderSize = 0; ///< Set by the descriptor builder when deserialized
745 std::uint64_t fOnDiskHeaderXxHash3 = 0; ///< Set by the descriptor builder when deserialized
746 std::uint64_t fOnDiskFooterSize = 0; ///< Like fOnDiskHeaderSize, contains both cluster summaries and page locations
747
748 std::uint64_t fNEntries = 0; ///< Updated by the descriptor builder when the cluster groups are added
749 std::uint64_t fNClusters = 0; ///< Updated by the descriptor builder when the cluster groups are added
750
751 /// \brief The generation of the descriptor
752 ///
753 /// Once constructed by an RNTupleDescriptorBuilder, the descriptor is mostly immutable except for the set of
754 /// active page locations. During the lifetime of the descriptor, page location information for clusters
755 /// can be added or removed. When this happens, the generation should be increased, so that users of the
756 /// descriptor know that the information changed. The generation is increased, e.g., by the page source's
757 /// exclusive lock guard around the descriptor. It is used, e.g., by the descriptor cache in RNTupleReader.
758 std::uint64_t fGeneration = 0;
759
760 std::unordered_map<ROOT::DescriptorId_t, RClusterGroupDescriptor> fClusterGroupDescriptors;
761 /// References cluster groups sorted by entry range and thus allows for binary search.
762 /// Note that this list is empty during the descriptor building process and will only be
763 /// created when the final descriptor is extracted from the builder.
764 std::vector<ROOT::DescriptorId_t> fSortedClusterGroupIds;
765 /// Potentially a subset of all the available clusters
766 std::unordered_map<ROOT::DescriptorId_t, RClusterDescriptor> fClusterDescriptors;
767 /// List of AttributeSets linked to this RNTuple
768 std::vector<Experimental::RNTupleAttrSetDescriptor> fAttributeSets;
769
770 // We don't expose this publicly because when we add sharded clusters, this interface does not make sense anymore
772
773 /// Creates a descriptor containing only the schema information about this RNTuple, i.e. all the information needed
774 /// to create a new RNTuple with the same schema as this one but not necessarily the same clustering. This is used
775 /// when merging two RNTuples.
777
778 /// ROOT v6.34, with spec versions before 1.0.0.1, did not properly renormalize the type name.
779 /// This function returns true if this descriptor has a version prior to 1.0.0.1 and may therefore contain such
780 /// fields. This is only valid to call after SetVersion() or SetVersionForWriting() has been called on this
781 /// descriptor.
782 bool FieldTypeNamesMayNeedFixup() const;
783
784public:
785 /// All known feature flags.
786 /// Note that the flag values represent the bit _index_, not the already-bitshifted integer.
788 /// Signals that the RNTuple contains at least one deferred column that is part of a collection and was extended
789 /// (i.e. it appears in the footer). This can happen when merging two RNTuples that have the same collection field
790 /// backed by columns with different encoding, e.g. a vector<float> whose elements are represented by SplitReal32
791 /// in the first ntuple and by Real32 in the second.
792 /// Added in version 1.1.0.0 of the binary format.
794 // Insert new feature flags here, with contiguous values. If at any point a "hole" appears in the valid feature
795 // flags values, the check in RNTupleSerialize must be updated.
796
797 // End of regular feature flags
799
800 /// Reserved for forward-compatibility testing
802 };
803
804 class RColumnDescriptorIterable;
805 class RFieldDescriptorIterable;
806 class RClusterGroupDescriptorIterable;
807 class RClusterDescriptorIterable;
808 class RExtraTypeInfoDescriptorIterable;
810
811 /// Modifiers passed to CreateModel()
813 private:
814 /// If set to true, projected fields will be reconstructed as such. This will prevent the model to be used
815 /// with an RNTupleReader, but it is useful, e.g., to accurately merge data.
817 /// By default, creating a model will fail if any of the reconstructed fields contains an unknown column type
818 /// or an unknown field structural role.
819 /// If this option is enabled, the model will be created and all fields containing unknown data (directly
820 /// or indirectly) will be skipped instead.
821 bool fForwardCompatible = false;
822 /// If true, the model will be created without a default entry (bare model).
823 bool fCreateBare = false;
824 /// If true, fields with a user defined type that have no available dictionaries will be reconstructed
825 /// as record fields from the on-disk information; otherwise, they will cause an error.
827
828 public:
829 RCreateModelOptions() {} // Work around compiler bug, see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88165
830
833
836
837 void SetCreateBare(bool v) { fCreateBare = v; }
838 bool GetCreateBare() const { return fCreateBare; }
839
842 };
843
849
850 RNTupleDescriptor Clone() const;
851
852 bool operator==(const RNTupleDescriptor &other) const;
853
854 std::uint64_t GetOnDiskHeaderXxHash3() const { return fOnDiskHeaderXxHash3; }
855 std::uint64_t GetOnDiskHeaderSize() const { return fOnDiskHeaderSize; }
856 std::uint64_t GetOnDiskFooterSize() const { return fOnDiskFooterSize; }
857 /// \see ROOT::RNTuple::GetCurrentVersion()
858 std::uint64_t GetVersion() const
859 {
860 return (static_cast<std::uint64_t>(fVersionEpoch) << 48) | (static_cast<std::uint64_t>(fVersionMajor) << 32) |
861 (static_cast<std::uint64_t>(fVersionMinor) << 16) | (static_cast<std::uint64_t>(fVersionPatch));
862 }
863
880
881 RFieldDescriptorIterable GetFieldIterable(const RFieldDescriptor &fieldDesc) const;
882 RFieldDescriptorIterable
884 const std::function<bool(ROOT::DescriptorId_t, ROOT::DescriptorId_t)> &comparator) const;
885 RFieldDescriptorIterable GetFieldIterable(ROOT::DescriptorId_t fieldId) const;
886 RFieldDescriptorIterable
888 const std::function<bool(ROOT::DescriptorId_t, ROOT::DescriptorId_t)> &comparator) const;
889
890 RFieldDescriptorIterable GetTopLevelFields() const;
891 RFieldDescriptorIterable
892 GetTopLevelFields(const std::function<bool(ROOT::DescriptorId_t, ROOT::DescriptorId_t)> &comparator) const;
893
894 RColumnDescriptorIterable GetColumnIterable() const;
895 RColumnDescriptorIterable GetColumnIterable(const RFieldDescriptor &fieldDesc) const;
896 RColumnDescriptorIterable GetColumnIterable(ROOT::DescriptorId_t fieldId) const;
897
898 RClusterGroupDescriptorIterable GetClusterGroupIterable() const;
899
900 RClusterDescriptorIterable
902 "This function is unsafe to use because, in general, not all cluster "
903 "metadata are available (there may be cluster groups with unloaded cluster group details). Use the "
904 "'GetActiveClusterIterable()' method instead if you are aware of this limitation.")
907
909
911
912 const std::string &GetName() const { return fName; }
913 const std::string &GetDescription() const { return fDescription; }
914
915 std::size_t GetNFields() const { return fFieldDescriptors.size(); }
916 std::size_t GetNLogicalColumns() const { return fColumnDescriptors.size(); }
917 std::size_t GetNPhysicalColumns() const { return fNPhysicalColumns; }
918 std::size_t GetNClusterGroups() const { return fClusterGroupDescriptors.size(); }
919 std::size_t GetNClusters() const { return fNClusters; }
920 std::size_t GetNActiveClusters() const { return fClusterDescriptors.size(); }
921 std::size_t GetNExtraTypeInfos() const { return fExtraTypeInfoDescriptors.size(); }
922 std::size_t GetNAttributeSets() const { return fAttributeSets.size(); }
923
924 /// We know the number of entries from adding the cluster summaries
927 R__DEPRECATED(6, 46,
928 "This function is ill-conceived in the descriptor "
929 "as not all cluster descriptors may be present. This interface is no longer publicly exposed.")
931
932 /// Returns the logical parent of all top-level RNTuple data fields.
936 /// Searches for a top-level field
937 ROOT::DescriptorId_t FindFieldId(std::string_view fieldName) const;
939 std::uint16_t representationIndex) const;
941 std::uint16_t representationIndex) const;
943 R__DEPRECATED(6, 46,
944 "This function is ill-defined in the descriptor "
945 "as not all cluster descriptors may be present. This interface is no longer exposed.")
948 R__DEPRECATED(6, 46,
949 "This function is ill-defined in the descriptor "
951 FindNextClusterId(ROOT::DescriptorId_t clusterId) const;
953 R__DEPRECATED(6, 46,
954 "This function is ill-defined in the descriptor "
957
958 /// Walks up the parents of the field ID and returns a field name of the form a.b.c.d
959 /// In case of invalid field ID, an empty string is returned.
961
962 /// Adjust the type name of the passed RFieldDescriptor for comparison with another renormalized type name.
964
965 bool HasFeature(unsigned int flag) const { return fFeatureFlags.count(flag) > 0; }
966 std::vector<std::uint64_t> GetFeatureFlags() const;
967
968 /// Return header extension information; if the descriptor does not have a header extension, return `nullptr`
969 const RHeaderExtension *GetHeaderExtension() const { return fHeaderExtension.get(); }
970
971 /// Methods to load and drop cluster group details (cluster IDs and page locations)
975
976 std::uint64_t GetGeneration() const { return fGeneration; }
978
979 /// Re-create the C++ model from the stored metadata
980 std::unique_ptr<ROOT::RNTupleModel> CreateModel(const RCreateModelOptions &options = RCreateModelOptions()) const;
981 void PrintInfo(std::ostream &output) const;
982};
983
984// clang-format off
985/**
986\class ROOT::RNTupleDescriptor::RColumnDescriptorIterable
987\ingroup NTuple
988\brief Used to loop over a field's associated columns
989*/
990// clang-format on
992private:
993 /// The associated RNTuple for this range.
995 /// The descriptor ids of the columns ordered by field, representation, and column index
996 std::vector<ROOT::DescriptorId_t> fColumns = {};
997
998public:
1000 private:
1001 /// The enclosing RColumnDescriptorIterable.
1003 std::size_t fIndex;
1004
1005 public:
1006 using iterator_category = std::forward_iterator_tag;
1009 using difference_type = std::ptrdiff_t;
1012
1013 explicit RIterator(const RColumnDescriptorIterable *iterable = nullptr, std::size_t index = 0)
1015 {
1016 }
1017 iterator &operator++() /* prefix */
1018 {
1019 ++fIndex;
1020 return *this;
1021 }
1022 iterator operator++(int) /* postfix */
1023 {
1024 auto old = *this;
1025 operator++();
1026 return old;
1027 }
1029 {
1030 if (fIterable)
1031 return fIterable->fNTuple.GetColumnDescriptor(fIterable->fColumns.at(fIndex));
1032 throw RException(R__FAIL("dereference of RNTupleDescriptor::RColumnDescriptorIterable::RIterator"
1033 " constructed without RNTupleDescriptor::RColumnDescriptorIterable"));
1034 }
1036 {
1037 return fIterable ? &fIterable->fNTuple.GetColumnDescriptor(fIterable->fColumns.at(fIndex)) : nullptr;
1038 }
1039 bool operator!=(const iterator &rh) const { return fIndex != rh.fIndex || fIterable != rh.fIterable; }
1040 bool operator==(const iterator &rh) const { return fIndex == rh.fIndex && fIterable == rh.fIterable; }
1041 };
1042
1045
1046 RIterator begin() { return RIterator(this, 0); }
1047 RIterator end() { return RIterator(this, fColumns.size()); }
1048 size_t size() { return fColumns.size(); }
1049};
1050
1051// clang-format off
1052/**
1053\class ROOT::RNTupleDescriptor::RFieldDescriptorIterable
1054\ingroup NTuple
1055\brief Used to loop over a field's child fields
1056*/
1057// clang-format on
1059private:
1060 /// The associated RNTuple for this range.
1062 /// The descriptor IDs of the child fields. These may be sorted using
1063 /// a comparison function.
1064 std::vector<ROOT::DescriptorId_t> fFieldChildren = {};
1065
1066public:
1068 private:
1069 /// The enclosing RFieldDescriptorIterable.
1071 std::size_t fIndex;
1072
1073 public:
1074 using iterator_category = std::forward_iterator_tag;
1077 using difference_type = std::ptrdiff_t;
1078 using pointer = const RFieldDescriptor *;
1080
1081 explicit RIterator(const RFieldDescriptorIterable *iterable = nullptr, std::size_t index = 0)
1083 {
1084 }
1085 iterator &operator++() /* prefix */
1086 {
1087 ++fIndex;
1088 return *this;
1089 }
1090 iterator operator++(int) /* postfix */
1091 {
1092 auto old = *this;
1093 operator++();
1094 return old;
1095 }
1097 {
1098 if (fIterable)
1099 return fIterable->fNTuple.GetFieldDescriptor(fIterable->fFieldChildren.at(fIndex));
1100 throw RException(R__FAIL("dereference of RNTupleDescriptor::RFieldDescriptorIterable::RIterator"
1101 " constructed without RNTupleDescriptor::RFieldDescriptorIterable"));
1102 }
1104 {
1105 return fIterable ? &fIterable->fNTuple.GetFieldDescriptor(fIterable->fFieldChildren.at(fIndex)) : nullptr;
1106 }
1107 bool operator!=(const iterator &rh) const { return fIndex != rh.fIndex || fIterable != rh.fIterable; }
1108 bool operator==(const iterator &rh) const { return fIndex == rh.fIndex && fIterable == rh.fIterable; }
1109 };
1114 /// Sort the range using an arbitrary comparison function.
1116 const std::function<bool(ROOT::DescriptorId_t, ROOT::DescriptorId_t)> &comparator)
1117 : fNTuple(ntuple), fFieldChildren(field.GetLinkIds())
1118 {
1119 std::sort(fFieldChildren.begin(), fFieldChildren.end(), comparator);
1120 }
1121 RIterator begin() { return RIterator(this, 0); }
1122 RIterator end() { return RIterator(this, fFieldChildren.size()); }
1123};
1124
1125// clang-format off
1126/**
1127\class ROOT::RNTupleDescriptor::RClusterGroupDescriptorIterable
1128\ingroup NTuple
1129\brief Used to loop over all the cluster groups of an RNTuple in order of entry ranges
1130
1131Enumerate all cluster group IDs from the descriptor. No specific order can be assumed.
1132*/
1133// clang-format on
1135private:
1136 /// The associated RNTuple for this range.
1138
1139public:
1142
1143 private:
1144 const RNTupleDescriptor *fNTuple = nullptr;
1145 const std::vector<ROOT::DescriptorId_t> *fSortedClusterGroupIds = nullptr;
1146 std::size_t fIdx = 0;
1147
1148 RIterator(const RNTupleDescriptor *ntuple, const std::vector<ROOT::DescriptorId_t> *sortedClusterGroupIds,
1149 std::size_t idx)
1151 {
1152 }
1153
1154 public:
1155 using iterator_category = std::forward_iterator_tag;
1158 using difference_type = std::ptrdiff_t;
1161
1162 RIterator() = default;
1163 iterator &operator++() /* prefix */
1164 {
1165 ++fIdx;
1166 return *this;
1167 }
1168 iterator operator++(int) /* postfix */
1169 {
1170 auto old = *this;
1171 fIdx++;
1172 return old;
1173 }
1174 iterator &operator+=(std::size_t n)
1175 {
1176 fIdx += n;
1177 return *this;
1178 }
1179 iterator operator+(std::size_t n) const { return RIterator(fNTuple, fSortedClusterGroupIds, fIdx + n); }
1180 reference operator*() const { return fNTuple->GetClusterGroupDescriptor((*fSortedClusterGroupIds)[fIdx]); }
1181 pointer operator->() const { return &fNTuple->GetClusterGroupDescriptor((*fSortedClusterGroupIds)[fIdx]); }
1182 bool operator==(const iterator &rh) const { return (fNTuple == rh.fNTuple) && (fIdx == rh.fIdx); }
1183 bool operator!=(const iterator &rh) const { return !(*this == rh); }
1184 };
1185
1187 RIterator begin() { return RIterator(&fNTuple, &fNTuple.fSortedClusterGroupIds, 0); }
1189 {
1190 return RIterator(&fNTuple, &fNTuple.fSortedClusterGroupIds, fNTuple.fSortedClusterGroupIds.size());
1191 }
1192 std::size_t size() const { return fNTuple.fSortedClusterGroupIds.size(); }
1193 bool empty() const { return fNTuple.fSortedClusterGroupIds.empty(); }
1194};
1195
1196// clang-format off
1197/**
1198\class ROOT::RNTupleDescriptor::RClusterDescriptorIterable
1199\ingroup NTuple
1200\brief Loop over all the clusters of an RNTuple, ordered by first entry number
1201
1202Enumerate all the active cluster IDs from all cluster groups. Iteration is ordered by first entry number.
1203Note that cluster groups without available cluster details (page lists) are silently skipped.
1204*/
1205// clang-format on
1207private:
1208 /// The associated RNTuple for this range.
1210
1211public:
1213 private:
1215 using ClusterInGroupContainer_t = std::vector<DescriptorId_t>;
1216 using ClusterInGroupIter_t = ClusterInGroupContainer_t::const_iterator;
1217
1218 const RNTupleDescriptor *fNTuple = nullptr;
1221 std::size_t fClusterInGroupNum = 0; // index into RClusterGroupDescriptor::GetClusterIds()
1222
1223 public:
1224 using iterator_category = std::forward_iterator_tag;
1227 using difference_type = std::ptrdiff_t;
1230
1231 RIterator() = default;
1238 iterator &operator++() /* prefix */
1239 {
1241 while ((fClusterGroupIter != fClusterGroupEnd) &&
1242 (fClusterInGroupNum >= fClusterGroupIter->GetClusterIds().size())) {
1245 }
1246 return *this;
1247 }
1249 {
1250 return fNTuple->GetClusterDescriptor(fClusterGroupIter->GetClusterIds()[fClusterInGroupNum]);
1251 }
1253 {
1254 return &fNTuple->GetClusterDescriptor(fClusterGroupIter->GetClusterIds()[fClusterInGroupNum]);
1255 }
1256 bool operator==(const iterator &rh) const
1257 {
1258 return (fClusterGroupIter == rh.fClusterGroupIter) && (fClusterInGroupNum == rh.fClusterInGroupNum);
1259 }
1260 bool operator!=(const iterator &rh) const { return !(*this == rh); }
1261 };
1262
1265 RIterator end() { return RIterator(fNTuple, fNTuple.GetNClusterGroups()); }
1266};
1267
1268// clang-format off
1269/**
1270\class ROOT::RNTupleDescriptor::RExtraTypeInfoDescriptorIterable
1271\ingroup NTuple
1272\brief Used to loop over all the extra type info record of an RNTuple (in unspecified order)
1273*/
1274// clang-format on
1276private:
1277 /// The associated RNTuple for this range.
1279
1280public:
1282 private:
1283 using Iter_t = std::vector<RExtraTypeInfoDescriptor>::const_iterator;
1284 /// The wrapped vector iterator
1286
1287 public:
1288 using iterator_category = std::forward_iterator_tag;
1291 using difference_type = std::ptrdiff_t;
1294
1295 RIterator() = default;
1296 explicit RIterator(Iter_t iter) : fIter(iter) {}
1297 iterator &operator++() /* prefix */
1298 {
1299 ++fIter;
1300 return *this;
1301 }
1302 iterator operator++(int) /* postfix */
1303 {
1304 auto old = *this;
1305 operator++();
1306 return old;
1307 }
1308 reference operator*() const { return *fIter; }
1309 pointer operator->() const { return fIter.operator->(); }
1310 bool operator!=(const iterator &rh) const { return fIter != rh.fIter; }
1311 bool operator==(const iterator &rh) const { return fIter == rh.fIter; }
1312 };
1313
1315 RIterator begin() { return RIterator(fNTuple.fExtraTypeInfoDescriptors.cbegin()); }
1316 RIterator end() { return RIterator(fNTuple.fExtraTypeInfoDescriptors.cend()); }
1317};
1318
1319namespace Experimental {
1320// clang-format off
1321/**
1322\class ROOT::Experimental::RNTupleAttrSetDescriptorIterable
1323\ingroup NTuple
1324\brief Used to loop over all the Attribute Sets linked to an RNTuple
1325*/
1326// clang-format on
1327// TODO: move this to RNTupleDescriptor::RNTupleAttrSetDescriptorIterable when it moves out of Experimental.
1329private:
1330 /// The associated RNTuple for this range.
1332
1333public:
1335 private:
1336 using Iter_t = std::vector<RNTupleAttrSetDescriptor>::const_iterator;
1337 /// The wrapped vector iterator
1339
1340 public:
1341 using iterator_category = std::forward_iterator_tag;
1344 using difference_type = std::ptrdiff_t;
1345 using pointer = const value_type *;
1346 using reference = const value_type &;
1347
1348 RIterator() = default;
1349 explicit RIterator(Iter_t iter) : fIter(iter) {}
1350 iterator &operator++() /* prefix */
1351 {
1352 ++fIter;
1353 return *this;
1354 }
1355 iterator operator++(int) /* postfix */
1356 {
1357 auto old = *this;
1358 operator++();
1359 return old;
1360 }
1361 reference operator*() const { return *fIter; }
1362 pointer operator->() const { return fIter.operator->(); }
1363 bool operator!=(const iterator &rh) const { return fIter != rh.fIter; }
1364 bool operator==(const iterator &rh) const { return fIter == rh.fIter; }
1365 };
1366
1368 RIterator begin() { return RIterator(fNTuple.fAttributeSets.cbegin()); }
1369 RIterator end() { return RIterator(fNTuple.fAttributeSets.cend()); }
1370};
1371} // namespace Experimental
1372
1373// clang-format off
1374/**
1375\class ROOT::RNTupleDescriptor::RHeaderExtension
1376\ingroup NTuple
1377\brief Summarizes information about fields and the corresponding columns that were added after the header has been serialized
1378*/
1379// clang-format on
1382
1383private:
1384 /// All field IDs of late model extensions, in the order of field addition. This is necessary to serialize the
1385 /// the fields in that order.
1386 std::vector<ROOT::DescriptorId_t> fFieldIdsOrder;
1387 /// All field IDs of late model extensions for efficient lookup. When a column gets added to the extension
1388 /// header, this enables us to determine if the column belongs to a field of the header extension of if it
1389 /// belongs to a field of the regular header that gets extended by additional column representations.
1390 std::unordered_set<ROOT::DescriptorId_t> fFieldIdsLookup;
1391 /// All logical column IDs of columns that extend, with additional column representations, fields of the regular
1392 /// header. During serialization, these columns are not picked up as columns of `fFieldIdsOrder`. But instead
1393 /// these columns need to be serialized in the extension header without re-serializing the field.
1394 std::vector<ROOT::DescriptorId_t> fExtendedColumnRepresentations;
1395 /// Number of logical and physical columns; updated by the descriptor builder when columns are added
1396 std::uint32_t fNLogicalColumns = 0;
1397 std::uint32_t fNPhysicalColumns = 0;
1398
1399 /// Marks `fieldDesc` as an extended field, i.e. a field that appears in the Header Extension (e.g. having been added
1400 /// through late model extension). Note that the field descriptor should also have been added to the RNTuple
1401 /// Descriptor alongside non-extended fields.
1403 {
1404 fFieldIdsOrder.emplace_back(fieldDesc.GetId());
1405 fFieldIdsLookup.insert(fieldDesc.GetId());
1406 }
1407
1408 /// Marks `columnDesc` as an extended column, i.e. a column that appears in the Header Extension (e.g. having been
1409 /// added through late model extension as an additional representation of an existing column). Note that the column
1410 /// descriptor should also have been added to the RNTuple Descriptor alongside non-extended columns.
1412 {
1414 if (!columnDesc.IsAliasColumn())
1416 if (fFieldIdsLookup.count(columnDesc.GetFieldId()) == 0) {
1417 fExtendedColumnRepresentations.emplace_back(columnDesc.GetLogicalId());
1418 }
1419 }
1420
1421public:
1422 std::size_t GetNFields() const { return fFieldIdsOrder.size(); }
1423 std::size_t GetNLogicalColumns() const { return fNLogicalColumns; }
1424 std::size_t GetNPhysicalColumns() const { return fNPhysicalColumns; }
1425 const std::vector<ROOT::DescriptorId_t> &GetExtendedColumnRepresentations() const
1426 {
1428 }
1429 /// Return a vector containing the IDs of the top-level fields defined in the extension header, in the order
1430 /// of their addition. Note that these fields are not necessarily top-level fields in the overall schema.
1431 /// If a nested field is extended, it will return the top-most field of the extended subtree.
1432 /// We cannot create this vector when building the fFields because at the time when AddExtendedField is called,
1433 /// the field is not yet linked into the schema tree.
1434 std::vector<ROOT::DescriptorId_t> GetTopMostFields(const RNTupleDescriptor &desc) const;
1435
1437 {
1438 return fFieldIdsLookup.find(fieldId) != fFieldIdsLookup.end();
1439 }
1445};
1446
1447namespace Experimental::Internal {
1450
1451public:
1453 {
1454 fDesc.fName = name;
1455 return *this;
1456 }
1458 {
1461 return *this;
1462 }
1469 {
1471 return *this;
1472 }
1473
1474 /// Attempt to make an AttributeSet descriptor. This may fail if the builder
1475 /// was not given enough information to make a proper descriptor.
1477};
1478} // namespace Experimental::Internal
1479
1480namespace Internal {
1481
1482// clang-format off
1483/**
1484\class ROOT::Internal::RColumnDescriptorBuilder
1485\ingroup NTuple
1486\brief A helper class for piece-wise construction of an RColumnDescriptor
1487
1488Dangling column descriptors can become actual descriptors when added to an
1489RNTupleDescriptorBuilder instance and then linked to their fields.
1490*/
1491// clang-format on
1493private:
1495
1496public:
1497 /// Make an empty column descriptor builder.
1499
1511 {
1513 return *this;
1514 }
1516 {
1517 fColumn.fType = type;
1518 return *this;
1519 }
1526 {
1528 return *this;
1529 }
1547 RColumnDescriptorBuilder &ValueRange(double min, double max)
1548 {
1549 fColumn.fValueRange = std::make_unique<RColumnDescriptor::RValueRange>(min, max);
1550 return *this;
1551 }
1552 RColumnDescriptorBuilder &ValueRange(std::optional<RColumnDescriptor::RValueRange> valueRange)
1553 {
1554 if (valueRange)
1555 fColumn.fValueRange = std::make_unique<RColumnDescriptor::RValueRange>(*valueRange);
1556 return *this;
1557 }
1560 /// Attempt to make a column descriptor. This may fail if the column
1561 /// was not given enough information to make a proper descriptor.
1563};
1564
1565// clang-format off
1566/**
1567\class ROOT::Internal::RFieldDescriptorBuilder
1568\ingroup NTuple
1569\brief A helper class for piece-wise construction of an RFieldDescriptor
1570
1571Dangling field descriptors describe a single field in isolation. They are
1572missing the necessary relationship information (parent field, any child fields)
1573required to describe a real RNTuple field.
1574
1575Dangling field descriptors can only become actual descriptors when added to an
1576RNTupleDescriptorBuilder instance and then linked to other fields.
1577*/
1578// clang-format on
1580private:
1583
1584public:
1586 {
1587 fField.fStringPool = std::make_unique<RStringPool>();
1589 }
1590
1591 // The passed string pool needs to live at least as long as the field descriptor to be moved out of this builder
1593
1594 // Takes an existing field descriptor to patch it up. The given string pool must be the one that is already
1595 // being used by the source descriptor.
1600
1601 // Makes a copy of the given descriptor and assigns the clone's strings to the new string pool
1603
1610 {
1612 return *this;
1613 }
1615 {
1617 return *this;
1618 }
1620 {
1622 return *this;
1623 }
1630 {
1632 return *this;
1633 }
1639 RFieldDescriptorBuilder &TypeName(const std::string &typeName)
1640 {
1641 fField.fTypeName = fStringPool->Intern(typeName);
1642 return *this;
1643 }
1645 {
1647 return *this;
1648 }
1650 {
1652 return *this;
1653 }
1655 {
1656 fField.fStructure = structure;
1657 return *this;
1658 }
1659 RFieldDescriptorBuilder &TypeChecksum(const std::optional<std::uint32_t> typeChecksum)
1660 {
1662 return *this;
1663 }
1665 {
1667 return *this;
1668 }
1670 /// Attempt to make a field descriptor. This may fail if the dangling field
1671 /// was not given enough information to make a proper descriptor.
1673};
1674
1675// clang-format off
1676/**
1677\class ROOT::Internal::RClusterDescriptorBuilder
1678\ingroup NTuple
1679\brief A helper class for piece-wise construction of an RClusterDescriptor
1680
1681The cluster descriptor builder starts from a summary-only cluster descriptor and allows for the
1682piecewise addition of page locations.
1683*/
1684// clang-format on
1686private:
1688
1689public:
1695
1701
1703 {
1705 return *this;
1706 }
1707
1710
1711 /// Books the given column ID as being suppressed in this cluster. The correct first element index and number of
1712 /// elements need to be set by CommitSuppressedColumnRanges() once all the calls to CommitColumnRange() and
1713 /// MarkSuppressedColumnRange() took place.
1715
1716 /// Sets the first element index and number of elements for all the suppressed column ranges.
1717 /// The information is taken from the corresponding columns from the primary representation.
1718 /// Needs to be called when all the columns (suppressed and regular) where added.
1720
1721 /// Add column and page ranges for columns created during late model extension missing in this cluster. The locator
1722 /// type for the synthesized page ranges is `kTypePageZero`. All the page sources must be able to populate the
1723 /// 'zero' page from such locator. Any call to CommitColumnRange() and CommitSuppressedColumnRanges()
1724 /// should happen before calling this function.
1726
1731
1732 /// Move out the full cluster descriptor including page locations
1734};
1735
1736// clang-format off
1737/**
1738\class ROOT::Internal::RClusterGroupDescriptorBuilder
1739\ingroup NTuple
1740\brief A helper class for piece-wise construction of an RClusterGroupDescriptor
1741*/
1742// clang-format on
1744private:
1746
1747public:
1750
1767 {
1769 return *this;
1770 }
1772 {
1774 return *this;
1775 }
1777 {
1779 return *this;
1780 }
1781 void AddSortedClusters(const std::vector<ROOT::DescriptorId_t> &clusterIds)
1782 {
1783 if (clusterIds.size() != fClusterGroup.GetNClusters())
1784 throw RException(R__FAIL("mismatch of number of clusters"));
1786 }
1787
1789};
1790
1791// clang-format off
1792/**
1793\class ROOT::Internal::RExtraTypeInfoDescriptorBuilder
1794\ingroup NTuple
1795\brief A helper class for piece-wise construction of an RExtraTypeInfoDescriptor
1796*/
1797// clang-format on
1799private:
1801
1802public:
1804
1811 {
1813 return *this;
1814 }
1815 RExtraTypeInfoDescriptorBuilder &TypeName(const std::string &typeName)
1816 {
1817 fExtraTypeInfo.fTypeName = typeName;
1818 return *this;
1819 }
1821 {
1823 return *this;
1824 }
1825
1827};
1828
1829// clang-format off
1830/**
1831\class ROOT::Internal::RNTupleDescriptorBuilder
1832\ingroup NTuple
1833\brief A helper class for piece-wise construction of an RNTupleDescriptor
1834
1835Used by RPageStorage implementations in order to construct the RNTupleDescriptor from the various header parts.
1836*/
1837// clang-format on
1839private:
1842
1843public:
1844 /// Checks whether invariants hold:
1845 /// * RNTuple epoch is valid
1846 /// * RNTuple name is valid
1847 /// * Fields have valid parents
1848 /// * Number of columns is constant across column representations
1853
1854 /// Copies the "schema" part of `descriptor` into the builder's descriptor.
1855 /// This resets the builder's descriptor.
1856 void SetSchemaFromExisting(const RNTupleDescriptor &descriptor);
1857
1858 void SetVersion(std::uint16_t versionEpoch, std::uint16_t versionMajor, std::uint16_t versionMinor,
1859 std::uint16_t versionPatch);
1860 void SetVersionForWriting();
1861
1862 void SetNTuple(std::string_view name, std::string_view description);
1863 /// Sets the `flag`-th bit of the feature flag to 1.
1864 /// Note that `flag` itself is not a bitmask, just the bit index of the flag to enable.
1865 void SetFeature(unsigned int flag);
1866
1869 /// The real footer size also include the page list envelopes
1871
1876
1877 // The field that the column belongs to has to be already available. For fields with multiple columns,
1878 // the columns need to be added in order of the column index
1880
1883
1886
1888
1889 /// Mark the beginning of the header extension; any fields and columns added after a call to this function are
1890 /// annotated as begin part of the header extension.
1891 void BeginHeaderExtension();
1892
1893 /// \brief Shift column IDs of alias columns by `offset`
1894 ///
1895 /// If the descriptor is constructed in pieces consisting of physical and alias columns
1896 /// (regular and projected fields), the natural column order would be
1897 /// - Physical and alias columns of piece one
1898 /// - Physical and alias columns of piece two
1899 /// - etc.
1900 /// What we want, however, are first all physical column IDs and then all alias column IDs.
1901 /// This method adds `offset` to the logical column IDs of all alias columns and fixes up the corresponding
1902 /// column IDs in the projected field descriptors. In this way, a new piece of physical and alias columns can
1903 /// first shift the existing alias columns by the number of new physical columns, resulting in the following order
1904 /// - Physical columns of piece one
1905 /// - Physical columns of piece two
1906 /// - ...
1907 // - Logical columns of piece one
1908 /// - Logical columns of piece two
1909 /// - ...
1910 void ShiftAliasColumns(std::uint32_t offset);
1911};
1912
1914{
1915 return desc.CloneSchema(false /* shareStringPool */);
1916}
1917
1918/// Tells if the field describes a user-defined enum type.
1919/// The dictionary does not need to be available for this method.
1920/// Needs the full descriptor to look up sub fields.
1922
1923/// Tells if the field describes a std::atomic<T> type
1925
1926} // namespace Internal
1927
1928} // namespace ROOT
1929
1930#endif // ROOT_RNTupleDescriptor
#define R__DEPRECATED(MAJOR, MINOR, REASON)
Definition RConfig.hxx:486
#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:322
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.
#define R__ASSERT(e)
Checks condition e and reports a fatal error if it's false.
Definition TError.h:130
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:142
The available trivial, native content types of a column.
RNTupleAttrSetDescriptorBuilder & AnchorLocator(const RNTupleLocator &loc)
RNTupleAttrSetDescriptorBuilder & SchemaVersion(std::uint16_t major, std::uint16_t minor)
RResult< ROOT::Experimental::RNTupleAttrSetDescriptor > MoveDescriptor()
Attempt to make an AttributeSet descriptor.
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.
RResult< void > MarkSuppressedColumnRange(ROOT::DescriptorId_t physicalId)
Books the given column ID as being suppressed in this cluster.
RResult< void > CommitColumnRange(ROOT::DescriptorId_t physicalId, std::uint64_t firstElementIndex, std::uint32_t compressionSettings, const RClusterDescriptor::RPageRange &pageRange)
RClusterDescriptorBuilder & AddExtendedColumnRanges(const RNTupleDescriptor &desc)
Add column and page ranges for columns created during late model extension missing in this cluster.
RClusterDescriptorBuilder & NEntries(std::uint64_t nEntries)
RResult< void > CommitSuppressedColumnRanges(const RNTupleDescriptor &desc)
Sets the first element index and number of elements for all the suppressed column ranges.
RResult< RClusterDescriptor > MoveDescriptor()
Move out the full cluster descriptor including page locations.
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)
static RClusterGroupDescriptorBuilder FromSummary(const RClusterGroupDescriptor &clusterGroupDesc)
RClusterGroupDescriptorBuilder & PageListLength(std::uint64_t pageListLength)
RClusterGroupDescriptorBuilder & MinEntry(std::uint64_t minEntry)
void AddSortedClusters(const std::vector< ROOT::DescriptorId_t > &clusterIds)
RResult< RClusterGroupDescriptor > MoveDescriptor()
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)
RResult< RColumnDescriptor > MoveDescriptor()
Attempt to make a column descriptor.
A column element encapsulates the translation between basic C++ types and their column representation...
A helper class for piece-wise construction of an RExtraTypeInfoDescriptor.
RResult< RExtraTypeInfoDescriptor > MoveDescriptor()
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.
RResult< RFieldDescriptor > MoveDescriptor()
Attempt to make a field descriptor.
RFieldDescriptorBuilder & NRepetitions(std::uint64_t nRepetitions)
RFieldDescriptorBuilder & Structure(const ROOT::ENTupleStructure &structure)
RFieldDescriptorBuilder & TypeAlias(const std::string &typeAlias)
RFieldDescriptorBuilder & ProjectionSourceId(ROOT::DescriptorId_t id)
static RFieldDescriptor CloneDescriptor(const RFieldDescriptor &source, RStringPool &stringPool)
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(RFieldDescriptor &&source, RStringPool &stringPool)
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.
void SetNTuple(std::string_view name, std::string_view description)
void SetSchemaFromExisting(const RNTupleDescriptor &descriptor)
Copies the "schema" part of descriptor into the builder's descriptor.
RResult< void > AddColumn(RColumnDescriptor &&columnDesc)
void AddField(RFieldDescriptor fieldDesc)
RResult< void > AddAttributeSet(Experimental::RNTupleAttrSetDescriptor &&attrSetDesc)
RResult< void > AddFieldProjection(ROOT::DescriptorId_t sourceId, ROOT::DescriptorId_t targetId)
void ReplaceExtraTypeInfo(RExtraTypeInfoDescriptor &&extraTypeInfoDesc)
RResult< void > AddExtraTypeInfo(RExtraTypeInfoDescriptor &&extraTypeInfoDesc)
void ShiftAliasColumns(std::uint32_t offset)
Shift column IDs of alias columns by offset
void SetVersion(std::uint16_t versionEpoch, std::uint16_t versionMajor, std::uint16_t versionMinor, std::uint16_t versionPatch)
const RNTupleDescriptor & GetDescriptor() const
void BeginHeaderExtension()
Mark the beginning of the header extension; any fields and columns added after a call to this functio...
RResult< void > AddCluster(RClusterDescriptor &&clusterDesc)
RResult< void > EnsureValidDescriptor() const
Checks whether invariants hold:
RResult< void > AddFieldLink(ROOT::DescriptorId_t fieldId, ROOT::DescriptorId_t linkId)
RResult< void > AddClusterGroup(RClusterGroupDescriptor &&clusterGroup)
void SetOnDiskHeaderXxHash3(std::uint64_t xxhash3)
RResult< void > EnsureFieldExists(ROOT::DescriptorId_t fieldId) const
void SetFeature(unsigned int flag)
Sets the flag-th bit of the feature flag to 1.
void AddToOnDiskFooterSize(std::uint64_t size)
The real footer size also include the page list envelopes.
Used for string interning of repeated type names, field names, etc.
const std::string * Intern(std::string_view str)
Searches for str in the pool.
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)
bool fIsSuppressed
Suppressed columns have an empty page range and unknown compression settings.
void SetPhysicalColumnId(ROOT::DescriptorId_t id)
ROOT::DescriptorId_t GetPhysicalColumnId() const
bool operator==(const RColumnRange &other) const
void SetFirstElementIndex(ROOT::NTupleSize_t idx)
ROOT::NTupleSize_t fFirstElementIndex
The global index of the first column element in the cluster.
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
ROOT::NTupleSize_t fNElements
The number of column elements in the cluster.
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
static constexpr std::size_t kLargeRangeThreshold
Create the fCumulativeNElements only when its needed, i.e. when there are many pages to search throug...
RPageRange(const RPageRange &other)=delete
const std::vector< RPageInfo > & GetPageInfos() const
RPageInfoExtended Find(ROOT::NTupleSize_t idxInCluster) const
Find the page in the RPageRange that contains the given element. The element must exist.
bool operator==(const RPageRange &other) const
ROOT::DescriptorId_t GetPhysicalColumnId() const
void SetPhysicalColumnId(ROOT::DescriptorId_t id)
std::size_t ExtendToFitColumnRange(const RColumnRange &columnRange, const ROOT::Internal::RColumnElementBase &element, std::size_t pageSize)
Extend this RPageRange to fit the given RColumnRange.
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
RClusterDescriptor Clone() const
bool operator==(const RClusterDescriptor &other) const
const RColumnRange & GetColumnRange(ROOT::DescriptorId_t physicalId) const
RColumnRangeIterable GetColumnRangeIterable() const
Returns an iterator over pairs { columnId, columnRange }. The iteration order is unspecified.
ROOT::NTupleSize_t GetFirstEntryIndex() const
std::unordered_map< ROOT::DescriptorId_t, RPageRange > fPageRanges
RClusterDescriptor(const RClusterDescriptor &other)=delete
std::uint64_t GetNBytesOnStorage() const
Clusters are bundled in cluster groups.
RNTupleLocator fPageListLocator
The page list that corresponds to the cluster group.
RClusterGroupDescriptor & operator=(const RClusterGroupDescriptor &other)=delete
RClusterGroupDescriptor Clone() const
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.
bool operator==(const RClusterGroupDescriptor &other) const
RClusterGroupDescriptor CloneSummary() const
Creates a clone without the cluster IDs.
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...
bool operator==(const RColumnDescriptor &other) const
ROOT::DescriptorId_t fLogicalColumnId
The actual column identifier, which is the link to the corresponding field.
std::unique_ptr< RValueRange > fValueRange
Optional value range (used e.g. by quantized real fields)
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::uint16_t GetBitsOnStorage() const
RColumnDescriptor Clone() const
Get a copy of the descriptor.
RColumnDescriptor & operator=(const RColumnDescriptor &other)=delete
ROOT::DescriptorId_t GetLogicalId() const
Base class for all ROOT issued exceptions.
Definition RError.hxx:78
Field specific extra type information from the header / extenstion header.
RExtraTypeInfoDescriptor & operator=(RExtraTypeInfoDescriptor &&other)=default
RExtraTypeInfoDescriptor & operator=(const RExtraTypeInfoDescriptor &other)=delete
bool operator==(const RExtraTypeInfoDescriptor &other) const
RExtraTypeInfoDescriptor Clone() const
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.
static const std::string & GetEmptyString()
ROOT::ENTupleStructure GetStructure() const
bool operator==(const RFieldDescriptor &other) const
const std::string * fFieldName
The leaf name, not including parent fields.
const std::string * fTypeName
The C++ type that was used when writing the field.
RFieldDescriptor(const RFieldDescriptor &other)=delete
std::uint32_t GetColumnCardinality() const
const 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
ROOT::ENTupleStructure fStructure
The structural information carried by this field in the data model tree.
const std::string * fTypeAlias
A typedef or using directive that resolved to the type name during field creation.
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.
const std::string & GetFieldDescription() const
std::optional< std::uint32_t > GetTypeChecksum() const
ROOT::DescriptorId_t GetProjectionSourceId() const
void InitFrom(const RFieldDescriptor &source, Internal::RStringPool &stringPool)
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::uint32_t GetTypeVersion() const
const std::string & GetFieldName() const
std::unique_ptr< Internal::RStringPool > fStringPool
Optional string storage for a free-standing field descriptor.
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...
RIterator(const RNTupleDescriptor &ntuple, std::size_t clusterGroupNum)
Loop over all the clusters of an RNTuple, ordered by first entry number.
const RNTupleDescriptor & fNTuple
The associated RNTuple for this range.
RClusterDescriptorIterable(const RNTupleDescriptor &ntuple)
RIterator(const RNTupleDescriptor *ntuple, const std::vector< ROOT::DescriptorId_t > *sortedClusterGroupIds, std::size_t idx)
Used to loop over all the cluster groups of an RNTuple in order of entry ranges.
const RNTupleDescriptor & fNTuple
The associated RNTuple for this range.
RIterator(const RColumnDescriptorIterable *iterable=nullptr, std::size_t index=0)
const RColumnDescriptorIterable * fIterable
The enclosing RColumnDescriptorIterable.
Used to loop over a field's associated columns.
const RNTupleDescriptor & fNTuple
The associated RNTuple for this range.
std::vector< ROOT::DescriptorId_t > fColumns
The descriptor ids of the columns ordered by field, representation, and column index.
RColumnDescriptorIterable(const RNTupleDescriptor &ntuple, const RFieldDescriptor &fieldDesc)
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 RFieldDescriptorIterable *iterable=nullptr, std::size_t index=0)
const RFieldDescriptorIterable * fIterable
The enclosing RFieldDescriptorIterable.
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)
std::vector< ROOT::DescriptorId_t > fFieldChildren
The descriptor IDs of the child fields.
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 > GetTopMostFields(const RNTupleDescriptor &desc) const
Return a vector containing the IDs of the top-level fields defined in the extension header,...
std::uint32_t fNLogicalColumns
Number of logical and physical columns; updated by the descriptor builder when columns are added.
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
RFieldDescriptorIterable GetFieldIterable(const RFieldDescriptor &fieldDesc) 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::uint64_t fNPhysicalColumns
Updated by the descriptor builder when columns are added.
std::vector< Experimental::RNTupleAttrSetDescriptor > fAttributeSets
List of AttributeSets linked to this RNTuple.
ROOT::DescriptorId_t fFieldZeroId
Set by the descriptor builder.
std::uint64_t fNEntries
Updated by the descriptor builder when the cluster groups are added.
std::size_t GetNExtraTypeInfos() const
std::uint64_t GetOnDiskFooterSize() const
RClusterDescriptorIterable GetActiveClusterIterable() const
RClusterGroupDescriptorIterable GetClusterGroupIterable() const
std::size_t GetNActiveClusters() const
RColumnDescriptorIterable GetColumnIterable() const
bool operator==(const RNTupleDescriptor &other) const
const std::string & GetName() const
std::uint64_t fOnDiskFooterSize
Like fOnDiskHeaderSize, contains both cluster summaries and page locations.
std::uint16_t fVersionMinor
Set by the descriptor builder when deserialized.
RClusterDescriptorIterable R__DEPRECATED(6, 46, "This function is unsafe to use because, in general, not all cluster " "metadata are available (there may be cluster groups with unloaded cluster group details). Use the " "'GetActiveClusterIterable()' method instead if you are aware of this limitation.") GetClusterIterable() const
ROOT::DescriptorId_t FindClusterId(ROOT::NTupleSize_t entryIdx) const
ROOT::NTupleSize_t R__DEPRECATED(6, 46, "This function is ill-conceived in the descriptor " "as not all cluster descriptors may be present. This interface is no longer publicly exposed.") GetNElements(ROOT ROOT::DescriptorId_t GetFieldZeroId() const
Returns the logical parent of all top-level RNTuple data fields.
std::vector< std::uint64_t > GetFeatureFlags() const
ROOT::NTupleSize_t GetNEntries() const
We know the number of entries from adding the cluster summaries.
std::unique_ptr< ROOT::RNTupleModel > CreateModel(const RCreateModelOptions &options=RCreateModelOptions()) const
Re-create the C++ model from the stored metadata.
std::string GetTypeNameForComparison(const RFieldDescriptor &fieldDesc) const
Adjust the type name of the passed RFieldDescriptor for comparison with another renormalized type nam...
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
ROOT::DescriptorId_t FindPhysicalColumnId(ROOT::DescriptorId_t fieldId, std::uint32_t columnIndex, std::uint16_t representationIndex) const
RExtraTypeInfoDescriptorIterable GetExtraTypeInfoIterable() const
std::size_t GetNPhysicalColumns() const
EFeatureFlags
All known feature flags.
@ kFeatureFlag_Test
Reserved for forward-compatibility testing.
@ kFeatureFlag_NestedDeferredColumns
Signals that the RNTuple contains at least one deferred column that is part of a collection and was e...
std::shared_ptr< Internal::RStringPool > fStringPool
Storage for all the field strings. Shared among descriptor clones.
const RHeaderExtension * GetHeaderExtension() const
Return header extension information; if the descriptor does not have a header extension,...
std::uint64_t GetVersion() const
void PrintInfo(std::ostream &output) const
std::uint64_t fNClusters
Updated by the descriptor builder when the cluster groups are added.
RNTupleDescriptor CloneSchema(bool shareStringPool) const
Creates a descriptor containing only the schema information about this RNTuple, i....
std::uint64_t fOnDiskHeaderXxHash3
Set by the descriptor builder when deserialized.
const RClusterDescriptor & GetClusterDescriptor(ROOT::DescriptorId_t clusterId) const
ROOT::DescriptorId_t FindFieldId(std::string_view fieldName, ROOT::DescriptorId_t parentId) 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.
friend class Experimental::RNTupleAttrSetDescriptorIterable
std::uint64_t GetOnDiskHeaderXxHash3() const
RResult< void > DropClusterGroupDetails(ROOT::DescriptorId_t clusterGroupId)
std::uint16_t fVersionMajor
Set by the descriptor builder when deserialized.
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
ROOT::DescriptorId_t FindLogicalColumnId(ROOT::DescriptorId_t fieldId, std::uint32_t columnIndex, std::uint16_t representationIndex) const
std::unordered_map< ROOT::DescriptorId_t, RFieldDescriptor > fFieldDescriptors
std::size_t GetNFields() const
RResult< void > AddClusterGroupDetails(ROOT::DescriptorId_t clusterGroupId, std::vector< RClusterDescriptor > &clusterDescs)
Methods to load and drop cluster group details (cluster IDs and page locations)
bool HasFeature(unsigned int flag) const
std::uint16_t fVersionPatch
Set by the descriptor builder when deserialized.
std::uint64_t GetOnDiskHeaderSize() const
std::string fDescription
Free text from the user.
ROOT::Experimental::RNTupleAttrSetDescriptorIterable GetAttrSetIterable() const
RFieldDescriptorIterable GetTopLevelFields() const
std::uint16_t fVersionEpoch
Set by the descriptor builder when deserialized.
std::vector< RExtraTypeInfoDescriptor > fExtraTypeInfoDescriptors
RNTupleDescriptor Clone() const
std::size_t GetNLogicalColumns() const
RNTupleDescriptor & operator=(const RNTupleDescriptor &other)=delete
std::size_t GetNClusterGroups() const
ROOT::DescriptorId_t R__DEPRECATED(6, 46, "This function is ill-defined in the descriptor " "as not all cluster descriptors may be present. This interface is no longer exposed.") FindClusterId(ROOT ROOT::DescriptorId_t R__DEPRECATED(6, 46, "This function is ill-defined in the descriptor " "as not all cluster descriptors may be present. This interface is no longer exposed.") FindNextClusterId(ROOT ROOT::DescriptorId_t R__DEPRECATED(6, 46, "This function is ill-defined in the descriptor " "as not all cluster descriptors may be present. This interface is no longer exposed.") FindPrevClusterId(ROOT std::string GetQualifiedFieldName(ROOT::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 ...
bool FieldTypeNamesMayNeedFixup() const
ROOT v6.34, with spec versions before 1.0.0.1, did not properly renormalize the type name.
const std::string & GetDescription() const
std::uint64_t fGeneration
The generation of the descriptor.
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)
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)
ROOT::NTupleSize_t fPageNumber
Page number in the corresponding RPageRange.
ROOT::NTupleSize_t fFirstElementIndex
Index (in cluster) of the first element in page.
void SetPageNumber(ROOT::NTupleSize_t pageNumber)
Information about a single page in the context of a cluster's page range.
bool fHasChecksum
If true, the 8 bytes following the serialized page are an xxhash of the on-disk page data.
void SetLocator(const RNTupleLocator &locator)
bool operator==(const RPageInfo &other) const
std::uint32_t fNElements
The sum of the elements of all the pages must match the corresponding fNElements field in fColumnRang...
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
bool fForwardCompatible
By default, creating a model will fail if any of the reconstructed fields contains an unknown column ...
bool fCreateBare
If true, the model will be created without a default entry (bare model).
bool fReconstructProjections
If set to true, projected fields will be reconstructed as such.
bool fEmulateUnknownTypes
If true, fields with a user defined type that have no available dictionaries will be reconstructed as...