48 clone.fFieldId = fFieldId;
49 clone.fFieldVersion = fFieldVersion;
50 clone.fTypeVersion = fTypeVersion;
51 clone.fFieldName = fFieldName;
52 clone.fFieldDescription = fFieldDescription;
54 clone.fTypeAlias = fTypeAlias;
55 clone.fNRepetitions = fNRepetitions;
56 clone.fStructure = fStructure;
57 clone.fParentId = fParentId;
58 clone.fLinkIds = fLinkIds;
62std::unique_ptr<ROOT::Experimental::RFieldBase>
65 if (GetTypeName().empty()) {
70 for (
auto id : fLinkIds) {
84 throw RException(
R__FAIL(
"unknown field type for field \"" + GetFieldName() +
"\""));
88 auto field =
RFieldBase::Create(GetFieldName(), GetTypeAlias().empty() ? GetTypeName() : GetTypeAlias()).Unwrap();
89 field->SetOnDiskId(fFieldId);
91 f.SetOnDiskId(
ntplDesc.FindFieldId(
f.GetFieldName(),
f.GetParent()->GetOnDiskId()));
101 return fLogicalColumnId ==
other.fLogicalColumnId && fPhysicalColumnId ==
other.fPhysicalColumnId &&
102 fModel ==
other.fModel && fFieldId ==
other.fFieldId && fIndex ==
other.fIndex;
110 clone.fLogicalColumnId = fLogicalColumnId;
111 clone.fPhysicalColumnId = fPhysicalColumnId;
112 clone.fModel = fModel;
113 clone.fFieldId = fFieldId;
114 clone.fIndex = fIndex;
115 clone.fFirstElementIndex = fFirstElementIndex;
129 for (
const auto &pi : fPageInfos) {
149 const auto nElements = std::accumulate(fPageInfos.begin(), fPageInfos.end(), 0U,
150 [](std::size_t
n,
const auto &
PI) { return n + PI.fNElements; });
165 PI.fLocator.fBytesOnStorage =
element.GetPackedSize(
PI.fNElements);
171 std::make_move_iterator(fPageInfos.end()));
178 return fClusterId ==
other.fClusterId && fFirstEntryIndex ==
other.fFirstEntryIndex &&
179 fNEntries ==
other.fNEntries && fColumnRanges ==
other.fColumnRanges && fPageRanges ==
other.fPageRanges;
185 std::unordered_set<DescriptorId_t>
result;
186 for (
const auto &
x : fColumnRanges)
194 for (
const auto &
pr : fPageRanges) {
195 for (
const auto &pi :
pr.second.fPageInfos) {
196 nbytes += pi.fLocator.fBytesOnStorage;
205 clone.fClusterId = fClusterId;
206 clone.fFirstEntryIndex = fFirstEntryIndex;
207 clone.fNEntries = fNEntries;
208 clone.fColumnRanges = fColumnRanges;
209 for (
const auto &
d : fPageRanges)
210 clone.fPageRanges.emplace(
d.first,
d.second.Clone());
220 return fName ==
other.fName &&
221 fDescription ==
other.fDescription &&
222 fNEntries ==
other.fNEntries &&
223 fGeneration ==
other.fGeneration &&
224 fFieldDescriptors ==
other.fFieldDescriptors &&
225 fColumnDescriptors ==
other.fColumnDescriptors &&
226 fClusterGroupDescriptors ==
other.fClusterGroupDescriptors &&
227 fClusterDescriptors ==
other.fClusterDescriptors;
235 for (
const auto &cd : fClusterDescriptors) {
250 if (
posDot != std::string::npos) {
255 for (
const auto &fd : fFieldDescriptors) {
256 if (fd.second.GetParentId() ==
parentId && fd.second.GetFieldName() ==
leafName)
257 return fd.second.GetId();
286 return FindFieldId(
fieldName, GetFieldZeroId());
292 for (
const auto &cd : fColumnDescriptors) {
294 return cd.second.GetLogicalId();
305 return GetColumnDescriptor(
logicalId).GetPhysicalId();
312 for (
const auto &cd : fClusterDescriptors) {
317 return cd.second.GetId();
330 for (
const auto &cd : fClusterDescriptors) {
332 return cd.second.GetId();
344 for (
const auto &cd : fClusterDescriptors) {
345 if (cd.second.GetFirstEntryIndex() + cd.second.GetNEntries() ==
clusterDesc.GetFirstEntryIndex())
346 return cd.second.GetId();
351std::vector<ROOT::Experimental::DescriptorId_t>
356 std::vector<DescriptorId_t>
fields;
365 for (
unsigned int i = 0;
true; ++i) {
401 std::vector<std::uint64_t>
result;
402 unsigned int base = 0;
403 std::uint64_t flags = 0;
405 if ((
f > 0) && ((
f % 64) == 0))
407 while (
f > base + 64) {
408 result.emplace_back(flags);
415 result.emplace_back(flags);
425 return R__FAIL(
"invalid attempt to add details of unknown cluster group");
426 if (iter->second.HasClusterDetails())
427 return R__FAIL(
"invalid attempt to re-populate cluster group details");
429 return R__FAIL(
"mismatch of number of clusters");
436 return R__FAIL(
"invalid attempt to re-populate existing cluster");
441 iter->second =
cgBuilder.MoveDescriptor().Unwrap();
450 return R__FAIL(
"invalid attempt to drop cluster details of unknown cluster group");
451 if (!iter->second.HasClusterDetails())
452 return R__FAIL(
"invalid attempt to drop details of cluster group summary");
454 for (
auto clusterId : iter->second.GetClusterIds())
456 iter->second = iter->second.CloneSummary();
462 auto fieldZero = std::make_unique<RFieldZero>();
466 model->AddField(
topDesc.CreateField(*
this));
473 auto clone = std::make_unique<RNTupleDescriptor>();
484 clone->fFieldDescriptors.emplace(
d.first,
d.second.Clone());
486 clone->fColumnDescriptors.emplace(
d.first,
d.second.Clone());
488 clone->fClusterGroupDescriptors.emplace(
d.first,
d.second.Clone());
490 clone->fClusterDescriptors.emplace(
d.first,
d.second.Clone());
500 return fColumnGroupId ==
other.fColumnGroupId && fPhysicalColumnIds ==
other.fPhysicalColumnIds;
507 return fClusterGroupId ==
other.fClusterGroupId && fClusterIds ==
other.fClusterIds &&
514 clone.fClusterGroupId = fClusterGroupId;
515 clone.fPageListLocator = fPageListLocator;
516 clone.fPageListLength = fPageListLength;
517 clone.fMinEntry = fMinEntry;
518 clone.fEntrySpan = fEntrySpan;
526 clone.fClusterIds = fClusterIds;
537 return R__FAIL(
"column ID mismatch");
538 if (fCluster.fPageRanges.count(
physicalId) > 0)
539 return R__FAIL(
"column ID conflict");
542 for (
const auto &pi :
pageRange.fPageInfos) {
575 for (const auto &c : desc.GetColumnIterable(fieldId)) {
576 const DescriptorId_t physicalId = c.GetPhysicalId();
577 auto &columnRange = fCluster.fColumnRanges[physicalId];
578 auto &pageRange = fCluster.fPageRanges[physicalId];
582 if (columnRange.fPhysicalColumnId == kInvalidDescriptorId) {
583 columnRange.fPhysicalColumnId = physicalId;
584 columnRange.fFirstElementIndex = 0;
585 columnRange.fNElements = 0;
587 pageRange.fPhysicalColumnId = physicalId;
595 if (c.IsDeferredColumn()) {
596 columnRange.fFirstElementIndex = fCluster.GetFirstEntryIndex() * nRepetitions;
597 columnRange.fNElements = fCluster.GetNEntries() * nRepetitions;
598 const auto element = Internal::RColumnElementBase::Generate<void>(c.GetModel().GetType());
599 pageRange.ExtendToFitColumnRange(columnRange, *element, Internal::RPage::kPageZeroSize);
612 return R__FAIL(
"unset cluster ID");
613 if (fCluster.fNEntries == 0)
614 return R__FAIL(
"empty cluster");
615 for (
const auto &
pr : fCluster.fPageRanges) {
616 if (fCluster.fColumnRanges.count(
pr.first) == 0) {
617 return R__FAIL(
"missing column range");
621 std::swap(
result, fCluster);
645 return R__FAIL(
"unset cluster group ID");
647 std::swap(
result, fClusterGroup);
657 return R__FAIL(
"unset column group ID");
659 std::swap(
result, fColumnGroup);
668 if (fDescriptor.fFieldDescriptors.count(
fieldId) == 0)
669 return R__FAIL(
"field with id '" + std::to_string(
fieldId) +
"' doesn't exist");
681 for (
const auto&
key_val: fDescriptor.fFieldDescriptors) {
682 const auto&
id =
key_val.first;
683 const auto& desc =
key_val.second;
686 return R__FAIL(
"field with id '" + std::to_string(
id) +
"' has an invalid parent id");
695 std::swap(
result, fDescriptor);
702 fDescriptor.fName = std::string(
name);
703 fDescriptor.fDescription = std::string(
description);
710 fDescriptor.fFeatureFlags.insert(
flag);
717 return R__FAIL(
"invalid logical column id");
719 return R__FAIL(
"invalid physical column id");
721 return R__FAIL(
"invalid column model");
723 return R__FAIL(
"invalid field id, dangling column");
724 return fColumn.Clone();
739 .TypeVersion(
field.GetTypeVersion())
740 .FieldName(
field.GetFieldName())
741 .FieldDescription(
field.GetDescription())
742 .TypeName(
field.GetTypeName())
743 .TypeAlias(
field.GetTypeAlias())
744 .Structure(
field.GetStructure())
745 .NRepetitions(
field.GetNRepetitions());
753 return R__FAIL(
"invalid field id");
756 return R__FAIL(
"invalid field structure");
765 return fField.Clone();
771 if (fDescriptor.fHeaderExtension)
772 fDescriptor.fHeaderExtension->AddFieldId(
fieldDesc.GetId());
782 return R__FAIL(
"child field with id '" + std::to_string(
linkId) +
"' doesn't exist in NTuple");
784 if (
linkId == fDescriptor.GetFieldZeroId()) {
785 return R__FAIL(
"cannot make FieldZero a child field");
788 auto parentId = fDescriptor.fFieldDescriptors.at(
linkId).GetParentId();
790 return R__FAIL(
"field '" + std::to_string(
linkId) +
"' already has a parent ('" +
794 return R__FAIL(
"cannot make field '" + std::to_string(
fieldId) +
"' a child of itself");
796 fDescriptor.fFieldDescriptors.at(
linkId).fParentId =
fieldId;
797 fDescriptor.fFieldDescriptors.at(
fieldId).fLinkIds.push_back(
linkId);
814 if (!
c.IsAliasColumn())
815 fDescriptor.fNPhysicalColumns++;
816 if (fDescriptor.fHeaderExtension)
817 fDescriptor.fHeaderExtension->AddColumn(
c.IsAliasColumn());
818 fDescriptor.fColumnDescriptors.emplace(
logicalId, std::move(
c));
831 return R__FAIL(
"column index clash");
835 return R__FAIL(
"out of bounds column index");
838 if (
columnDesc.GetModel() != fDescriptor.GetColumnDescriptor(
columnDesc.GetPhysicalId()).GetModel())
839 return R__FAIL(
"alias column type mismatch");
844 fDescriptor.fNPhysicalColumns++;
846 if (fDescriptor.fHeaderExtension)
847 fDescriptor.fHeaderExtension->AddColumn(
columnDesc.IsAliasColumn());
856 if (fDescriptor.fClusterGroupDescriptors.count(
id) > 0)
857 return R__FAIL(
"cluster group id clash");
860 fDescriptor.fClusterGroupDescriptors.emplace(
id, std::move(
clusterGroup));
866 fDescriptor.fName =
"";
867 fDescriptor.fDescription =
"";
868 fDescriptor.fFieldDescriptors.clear();
869 fDescriptor.fColumnDescriptors.clear();
870 fDescriptor.fClusterDescriptors.clear();
871 fDescriptor.fClusterGroupDescriptors.clear();
872 fDescriptor.fHeaderExtension.reset();
877 if (!fDescriptor.fHeaderExtension)
878 fDescriptor.fHeaderExtension = std::make_unique<RNTupleDescriptor::RHeaderExtension>();
885 if (fDescriptor.fClusterDescriptors.count(
clusterId) > 0)
886 return R__FAIL(
"cluster id clash");
#define R__FORWARD_ERROR(res)
Short-hand to return an RResult<T> in an error state (i.e. after checking)
#define R__FAIL(msg)
Short-hand to return an RResult<T> in an error state; the RError is implicitly converted into RResult...
TObject * clone(const char *newname) const override
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
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 result
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
A helper class for piece-wise construction of an RClusterDescriptor.
RClusterDescriptorBuilder & AddDeferredColumnRanges(const RNTupleDescriptor &desc)
Add column and page ranges for deferred columns missing in this cluster.
RResult< RClusterDescriptor > MoveDescriptor()
Move out the full cluster descriptor including page locations.
RResult< void > CommitColumnRange(DescriptorId_t physicalId, std::uint64_t firstElementIndex, std::uint32_t compressionSettings, const RClusterDescriptor::RPageRange &pageRange)
A helper class for piece-wise construction of an RClusterGroupDescriptor.
RResult< RClusterGroupDescriptor > MoveDescriptor()
static RClusterGroupDescriptorBuilder FromSummary(const RClusterGroupDescriptor &clusterGroupDesc)
RResult< RColumnDescriptor > MakeDescriptor() const
Attempt to make a column descriptor.
A column element encapsulates the translation between basic C++ types and their column representation...
RResult< RColumnGroupDescriptor > MoveDescriptor()
A helper class for piece-wise construction of an RFieldDescriptor.
static RFieldDescriptorBuilder FromField(const RFieldBase &field)
Make a new RFieldDescriptorBuilder based off a live NTuple field.
RResult< RFieldDescriptor > MakeDescriptor() const
Attempt to make a field descriptor.
RFieldDescriptorBuilder()=default
Make an empty dangling field descriptor.
void BeginHeaderExtension()
Mark the beginning of the header extension; any fields and columns added after a call to this functio...
RResult< void > EnsureFieldExists(DescriptorId_t fieldId) const
RResult< void > AddFieldLink(DescriptorId_t fieldId, DescriptorId_t linkId)
RResult< void > EnsureValidDescriptor() const
Checks whether invariants hold:
RResult< void > AddCluster(RClusterDescriptor &&clusterDesc)
void SetNTuple(const std::string_view name, const std::string_view description)
RResult< void > AddClusterGroup(RClusterGroupDescriptor &&clusterGroup)
void SetFeature(unsigned int flag)
void AddField(const RFieldDescriptor &fieldDesc)
void AddColumn(DescriptorId_t logicalId, DescriptorId_t physicalId, DescriptorId_t fieldId, const RColumnModel &model, std::uint32_t index, std::uint64_t firstElementIdx=0U)
RNTupleDescriptor MoveDescriptor()
void Reset()
Clears so-far stored clusters, fields, and columns and return to a pristine ntuple descriptor.
Meta-data for a set of ntuple clusters.
std::unordered_set< DescriptorId_t > GetColumnIds() const
RClusterDescriptor Clone() const
bool operator==(const RClusterDescriptor &other) const
std::uint64_t GetBytesOnStorage() const
Clusters are bundled in cluster groups.
RClusterGroupDescriptor Clone() const
RClusterGroupDescriptor CloneSummary() const
bool operator==(const RClusterGroupDescriptor &other) const
Meta-data stored for every column of an ntuple.
DescriptorId_t fLogicalColumnId
The actual column identifier, which is the link to the corresponding field.
RColumnDescriptor Clone() const
Get a copy of the descriptor.
bool operator==(const RColumnDescriptor &other) const
Meta-data for a sets of columns; non-trivial column groups are used for sharded clusters.
bool operator==(const RColumnGroupDescriptor &other) const
Holds the static meta-data of an RNTuple column.
Base class for all ROOT issued exceptions.
A field translates read and write calls from/to underlying columns to/from tree values.
static RResult< std::unique_ptr< RFieldBase > > Create(const std::string &fieldName, const std::string &canonicalType, const std::string &typeAlias, bool fContinueOnError=false)
Factory method to resurrect a field from the stored on-disk type information.
static RResult< void > EnsureValidFieldName(std::string_view fieldName)
Check whether a given string is a valid field name.
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::unique_ptr< RFieldBase > CreateField(const RNTupleDescriptor &ntplDesc) const
In general, we create a field simply from the C++ type name.
std::uint32_t fTypeVersion
The version of the C++ type itself.
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.
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.
std::uint64_t fNRepetitions
The number of elements per entry for fixed-size arrays.
RColumnDescriptorIterable(const RNTupleDescriptor &ntuple, const RFieldDescriptor &field)
void CollectColumnIds(DescriptorId_t fieldId)
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 groups are added.
DescriptorId_t FindPhysicalColumnId(DescriptorId_t fieldId, std::uint32_t columnIndex) const
std::set< unsigned int > fFeatureFlags
NTupleSize_t GetNElements(DescriptorId_t physicalColumnId) const
DescriptorId_t FindLogicalColumnId(DescriptorId_t fieldId, std::uint32_t columnIndex) const
std::unordered_map< DescriptorId_t, RClusterGroupDescriptor > fClusterGroupDescriptors
DescriptorId_t FindNextClusterId(DescriptorId_t clusterId) const
DescriptorId_t FindPrevClusterId(DescriptorId_t clusterId) const
DescriptorId_t GetFieldZeroId() const
Returns the logical parent of all top-level NTuple data fields.
std::unordered_map< DescriptorId_t, RColumnDescriptor > fColumnDescriptors
std::unique_ptr< RNTupleDescriptor > Clone() const
DescriptorId_t FindClusterId(DescriptorId_t physicalColumnId, NTupleSize_t index) const
std::uint64_t fNClusters
Updated by the descriptor builder when the cluster groups are added.
std::string fName
The ntuple name needs to be unique in a given storage location (file)
RFieldDescriptorIterable GetTopLevelFields() const
std::unordered_map< DescriptorId_t, RFieldDescriptor > fFieldDescriptors
RFieldDescriptorIterable GetFieldIterable(const RFieldDescriptor &fieldDesc) const
std::uint64_t fOnDiskHeaderXxHash3
Set by the descriptor builder when deserialized.
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 ...
RResult< void > AddClusterGroupDetails(DescriptorId_t clusterGroupId, std::vector< RClusterDescriptor > &clusterDescs)
Methods to load and drop cluster group details (cluster IDs and page locations)
DescriptorId_t FindFieldId(std::string_view fieldName, DescriptorId_t parentId) const
const RFieldDescriptor & GetFieldDescriptor(DescriptorId_t fieldId) const
std::unique_ptr< RNTupleModel > CreateModel() const
Re-create the C++ model from the stored meta-data.
RResult< void > DropClusterGroupDetails(DescriptorId_t clusterGroupId)
std::unique_ptr< RHeaderExtension > fHeaderExtension
std::string fDescription
Free text from the user.
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.
std::vector< std::uint64_t > GetFeatureFlags() const
static std::unique_ptr< RNTupleModel > Create()
The class is used as a return type for operations that can fail; wraps a value of type T or an RError...
const_iterator end() const
std::uint64_t NTupleSize_t
Integer type long enough to hold the maximum number of entries in a column.
std::uint64_t DescriptorId_t
Distriniguishes elements of the same type within a descriptor, e.g. different fields.
constexpr DescriptorId_t kInvalidDescriptorId
The window of element indexes of a particular column in a particular cluster.
Wrap the integer in a struct in order to avoid template specialization clash with std::uint64_t.