68std::unique_ptr<ROOT::Experimental::RFieldBase>
72 auto unsplitField = std::make_unique<RUnsplitField>(GetFieldName(), GetTypeName());
73 unsplitField->SetOnDiskId(fFieldId);
77 if (GetTypeName().empty()) {
81 std::vector<std::unique_ptr<RFieldBase>> memberFields;
82 for (
auto id : fLinkIds) {
84 memberFields.emplace_back(memberDesc.CreateField(ntplDesc));
87 auto recordField = std::make_unique<RRecordField>(GetFieldName(), memberFields);
88 recordField->SetOnDiskId(fFieldId);
91 auto recordField = std::make_unique<RRecordField>(
"_0", memberFields);
92 auto collectionField = std::make_unique<RVectorField>(GetFieldName(), std::move(recordField));
93 collectionField->SetOnDiskId(fFieldId);
94 return collectionField;
96 throw RException(
R__FAIL(
"unknown field type for field \"" + GetFieldName() +
"\""));
100 auto field =
RFieldBase::Create(GetFieldName(), GetTypeAlias().empty() ? GetTypeName() : GetTypeAlias()).Unwrap();
101 field->SetOnDiskId(fFieldId);
102 for (
auto &
f : *field)
103 f.SetOnDiskId(ntplDesc.
FindFieldId(
f.GetFieldName(),
f.GetParent()->GetOnDiskId()));
117 if (
fTypeName.compare(0, 10,
"std::pair<") == 0)
119 if (
fTypeName.compare(0, 11,
"std::tuple<") == 0)
156 decltype(idxInCluster) firstInPage = 0;
158 for (
const auto &pi : fPageInfos) {
159 if (firstInPage + pi.fNElements > idxInCluster) {
174 std::size_t pageSize)
179 const auto nElements = std::accumulate(fPageInfos.begin(), fPageInfos.end(), 0U,
180 [](std::size_t
n,
const auto &
PI) { return n + PI.fNElements; });
181 const auto nElementsRequired =
static_cast<std::uint64_t
>(columnRange.
fNElements);
183 if (nElementsRequired == nElements)
185 R__ASSERT((nElementsRequired > nElements) &&
"invalid attempt to shrink RPageRange");
187 std::vector<RPageInfo> pageInfos;
189 const std::uint64_t nElementsPerPage = pageSize / element.
GetSize();
191 for (
auto nRemainingElements = nElementsRequired - nElements; nRemainingElements > 0;) {
193 PI.
fNElements = std::min(nElementsPerPage, nRemainingElements);
196 pageInfos.emplace_back(
PI);
197 nRemainingElements -=
PI.fNElements;
200 pageInfos.insert(pageInfos.end(), std::make_move_iterator(fPageInfos.begin()),
201 std::make_move_iterator(fPageInfos.end()));
202 std::swap(fPageInfos, pageInfos);
203 return nElementsRequired - nElements;
214 std::uint64_t nbytes = 0;
215 for (
const auto &pr : fPageRanges) {
216 for (
const auto &pi : pr.second.fPageInfos) {
217 nbytes += pi.fLocator.fBytesOnStorage;
230 for (
const auto &
d : fPageRanges)
259 return fName == other.
fName &&
275 for (
const auto &cd : fClusterDescriptors) {
276 if (!cd.second.ContainsColumn(physicalColumnId))
278 auto columnRange = cd.second.GetColumnRange(physicalColumnId);
279 result = std::max(
result, columnRange.fFirstElementIndex + columnRange.fNElements);
287 std::string leafName(fieldName);
288 auto posDot = leafName.find_last_of(
'.');
289 if (posDot != std::string::npos) {
290 auto parentName = leafName.substr(0, posDot);
291 leafName = leafName.substr(posDot + 1);
292 parentId = FindFieldId(parentName, parentId);
294 auto itrFieldDesc = fFieldDescriptors.find(parentId);
295 if (itrFieldDesc == fFieldDescriptors.end())
297 for (
const auto linkId : itrFieldDesc->second.GetLinkIds()) {
298 if (fFieldDescriptors.at(linkId).GetFieldName() == leafName)
309 const auto &fieldDescriptor = fFieldDescriptors.at(fieldId);
310 auto prefix = GetQualifiedFieldName(fieldDescriptor.GetParentId());
312 return fieldDescriptor.GetFieldName();
313 return prefix +
"." + fieldDescriptor.GetFieldName();
318 return FindFieldId(fieldName, GetFieldZeroId());
323 std::uint16_t representationIndex)
const
325 auto itr = fFieldDescriptors.find(fieldId);
326 if (itr == fFieldDescriptors.cend())
328 if (columnIndex >= itr->second.GetColumnCardinality())
330 const auto idx = representationIndex * itr->second.GetColumnCardinality() + columnIndex;
331 if (itr->second.GetLogicalColumnIds().size() <= idx)
333 return itr->second.GetLogicalColumnIds()[idx];
338 std::uint16_t representationIndex)
const
340 auto logicalId = FindLogicalColumnId(fieldId, columnIndex, representationIndex);
343 return GetColumnDescriptor(logicalId).GetPhysicalId();
350 for (
const auto &cd : fClusterDescriptors) {
351 if (!cd.second.ContainsColumn(physicalColumnId))
353 auto columnRange = cd.second.GetColumnRange(physicalColumnId);
354 if (columnRange.Contains(
index))
355 return cd.second.GetId();
364 const auto &clusterDesc = GetClusterDescriptor(clusterId);
365 auto firstEntryInNextCluster = clusterDesc.GetFirstEntryIndex() + clusterDesc.GetNEntries();
367 for (
const auto &cd : fClusterDescriptors) {
368 if (cd.second.GetFirstEntryIndex() == firstEntryInNextCluster)
369 return cd.second.GetId();
378 const auto &clusterDesc = GetClusterDescriptor(clusterId);
380 for (
const auto &cd : fClusterDescriptors) {
381 if (cd.second.GetFirstEntryIndex() + cd.second.GetNEntries() == clusterDesc.GetFirstEntryIndex())
382 return cd.second.GetId();
387std::vector<ROOT::Experimental::DescriptorId_t>
392 std::vector<DescriptorId_t> fields;
395 fields.emplace_back(fieldId);
402 : fNTuple(ntuple), fColumns(field.GetLogicalColumnIds())
412 while (!fieldIdQueue.empty()) {
413 auto currFieldId = fieldIdQueue.front();
414 fieldIdQueue.pop_front();
420 auto fieldId = field.GetId();
421 fieldIdQueue.push_back(fieldId);
428 std::vector<std::uint64_t>
result;
429 unsigned int base = 0;
430 std::uint64_t flags = 0;
432 if ((
f > 0) && ((
f % 64) == 0))
434 while (
f > base + 64) {
435 result.emplace_back(flags);
442 result.emplace_back(flags);
448 std::vector<RClusterDescriptor> &clusterDescs)
452 return R__FAIL(
"invalid attempt to add details of unknown cluster group");
453 if (iter->second.HasClusterDetails())
454 return R__FAIL(
"invalid attempt to re-populate cluster group details");
455 if (iter->second.GetNClusters() != clusterDescs.size())
456 return R__FAIL(
"mismatch of number of clusters");
458 std::vector<DescriptorId_t> clusterIds;
459 for (
unsigned i = 0; i < clusterDescs.size(); ++i) {
460 clusterIds.emplace_back(clusterDescs[i].GetId());
463 return R__FAIL(
"invalid attempt to re-populate existing cluster");
467 cgBuilder.AddClusters(clusterIds);
468 iter->second = cgBuilder.MoveDescriptor().Unwrap();
477 return R__FAIL(
"invalid attempt to drop cluster details of unknown cluster group");
478 if (!iter->second.HasClusterDetails())
479 return R__FAIL(
"invalid attempt to drop details of cluster group summary");
481 for (
auto clusterId : iter->second.GetClusterIds())
483 iter->second = iter->second.CloneSummary();
487std::unique_ptr<ROOT::Experimental::RNTupleModel>
490 auto fieldZero = std::make_unique<RFieldZero>();
494 auto field = topDesc.CreateField(*
this);
496 model->AddProjectedField(std::move(field), [
this](
const std::string &targetName) -> std::string {
500 model->AddField(std::move(field));
509 auto clone = std::make_unique<RNTupleDescriptor>();
510 clone->fName =
fName;
521 clone->fFieldDescriptors.emplace(
d.first,
d.second.Clone());
523 clone->fColumnDescriptors.emplace(
d.first,
d.second.Clone());
525 clone->fClusterGroupDescriptors.emplace(
d.first,
d.second.Clone());
527 clone->fClusterDescriptors.emplace(
d.first,
d.second.Clone());
529 clone->fExtraTypeInfoDescriptors.emplace_back(
d.Clone());
531 clone->fHeaderExtension = std::make_unique<RHeaderExtension>(*
fHeaderExtension);
572 DescriptorId_t physicalId, std::uint64_t firstElementIndex, std::uint32_t compressionSettings,
576 return R__FAIL(
"column ID mismatch");
577 if (fCluster.fColumnRanges.count(physicalId) > 0)
578 return R__FAIL(
"column ID conflict");
580 columnRange.fCompressionSettings = compressionSettings;
582 columnRange.fNElements += pi.fNElements;
584 fCluster.fPageRanges[physicalId] = pageRange.
Clone();
585 fCluster.fColumnRanges[physicalId] = columnRange;
592 if (fCluster.fColumnRanges.count(physicalId) > 0)
593 return R__FAIL(
"column ID conflict");
599 fCluster.fColumnRanges[physicalId] = columnRange;
606 for (
auto &[
_, columnRange] : fCluster.fColumnRanges) {
607 if (!columnRange.fIsSuppressed)
614 for (
const auto otherColumnLogicalId : fieldDesc.GetLogicalColumnIds()) {
616 if (otherColumnDesc.GetRepresentationIndex() == columnDesc.GetRepresentationIndex())
618 if (otherColumnDesc.GetIndex() != columnDesc.GetIndex())
622 const auto &otherColumnRange = fCluster.GetColumnRange(otherColumnDesc.GetPhysicalId());
623 if (otherColumnRange.fIsSuppressed)
627 columnRange.fNElements = otherColumnRange.fNElements;
632 return R__FAIL(std::string(
"cannot find non-suppressed column for column ID ") +
633 std::to_string(columnRange.fPhysicalColumnId) +
634 ", cluster ID: " + std::to_string(fCluster.GetId()));
646 auto fnTraverseSubtree = [&](
DescriptorId_t rootFieldId, std::uint64_t nRepetitionsAtThisLevel,
647 const auto &visitField,
const auto &enterSubtree) ->
void {
648 visitField(rootFieldId, nRepetitionsAtThisLevel);
650 const std::uint64_t nRepetitions = std::max(
f.GetNRepetitions(), std::uint64_t{1U}) * nRepetitionsAtThisLevel;
651 enterSubtree(
f.GetId(), nRepetitions, visitField, enterSubtree);
663 topLevelField.GetId(), std::max(topLevelField.GetNRepetitions(), std::uint64_t{1U}),
665 for (const auto &c : desc.GetColumnIterable(fieldId)) {
666 const DescriptorId_t physicalId = c.GetPhysicalId();
667 auto &columnRange = fCluster.fColumnRanges[physicalId];
672 if (columnRange.fPhysicalColumnId == kInvalidDescriptorId) {
673 columnRange.fPhysicalColumnId = physicalId;
674 columnRange.fFirstElementIndex = 0;
675 columnRange.fNElements = 0;
676 columnRange.fIsSuppressed = c.IsSuppressedDeferredColumn();
684 if (c.IsDeferredColumn()) {
685 columnRange.fFirstElementIndex = fCluster.GetFirstEntryIndex() * nRepetitions;
686 columnRange.fNElements = fCluster.GetNEntries() * nRepetitions;
687 if (!columnRange.fIsSuppressed) {
688 auto &pageRange = fCluster.fPageRanges[physicalId];
689 pageRange.fPhysicalColumnId = physicalId;
690 const auto element = Internal::RColumnElementBase::Generate<void>(c.GetType());
691 pageRange.ExtendToFitColumnRange(columnRange, *element, Internal::RPage::kPageZeroSize);
693 } else if (!columnRange.fIsSuppressed) {
694 fCluster.fPageRanges[physicalId].fPhysicalColumnId = physicalId;
707 return R__FAIL(
"unset cluster ID");
708 if (fCluster.fNEntries == 0)
709 return R__FAIL(
"empty cluster");
710 for (
const auto &pr : fCluster.fPageRanges) {
711 if (fCluster.fColumnRanges.count(pr.first) == 0) {
712 return R__FAIL(
"missing column range");
716 std::swap(
result, fCluster);
740 return R__FAIL(
"unset cluster group ID");
742 std::swap(
result, fClusterGroup);
752 return R__FAIL(
"unset column group ID");
754 std::swap(
result, fColumnGroup);
766 std::swap(
result, fExtraTypeInfo);
775 if (fDescriptor.fFieldDescriptors.count(fieldId) == 0)
776 return R__FAIL(
"field with id '" + std::to_string(fieldId) +
"' doesn't exist");
788 for (
const auto &[fieldId, fieldDesc] : fDescriptor.fFieldDescriptors) {
790 if (fieldId != fDescriptor.GetFieldZeroId() && fieldDesc.GetParentId() ==
kInvalidDescriptorId) {
791 return R__FAIL(
"field with id '" + std::to_string(fieldId) +
"' has an invalid parent id");
795 const auto columnCardinality = fieldDesc.GetColumnCardinality();
796 if (columnCardinality == 0)
801 const auto &logicalColumnIds = fieldDesc.GetLogicalColumnIds();
802 const auto nColumns = logicalColumnIds.size();
804 if ((nColumns + 1) == columnCardinality)
807 const auto &lastColumn = fDescriptor.GetColumnDescriptor(logicalColumnIds.back());
808 if (lastColumn.GetIndex() + 1 != columnCardinality)
809 return R__FAIL(
"field with id '" + std::to_string(fieldId) +
"' has incomplete column representations");
817 EnsureValidDescriptor().ThrowOnError();
819 std::swap(
result, fDescriptor);
824 const std::string_view description)
826 fDescriptor.fName = std::string(
name);
827 fDescriptor.fDescription = std::string(description);
834 fDescriptor.fFeatureFlags.insert(flag);
841 return R__FAIL(
"invalid logical column id");
843 return R__FAIL(
"invalid physical column id");
845 return R__FAIL(
"invalid column model");
847 return R__FAIL(
"invalid field id, dangling column");
849 const auto [minBits, maxBits] = RColumnElementBase::GetValidBitRange(fColumn.GetType());
850 if (fColumn.GetBitsOnStorage() < minBits || fColumn.GetBitsOnStorage() > maxBits)
851 return R__FAIL(
"invalid column bit width");
853 return fColumn.Clone();
857 : fField(fieldDesc.
Clone())
885 return R__FAIL(
"invalid field id");
888 return R__FAIL(
"invalid field structure");
897 return fField.Clone();
902 fDescriptor.fFieldDescriptors.emplace(fieldDesc.
GetId(), fieldDesc.
Clone());
903 if (fDescriptor.fHeaderExtension)
904 fDescriptor.fHeaderExtension->AddExtendedField(fieldDesc);
906 fDescriptor.fFieldZeroId = fieldDesc.
GetId();
914 if (!(fieldExists = EnsureFieldExists(fieldId)))
916 if (!(fieldExists = EnsureFieldExists(linkId)))
917 return R__FAIL(
"child field with id '" + std::to_string(linkId) +
"' doesn't exist in NTuple");
919 if (linkId == fDescriptor.GetFieldZeroId()) {
920 return R__FAIL(
"cannot make FieldZero a child field");
923 auto parentId = fDescriptor.fFieldDescriptors.at(linkId).GetParentId();
925 return R__FAIL(
"field '" + std::to_string(linkId) +
"' already has a parent ('" + std::to_string(parentId) +
")");
927 if (fieldId == linkId) {
928 return R__FAIL(
"cannot make field '" + std::to_string(fieldId) +
"' a child of itself");
930 fDescriptor.fFieldDescriptors.at(linkId).fParentId = fieldId;
931 fDescriptor.fFieldDescriptors.at(fieldId).fLinkIds.push_back(linkId);
940 if (!(fieldExists = EnsureFieldExists(sourceId)))
942 if (!(fieldExists = EnsureFieldExists(targetId)))
943 return R__FAIL(
"projected field with id '" + std::to_string(targetId) +
"' doesn't exist in NTuple");
945 if (targetId == fDescriptor.GetFieldZeroId()) {
946 return R__FAIL(
"cannot make FieldZero a projected field");
948 if (sourceId == targetId) {
949 return R__FAIL(
"cannot make field '" + std::to_string(targetId) +
"' a projection of itself");
951 if (fDescriptor.fFieldDescriptors.at(sourceId).IsProjectedField()) {
952 return R__FAIL(
"cannot make field '" + std::to_string(targetId) +
"' a projection of an already projected field");
955 auto &targetDesc = fDescriptor.fFieldDescriptors.at(targetId);
956 if (targetDesc.IsProjectedField() && targetDesc.GetProjectionSourceId() != sourceId) {
957 return R__FAIL(
"field '" + std::to_string(targetId) +
"' has already a projection source ('" +
958 std::to_string(targetDesc.GetProjectionSourceId()) +
")");
960 fDescriptor.fFieldDescriptors.at(targetId).fProjectionSourceId = sourceId;
967 const auto fieldId = columnDesc.GetFieldId();
968 const auto columnIndex = columnDesc.GetIndex();
969 const auto representationIndex = columnDesc.GetRepresentationIndex();
971 auto fieldExists = EnsureFieldExists(fieldId);
975 auto &fieldDesc = fDescriptor.fFieldDescriptors.find(fieldId)->second;
977 if (columnDesc.IsAliasColumn()) {
978 if (columnDesc.GetType() != fDescriptor.GetColumnDescriptor(columnDesc.GetPhysicalId()).GetType())
979 return R__FAIL(
"alias column type mismatch");
981 if (fDescriptor.FindLogicalColumnId(fieldId, columnIndex, representationIndex) !=
kInvalidDescriptorId) {
982 return R__FAIL(
"column index clash");
984 if (columnIndex > 0) {
985 if (fDescriptor.FindLogicalColumnId(fieldId, columnIndex - 1, representationIndex) ==
kInvalidDescriptorId)
986 return R__FAIL(
"out of bounds column index");
988 if (representationIndex > 0) {
989 if (fDescriptor.FindLogicalColumnId(fieldId, 0, representationIndex - 1) ==
kInvalidDescriptorId) {
990 return R__FAIL(
"out of bounds representation index");
992 if (columnIndex == 0) {
993 assert(fieldDesc.fColumnCardinality > 0);
994 if (fDescriptor.FindLogicalColumnId(fieldId, fieldDesc.fColumnCardinality - 1, representationIndex - 1) ==
996 return R__FAIL(
"incomplete column representations");
999 if (columnIndex >= fieldDesc.fColumnCardinality)
1000 return R__FAIL(
"irregular column representations");
1004 fieldDesc.fColumnCardinality = columnIndex + 1;
1007 const auto logicalId = columnDesc.GetLogicalId();
1008 fieldDesc.fLogicalColumnIds.emplace_back(logicalId);
1010 if (!columnDesc.IsAliasColumn())
1011 fDescriptor.fNPhysicalColumns++;
1012 fDescriptor.fColumnDescriptors.emplace(logicalId, std::move(columnDesc));
1013 if (fDescriptor.fHeaderExtension)
1014 fDescriptor.fHeaderExtension->AddExtendedColumn(columnDesc);
1022 const auto id = clusterGroup.GetId();
1023 if (fDescriptor.fClusterGroupDescriptors.count(
id) > 0)
1024 return R__FAIL(
"cluster group id clash");
1025 fDescriptor.fNEntries = std::max(fDescriptor.fNEntries, clusterGroup.GetMinEntry() + clusterGroup.GetEntrySpan());
1026 fDescriptor.fNClusters += clusterGroup.GetNClusters();
1027 fDescriptor.fClusterGroupDescriptors.emplace(
id, std::move(clusterGroup));
1033 fDescriptor.fName =
"";
1034 fDescriptor.fDescription =
"";
1035 fDescriptor.fFieldDescriptors.clear();
1036 fDescriptor.fColumnDescriptors.clear();
1037 fDescriptor.fClusterDescriptors.clear();
1038 fDescriptor.fClusterGroupDescriptors.clear();
1039 fDescriptor.fHeaderExtension.reset();
1044 if (!fDescriptor.fHeaderExtension)
1045 fDescriptor.fHeaderExtension = std::make_unique<RNTupleDescriptor::RHeaderExtension>();
1051 auto clusterId = clusterDesc.GetId();
1052 if (fDescriptor.fClusterDescriptors.count(clusterId) > 0)
1053 return R__FAIL(
"cluster id clash");
1054 fDescriptor.fClusterDescriptors.emplace(clusterId, std::move(clusterDesc));
1062 if (std::find(fDescriptor.fExtraTypeInfoDescriptors.begin(), fDescriptor.fExtraTypeInfoDescriptors.end(),
1063 extraTypeInfoDesc) != fDescriptor.fExtraTypeInfoDescriptors.end()) {
1064 return R__FAIL(
"extra type info duplicates");
1066 fDescriptor.fExtraTypeInfoDescriptors.emplace_back(std::move(extraTypeInfoDesc));
1074 const auto &desc = GetDescriptor();
1077 fnWalkFieldTree = [&desc, &streamerInfoMap, &fnWalkFieldTree](
const RFieldDescriptor &fieldDesc) {
1078 if (fieldDesc.IsCustomClass()) {
1082 throw RException(
R__FAIL(std::string(
"cannot get TClass for ") + fieldDesc.GetTypeName()));
1084 auto streamerInfo = cl->GetStreamerInfo(fieldDesc.GetTypeVersion());
1085 if (!streamerInfo) {
1086 throw RException(
R__FAIL(std::string(
"cannot get streamerInfo for ") + fieldDesc.GetTypeName()));
1088 streamerInfoMap[streamerInfo->GetNumber()] = streamerInfo;
1092 for (
const auto &subFieldDesc : desc.GetFieldIterable(fieldDesc)) {
1093 fnWalkFieldTree(subFieldDesc);
1097 fnWalkFieldTree(desc.GetFieldZero());
1101 for (
const auto &extraTypeInfo : desc.GetExtraTypeInfoIterable()) {
1107 return streamerInfoMap;
1131 return GetFieldIterable(GetFieldDescriptor(fieldId));
1137 return GetFieldIterable(GetFieldDescriptor(fieldId), comparator);
1143 return GetFieldIterable(GetFieldZeroId());
1150 return GetFieldIterable(GetFieldZeroId(), comparator);
#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...
#define R__ASSERT(e)
Checks condition e and reports a fatal error if it's false.
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.
RResult< RClusterDescriptor > MoveDescriptor()
Move out the full cluster descriptor including page locations.
RResult< void > MarkSuppressedColumnRange(DescriptorId_t physicalId)
Books the given column ID as being suppressed in this cluster.
RClusterDescriptorBuilder & AddExtendedColumnRanges(const RNTupleDescriptor &desc)
Add column and page ranges for columns created during late model extension missing in this cluster.
RResult< void > CommitColumnRange(DescriptorId_t physicalId, std::uint64_t firstElementIndex, std::uint32_t compressionSettings, const RClusterDescriptor::RPageRange &pageRange)
RResult< void > CommitSuppressedColumnRanges(const RNTupleDescriptor &desc)
Sets the first element index and number of elements for all the suppressed column ranges.
A helper class for piece-wise construction of an RClusterGroupDescriptor.
RClusterGroupDescriptorBuilder & PageListLocator(const RNTupleLocator &pageListLocator)
RClusterGroupDescriptorBuilder & MinEntry(std::uint64_t minEntry)
RClusterGroupDescriptorBuilder & ClusterGroupId(DescriptorId_t clusterGroupId)
RClusterGroupDescriptorBuilder & EntrySpan(std::uint64_t entrySpan)
RClusterGroupDescriptorBuilder & NClusters(std::uint32_t nClusters)
RClusterGroupDescriptorBuilder & PageListLength(std::uint64_t pageListLength)
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...
std::size_t GetSize() const
std::size_t GetPackedSize(std::size_t nElements=1U) const
RResult< RColumnGroupDescriptor > MoveDescriptor()
A helper class for piece-wise construction of an RFieldDescriptor.
RFieldDescriptorBuilder & TypeVersion(std::uint32_t typeVersion)
RFieldDescriptorBuilder & NRepetitions(std::uint64_t nRepetitions)
RFieldDescriptorBuilder & FieldVersion(std::uint32_t fieldVersion)
RFieldDescriptorBuilder & Structure(const ENTupleStructure &structure)
RFieldDescriptorBuilder & TypeName(const std::string &typeName)
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 & FieldName(const std::string &fieldName)
RFieldDescriptorBuilder()=default
Make an empty dangling field descriptor.
RFieldDescriptorBuilder & TypeChecksum(const std::optional< std::uint32_t > typeChecksum)
RFieldDescriptorBuilder & TypeAlias(const std::string &typeAlias)
RFieldDescriptorBuilder & FieldDescription(const std::string &fieldDescription)
RNTupleSerializer::StreamerInfoMap_t BuildStreamerInfos() const
Get the streamer info records for custom classes. Currently requires the corresponding dictionaires t...
RResult< void > AddFieldProjection(DescriptorId_t sourceId, DescriptorId_t targetId)
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)
RResult< void > AddColumn(RColumnDescriptor &&columnDesc)
RNTupleDescriptor MoveDescriptor()
void Reset()
Clears so-far stored clusters, fields, and columns and return to a pristine ntuple descriptor.
RResult< void > AddExtraTypeInfo(RExtraTypeInfoDescriptor &&extraTypeInfoDesc)
static RResult< StreamerInfoMap_t > DeserializeStreamerInfos(const std::string &extraTypeInfoContent)
std::map< Int_t, TVirtualStreamerInfo * > StreamerInfoMap_t
Meta-data for a set of ntuple clusters.
std::unordered_map< DescriptorId_t, RPageRange > fPageRanges
RColumnRangeIterable GetColumnRangeIterable() const
Returns an iterator over pairs { columnId, columnRange }. The iteration order is unspecified.
NTupleSize_t fFirstEntryIndex
Clusters can be swapped by adjusting the entry offsets.
DescriptorId_t fClusterId
RClusterDescriptor Clone() const
std::unordered_map< DescriptorId_t, RColumnRange > fColumnRanges
bool operator==(const RClusterDescriptor &other) const
std::uint64_t GetBytesOnStorage() const
Clusters are bundled in cluster groups.
std::uint64_t fMinEntry
The minimum first entry number of the clusters in the cluster group.
RClusterGroupDescriptor Clone() const
std::uint64_t fEntrySpan
Number of entries that are (partially for sharded clusters) covered by this cluster group.
std::uint64_t fPageListLength
Uncompressed size of the page list.
std::uint64_t GetMinEntry() const
std::uint64_t GetPageListLength() const
RClusterGroupDescriptor CloneSummary() const
std::uint32_t fNClusters
Number of clusters is always known even if the cluster IDs are not (yet) populated.
std::uint32_t GetNClusters() const
RNTupleLocator fPageListLocator
The page list that corresponds to the cluster group.
DescriptorId_t fClusterGroupId
bool operator==(const RClusterGroupDescriptor &other) const
RNTupleLocator GetPageListLocator() const
std::vector< DescriptorId_t > fClusterIds
The cluster IDs can be empty if the corresponding page list is not loaded.
std::uint64_t GetEntrySpan() const
DescriptorId_t GetId() const
Meta-data stored for every column of an ntuple.
std::uint16_t fBitsOnStorage
The size in bits of elements of this column.
DescriptorId_t fPhysicalColumnId
Usually identical to the logical column ID, except for alias columns where it references the shadowed...
DescriptorId_t fLogicalColumnId
The actual column identifier, which is the link to the corresponding field.
RColumnDescriptor Clone() const
Get a copy of the descriptor.
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.
std::uint16_t fRepresentationIndex
A field may use multiple column representations, which are numbered from zero to $m$.
EColumnType fType
The on-disk column type.
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
Meta-data for a sets of columns; non-trivial column groups are used for sharded clusters.
std::unordered_set< DescriptorId_t > fPhysicalColumnIds
bool operator==(const RColumnGroupDescriptor &other) const
DescriptorId_t fColumnGroupId
Base class for all ROOT issued exceptions.
A field translates read and write calls from/to underlying columns to/from tree values.
const std::string & GetTypeAlias() const
const std::string & GetDescription() const
Get the field's description.
const std::string & GetFieldName() const
ENTupleStructure GetStructure() const
const std::string & GetTypeName() const
static constexpr int kTraitTypeChecksum
The TClass checksum is set and valid.
virtual std::uint32_t GetTypeVersion() const
Indicates an evolution of the C++ type itself.
virtual std::uint32_t GetTypeChecksum() const
Return the current TClass reported checksum of this class. Only valid if kTraitTypeChecksum is set.
virtual std::uint32_t GetFieldVersion() const
Indicates an evolution of the mapping scheme from C++ type to columns.
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.
std::size_t GetNRepetitions() const
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.
DescriptorId_t GetParentId() const
std::unique_ptr< RFieldBase > CreateField(const RNTupleDescriptor &ntplDesc) const
In general, we create a field simply from the C++ type name.
const std::string & GetFieldName() const
std::uint32_t fTypeVersion
The version of the C++ type itself.
std::uint32_t fColumnCardinality
The number of columns in the column representations of the field.
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...
bool IsCustomClass() const
Tells if the field describes a user-defined class with a dictionary.
const std::vector< DescriptorId_t > & GetLogicalColumnIds() const
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.
std::vector< DescriptorId_t > fLogicalColumnIds
The ordered list of columns attached to this field: first by representation index then by column inde...
DescriptorId_t GetId() const
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::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.
DescriptorId_t fProjectionSourceId
For projected fields, the source field ID.
Used to loop over all the clusters of an ntuple (in unspecified order)
Used to loop over all the cluster groups of an ntuple (in unspecified order)
Used to loop over a field's associated columns.
std::vector< DescriptorId_t > fColumns
The descriptor ids of the columns ordered by field, representation, and column index.
RColumnDescriptorIterable(const RNTupleDescriptor &ntuple, const RFieldDescriptor &fieldDesc)
Used to loop over a field's child fields.
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.
std::set< unsigned int > fFeatureFlags
std::vector< RExtraTypeInfoDescriptor > fExtraTypeInfoDescriptors
NTupleSize_t GetNElements(DescriptorId_t physicalColumnId) const
std::unordered_map< DescriptorId_t, RClusterGroupDescriptor > fClusterGroupDescriptors
std::unique_ptr< RNTupleModel > CreateModel(const RCreateModelOptions &options=RCreateModelOptions()) const
Re-create the C++ model from the stored meta-data.
DescriptorId_t FindLogicalColumnId(DescriptorId_t fieldId, std::uint32_t columnIndex, std::uint16_t representationIndex) const
DescriptorId_t FindNextClusterId(DescriptorId_t clusterId) const
DescriptorId_t FindPrevClusterId(DescriptorId_t clusterId) const
std::unordered_map< DescriptorId_t, RColumnDescriptor > fColumnDescriptors
std::unique_ptr< RNTupleDescriptor > Clone() const
RColumnDescriptorIterable GetColumnIterable() 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)
std::unordered_map< DescriptorId_t, RFieldDescriptor > fFieldDescriptors
DescriptorId_t GetFieldZeroId() const
Returns the logical parent of all top-level NTuple data fields.
DescriptorId_t FindPhysicalColumnId(DescriptorId_t fieldId, std::uint32_t columnIndex, std::uint16_t representationIndex) 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 RColumnDescriptor & GetColumnDescriptor(DescriptorId_t columnId) const
RExtraTypeInfoDescriptorIterable GetExtraTypeInfoIterable() const
const RFieldDescriptor & GetFieldDescriptor(DescriptorId_t fieldId) const
RResult< void > DropClusterGroupDetails(DescriptorId_t clusterGroupId)
std::unique_ptr< RHeaderExtension > fHeaderExtension
RClusterGroupDescriptorIterable GetClusterGroupIterable() const
RClusterDescriptorIterable GetClusterIterable() const
std::string fDescription
Free text from the user.
RFieldDescriptorIterable GetTopLevelFields() const
DescriptorId_t fFieldZeroId
Set by the descriptor builder.
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.
RFieldDescriptorIterable GetFieldIterable(const RFieldDescriptor &fieldDesc) const
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...
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
std::uint64_t NTupleSize_t
Integer type long enough to hold the maximum number of entries in a column.
constexpr int kUnknownCompressionSettings
std::uint64_t DescriptorId_t
Distriniguishes elements of the same type within a descriptor, e.g. different fields.
constexpr NTupleSize_t kInvalidNTupleIndex
constexpr DescriptorId_t kInvalidDescriptorId
The window of element indexes of a particular column in a particular cluster.
bool fIsSuppressed
Suppressed columns have an empty page range and unknown compression settings.
int fCompressionSettings
The usual format for ROOT compression settings (see Compression.h).
ClusterSize_t fNElements
The number of column elements in the cluster.
DescriptorId_t fPhysicalColumnId
Wrap the integer in a struct in order to avoid template specialization clash with std::uint64_t.
Modifiers passed to CreateModel
bool fReconstructProjections
If set to true, projected fields will be reconstructed as such.