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 ROOT7
3/// \author Jakob Blomer <jblomer@cern.ch>
4/// \date 2018-07-19
5/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
6/// is welcome!
7
8/*************************************************************************
9 * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. *
10 * All rights reserved. *
11 * *
12 * For the licensing terms see $ROOTSYS/LICENSE. *
13 * For the list of contributors see $ROOTSYS/README/CREDITS. *
14 *************************************************************************/
15
16#ifndef ROOT7_RNTupleDescriptor
17#define ROOT7_RNTupleDescriptor
18
19#include <ROOT/RColumnModel.hxx>
20#include <ROOT/RError.hxx>
22#include <ROOT/RNTupleUtil.hxx>
23#include <ROOT/RSpan.hxx>
24#include <ROOT/RStringView.hxx>
25
26#include <algorithm>
27#include <chrono>
28#include <functional>
29#include <iterator>
30#include <map>
31#include <memory>
32#include <ostream>
33#include <vector>
34#include <string>
35#include <unordered_map>
36#include <unordered_set>
37
38namespace ROOT {
39namespace Experimental {
40
41class RFieldDescriptorBuilder;
42class RNTupleDescriptor;
43class RNTupleDescriptorBuilder;
44class RNTupleModel;
45
46namespace Detail {
47 class RFieldBase;
48}
49
50
51// clang-format off
52/**
53\class ROOT::Experimental::RFieldDescriptor
54\ingroup NTuple
55\brief Meta-data stored for every field of an ntuple
56*/
57// clang-format on
61
62private:
64 /// The version of the C++-type-to-column translation mechanics
65 std::uint32_t fFieldVersion = 0;
66 /// The version of the C++ type itself
67 std::uint32_t fTypeVersion = 0;
68 /// The leaf name, not including parent fields
69 std::string fFieldName;
70 /// Free text set by the user
71 std::string fFieldDescription;
72 /// The C++ type that was used when writing the field
73 std::string fTypeName;
74 /// A typedef or using directive that resolved to the type name during field creation
75 std::string fTypeAlias;
76 /// The number of elements per entry for fixed-size arrays
77 std::uint64_t fNRepetitions = 0;
78 /// The structural information carried by this field in the data model tree
80 /// Establishes sub field relationships, such as classes and collections
82 /// The pointers in the other direction from parent to children. They are serialized, too, to keep the
83 /// order of sub fields.
84 std::vector<DescriptorId_t> fLinkIds;
85
86public:
87 RFieldDescriptor() = default;
88 RFieldDescriptor(const RFieldDescriptor &other) = delete;
92
93 bool operator==(const RFieldDescriptor &other) const;
94 /// Get a copy of the descriptor
95 RFieldDescriptor Clone() const;
96 /// In general, we create a field simply from the C++ type name. For untyped fields, however, we potentially need
97 /// access to sub fields, which is provided by the ntuple descriptor argument.
98 std::unique_ptr<Detail::RFieldBase> CreateField(const RNTupleDescriptor &ntplDesc) const;
99
100 DescriptorId_t GetId() const { return fFieldId; }
101 std::uint32_t GetFieldVersion() const { return fFieldVersion; }
102 std::uint32_t GetTypeVersion() const { return fTypeVersion; }
103 std::string GetFieldName() const { return fFieldName; }
104 std::string GetFieldDescription() const { return fFieldDescription; }
105 std::string GetTypeName() const { return fTypeName; }
106 std::string GetTypeAlias() const { return fTypeAlias; }
107 std::uint64_t GetNRepetitions() const { return fNRepetitions; }
110 const std::vector<DescriptorId_t> &GetLinkIds() const { return fLinkIds; }
111};
112
113
114// clang-format off
115/**
116\class ROOT::Experimental::RColumnDescriptor
117\ingroup NTuple
118\brief Meta-data stored for every column of an ntuple
119*/
120// clang-format on
124
125private:
126 /// The actual column identifier, which is the link to the corresponding field
128 /// Usually identical to the logical column ID, except for alias columns where it references the shadowed column
130 /// Contains the column type and whether it is sorted
132 /// Every column belongs to one and only one field
134 /// A field can be serialized into several columns, which are numbered from zero to $n$
135 std::uint32_t fIndex;
136
137public:
138 RColumnDescriptor() = default;
139 RColumnDescriptor(const RColumnDescriptor &other) = delete;
143
144 bool operator==(const RColumnDescriptor &other) const;
145 /// Get a copy of the descriptor
146 RColumnDescriptor Clone() const;
147
150 RColumnModel GetModel() const { return fModel; }
151 std::uint32_t GetIndex() const { return fIndex; }
154};
155
156// clang-format off
157/**
158\class ROOT::Experimental::RColumnGroupDescriptor
159\ingroup NTuple
160\brief Meta-data for a sets of columns; non-trivial column groups are used for sharded clusters
161
162Clusters can span a subset of columns. Such subsets are described as a column group. An empty column group
163is used to denote the column group of all the columns. Every ntuple has at least one column group.
164*/
165// clang-format on
168
169private:
171 std::unordered_set<DescriptorId_t> fPhysicalColumnIds;
172
173public:
179
180 bool operator==(const RColumnGroupDescriptor &other) const;
181
183 const std::unordered_set<DescriptorId_t> &GetPhysicalColumnIds() const { return fPhysicalColumnIds; }
184 bool Contains(DescriptorId_t physicalId) const
185 {
186 return fPhysicalColumnIds.empty() || fPhysicalColumnIds.count(physicalId) > 0;
187 }
188 bool HasAllColumns() const { return fPhysicalColumnIds.empty(); }
189};
190
191// clang-format off
192/**
193\class ROOT::Experimental::RClusterDescriptor
194\ingroup NTuple
195\brief Meta-data for a set of ntuple clusters
196
197The cluster descriptor is built in two phases. In a first phase, the descriptor has only summary data,
198i.e. the ID and the event range. In a second phase, page locations and column ranges are added.
199Both phases are populated by the RClusterDescriptorBuilder.
200Clusters usually span across all available columns but in some cases they can describe only a subset of the columns,
201for instance when describing friend ntuples.
202*/
203// clang-format on
206
207public:
208 /// The window of element indexes of a particular column in a particular cluster
211 /// A 64bit element index
213 /// The number of column elements in the cluster
215 /// The usual format for ROOT compression settings (see Compression.h).
216 /// The pages of a particular column in a particular cluster are all compressed with the same settings.
217 std::int64_t fCompressionSettings = 0;
218
219 // TODO(jblomer): we perhaps want to store summary information, such as average, min/max, etc.
220 // Should this be done on the field level?
221
222 bool operator==(const RColumnRange &other) const {
225 }
226
229 }
230 };
231
232 /// Records the parition of data into pages for a particular column in a particular cluster
233 struct RPageRange {
234 /// We do not need to store the element size / uncompressed page size because we know to which column
235 /// the page belongs
236 struct RPageInfo {
237 /// The sum of the elements of all the pages must match the corresponding fNElements field in fColumnRanges
238 std::uint32_t fNElements = std::uint32_t(-1);
239 /// The meaning of fLocator depends on the storage backend.
241
242 bool operator==(const RPageInfo &other) const {
243 return fNElements == other.fNElements && fLocator == other.fLocator;
244 }
245 };
247 /// Index (in cluster) of the first element in page.
249 /// Page number in the corresponding RPageRange.
251
252 RPageInfoExtended() = default;
254 : RPageInfo(pi), fFirstInPage(i), fPageNo(n) {}
255 };
256
257 RPageRange() = default;
258 RPageRange(const RPageRange &other) = delete;
259 RPageRange &operator =(const RPageRange &other) = delete;
260 RPageRange(RPageRange &&other) = default;
261 RPageRange &operator =(RPageRange &&other) = default;
262
264 RPageRange clone;
266 clone.fPageInfos = fPageInfos;
267 return clone;
268 }
269
270 /// Find the page in the RPageRange that contains the given element. The element must exist.
271 RPageInfoExtended Find(RClusterSize::ValueType idxInCluster) const;
272
274 std::vector<RPageInfo> fPageInfos;
275
276 bool operator==(const RPageRange &other) const {
277 return fPhysicalColumnId == other.fPhysicalColumnId && fPageInfos == other.fPageInfos;
278 }
279 };
280
281private:
283 /// Clusters can be swapped by adjusting the entry offsets
285 // TODO(jblomer): change to std::uint64_t
287 bool fHasPageLocations = false;
288
289 std::unordered_map<DescriptorId_t, RColumnRange> fColumnRanges;
290 std::unordered_map<DescriptorId_t, RPageRange> fPageRanges;
291
292 void EnsureHasPageLocations() const;
293
294public:
296 // Constructor for a summary-only cluster descriptor without page locations
297 RClusterDescriptor(DescriptorId_t clusterId, std::uint64_t firstEntryIndex, std::uint64_t nEntries)
298 : fClusterId(clusterId), fFirstEntryIndex(firstEntryIndex), fNEntries(ClusterSize_t(nEntries))
299 {
300 }
305
307
308 bool operator==(const RClusterDescriptor &other) const;
309
310 DescriptorId_t GetId() const { return fClusterId; }
314 {
316 return fColumnRanges.at(physicalId);
317 }
318 const RPageRange &GetPageRange(DescriptorId_t physicalId) const
319 {
321 return fPageRanges.at(physicalId);
322 }
323 bool ContainsColumn(DescriptorId_t physicalId) const;
324 std::unordered_set<DescriptorId_t> GetColumnIds() const;
325 std::uint64_t GetBytesOnStorage() const;
326 bool HasPageLocations() const { return fHasPageLocations; }
327};
328
329// clang-format off
330/**
331\class ROOT::Experimental::RClusterGroupDescriptor
332\ingroup NTuple
333\brief Clusters are stored in cluster groups. Cluster groups span all the columns of a certain event range.
334
335Very large ntuples or combined ntuples (chains, friends) contain multiple cluster groups. The cluster groups
336may contain sharded clusters. However, a cluster group must contain the clusters spanning all the columns for the
337given event range. Cluster groups must partition the entry range of an ntuple.
338Every ntuple has at least one cluster group. The clusters in a cluster group are ordered corresponding to
339the order of page locations in the page list envelope that belongs to the cluster group (see format specification)
340*/
341// clang-format on
344
345private:
347 std::vector<DescriptorId_t> fClusterIds;
348 /// The page list that corresponds to the cluster group
350 /// Uncompressed size of the page list
351 std::uint32_t fPageListLength = 0;
352
353public:
359
361
362 bool operator==(const RClusterGroupDescriptor &other) const;
363
365 std::uint64_t GetNClusters() const { return fClusterIds.size(); }
367 std::uint32_t GetPageListLength() const { return fPageListLength; }
368 bool Contains(DescriptorId_t clusterId) const
369 {
370 return std::find(fClusterIds.begin(), fClusterIds.end(), clusterId) != fClusterIds.end();
371 }
372 const std::vector<DescriptorId_t> &GetClusterIds() const { return fClusterIds; }
373};
374
375// clang-format off
376/**
377\class ROOT::Experimental::RNTupleDescriptor
378\ingroup NTuple
379\brief The on-storage meta-data of an ntuple
380
381Represents the on-disk (on storage) information about an ntuple. The meta-data consists of a header and one or
382several footers. The header carries the ntuple schema, i.e. the fields and the associated columns and their
383relationships. The footer(s) carry information about one or several clusters. For every cluster, a footer stores
384its location and size, and for every column the range of element indexes as well as a list of pages and page
385locations.
386
387The descriptor provide machine-independent (de-)serialization of headers and footers, and it provides lookup routines
388for ntuple objects (pages, clusters, ...). It is supposed to be usable by all RPageStorage implementations.
389
390The serialization does not use standard ROOT streamers in order to not let it depend on libCore. The serialization uses
391the concept of frames: header, footer, and substructures have a preamble with version numbers and the size of the
392writte struct. This allows for forward and backward compatibility when the meta-data evolves.
393*/
394// clang-format on
397
398public:
399 class RHeaderExtension;
400
401private:
402 /// The ntuple name needs to be unique in a given storage location (file)
403 std::string fName;
404 /// Free text from the user
405 std::string fDescription;
406
407 std::uint64_t fOnDiskHeaderSize = 0; ///< Set by the descriptor builder when deserialized
408 std::uint64_t fOnDiskFooterSize = 0; ///< Like fOnDiskHeaderSize, contains both cluster summaries and page locations
409
410 std::uint64_t fNEntries = 0; ///< Updated by the descriptor builder when the cluster summaries are added
411 std::uint64_t fNPhysicalColumns = 0; ///< Updated by the descriptor builder when columns are added
412
413 /**
414 * Once constructed by an RNTupleDescriptorBuilder, the descriptor is mostly immutable except for set of
415 * active the page locations. During the lifetime of the descriptor, page location information for clusters
416 * can be added or removed. When this happens, the generation should be increased, so that users of the
417 * descriptor know that the information changed. The generation is increased, e.g., by the page source's
418 * exclusive lock guard around the descriptor. It is used, e.g., by the descriptor cache in RNTupleReader.
419 */
420 std::uint64_t fGeneration = 0;
421
422 std::unordered_map<DescriptorId_t, RFieldDescriptor> fFieldDescriptors;
423 std::unordered_map<DescriptorId_t, RColumnDescriptor> fColumnDescriptors;
424 std::unordered_map<DescriptorId_t, RClusterGroupDescriptor> fClusterGroupDescriptors;
425 /// May contain only a subset of all the available clusters, e.g. the clusters of the current file
426 /// from a chain of files
427 std::unordered_map<DescriptorId_t, RClusterDescriptor> fClusterDescriptors;
428 std::unique_ptr<RHeaderExtension> fHeaderExtension;
429
430public:
431 // clang-format off
432 /**
433 \class ROOT::Experimental::RNTupleDescriptor::RHeaderExtension
434 \ingroup NTuple
435 \brief Summarizes information about fields and the corresponding columns that were added after the header has been serialized
436 */
437 // clang-format on
440
441 private:
442 /// Contains the list of field IDs that are part of the header extension; the corresponding columns are
443 /// available via `GetColumnIterable()`.
444 std::vector<DescriptorId_t> fFields;
445 /// Number of logical and physical columns; updated by the descriptor builder when columns are added
446 std::uint64_t fNLogicalColumns = 0;
447 std::uint64_t fNPhysicalColumns = 0;
448
449 void AddFieldId(DescriptorId_t id) { fFields.push_back(id); }
450 void AddColumn(bool isAliasColumn)
451 {
453 if (!isAliasColumn)
455 }
456
457 public:
458 std::size_t GetNFields() const { return fFields.size(); }
459 std::size_t GetNLogicalColumns() const { return fNLogicalColumns; }
460 std::size_t GetNPhysicalColumns() const { return fNPhysicalColumns; }
461 /// Return a vector containing the IDs of the top-level fields defined in the extension header
462 std::vector<DescriptorId_t> GetTopLevelFields(const RNTupleDescriptor &desc) const;
463 };
464
465 // clang-format off
466 /**
467 \class ROOT::Experimental::RNTupleDescriptor::RColumnDescriptorIterable
468 \ingroup NTuple
469 \brief Used to loop over a field's associated columns
470 */
471 // clang-format on
473 private:
474 /// The associated NTuple for this range.
476 /// The descriptor ids of the columns ordered by index id
477 std::vector<DescriptorId_t> fColumns = {};
478 public:
479 class RIterator {
480 private:
481 /// The enclosing range's NTuple.
483 /// The enclosing range's descriptor id list.
484 const std::vector<DescriptorId_t> &fColumns;
485 std::size_t fIndex = 0;
486 public:
487 using iterator_category = std::forward_iterator_tag;
490 using difference_type = std::ptrdiff_t;
493
494 RIterator(const RNTupleDescriptor &ntuple, const std::vector<DescriptorId_t> &columns, std::size_t index)
495 : fNTuple(ntuple), fColumns(columns), fIndex(index) {}
496 iterator operator++() { ++fIndex; return *this; }
498 bool operator!=(const iterator &rh) const { return fIndex != rh.fIndex; }
499 bool operator==(const iterator &rh) const { return fIndex == rh.fIndex; }
500 };
501
503 : fNTuple(ntuple)
504 {
505 for (unsigned int i = 0; true; ++i) {
506 auto logicalId = ntuple.FindLogicalColumnId(field.GetId(), i);
507 if (logicalId == kInvalidDescriptorId)
508 break;
509 fColumns.emplace_back(logicalId);
510 }
511 }
514 };
515
516 // clang-format off
517 /**
518 \class ROOT::Experimental::RNTupleDescriptor::RFieldDescriptorIterable
519 \ingroup NTuple
520 \brief Used to loop over a field's child fields
521 */
522 // clang-format on
524 private:
525 /// The associated NTuple for this range.
527 /// The descriptor ids of the child fields. These may be sorted using
528 /// a comparison function.
529 std::vector<DescriptorId_t> fFieldChildren = {};
530
531 public:
532 class RIterator {
533 private:
534 /// The enclosing range's NTuple.
536 /// The enclosing range's descriptor id list.
537 const std::vector<DescriptorId_t>& fFieldChildren;
538 std::size_t fIndex = 0;
539 public:
540 using iterator_category = std::forward_iterator_tag;
543 using difference_type = std::ptrdiff_t;
546
547 RIterator(const RNTupleDescriptor& ntuple, const std::vector<DescriptorId_t>& fieldChildren,
548 std::size_t index) : fNTuple(ntuple), fFieldChildren(fieldChildren), fIndex(index) {}
549 iterator operator++() { ++fIndex; return *this; }
553 );
554 }
555 bool operator!=(const iterator& rh) const { return fIndex != rh.fIndex; }
556 bool operator==(const iterator& rh) const { return fIndex == rh.fIndex; }
557 };
559 : fNTuple(ntuple), fFieldChildren(field.GetLinkIds()) {}
560 /// Sort the range using an arbitrary comparison function.
562 const std::function<bool(DescriptorId_t, DescriptorId_t)>& comparator)
563 : fNTuple(ntuple), fFieldChildren(field.GetLinkIds())
564 {
565 std::sort(fFieldChildren.begin(), fFieldChildren.end(), comparator);
566 }
568 return RIterator(fNTuple, fFieldChildren, 0);
569 }
572 }
573 };
574
575 // clang-format off
576 /**
577 \class ROOT::Experimental::RNTupleDescriptor::RClusterGroupDescriptorIterable
578 \ingroup NTuple
579 \brief Used to loop over all the cluster groups of an ntuple (in unspecified order)
580
581 Enumerate all cluster group IDs from the cluster group descriptor. No specific order can be assumed, use
582 FindNextClusterGroupId and FindPrevClusterGroupId to traverse clusters groups by entry number.
583 */
584 // clang-format on
586 private:
587 /// The associated NTuple for this range.
589
590 public:
591 class RIterator {
592 private:
593 /// The enclosing range's NTuple.
595 std::size_t fIndex = 0;
596
597 public:
598 using iterator_category = std::forward_iterator_tag;
601 using difference_type = std::ptrdiff_t;
604
605 RIterator(const RNTupleDescriptor &ntuple, std::size_t index) : fNTuple(ntuple), fIndex(index) {}
607 {
608 ++fIndex;
609 return *this;
610 }
612 {
613 auto it = fNTuple.fClusterGroupDescriptors.begin();
614 std::advance(it, fIndex);
615 return it->second;
616 }
617 bool operator!=(const iterator &rh) const { return fIndex != rh.fIndex; }
618 bool operator==(const iterator &rh) const { return fIndex == rh.fIndex; }
619 };
620
624 };
625
626 // clang-format off
627 /**
628 \class ROOT::Experimental::RNTupleDescriptor::RClusterDescriptorIterable
629 \ingroup NTuple
630 \brief Used to loop over all the clusters of an ntuple (in unspecified order)
631
632 Enumerate all cluster IDs from the cluster descriptor. No specific order can be assumed, use
633 FindNextClusterId and FindPrevClusterId to travers clusters by entry number.
634 */
635 // clang-format on
637 private:
638 /// The associated NTuple for this range.
640 public:
641 class RIterator {
642 private:
643 /// The enclosing range's NTuple.
645 std::size_t fIndex = 0;
646 public:
647 using iterator_category = std::forward_iterator_tag;
650 using difference_type = std::ptrdiff_t;
653
654 RIterator(const RNTupleDescriptor &ntuple, std::size_t index) : fNTuple(ntuple), fIndex(index) {}
655 iterator operator++() { ++fIndex; return *this; }
657 auto it = fNTuple.fClusterDescriptors.begin();
658 std::advance(it, fIndex);
659 return it->second;
660 }
661 bool operator!=(const iterator &rh) const { return fIndex != rh.fIndex; }
662 bool operator==(const iterator &rh) const { return fIndex == rh.fIndex; }
663 };
664
668 };
669
670 RNTupleDescriptor() = default;
671 RNTupleDescriptor(const RNTupleDescriptor &other) = delete;
675
676 std::unique_ptr<RNTupleDescriptor> Clone() const;
677
678 bool operator ==(const RNTupleDescriptor &other) const;
679
680 std::uint64_t GetOnDiskHeaderSize() const { return fOnDiskHeaderSize; }
681 std::uint64_t GetOnDiskFooterSize() const { return fOnDiskFooterSize; }
682
684 return fFieldDescriptors.at(fieldId);
685 }
687 return fColumnDescriptors.at(columnId);
688 }
690 {
691 return fClusterGroupDescriptors.at(clusterGroupId);
692 }
694 return fClusterDescriptors.at(clusterId);
695 }
696
698 return RFieldDescriptorIterable(*this, fieldDesc);
699 }
701 const std::function<bool(DescriptorId_t, DescriptorId_t)>& comparator) const
702 {
703 return RFieldDescriptorIterable(*this, fieldDesc, comparator);
704 }
706 return GetFieldIterable(GetFieldDescriptor(fieldId));
707 }
709 const std::function<bool(DescriptorId_t, DescriptorId_t)>& comparator) const
710 {
711 return GetFieldIterable(GetFieldDescriptor(fieldId), comparator);
712 }
715 }
717 const std::function<bool(DescriptorId_t, DescriptorId_t)>& comparator) const
718 {
719 return GetFieldIterable(GetFieldZeroId(), comparator);
720 }
721
723 {
724 return RColumnDescriptorIterable(*this, fieldDesc);
725 }
727 {
728 return RColumnDescriptorIterable(*this, GetFieldDescriptor(fieldId));
729 }
730
732
734 {
735 return RClusterDescriptorIterable(*this);
736 }
737
738 std::string GetName() const { return fName; }
739 std::string GetDescription() const { return fDescription; }
740
741 std::size_t GetNFields() const { return fFieldDescriptors.size(); }
742 std::size_t GetNLogicalColumns() const { return fColumnDescriptors.size(); }
743 std::size_t GetNPhysicalColumns() const { return fNPhysicalColumns; }
744 std::size_t GetNClusterGroups() const { return fClusterGroupDescriptors.size(); }
745 std::size_t GetNClusters() const { return fClusterDescriptors.size(); }
746
747 /// We know the number of entries from adding the cluster summaries
749 NTupleSize_t GetNElements(DescriptorId_t physicalColumnId) const;
750
751 /// Returns the logical parent of all top-level NTuple data fields.
754 DescriptorId_t FindFieldId(std::string_view fieldName, DescriptorId_t parentId) const;
755 /// Searches for a top-level field
756 DescriptorId_t FindFieldId(std::string_view fieldName) const;
757 DescriptorId_t FindLogicalColumnId(DescriptorId_t fieldId, std::uint32_t columnIndex) const;
758 DescriptorId_t FindPhysicalColumnId(DescriptorId_t fieldId, std::uint32_t columnIndex) const;
762
763 /// Walks up the parents of the field ID and returns a field name of the form a.b.c.d
764 /// In case of invalid field ID, an empty string is returned.
765 std::string GetQualifiedFieldName(DescriptorId_t fieldId) const;
766
767 /// Return header extension information; if the descriptor does not have a header extension, return `nullptr`
768 const RHeaderExtension *GetHeaderExtension() const { return fHeaderExtension.get(); }
769
770 /// Methods to load and drop cluster details
773
774 std::uint64_t GetGeneration() const { return fGeneration; }
776
777 /// Re-create the C++ model from the stored meta-data
778 std::unique_ptr<RNTupleModel> GenerateModel() const;
779 void PrintInfo(std::ostream &output) const;
780};
781
782
783// clang-format off
784/**
785\class ROOT::Experimental::RColumnDescriptorBuilder
786\ingroup NTuple
787\brief A helper class for piece-wise construction of an RColumnDescriptor
788
789Dangling column descriptors can become actual descriptors when added to an
790RNTupleDescriptorBuilder instance and then linked to their fields.
791*/
792// clang-format on
794private:
796public:
797 /// Make an empty column descriptor builder.
799
801 {
802 fColumn.fLogicalColumnId = logicalColumnId;
803 return *this;
804 }
806 {
807 fColumn.fPhysicalColumnId = physicalColumnId;
808 return *this;
809 }
811 fColumn.fModel = model;
812 return *this;
813 }
815 fColumn.fFieldId = fieldId;
816 return *this;
817 }
820 return *this;
821 }
823 /// Attempt to make a column descriptor. This may fail if the column
824 /// was not given enough information to make a proper descriptor.
826};
827
828
829// clang-format off
830/**
831\class ROOT::Experimental::RFieldDescriptorBuilder
832\ingroup NTuple
833\brief A helper class for piece-wise construction of an RFieldDescriptor
834
835Dangling field descriptors describe a single field in isolation. They are
836missing the necessary relationship information (parent field, any child fields)
837required to describe a real NTuple field.
838
839Dangling field descriptors can only become actual descriptors when added to an
840RNTupleDescriptorBuilder instance and then linked to other fields.
841*/
842// clang-format on
844private:
846public:
847 /// Make an empty dangling field descriptor.
849 /// Make a new RFieldDescriptorBuilder based off an existing descriptor.
850 /// Relationship information is lost during the conversion to a
851 /// dangling descriptor:
852 /// * Parent id is reset to an invalid id.
853 /// * Field children ids are forgotten.
854 ///
855 /// These properties must be set using RNTupleDescriptorBuilder::AddFieldLink().
856 explicit RFieldDescriptorBuilder(const RFieldDescriptor& fieldDesc);
857
858 /// Make a new RFieldDescriptorBuilder based off a live NTuple field.
860
862 fField.fFieldId = fieldId;
863 return *this;
864 }
865 RFieldDescriptorBuilder &FieldVersion(std::uint32_t fieldVersion)
866 {
867 fField.fFieldVersion = fieldVersion;
868 return *this;
869 }
870 RFieldDescriptorBuilder &TypeVersion(std::uint32_t typeVersion)
871 {
872 fField.fTypeVersion = typeVersion;
873 return *this;
874 }
877 return *this;
878 }
879 RFieldDescriptorBuilder& FieldName(const std::string& fieldName) {
880 fField.fFieldName = fieldName;
881 return *this;
882 }
883 RFieldDescriptorBuilder& FieldDescription(const std::string& fieldDescription) {
884 fField.fFieldDescription = fieldDescription;
885 return *this;
886 }
887 RFieldDescriptorBuilder& TypeName(const std::string& typeName) {
888 fField.fTypeName = typeName;
889 return *this;
890 }
891 RFieldDescriptorBuilder &TypeAlias(const std::string &typeAlias)
892 {
893 fField.fTypeAlias = typeAlias;
894 return *this;
895 }
896 RFieldDescriptorBuilder& NRepetitions(std::uint64_t nRepetitions) {
897 fField.fNRepetitions = nRepetitions;
898 return *this;
899 }
901 fField.fStructure = structure;
902 return *this;
903 }
905 /// Attempt to make a field descriptor. This may fail if the dangling field
906 /// was not given enough information to make a proper descriptor.
908};
909
910
911// clang-format off
912/**
913\class ROOT::Experimental::RClusterDescriptorBuilder
914\ingroup NTuple
915\brief A helper class for piece-wise construction of an RClusterDescriptor
916
917The cluster descriptor builder starts from a summary-only cluster descriptor and allows for the
918piecewise addition of page locations.
919*/
920// clang-format on
922private:
924
925public:
926 /// Make an empty cluster descriptor builder.
927 RClusterDescriptorBuilder(DescriptorId_t clusterId, std::uint64_t firstEntryIndex, std::uint64_t nEntries)
928 : fCluster(clusterId, firstEntryIndex, nEntries)
929 {
930 }
931
932 RResult<void> CommitColumnRange(DescriptorId_t physicalId, std::uint64_t firstElementIndex,
933 std::uint32_t compressionSettings, const RClusterDescriptor::RPageRange &pageRange);
934
935 /// Move out the full cluster descriptor including page locations
937};
938
939// clang-format off
940/**
941\class ROOT::Experimental::RClusterGroupDescriptorBuilder
942\ingroup NTuple
943\brief A helper class for piece-wise construction of an RClusterGroupDescriptor
944*/
945// clang-format on
947private:
949
950public:
952
954 {
955 fClusterGroup.fClusterGroupId = clusterGroupId;
956 return *this;
957 }
959 {
960 fClusterGroup.fPageListLocator = pageListLocator;
961 return *this;
962 }
963 RClusterGroupDescriptorBuilder &PageListLength(std::uint32_t pageListLength)
964 {
965 fClusterGroup.fPageListLength = pageListLength;
966 return *this;
967 }
968 void AddCluster(DescriptorId_t clusterId) { fClusterGroup.fClusterIds.emplace_back(clusterId); }
969
971
972 /// Used to prepare the cluster descriptor builders when loading the page locations for a certain cluster group
973 static std::vector<RClusterDescriptorBuilder>
974 GetClusterSummaries(const RNTupleDescriptor &ntplDesc, DescriptorId_t clusterGroupId);
975
977};
978
979// clang-format off
980/**
981\class ROOT::Experimental::RColumnGroupDescriptorBuilder
982\ingroup NTuple
983\brief A helper class for piece-wise construction of an RColumnGroupDescriptor
984*/
985// clang-format on
987private:
989
990public:
992
994 {
995 fColumnGroup.fColumnGroupId = columnGroupId;
996 return *this;
997 }
998 void AddColumn(DescriptorId_t physicalId) { fColumnGroup.fPhysicalColumnIds.insert(physicalId); }
999
1001};
1002
1003// clang-format off
1004/**
1005\class ROOT::Experimental::RNTupleDescriptorBuilder
1006\ingroup NTuple
1007\brief A helper class for piece-wise construction of an RNTupleDescriptor
1008
1009Used by RPageStorage implementations in order to construct the RNTupleDescriptor from the various header parts.
1010*/
1011// clang-format on
1013private:
1015 std::uint32_t fHeaderCRC32 = 0;
1016
1018public:
1019 /// Checks whether invariants hold:
1020 /// * NTuple name is valid
1021 /// * Fields have valid parent and child ids
1025
1026 void SetNTuple(const std::string_view name, const std::string_view description);
1027 void SetHeaderCRC32(std::uint32_t crc32) { fHeaderCRC32 = crc32; }
1028 std::uint32_t GetHeaderCRC32() const { return fHeaderCRC32; }
1029
1031 /// The real footer size also include the page list envelopes
1033
1034 void AddField(const RFieldDescriptor& fieldDesc);
1036
1037 void AddColumn(DescriptorId_t logicalId, DescriptorId_t physicalId, DescriptorId_t fieldId,
1038 const RColumnModel &model, std::uint32_t index);
1040
1041 RResult<void> AddClusterSummary(DescriptorId_t clusterId, std::uint64_t firstEntry, std::uint64_t nEntries);
1043
1044 /// Used during writing. For reading, cluster summaries are added in the builder and cluster details are added
1045 /// on demand through the RNTupleDescriptor.
1047
1048 /// Clears so-far stored clusters, fields, and columns and return to a pristine ntuple descriptor
1049 void Reset();
1050
1051 /// Mark the beginning of the header extension; any fields and columns added after a call to this function are
1052 /// annotated as begin part of the header extension.
1053 void BeginHeaderExtension();
1054};
1055
1056} // namespace Experimental
1057} // namespace ROOT
1058
1059#endif // ROOT7_RNTupleDescriptor
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
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 id
char name[80]
Definition TGX11.cxx:110
A helper class for piece-wise construction of an RClusterDescriptor.
RClusterDescriptorBuilder(DescriptorId_t clusterId, std::uint64_t firstEntryIndex, std::uint64_t nEntries)
Make an empty cluster descriptor builder.
RResult< void > CommitColumnRange(DescriptorId_t physicalId, std::uint64_t firstElementIndex, std::uint32_t compressionSettings, const RClusterDescriptor::RPageRange &pageRange)
RResult< RClusterDescriptor > MoveDescriptor()
Move out the full cluster descriptor including page locations.
Meta-data for a set of ntuple clusters.
std::unordered_map< DescriptorId_t, RPageRange > fPageRanges
RClusterDescriptor(DescriptorId_t clusterId, std::uint64_t firstEntryIndex, std::uint64_t nEntries)
RClusterDescriptor(RClusterDescriptor &&other)=default
bool ContainsColumn(DescriptorId_t physicalId) const
RClusterDescriptor(const RClusterDescriptor &other)=delete
NTupleSize_t fFirstEntryIndex
Clusters can be swapped by adjusting the entry offsets.
RClusterDescriptor & operator=(const RClusterDescriptor &other)=delete
const RColumnRange & GetColumnRange(DescriptorId_t physicalId) const
std::unordered_set< DescriptorId_t > GetColumnIds() const
std::unordered_map< DescriptorId_t, RColumnRange > fColumnRanges
bool operator==(const RClusterDescriptor &other) const
const RPageRange & GetPageRange(DescriptorId_t physicalId) const
A helper class for piece-wise construction of an RClusterGroupDescriptor.
RClusterGroupDescriptorBuilder & ClusterGroupId(DescriptorId_t clusterGroupId)
RResult< RClusterGroupDescriptor > MoveDescriptor()
RClusterGroupDescriptorBuilder & PageListLength(std::uint32_t pageListLength)
static std::vector< RClusterDescriptorBuilder > GetClusterSummaries(const RNTupleDescriptor &ntplDesc, DescriptorId_t clusterGroupId)
Used to prepare the cluster descriptor builders when loading the page locations for a certain cluster...
RClusterGroupDescriptorBuilder & PageListLocator(const RNTupleLocator &pageListLocator)
Clusters are stored in cluster groups.
RClusterGroupDescriptor(const RClusterGroupDescriptor &other)=delete
RClusterGroupDescriptor & operator=(RClusterGroupDescriptor &&other)=default
const std::vector< DescriptorId_t > & GetClusterIds() const
RClusterGroupDescriptor & operator=(const RClusterGroupDescriptor &other)=delete
std::uint32_t fPageListLength
Uncompressed size of the page list.
RNTupleLocator fPageListLocator
The page list that corresponds to the cluster group.
bool Contains(DescriptorId_t clusterId) const
bool operator==(const RClusterGroupDescriptor &other) const
RClusterGroupDescriptor(RClusterGroupDescriptor &&other)=default
A helper class for piece-wise construction of an RColumnDescriptor.
RColumnDescriptorBuilder & Model(const RColumnModel &model)
RColumnDescriptorBuilder()=default
Make an empty column descriptor builder.
RResult< RColumnDescriptor > MakeDescriptor() const
Attempt to make a column descriptor.
RColumnDescriptorBuilder & FieldId(DescriptorId_t fieldId)
RColumnDescriptorBuilder & Index(std::uint32_t index)
RColumnDescriptorBuilder & LogicalColumnId(DescriptorId_t logicalColumnId)
RColumnDescriptorBuilder & PhysicalColumnId(DescriptorId_t physicalColumnId)
Meta-data stored for every column of an ntuple.
DescriptorId_t fPhysicalColumnId
Usually identical to the logical column ID, except for alias columns where it references the shadowed...
RColumnDescriptor(const RColumnDescriptor &other)=delete
DescriptorId_t fLogicalColumnId
The actual column identifier, which is the link to the corresponding field.
RColumnDescriptor Clone() const
Get a copy of the descriptor.
RColumnDescriptor(RColumnDescriptor &&other)=default
DescriptorId_t fFieldId
Every column belongs to one and only one field.
RColumnDescriptor & operator=(const RColumnDescriptor &other)=delete
RColumnModel fModel
Contains the column type and whether it is sorted.
std::uint32_t fIndex
A field can be serialized into several columns, which are numbered from zero to $n$.
bool operator==(const RColumnDescriptor &other) const
A helper class for piece-wise construction of an RColumnGroupDescriptor.
RColumnGroupDescriptorBuilder & ColumnGroupId(DescriptorId_t columnGroupId)
RResult< RColumnGroupDescriptor > MoveDescriptor()
Meta-data for a sets of columns; non-trivial column groups are used for sharded clusters.
RColumnGroupDescriptor(const RColumnGroupDescriptor &other)=delete
RColumnGroupDescriptor & operator=(const RColumnGroupDescriptor &other)=delete
std::unordered_set< DescriptorId_t > fPhysicalColumnIds
RColumnGroupDescriptor & operator=(RColumnGroupDescriptor &&other)=default
bool operator==(const RColumnGroupDescriptor &other) const
bool Contains(DescriptorId_t physicalId) const
const std::unordered_set< DescriptorId_t > & GetPhysicalColumnIds() const
RColumnGroupDescriptor(RColumnGroupDescriptor &&other)=default
Holds the static meta-data of an RNTuple column.
A field translates read and write calls from/to underlying columns to/from tree values.
A helper class for piece-wise construction of an RFieldDescriptor.
RFieldDescriptorBuilder & FieldName(const std::string &fieldName)
RFieldDescriptorBuilder & NRepetitions(std::uint64_t nRepetitions)
static RFieldDescriptorBuilder FromField(const Detail::RFieldBase &field)
Make a new RFieldDescriptorBuilder based off a live NTuple field.
RFieldDescriptorBuilder & Structure(const ENTupleStructure &structure)
RResult< RFieldDescriptor > MakeDescriptor() const
Attempt to make a field descriptor.
RFieldDescriptorBuilder & TypeName(const std::string &typeName)
RFieldDescriptorBuilder & TypeVersion(std::uint32_t typeVersion)
RFieldDescriptorBuilder & ParentId(DescriptorId_t id)
RFieldDescriptorBuilder & FieldDescription(const std::string &fieldDescription)
RFieldDescriptorBuilder & FieldVersion(std::uint32_t fieldVersion)
RFieldDescriptorBuilder()=default
Make an empty dangling field descriptor.
RFieldDescriptorBuilder & TypeAlias(const std::string &typeAlias)
RFieldDescriptorBuilder & FieldId(DescriptorId_t fieldId)
Meta-data stored for every field of an ntuple.
std::vector< DescriptorId_t > fLinkIds
The pointers in the other direction from parent to children.
std::uint32_t fTypeVersion
The version of the C++ type itself.
std::unique_ptr< Detail::RFieldBase > CreateField(const RNTupleDescriptor &ntplDesc) const
In general, we create a field simply from the C++ type name.
std::string fFieldDescription
Free text set by the user.
std::string fFieldName
The leaf name, not including parent fields.
std::uint32_t fFieldVersion
The version of the C++-type-to-column translation mechanics.
const std::vector< DescriptorId_t > & GetLinkIds() const
RFieldDescriptor(const RFieldDescriptor &other)=delete
DescriptorId_t fParentId
Establishes sub field relationships, such as classes and collections.
RFieldDescriptor Clone() const
Get a copy of the descriptor.
bool operator==(const RFieldDescriptor &other) const
std::string fTypeAlias
A typedef or using directive that resolved to the type name during field creation.
ENTupleStructure fStructure
The structural information carried by this field in the data model tree.
RFieldDescriptor & operator=(const RFieldDescriptor &other)=delete
RFieldDescriptor(RFieldDescriptor &&other)=default
std::string fTypeName
The C++ type that was used when writing the field.
std::uint64_t fNRepetitions
The number of elements per entry for fixed-size arrays.
A helper class for piece-wise construction of an RNTupleDescriptor.
RResult< void > EnsureValidDescriptor() const
Checks whether invariants hold:
void AddToOnDiskFooterSize(std::uint64_t size)
The real footer size also include the page list envelopes.
RResult< void > AddClusterSummary(DescriptorId_t clusterId, std::uint64_t firstEntry, std::uint64_t nEntries)
RResult< void > EnsureFieldExists(DescriptorId_t fieldId) const
RResult< void > AddFieldLink(DescriptorId_t fieldId, DescriptorId_t linkId)
void SetNTuple(const std::string_view name, const std::string_view description)
const RNTupleDescriptor & GetDescriptor() const
void Reset()
Clears so-far stored clusters, fields, and columns and return to a pristine ntuple descriptor.
void AddColumn(DescriptorId_t logicalId, DescriptorId_t physicalId, DescriptorId_t fieldId, const RColumnModel &model, std::uint32_t index)
void AddClusterGroup(RClusterGroupDescriptorBuilder &&clusterGroup)
RResult< void > AddClusterWithDetails(RClusterDescriptor &&clusterDesc)
Used during writing.
void BeginHeaderExtension()
Mark the beginning of the header extension; any fields and columns added after a call to this functio...
void AddField(const RFieldDescriptor &fieldDesc)
Used to loop over all the clusters of an ntuple (in unspecified order)
const RNTupleDescriptor & fNTuple
The associated NTuple for this range.
Used to loop over all the cluster groups of an ntuple (in unspecified order)
const RNTupleDescriptor & fNTuple
The associated NTuple for this range.
RIterator(const RNTupleDescriptor &ntuple, const std::vector< DescriptorId_t > &columns, std::size_t index)
const std::vector< DescriptorId_t > & fColumns
The enclosing range's descriptor id list.
const RNTupleDescriptor & fNTuple
The enclosing range's NTuple.
const RNTupleDescriptor & fNTuple
The associated NTuple for this range.
std::vector< DescriptorId_t > fColumns
The descriptor ids of the columns ordered by index id.
RColumnDescriptorIterable(const RNTupleDescriptor &ntuple, const RFieldDescriptor &field)
const std::vector< DescriptorId_t > & fFieldChildren
The enclosing range's descriptor id list.
const RNTupleDescriptor & fNTuple
The enclosing range's NTuple.
RIterator(const RNTupleDescriptor &ntuple, const std::vector< DescriptorId_t > &fieldChildren, std::size_t index)
std::vector< DescriptorId_t > fFieldChildren
The descriptor ids of the child fields.
const RNTupleDescriptor & fNTuple
The associated NTuple for this range.
RFieldDescriptorIterable(const RNTupleDescriptor &ntuple, const RFieldDescriptor &field, const std::function< bool(DescriptorId_t, 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...
std::vector< DescriptorId_t > fFields
Contains the list of field IDs that are part of the header extension; the corresponding columns are a...
std::uint64_t fNLogicalColumns
Number of logical and physical columns; updated by the descriptor builder when columns are added.
The on-storage meta-data of an ntuple.
std::uint64_t fNPhysicalColumns
Updated by the descriptor builder when columns are added.
std::unordered_map< DescriptorId_t, RClusterDescriptor > fClusterDescriptors
May contain only a subset of all the available clusters, e.g.
std::uint64_t fGeneration
Once constructed by an RNTupleDescriptorBuilder, the descriptor is mostly immutable except for set of...
std::uint64_t fOnDiskFooterSize
Like fOnDiskHeaderSize, contains both cluster summaries and page locations.
std::uint64_t fNEntries
Updated by the descriptor builder when the cluster summaries are added.
DescriptorId_t FindPhysicalColumnId(DescriptorId_t fieldId, std::uint32_t columnIndex) const
NTupleSize_t GetNElements(DescriptorId_t physicalColumnId) const
std::unique_ptr< RNTupleModel > GenerateModel() const
Re-create the C++ model from the stored meta-data.
DescriptorId_t FindLogicalColumnId(DescriptorId_t fieldId, std::uint32_t columnIndex) const
RClusterGroupDescriptorIterable GetClusterGroupIterable() const
std::unordered_map< DescriptorId_t, RClusterGroupDescriptor > fClusterGroupDescriptors
DescriptorId_t FindNextClusterId(DescriptorId_t clusterId) const
DescriptorId_t FindPrevClusterId(DescriptorId_t clusterId) const
RResult< void > DropClusterDetails(DescriptorId_t clusterId)
RFieldDescriptorIterable GetFieldIterable(const RFieldDescriptor &fieldDesc, const std::function< bool(DescriptorId_t, DescriptorId_t)> &comparator) const
DescriptorId_t GetFieldZeroId() const
Returns the logical parent of all top-level NTuple data fields.
RColumnDescriptorIterable GetColumnIterable(const RFieldDescriptor &fieldDesc) const
std::unordered_map< DescriptorId_t, RColumnDescriptor > fColumnDescriptors
std::unique_ptr< RNTupleDescriptor > Clone() const
DescriptorId_t FindClusterId(DescriptorId_t physicalColumnId, NTupleSize_t index) const
RNTupleDescriptor(RNTupleDescriptor &&other)=default
std::string fName
The ntuple name needs to be unique in a given storage location (file)
RFieldDescriptorIterable GetTopLevelFields() const
const RClusterDescriptor & GetClusterDescriptor(DescriptorId_t clusterId) const
RNTupleDescriptor(const RNTupleDescriptor &other)=delete
std::unordered_map< DescriptorId_t, RFieldDescriptor > fFieldDescriptors
RFieldDescriptorIterable GetFieldIterable(const RFieldDescriptor &fieldDesc) const
RNTupleDescriptor & operator=(RNTupleDescriptor &&other)=default
NTupleSize_t GetNEntries() const
We know the number of entries from adding the cluster summaries.
RFieldDescriptorIterable GetTopLevelFields(const std::function< bool(DescriptorId_t, DescriptorId_t)> &comparator) const
RFieldDescriptorIterable GetFieldIterable(DescriptorId_t fieldId) const
bool operator==(const RNTupleDescriptor &other) const
std::string GetQualifiedFieldName(DescriptorId_t fieldId) const
Walks up the parents of the field ID and returns a field name of the form a.b.c.d In case of invalid ...
DescriptorId_t FindFieldId(std::string_view fieldName, DescriptorId_t parentId) const
const RColumnDescriptor & GetColumnDescriptor(DescriptorId_t columnId) const
RClusterDescriptorIterable GetClusterIterable() const
RResult< void > AddClusterDetails(RClusterDescriptor &&clusterDesc)
Methods to load and drop cluster details.
const RFieldDescriptor & GetFieldDescriptor(DescriptorId_t fieldId) const
std::unique_ptr< RHeaderExtension > fHeaderExtension
const RClusterGroupDescriptor & GetClusterGroupDescriptor(DescriptorId_t clusterGroupId) const
RNTupleDescriptor & operator=(const RNTupleDescriptor &other)=delete
std::string fDescription
Free text from the user.
RColumnDescriptorIterable GetColumnIterable(DescriptorId_t fieldId) const
const RHeaderExtension * GetHeaderExtension() const
Return header extension information; if the descriptor does not have a header extension,...
std::uint64_t fOnDiskHeaderSize
Set by the descriptor builder when deserialized.
const RFieldDescriptor & GetFieldZero() const
void PrintInfo(std::ostream &output) const
RFieldDescriptorIterable GetFieldIterable(DescriptorId_t fieldId, const std::function< bool(DescriptorId_t, DescriptorId_t)> &comparator) const
The class is used as a return type for operations that can fail; wraps a value of type T or an RError...
Definition RError.hxx:207
const Int_t n
Definition legend1.C:16
std::uint64_t NTupleSize_t
Integer type long enough to hold the maximum number of entries in a column.
ENTupleStructure
The fields in the ntuple model tree can carry different structural information about the type system.
std::uint64_t DescriptorId_t
Distriniguishes elements of the same type within a descriptor, e.g. different fields.
constexpr NTupleSize_t kInvalidNTupleIndex
constexpr ClusterSize_t kInvalidClusterIndex(std::uint64_t(-1))
constexpr DescriptorId_t kInvalidDescriptorId
This file contains a specialised ROOT message handler to test for diagnostic in unit tests.
The window of element indexes of a particular column in a particular cluster.
std::int64_t fCompressionSettings
The usual format for ROOT compression settings (see Compression.h).
ClusterSize_t fNElements
The number of column elements in the cluster.
RPageInfoExtended(const RPageInfo &pi, RClusterSize::ValueType i, NTupleSize_t n)
RClusterSize::ValueType fFirstInPage
Index (in cluster) of the first element in page.
NTupleSize_t fPageNo
Page number in the corresponding RPageRange.
We do not need to store the element size / uncompressed page size because we know to which column the...
std::uint32_t fNElements
The sum of the elements of all the pages must match the corresponding fNElements field in fColumnRang...
RNTupleLocator fLocator
The meaning of fLocator depends on the storage backend.
Records the parition of data into pages for a particular column in a particular cluster.
RPageInfoExtended Find(RClusterSize::ValueType idxInCluster) const
Find the page in the RPageRange that contains the given element. The element must exist.
RPageRange(const RPageRange &other)=delete
RPageRange & operator=(const RPageRange &other)=delete
Wrap the integer in a struct in order to avoid template specialization clash with std::uint32_t.
Generic information about the physical location of data.
static void output()