@@ -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
5858Projected 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
6162could 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
6566class 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
122124and queried, but it can't be unfrozen anymore and no new entries can be created. This state is used for models
123125that 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
126141class RNTupleModel {
127142 friend ROOT::RFieldZero &Internal::GetFieldZeroOfModel (RNTupleModel &);
128143 friend Internal::RProjectedFields &Internal::GetProjectedFieldsOfModel (RNTupleModel &);
129144
130145public:
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
138154private:
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