Skip to content

Commit 6ee83fe

Browse files
committed
[ntuple] update RNTupleModel's documentation
1 parent 76a8fa3 commit 6ee83fe

File tree

1 file changed

+80
-33
lines changed

1 file changed

+80
-33
lines changed

tree/ntuple/v7/inc/ROOT/RNTupleModel.hxx

Lines changed: 80 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,14 @@ RProjectedFields &GetProjectedFieldsOfModel(RNTupleModel &model);
5353
/**
5454
\class ROOT::Internal::RProjectedFields
5555
\ingroup NTuple
56-
\brief The projected fields of a `RNTupleModel`
56+
\brief Container for the projected fields of an RNTupleModel
5757
5858
Projected fields are fields whose columns are reused from existing fields. Projected fields are not attached
59-
to the models zero field. Only the real source fields are written to, projected fields are stored as metadata
60-
(header) information only. Only top-level projected fields are supported because otherwise the layout of types
59+
to the model's zero field but form a separate hierarchy with their own zero field (which is stored in this class).
60+
Only the real source fields are written to: projected fields are stored as metadata
61+
(header) information only. Only top-level projected fields are supported because otherwise the layout of types
6162
could be altered in unexpected ways.
62-
All projected fields and the source fields used to back them are kept in this class.
63+
This class owns the hierarchy of projected fields and keeps the mapping between them and their backing source fields.
6364
*/
6465
// clang-format on
6566
class RProjectedFields {
@@ -92,7 +93,8 @@ public:
9293
RProjectedFields &operator=(RProjectedFields &&) = default;
9394
~RProjectedFields() = default;
9495

95-
/// The new model needs to be a clone of fModel
96+
/// Clones this container and all the projected fields it owns. `newModel` must be a clone of the model
97+
/// that this RProjectedFields was constructed with.
9698
std::unique_ptr<RProjectedFields> Clone(const RNTupleModel &newModel) const;
9799

98100
ROOT::RFieldZero &GetFieldZero() { return *fFieldZero; }
@@ -109,35 +111,50 @@ public:
109111
/**
110112
\class ROOT::RNTupleModel
111113
\ingroup NTuple
112-
\brief The RNTupleModel encapulates the schema of an ntuple.
114+
\brief The RNTupleModel encapulates the schema of an RNTuple.
113115
114-
The ntuple model comprises a collection of hierarchically organized fields. From a model, "entries"
115-
can be extracted. For convenience, the model provides a default entry unless it is created as a "bare model".
116-
Models have a unique model identifier that faciliates checking whether entries are compatible with it
116+
The RNTupleModel comprises a collection of hierarchically organized fields. From a model, "entries"
117+
can be extracted or created. For convenience, the RNTupleModel provides a default entry unless it is created as a "bare model".
118+
Models have a unique model identifier that facilitates checking whether entries are compatible with it
117119
(i.e.: have been extracted from that model).
118120
119-
A model is subject to a state transition during its lifetime: it starts in a building state, in which fields can be
120-
added and modified. Once the schema is finalized, the model gets frozen. Only frozen models can create entries.
121-
From frozen, models move into a expired state. In this state, the model is only partially usable: it can be cloned
121+
A model is subject to state transitions during its lifetime: it starts in a *building* state, in which fields can be
122+
added and modified. Once the schema is finalized, the model gets *frozen*. Only frozen models can create entries.
123+
From frozen, models move into an *expired* state. In this state, the model is only partially usable: it can be cloned
122124
and queried, but it can't be unfrozen anymore and no new entries can be created. This state is used for models
123125
that were used for writing and are no longer connected to a page sink.
126+
127+
```
128+
(Model gets created)
129+
|
130+
| (passed to a Sink (detached from
131+
____v______ or explicitly __________ Sink after ___________
132+
| | frozen) | | writing) | |
133+
| Building |---------------->| Frozen |-------------->| Expired |
134+
|___________|<----------------|__________| |___________|
135+
(explicitly
136+
unfrozen)
137+
```
138+
124139
*/
125140
// clang-format on
126141
class RNTupleModel {
127142
friend ROOT::RFieldZero &Internal::GetFieldZeroOfModel(RNTupleModel &);
128143
friend Internal::RProjectedFields &Internal::GetProjectedFieldsOfModel(RNTupleModel &);
129144

130145
public:
131-
/// User provided function that describes the mapping of existing source fields to projected fields in terms
146+
/// User-provided function that describes the mapping of existing source fields to projected fields in terms
132147
/// of fully qualified field names. The mapping function is called with the qualified field names of the provided
133-
/// field and the subfields. It should return the qualified field names used as a mapping source.
148+
/// field and the subfields. It should return the qualified field names used as a mapping source.
149+
/// See AddProjectedFields() for more details.
134150
using FieldMappingFunc_t = std::function<std::string(const std::string &)>;
135151

136152
class RUpdater;
137153

138154
private:
139-
// The states a model can be in. Possible transitions are between kBuilding and kFrozen
140-
// and from kFrozen to kExpired.
155+
/// The states a model can be in. Possible transitions are between kBuilding and kFrozen
156+
/// and from kFrozen to kExpired.
157+
/// See RNTupleModel for the state transition graph.
141158
enum class EState {
142159
kBuilding,
143160
kFrozen,
@@ -164,7 +181,7 @@ private:
164181
/// Changed by Freeze() / Unfreeze() and by the RUpdater.
165182
EState fModelState = EState::kBuilding;
166183

167-
/// Checks that user-provided field names are valid in the context of this RNTuple model.
184+
/// Checks that user-provided field names are valid in the context of this RNTupleModel.
168185
/// Throws an RException for invalid names, empty names (which is reserved for the zero field) and duplicate field
169186
/// names.
170187
void EnsureValidFieldName(std::string_view fieldName);
@@ -192,8 +209,9 @@ public:
192209
std::unique_ptr<RNTupleModel> Clone() const;
193210
static std::unique_ptr<RNTupleModel> Create();
194211
static std::unique_ptr<RNTupleModel> Create(std::unique_ptr<ROOT::RFieldZero> fieldZero);
195-
/// A bare model has no default entry
212+
/// Creates a "bare model", i.e. an RNTupleModel with no default entry
196213
static std::unique_ptr<RNTupleModel> CreateBare();
214+
/// Creates a "bare model", i.e. an RNTupleModel with no default entry, with the given field zero.
197215
static std::unique_ptr<RNTupleModel> CreateBare(std::unique_ptr<ROOT::RFieldZero> fieldZero);
198216

199217
/// Creates a new field given a `name` or `{name, description}` pair and a
@@ -246,20 +264,21 @@ public:
246264
return ptr;
247265
}
248266

249-
/// Adds a field whose type is not known at compile time. Thus there is no shared pointer returned.
267+
/// Adds a field whose type is not known at compile time. No shared pointer is returned in this case:
268+
/// pointers should be retrieved or bound via REntry.
250269
///
251-
/// Throws an exception if the field is null.
270+
/// Throws an RException if the field is null.
252271
void AddField(std::unique_ptr<ROOT::RFieldBase> field);
253272

254273
/// Register a subfield so it can be accessed directly from entries belonging to the model. Because registering a
255274
/// subfield does not fundamentally change the model, previously created entries will not be invalidated, nor
256275
/// modified in any way; a registered subfield is merely an accessor added to the default entry (if present) and any
257-
/// entries created afterwards.
276+
/// entries created afterwards. Note that previously created entries won't have this subfield added to them.
258277
///
259278
/// Using models with registered subfields for writing is not allowed. Attempting to do so will result in an
260279
/// exception.
261280
///
262-
/// Throws an exception if the provided subfield could not be found in the model.
281+
/// Throws an RException if the provided subfield could not be found in the model.
263282
void RegisterSubfield(std::string_view qualifiedFieldName);
264283

265284
/// Adds a top-level field based on existing fields.
@@ -298,33 +317,57 @@ public:
298317
/// Creating projections for fields containing `std::variant` or fixed-size arrays is unsupported.
299318
RResult<void> AddProjectedField(std::unique_ptr<ROOT::RFieldBase> field, FieldMappingFunc_t mapping);
300319

320+
/// Transitions an RNTupleModel from the *building* state to the *frozen* state, disabling adding additional fields
321+
/// and enabling creating entries from it. Freezing an already-frozen model is a no-op. Throws an RException if the
322+
/// model is in the *expired* state. See RNTupleModel for more detailed explanation on the state transitions.
301323
void Freeze();
324+
/// Transitions an RNTupleModel from the *frozen* state back to the *building* state, invalidating all previously
325+
/// created entries, re-enabling adding additional fields and disabling creating entries from it. Unfreezing a model
326+
/// that is already in the *building* state is a no-op. Throws an RException if the model is in the *expired* state.
327+
/// See RNTupleModel for a more detailed explanation on the state transitions.
302328
void Unfreeze();
329+
/// Transitions an RNTupleModel from the *frozen* state to the *expired* state, invalidating all previously created
330+
/// entries, disabling creating new entries from it and disabling further state transitions. Expiring a model that is
331+
/// already expired is a no-op. Throws an RException if the model is in the *building* state. See RNTupleModel for a
332+
/// more detailed explanation on the state transitions.
303333
void Expire();
334+
/// \see Expire()
304335
bool IsExpired() const { return fModelState == EState::kExpired; }
336+
/// \see Freeze()
305337
bool IsFrozen() const { return (fModelState == EState::kFrozen) || (fModelState == EState::kExpired); }
338+
/// \see CreateBare()
306339
bool IsBare() const { return !fDefaultEntry; }
307340
std::uint64_t GetModelId() const { return fModelId; }
308341
std::uint64_t GetSchemaId() const { return fSchemaId; }
309342

310-
std::unique_ptr<ROOT::REntry> CreateEntry() const;
311-
/// In a bare entry, all values point to nullptr. The resulting entry shall use BindValue() in order
312-
/// set memory addresses to be serialized / deserialized
313-
std::unique_ptr<ROOT::REntry> CreateBareEntry() const;
343+
/// Creates a new entry with default values for each field.
344+
std::unique_ptr<REntry> CreateEntry() const;
345+
/// Creates a "bare entry", i.e. a entry with all null values. The user needs to explicitly call BindValue() or
346+
/// BindRawPtr() to set memory addresses before serializing / deserializing the entry.
347+
std::unique_ptr<REntry> CreateBareEntry() const;
314348
std::unique_ptr<Experimental::Detail::RRawPtrWriteEntry> CreateRawPtrWriteEntry() const;
315-
316349
/// Creates a token to be used in REntry methods to address a field present in the entry
317350
ROOT::RFieldToken GetToken(std::string_view fieldName) const;
318-
/// Calls the given field's CreateBulk() method. Throws an exception if no field with the given name exists.
351+
/// Calls the given field's CreateBulk() method. Throws an RException if no field with the given name exists.
319352
ROOT::RFieldBase::RBulk CreateBulk(std::string_view fieldName) const;
320353

321-
ROOT::REntry &GetDefaultEntry();
322-
const ROOT::REntry &GetDefaultEntry() const;
354+
/// Retrieves the default entry of this model.
355+
/// Throws an RException if this is a bare model (i.e. if it was created with CreateBare()).
356+
REntry &GetDefaultEntry();
357+
/// \see GetDefaultEntry()
358+
const REntry &GetDefaultEntry() const;
323359

324-
/// Mutable access to the root field is used to make adjustments to the fields.
360+
/// Retrieves the field zero of this model, i.e. the root of the field hierarchy.
361+
/// This may be used to make adjustments on the field hierarchy before the model is frozen.
325362
ROOT::RFieldZero &GetMutableFieldZero();
363+
/// Retrieves the field zero of this model, i.e. the root of the field hierarchy.
326364
const ROOT::RFieldZero &GetConstFieldZero() const { return *fFieldZero; }
365+
/// Retrieves the field with fully-qualified name `fieldName`.
366+
/// Dot-separated names are used to walk down the field hierarchy: e.g. `"parent.child"` should
367+
/// be used to retrieve a field with name `"child"` whose parent is the top-level field with name `"parent"`.
368+
/// Throws an RException if no field is found with the given name.
327369
ROOT::RFieldBase &GetMutableField(std::string_view fieldName);
370+
/// \see GetMutableField()
328371
const ROOT::RFieldBase &GetConstField(std::string_view fieldName) const;
329372

330373
const std::string &GetDescription() const { return fDescription; }
@@ -333,13 +376,14 @@ public:
333376
/// Get the names of the fields currently present in the model, including projected fields. Registered subfields
334377
/// are not included, use GetRegisteredSubfieldnames() for this.
335378
const std::unordered_set<std::string> &GetFieldNames() const { return fFieldNames; }
336-
/// Get the (qualified) names of subfields that have been registered to be included in entries from this model.
379+
/// Get the (qualified) names of subfields that have been registered (via RegisterSubfield()) to be included in
380+
/// entries from this model.
337381
const std::unordered_set<std::string> &GetRegisteredSubfieldNames() const { return fRegisteredSubfields; }
338382

339383
/// Estimate the memory usage for this model during writing
340384
///
341385
/// This will return an estimate in bytes for the internal page and compression buffers. The value should be
342-
/// understood per sequential RNTupleWriter or per RNTupleFillContext created for a RNTupleParallelWriter
386+
/// understood per sequential RNTupleWriter or per RNTupleFillContext created for an RNTupleParallelWriter
343387
/// constructed with this model.
344388
std::size_t EstimateWriteMemoryUsage(const ROOT::RNTupleWriteOptions &options = ROOT::RNTupleWriteOptions()) const;
345389
};
@@ -368,6 +412,8 @@ struct RNTupleModelChangeset {
368412
bool IsEmpty() const { return fAddedFields.empty() && fAddedProjectedFields.empty(); }
369413

370414
void AddField(std::unique_ptr<ROOT::RFieldBase> field);
415+
416+
/// \see RNTupleModel::AddProjectedField()
371417
ROOT::RResult<void>
372418
AddProjectedField(std::unique_ptr<ROOT::RFieldBase> field, RNTupleModel::FieldMappingFunc_t mapping);
373419
};
@@ -410,6 +456,7 @@ public:
410456

411457
void AddField(std::unique_ptr<ROOT::RFieldBase> field);
412458

459+
/// \see RNTupleModel::AddProjectedField()
413460
RResult<void> AddProjectedField(std::unique_ptr<ROOT::RFieldBase> field, FieldMappingFunc_t mapping);
414461
};
415462

0 commit comments

Comments
 (0)