Logo ROOT  
Reference Guide
RNTupleDescriptor.cxx
Go to the documentation of this file.
1/// \file RNTupleDescriptor.cxx
2/// \ingroup NTuple ROOT7
3/// \author Jakob Blomer <jblomer@cern.ch>
4/// \date 2018-10-04
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#include <ROOT/RError.hxx>
17#include <ROOT/RField.hxx>
19#include <ROOT/RNTupleModel.hxx>
20#include <ROOT/RNTupleUtil.hxx>
21#include <ROOT/RStringView.hxx>
22
23#include <RZip.h>
24#include <TError.h>
25
26#include <algorithm>
27#include <cstdint>
28#include <deque>
29#include <iostream>
30#include <set>
31#include <utility>
32
33
35{
36 return fFieldId == other.fFieldId &&
38 fTypeVersion == other.fTypeVersion &&
39 fFieldName == other.fFieldName &&
41 fTypeName == other.fTypeName &&
43 fStructure == other.fStructure &&
44 fParentId == other.fParentId &&
45 fLinkIds == other.fLinkIds;
46}
47
50{
51 RFieldDescriptor clone;
52 clone.fFieldId = fFieldId;
53 clone.fFieldVersion = fFieldVersion;
54 clone.fTypeVersion = fTypeVersion;
55 clone.fFieldName = fFieldName;
56 clone.fFieldDescription = fFieldDescription;
57 clone.fTypeName = fTypeName;
58 clone.fNRepetitions = fNRepetitions;
59 clone.fStructure = fStructure;
60 clone.fParentId = fParentId;
61 clone.fLinkIds = fLinkIds;
62 return clone;
63}
64
65std::unique_ptr<ROOT::Experimental::Detail::RFieldBase>
67{
68 if (GetTypeName().empty() && GetStructure() == ENTupleStructure::kCollection) {
69 // For untyped collections, we have no class available to collect all the sub fields.
70 // Therefore, we create an untyped record field as an artifical binder for the collection items.
71 std::vector<std::unique_ptr<Detail::RFieldBase>> memberFields;
72 for (auto id : fLinkIds) {
73 const auto &memberDesc = ntplDesc.GetFieldDescriptor(id);
74 memberFields.emplace_back(memberDesc.CreateField(ntplDesc));
75 }
76 auto recordField = std::make_unique<RRecordField>("_0", memberFields);
77 auto collectionField = std::make_unique<RVectorField>(GetFieldName(), std::move(recordField));
78 collectionField->SetOnDiskId(fFieldId);
79 return collectionField;
80 }
81
82 auto field = Detail::RFieldBase::Create(GetFieldName(), GetTypeName()).Unwrap();
83 field->SetOnDiskId(fFieldId);
84 for (auto &f : *field)
85 f.SetOnDiskId(ntplDesc.FindFieldId(f.GetName(), f.GetParent()->GetOnDiskId()));
86 return field;
87}
88
89
90////////////////////////////////////////////////////////////////////////////////
91
92
94{
95 return fLogicalColumnId == other.fLogicalColumnId && fPhysicalColumnId == other.fPhysicalColumnId &&
96 fModel == other.fModel && fFieldId == other.fFieldId && fIndex == other.fIndex;
97}
98
99
102{
103 RColumnDescriptor clone;
104 clone.fLogicalColumnId = fLogicalColumnId;
105 clone.fPhysicalColumnId = fPhysicalColumnId;
106 clone.fModel = fModel;
107 clone.fFieldId = fFieldId;
108 clone.fIndex = fIndex;
109 return clone;
110}
111
112
113////////////////////////////////////////////////////////////////////////////////
114
115
118{
119 // TODO(jblomer): binary search
120 RPageInfo pageInfo;
121 decltype(idxInCluster) firstInPage = 0;
122 NTupleSize_t pageNo = 0;
123 for (const auto &pi : fPageInfos) {
124 if (firstInPage + pi.fNElements > idxInCluster) {
125 pageInfo = pi;
126 break;
127 }
128 firstInPage += pi.fNElements;
129 ++pageNo;
130 }
131 R__ASSERT(firstInPage <= idxInCluster);
132 R__ASSERT((firstInPage + pageInfo.fNElements) > idxInCluster);
133 return RPageInfoExtended{pageInfo, firstInPage, pageNo};
134}
135
136
138{
139 return fClusterId == other.fClusterId && fFirstEntryIndex == other.fFirstEntryIndex &&
140 fNEntries == other.fNEntries && fHasPageLocations == other.fHasPageLocations &&
141 fColumnRanges == other.fColumnRanges && fPageRanges == other.fPageRanges;
142}
143
144
145std::unordered_set<ROOT::Experimental::DescriptorId_t> ROOT::Experimental::RClusterDescriptor::GetColumnIds() const
146{
147 EnsureHasPageLocations();
148 std::unordered_set<DescriptorId_t> result;
149 for (const auto &x : fColumnRanges)
150 result.emplace(x.first);
151 return result;
152}
153
155{
156 EnsureHasPageLocations();
157 return fColumnRanges.find(physicalId) != fColumnRanges.end();
158}
159
160
162{
163 EnsureHasPageLocations();
164 std::uint64_t nbytes = 0;
165 for (const auto &pr : fPageRanges) {
166 for (const auto &pi : pr.second.fPageInfos) {
167 nbytes += pi.fLocator.fBytesOnStorage;
168 }
169 }
170 return nbytes;
171}
172
174{
175 if (!fHasPageLocations)
176 throw RException(R__FAIL("invalid attempt to access page locations of summary-only cluster descriptor"));
177}
178
180{
181 RClusterDescriptor clone;
182 clone.fClusterId = fClusterId;
183 clone.fFirstEntryIndex = fFirstEntryIndex;
184 clone.fNEntries = fNEntries;
185 clone.fHasPageLocations = fHasPageLocations;
186 clone.fColumnRanges = fColumnRanges;
187 for (const auto &d : fPageRanges)
188 clone.fPageRanges.emplace(d.first, d.second.Clone());
189 return clone;
190}
191
192////////////////////////////////////////////////////////////////////////////////
193
194
196{
197 return fName == other.fName && fDescription == other.fDescription && fNEntries == other.fNEntries &&
198 fGeneration == other.fGeneration && fFieldDescriptors == other.fFieldDescriptors &&
199 fColumnDescriptors == other.fColumnDescriptors &&
200 fClusterGroupDescriptors == other.fClusterGroupDescriptors &&
201 fClusterDescriptors == other.fClusterDescriptors;
202}
203
206{
208 for (const auto &cd : fClusterDescriptors) {
209 if (!cd.second.ContainsColumn(physicalColumnId))
210 continue;
211 auto columnRange = cd.second.GetColumnRange(physicalColumnId);
212 result = std::max(result, columnRange.fFirstElementIndex + columnRange.fNElements);
213 }
214 return result;
215}
216
217
220{
221 std::string leafName(fieldName);
222 auto posDot = leafName.find_last_of('.');
223 if (posDot != std::string::npos) {
224 auto parentName = leafName.substr(0, posDot);
225 leafName = leafName.substr(posDot + 1);
226 parentId = FindFieldId(parentName, parentId);
227 }
228 for (const auto &fd : fFieldDescriptors) {
229 if (fd.second.GetParentId() == parentId && fd.second.GetFieldName() == leafName)
230 return fd.second.GetId();
231 }
233}
234
235
237{
238 if (fieldId == kInvalidDescriptorId)
239 return "";
240
241 const auto &fieldDescriptor = fFieldDescriptors.at(fieldId);
242 auto prefix = GetQualifiedFieldName(fieldDescriptor.GetParentId());
243 if (prefix.empty())
244 return fieldDescriptor.GetFieldName();
245 return prefix + "." + fieldDescriptor.GetFieldName();
246}
247
248
251{
252 return FindFieldId("", kInvalidDescriptorId);
253}
254
255
258{
259 return FindFieldId(fieldName, GetFieldZeroId());
260}
261
264{
265 for (const auto &cd : fColumnDescriptors) {
266 if (cd.second.GetFieldId() == fieldId && cd.second.GetIndex() == columnIndex)
267 return cd.second.GetLogicalId();
268 }
270}
271
274{
275 auto logicalId = FindLogicalColumnId(fieldId, columnIndex);
276 if (logicalId == kInvalidDescriptorId)
278 return GetColumnDescriptor(logicalId).GetPhysicalId();
279}
280
283{
284 // TODO(jblomer): binary search?
285 for (const auto &cd : fClusterDescriptors) {
286 if (!cd.second.ContainsColumn(physicalColumnId))
287 continue;
288 auto columnRange = cd.second.GetColumnRange(physicalColumnId);
289 if (columnRange.Contains(index))
290 return cd.second.GetId();
291 }
293}
294
295
296// TODO(jblomer): fix for cases of sharded clasters
299{
300 const auto &clusterDesc = GetClusterDescriptor(clusterId);
301 auto firstEntryInNextCluster = clusterDesc.GetFirstEntryIndex() + clusterDesc.GetNEntries();
302 // TODO(jblomer): binary search?
303 for (const auto &cd : fClusterDescriptors) {
304 if (cd.second.GetFirstEntryIndex() == firstEntryInNextCluster)
305 return cd.second.GetId();
306 }
308}
309
310
311// TODO(jblomer): fix for cases of sharded clasters
314{
315 const auto &clusterDesc = GetClusterDescriptor(clusterId);
316 // TODO(jblomer): binary search?
317 for (const auto &cd : fClusterDescriptors) {
318 if (cd.second.GetFirstEntryIndex() + cd.second.GetNEntries() == clusterDesc.GetFirstEntryIndex())
319 return cd.second.GetId();
320 }
322}
323
326{
327 auto iter = fClusterDescriptors.find(clusterDesc.GetId());
328 if (iter == fClusterDescriptors.end())
329 return R__FAIL("invalid attempt to add cluster details without known cluster summary");
330 if (iter->second.HasPageLocations())
331 return R__FAIL("invalid attempt to re-populate page list");
332 if (!clusterDesc.HasPageLocations())
333 return R__FAIL("provided cluster descriptor does not contain page locations");
334 iter->second = std::move(clusterDesc);
335 return RResult<void>::Success();
336}
337
339{
340 auto iter = fClusterDescriptors.find(clusterId);
341 if (iter == fClusterDescriptors.end())
342 return R__FAIL("invalid attempt to drop cluster details of unknown cluster");
343 if (!iter->second.HasPageLocations())
344 return R__FAIL("invalid attempt to drop details of cluster summary");
345 iter->second = RClusterDescriptor(clusterId, iter->second.GetFirstEntryIndex(), iter->second.GetNEntries());
346 return RResult<void>::Success();
347}
348
349std::unique_ptr<ROOT::Experimental::RNTupleModel> ROOT::Experimental::RNTupleDescriptor::GenerateModel() const
350{
351 auto model = RNTupleModel::Create();
352 model->GetFieldZero()->SetOnDiskId(GetFieldZeroId());
353 for (const auto &topDesc : GetTopLevelFields())
354 model->AddField(topDesc.CreateField(*this));
355 model->Freeze();
356 return model;
357}
358
359std::unique_ptr<ROOT::Experimental::RNTupleDescriptor> ROOT::Experimental::RNTupleDescriptor::Clone() const
360{
361 auto clone = std::make_unique<RNTupleDescriptor>();
362 clone->fName = fName;
363 clone->fDescription = fDescription;
364 clone->fOnDiskHeaderSize = fOnDiskHeaderSize;
365 clone->fOnDiskFooterSize = fOnDiskFooterSize;
366 clone->fNEntries = fNEntries;
367 clone->fNPhysicalColumns = fNPhysicalColumns;
368 clone->fGeneration = fGeneration;
369 for (const auto &d : fFieldDescriptors)
370 clone->fFieldDescriptors.emplace(d.first, d.second.Clone());
371 for (const auto &d : fColumnDescriptors)
372 clone->fColumnDescriptors.emplace(d.first, d.second.Clone());
373 for (const auto &d : fClusterGroupDescriptors)
374 clone->fClusterGroupDescriptors.emplace(d.first, d.second.Clone());
375 for (const auto &d : fClusterDescriptors)
376 clone->fClusterDescriptors.emplace(d.first, d.second.Clone());
377 return clone;
378}
379
380////////////////////////////////////////////////////////////////////////////////
381
383{
384 return fColumnGroupId == other.fColumnGroupId && fPhysicalColumnIds == other.fPhysicalColumnIds;
385}
386
387////////////////////////////////////////////////////////////////////////////////
388
390{
391 return fClusterGroupId == other.fClusterGroupId && fClusterIds == other.fClusterIds;
392}
393
395{
397 clone.fClusterGroupId = fClusterGroupId;
398 clone.fClusterIds = fClusterIds;
399 clone.fPageListLocator = fPageListLocator;
400 clone.fPageListLength = fPageListLength;
401 return clone;
402}
403
404////////////////////////////////////////////////////////////////////////////////
405
408 std::uint64_t firstElementIndex,
409 std::uint32_t compressionSettings,
410 const RClusterDescriptor::RPageRange &pageRange)
411{
412 if (physicalId != pageRange.fPhysicalColumnId)
413 return R__FAIL("column ID mismatch");
414 if (fCluster.fPageRanges.count(physicalId) > 0)
415 return R__FAIL("column ID conflict");
416 RClusterDescriptor::RColumnRange columnRange{physicalId, firstElementIndex, RClusterSize(0)};
417 columnRange.fCompressionSettings = compressionSettings;
418 for (const auto &pi : pageRange.fPageInfos) {
419 columnRange.fNElements += pi.fNElements;
420 }
421 fCluster.fPageRanges[physicalId] = pageRange.Clone();
422 fCluster.fColumnRanges[physicalId] = columnRange;
423 return RResult<void>::Success();
424}
425
426
429{
430 if (fCluster.fClusterId == kInvalidDescriptorId)
431 return R__FAIL("unset cluster ID");
432 if (fCluster.fNEntries == 0)
433 return R__FAIL("empty cluster");
434 for (const auto &pr : fCluster.fPageRanges) {
435 if (fCluster.fColumnRanges.count(pr.first) == 0) {
436 return R__FAIL("missing column range");
437 }
438 }
439 fCluster.fHasPageLocations = true;
441 std::swap(result, fCluster);
442 return result;
443}
444
445std::vector<ROOT::Experimental::RClusterDescriptorBuilder>
447 DescriptorId_t clusterGroupId)
448{
449 const auto &clusterGroupDesc = ntplDesc.GetClusterGroupDescriptor(clusterGroupId);
450 std::vector<RClusterDescriptorBuilder> result;
451 for (auto clusterId : clusterGroupDesc.fClusterIds) {
452 const auto &cluster = ntplDesc.GetClusterDescriptor(clusterId);
453 result.emplace_back(RClusterDescriptorBuilder(clusterId, cluster.GetFirstEntryIndex(), cluster.GetNEntries()));
454 }
455 return result;
456}
457
458////////////////////////////////////////////////////////////////////////////////
459
462{
463 if (fClusterGroup.fClusterGroupId == kInvalidDescriptorId)
464 return R__FAIL("unset cluster group ID");
466 std::swap(result, fClusterGroup);
467 return result;
468}
469
470////////////////////////////////////////////////////////////////////////////////
471
474{
475 if (fColumnGroup.fColumnGroupId == kInvalidDescriptorId)
476 return R__FAIL("unset column group ID");
478 std::swap(result, fColumnGroup);
479 return result;
480}
481
482////////////////////////////////////////////////////////////////////////////////
483
486 if (fDescriptor.fFieldDescriptors.count(fieldId) == 0)
487 return R__FAIL("field with id '" + std::to_string(fieldId) + "' doesn't exist");
488 return RResult<void>::Success();
489}
490
493 // Reuse field name validity check
494 auto validName = Detail::RFieldBase::EnsureValidFieldName(fDescriptor.GetName());
495 if (!validName) {
496 return R__FORWARD_ERROR(validName);
497 }
498 // open-ended list of invariant checks
499 for (const auto& key_val: fDescriptor.fFieldDescriptors) {
500 const auto& id = key_val.first;
501 const auto& desc = key_val.second;
502 // parent not properly set
503 if (id != DescriptorId_t(0) && desc.GetParentId() == kInvalidDescriptorId) {
504 return R__FAIL("field with id '" + std::to_string(id) + "' has an invalid parent id");
505 }
506 }
507 return RResult<void>::Success();
508}
509
511{
513 std::swap(result, fDescriptor);
514 return result;
515}
516
518 const std::string_view description)
519{
520 fDescriptor.fName = std::string(name);
521 fDescriptor.fDescription = std::string(description);
522}
523
526{
527 if (fColumn.GetLogicalId() == kInvalidDescriptorId)
528 return R__FAIL("invalid logical column id");
529 if (fColumn.GetPhysicalId() == kInvalidDescriptorId)
530 return R__FAIL("invalid physical column id");
531 if (fColumn.GetModel().GetType() == EColumnType::kUnknown)
532 return R__FAIL("invalid column model");
533 if (fColumn.GetFieldId() == kInvalidDescriptorId)
534 return R__FAIL("invalid field id, dangling column");
535 return fColumn.Clone();
536}
537
539 const RFieldDescriptor& fieldDesc) : fField(fieldDesc.Clone())
540{
542 fField.fLinkIds = {};
543}
544
547 RFieldDescriptorBuilder fieldDesc;
548 fieldDesc.FieldVersion(field.GetFieldVersion())
550 .FieldName(field.GetName())
552 .TypeName(field.GetType())
553 .Structure(field.GetStructure())
555 return fieldDesc;
556}
557
560 if (fField.GetId() == kInvalidDescriptorId) {
561 return R__FAIL("invalid field id");
562 }
563 if (fField.GetStructure() == ENTupleStructure::kInvalid) {
564 return R__FAIL("invalid field structure");
565 }
566 // FieldZero is usually named "" and would be a false positive here
567 if (fField.GetParentId() != kInvalidDescriptorId) {
568 auto validName = Detail::RFieldBase::EnsureValidFieldName(fField.GetFieldName());
569 if (!validName) {
570 return R__FORWARD_ERROR(validName);
571 }
572 }
573 return fField.Clone();
574}
575
577 fDescriptor.fFieldDescriptors.emplace(fieldDesc.GetId(), fieldDesc.Clone());
578}
579
582{
583 auto fieldExists = RResult<void>::Success();
584 if (!(fieldExists = EnsureFieldExists(fieldId)))
585 return R__FORWARD_ERROR(fieldExists);
586 if (!(fieldExists = EnsureFieldExists(linkId)))
587 return R__FAIL("child field with id '" + std::to_string(linkId) + "' doesn't exist in NTuple");
588
589 if (linkId == fDescriptor.GetFieldZeroId()) {
590 return R__FAIL("cannot make FieldZero a child field");
591 }
592 // fail if field already has another valid parent
593 auto parentId = fDescriptor.fFieldDescriptors.at(linkId).GetParentId();
594 if ((parentId != kInvalidDescriptorId) && (parentId != fieldId)) {
595 return R__FAIL("field '" + std::to_string(linkId) + "' already has a parent ('" +
596 std::to_string(parentId) + ")");
597 }
598 if (fieldId == linkId) {
599 return R__FAIL("cannot make field '" + std::to_string(fieldId) + "' a child of itself");
600 }
601 fDescriptor.fFieldDescriptors.at(linkId).fParentId = fieldId;
602 fDescriptor.fFieldDescriptors.at(fieldId).fLinkIds.push_back(linkId);
603 return RResult<void>::Success();
604}
605
607 DescriptorId_t fieldId, const RColumnModel &model,
608 std::uint32_t index)
609{
611 c.fLogicalColumnId = logicalId;
612 c.fPhysicalColumnId = physicalId;
613 c.fFieldId = fieldId;
614 c.fModel = model;
615 c.fIndex = index;
616 if (!c.IsAliasColumn())
617 fDescriptor.fNPhysicalColumns++;
618 fDescriptor.fColumnDescriptors.emplace(logicalId, std::move(c));
619}
620
621
624{
625 const auto fieldId = columnDesc.GetFieldId();
626 const auto index = columnDesc.GetIndex();
627
628 auto fieldExists = EnsureFieldExists(fieldId);
629 if (!fieldExists)
630 return R__FORWARD_ERROR(fieldExists);
631 if (fDescriptor.FindLogicalColumnId(fieldId, index) != kInvalidDescriptorId) {
632 return R__FAIL("column index clash");
633 }
634 if (index > 0) {
635 if (fDescriptor.FindLogicalColumnId(fieldId, index - 1) == kInvalidDescriptorId)
636 return R__FAIL("out of bounds column index");
637 }
638 if (columnDesc.IsAliasColumn()) {
639 if (columnDesc.GetModel() != fDescriptor.GetColumnDescriptor(columnDesc.GetPhysicalId()).GetModel())
640 return R__FAIL("alias column type mismatch");
641 }
642
643 auto logicalId = columnDesc.GetLogicalId();
644 if (!columnDesc.IsAliasColumn())
645 fDescriptor.fNPhysicalColumns++;
646 fDescriptor.fColumnDescriptors.emplace(logicalId, std::move(columnDesc));
647
648 return RResult<void>::Success();
649}
650
653 std::uint64_t nEntries)
654{
655 if (fDescriptor.fClusterDescriptors.count(clusterId) > 0)
656 return R__FAIL("cluster id clash while adding cluster summary");
657 fDescriptor.fNEntries = std::max(fDescriptor.fNEntries, firstEntry + nEntries);
658 fDescriptor.fClusterDescriptors.emplace(clusterId, RClusterDescriptor(clusterId, firstEntry, nEntries));
659 return RResult<void>::Success();
660}
661
663{
664 auto id = clusterGroup.GetId();
665 fDescriptor.fClusterGroupDescriptors.emplace(id, clusterGroup.MoveDescriptor().Unwrap());
666}
667
669{
670 fDescriptor.fName = "";
671 fDescriptor.fDescription = "";
672 fDescriptor.fFieldDescriptors.clear();
673 fDescriptor.fColumnDescriptors.clear();
674 fDescriptor.fClusterDescriptors.clear();
675 fDescriptor.fClusterGroupDescriptors.clear();
676}
677
680{
681 auto clusterId = clusterDesc.GetId();
682 if (fDescriptor.fClusterDescriptors.count(clusterId) > 0)
683 return R__FAIL("cluster id clash");
684 fDescriptor.fNEntries =
685 std::max(fDescriptor.fNEntries, clusterDesc.GetFirstEntryIndex() + clusterDesc.GetNEntries());
686 fDescriptor.fClusterDescriptors.emplace(clusterId, std::move(clusterDesc));
687 return RResult<void>::Success();
688}
#define R__FORWARD_ERROR(res)
Short-hand to return an RResult<T> in an error state (i.e. after checking)
Definition: RError.hxx:307
#define R__FAIL(msg)
Short-hand to return an RResult<T> in an error state; the RError is implicitly converted into RResult...
Definition: RError.hxx:303
#define d(i)
Definition: RSha256.hxx:102
#define f(i)
Definition: RSha256.hxx:104
#define c(i)
Definition: RSha256.hxx:101
#define R__ASSERT(e)
Definition: TError.h:118
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
char name[80]
Definition: TGX11.cxx:110
@ kCollection
Definition: TStructNode.h:21
@ kInvalid
Definition: TSystem.h:79
virtual std::uint32_t GetFieldVersion() const
Indicates an evolution of the mapping scheme from C++ type to columns.
Definition: RField.hxx:355
std::string GetDescription() const
Get the field's description.
Definition: RField.hxx:336
std::size_t GetNRepetitions() const
Definition: RField.hxx:330
virtual std::uint32_t GetTypeVersion() const
Indicates an evolution of the C++ type itself.
Definition: RField.hxx:357
static RResult< void > EnsureValidFieldName(std::string_view fieldName)
Check whether a given string is a valid field name.
Definition: RField.cxx:332
static RResult< std::unique_ptr< RFieldBase > > Create(const std::string &fieldName, const std::string &typeName)
Factory method to resurrect a field from the stored on-disk type information.
Definition: RField.cxx:225
ENTupleStructure GetStructure() const
Definition: RField.hxx:329
A helper class for piece-wise construction of an RClusterDescriptor.
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
bool ContainsColumn(DescriptorId_t physicalId) const
NTupleSize_t fFirstEntryIndex
Clusters can be swapped by adjusting the entry offsets.
std::unordered_set< DescriptorId_t > GetColumnIds() const
std::unordered_map< DescriptorId_t, RColumnRange > fColumnRanges
bool operator==(const RClusterDescriptor &other) const
A helper class for piece-wise construction of an RClusterGroupDescriptor.
RResult< RClusterGroupDescriptor > MoveDescriptor()
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...
Clusters are stored in cluster groups.
std::uint32_t fPageListLength
Uncompressed size of the page list.
RNTupleLocator fPageListLocator
The page list that corresponds to the cluster group.
bool operator==(const RClusterGroupDescriptor &other) const
RResult< RColumnDescriptor > MakeDescriptor() const
Attempt to make a column descriptor.
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...
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.
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
RResult< RColumnGroupDescriptor > MoveDescriptor()
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
Holds the static meta-data of an RNTuple column.
Base class for all ROOT issued exceptions.
Definition: RError.hxx:78
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 & FieldDescription(const std::string &fieldDescription)
RFieldDescriptorBuilder & FieldVersion(std::uint32_t fieldVersion)
RFieldDescriptorBuilder()=default
Make an empty dangling field descriptor.
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.
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
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.
RResult< void > EnsureValidDescriptor() const
Checks whether invariants hold:
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)
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 AddField(const RFieldDescriptor &fieldDesc)
The on-storage meta-data of an ntuple.
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 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
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)
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::string fName
The ntuple name needs to be unique in a given storage location (file)
const RClusterDescriptor & GetClusterDescriptor(DescriptorId_t clusterId) const
std::unordered_map< DescriptorId_t, RFieldDescriptor > fFieldDescriptors
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
RResult< void > AddClusterDetails(RClusterDescriptor &&clusterDesc)
Methods to load and drop cluster details.
const RFieldDescriptor & GetFieldDescriptor(DescriptorId_t fieldId) const
const RClusterGroupDescriptor & GetClusterGroupDescriptor(DescriptorId_t clusterGroupId) const
std::string fDescription
Free text from the user.
static std::unique_ptr< RNTupleModel > Create()
RResult<void> has no data member and no Inspect() method but instead a Success() factory method.
Definition: RError.hxx:269
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
struct void * fTypeName
Definition: cppyy.h:9
Double_t x[n]
Definition: legend1.C:17
basic_string_view< char > string_view
void swap(RDirectoryEntry &e1, RDirectoryEntry &e2) noexcept
std::uint64_t NTupleSize_t
Integer type long enough to hold the maximum number of entries in a column.
Definition: RNTupleUtil.hxx:48
std::uint64_t DescriptorId_t
Distriniguishes elements of the same type within a descriptor, e.g. different fields.
constexpr DescriptorId_t kInvalidDescriptorId
static constexpr double pi
The window of element indexes of a particular column in a particular cluster.
We do not need to store the element size / uncompressed page size because we know to which column the...
ClusterSize_t fNElements
The sum of the elements of all the pages must match the corresponding fNElements field in fColumnRang...
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.
Wrap the 32bit integer in a struct in order to avoid template specialization clash with std::uint32_t...
Definition: RNTupleUtil.hxx:51