Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RNTupleAttrWriting.hxx
Go to the documentation of this file.
1/// \file ROOT/RNTupleAttrWriting.hxx
2/// \ingroup NTuple ROOT7
3/// \author Giacomo Parolini <giacomo.parolini@cern.ch>
4/// \date 2026-01-27
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#ifndef ROOT7_RNTuple_Attr_Writing
9#define ROOT7_RNTuple_Attr_Writing
10
11#include <memory>
12#include <string_view>
13
14#include <ROOT/REntry.hxx>
16#include <ROOT/RNTupleUtils.hxx>
17
18namespace ROOT {
19
20class RNTupleModel;
21class RNTuple;
22class RNTupleWriter;
23
24namespace Experimental {
25
26class RNTupleAttrSetWriter;
27
28namespace Internal {
29
30// clang-format off
31/**
32\class ROOT::Experimental::Internal::RNTupleAttrEntry
33\ingroup NTuple
34\brief A pair of scoped + meta entry used by the RNTupleAttrSetWriter.
35
36The meta entry is used to write the "meta fields" that are always present in an Attribute Set (start/len); the scoped
37entry is used to write the user-provided fields.
38*/
39// clang-format on
48
49} // namespace Internal
50
51// clang-format off
52/**
53\class ROOT::Experimental::RNTupleAttrPendingRange
54\ingroup NTuple
55\brief A not-yet-finalized Attribute Range used for writing
56
57A range used for writing. It has a well-defined start but not a length/end yet.
58It is artificially made non-copyable in order to clarify the semantics of Begin/CommitRange.
59For the same reason, it can only be created by the AttrSetWriter.
60*/
61// clang-format on
64
66 std::uint64_t fModelId = 0;
67 bool fWasCommitted = false;
68
73
74public:
78
80
81 // NOTE: explicitly implemented to make sure that 'other' gets invalidated upon move.
83 {
84 if (&other != this) {
85 std::swap(fStart, other.fStart);
86 std::swap(fModelId, other.fModelId);
87 other.fWasCommitted = true;
88 fWasCommitted = false;
89 }
90 return *this;
91 }
92
94 {
96 R__LOG_WARNING(ROOT::Internal::NTupleLog()) << "A pending attribute range was not committed! If CommitRange() "
97 "is not explicitly called before closing the main "
98 "Writer, the attributes will not be saved to storage!";
99 }
100
102 {
103 if (!IsValid())
104 throw ROOT::RException(R__FAIL("Tried to get the start of an invalid AttrPendingRange."));
105 return fStart;
106 }
107
109
110 /// Returns true if this PendingRange is valid
111 operator bool() const { return IsValid(); }
112 bool IsValid() const { return fModelId != 0; }
113};
114
115// clang-format off
116/**
117\class ROOT::Experimental::RNTupleAttrSetWriter
118\ingroup NTuple
119\brief Class used to write an RNTupleAttrSet in the context of an RNTupleWriter.
120
121An Attribute Set is written as a separate RNTuple linked to the "main" RNTuple that created it.
122A RNTupleAttrSetWriter only lives as long as the RNTupleWriter that created it (or until CloseAttributeSet() is called).
123Users should not use this class directly but rather via RNTupleAttrSetWriterHandle, which is the type returned by
124RNTupleWriter::CreateAttributeSet().
125
126~~~ {.cpp}
127// Writing attributes via RNTupleAttrSetWriter
128// -------------------------------------------
129
130// First define the schema of your Attribute Set:
131auto attrModel = ROOT::RNTupleModel::Create();
132auto pMyAttr = attrModel->MakeField<std::string>("myAttr");
133
134// Then, assuming `writer` is an RNTupleWriter, create it:
135auto attrSet = writer->CreateAttributeSet(std::move(attrModel), "MyAttrSet");
136
137// Attributes are assigned to entry ranges. A range is started via BeginRange():
138auto range = attrSet->BeginRange();
139
140// To assign actual attributes, you use the same interface as the main RNTuple:
141*pMyAttr = "This is my attribute for this range";
142
143// ... here you can fill your main RNTuple with data ...
144
145// Once you're done, close the range. This will commit the attribute data and bind it to all data written
146// between BeginRange() and CommitRange().
147attrSet->CommitRange(std::move(range));
148
149// You don't need to explicitly close the AttributeSet, but if you want to do so, use:
150// writer->CloseAttributeSet(std::move(attrSet));
151~~~
152*/
153// clang-format on
156
157 /// Our own fill context.
159 /// Fill context of the main RNTuple being written (i.e. the RNTuple whose attributes we are).
161 /// The model that the user provided on creation. Used to create user-visible entries.
162 std::unique_ptr<RNTupleModel> fUserModel;
163
164 // Cached values of the meta entry pointers.
165 std::shared_ptr<ROOT::NTupleSize_t> fRangeStartPtr;
166 std::shared_ptr<ROOT::NTupleSize_t> fRangeLenPtr;
167
168 /// Creates an RNTupleAttrSetWriter associated to the RNTupleWriter owning `mainFillContext` and writing
169 /// using `sink`. `userModel` is the schema of the AttributeSet.
170 static std::unique_ptr<RNTupleAttrSetWriter> Create(const RNTupleFillContext &mainFillContext,
171 std::unique_ptr<ROOT::Internal::RPageSink> sink,
172 std::unique_ptr<RNTupleModel> userModel);
173
174 RNTupleAttrSetWriter(const RNTupleFillContext &mainFillContext, std::unique_ptr<ROOT::Internal::RPageSink> sink,
175 std::unique_ptr<RNTupleModel> metaModel, std::unique_ptr<RNTupleModel> userModel,
176 std::shared_ptr<ROOT::NTupleSize_t> rangeStartPtr,
177 std::shared_ptr<ROOT::NTupleSize_t> rangeLenPtr);
178
179 /// Commits the attributes written so far to disk and disables writing any new ones.
181
182public:
183 /// Returns the descriptor of the underlying attribute RNTuple. This is **NOT** the same descriptor as the
184 /// main RNTuple being written!
185 const ROOT::RNTupleDescriptor &GetDescriptor() const { return fFillContext.fSink->GetDescriptor(); }
186 /// Returns the user-defined model used to create this attribute set.
187 const ROOT::RNTupleModel &GetModel() const { return *fUserModel; }
188
189 /// Begins an attribute range. All entries filled in the main RNTupleWriter between BeginRange and CommitRange
190 /// will be associated with the set of values of the fields of this attribute set at the moment of CommitRange.
191 /// Note that every attribute range must be explicitly committed for it to be stored on disk.
192 /// \return An object describing the pending range, which must be passed back to CommitRange to end the attribute
193 /// range
195 /// Ends an attribute range and associates the current values of the fields of the attribute model's default entry
196 /// with all the main RNTuple entries filled since the BeginRange that created the given `range`.
197 /// This is only valid if the model used to create this attribute set is not bare.
199 /// Like CommitRange(RNTupleAttrPendingRange range) but uses the given entry rather than the default entry.
200 /// The given entry must have been created by CreateEntry().
202
203 /// Creates an REntry fit to pass to CommitRange(RNTupleAttrPendingRange range, REntry entry).
204 std::unique_ptr<REntry> CreateEntry() { return fUserModel->CreateEntry(); }
205};
206
207// clang-format off
208/**
209\class ROOT::Experimental::RNTupleAttrSetWriterHandle
210\ingroup NTuple
211\brief Non-owning handle to an RNTupleAttrSetWriter
212
213RNTupleAttrSetWriter can only be used through an RNTupleAttrSetWriterHandle, a weak_ptr-like object that allows safe
214access to it. The lifetime of an attribute set writer is tied to its parent RNTupleWriter, so the handle handed out
215by RNTupleWriter::CreateAttributeSet is invalidated as soon as the parent writer is destructed.
216
217*/
218// clang-format on
221
222 std::weak_ptr<RNTupleAttrSetWriter> fWriter;
223
224 explicit RNTupleAttrSetWriterHandle(const std::shared_ptr<RNTupleAttrSetWriter> &range) : fWriter(range) {}
225
226public:
231
232 /// Retrieves the underlying pointer to the AttrSetWriter, throwing if it's invalid.
234 {
235 auto ptr = fWriter.lock();
236 if (R__unlikely(!ptr))
237 throw ROOT::RException(R__FAIL("Tried to access invalid RNTupleAttrSetWriterHandle"));
238 return ptr.get();
239 }
240};
241
242} // namespace Experimental
243} // namespace ROOT
244
245#endif
#define R__unlikely(expr)
Definition RConfig.hxx:592
#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:300
#define R__LOG_WARNING(...)
Definition RLogger.hxx:358
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
A not-yet-finalized Attribute Range used for writing.
RNTupleAttrPendingRange(ROOT::NTupleSize_t start, ROOT::DescriptorId_t modelId)
RNTupleAttrPendingRange(RNTupleAttrPendingRange &&other)
RNTupleAttrPendingRange & operator=(RNTupleAttrPendingRange &&other)
RNTupleAttrPendingRange & operator=(const RNTupleAttrPendingRange &)=delete
RNTupleAttrPendingRange(const RNTupleAttrPendingRange &)=delete
Non-owning handle to an RNTupleAttrSetWriter.
std::weak_ptr< RNTupleAttrSetWriter > fWriter
RNTupleAttrSetWriterHandle & operator=(RNTupleAttrSetWriterHandle &&other)=default
RNTupleAttrSetWriterHandle(RNTupleAttrSetWriterHandle &&)=default
RNTupleAttrSetWriterHandle & operator=(const RNTupleAttrSetWriterHandle &)=delete
RNTupleAttrSetWriter * operator->()
Retrieves the underlying pointer to the AttrSetWriter, throwing if it's invalid.
RNTupleAttrSetWriterHandle(const std::shared_ptr< RNTupleAttrSetWriter > &range)
RNTupleAttrSetWriterHandle(const RNTupleAttrSetWriterHandle &)=delete
Class used to write an RNTupleAttrSet in the context of an RNTupleWriter.
static std::unique_ptr< RNTupleAttrSetWriter > Create(const RNTupleFillContext &mainFillContext, std::unique_ptr< ROOT::Internal::RPageSink > sink, std::unique_ptr< RNTupleModel > userModel)
Creates an RNTupleAttrSetWriter associated to the RNTupleWriter owning mainFillContext and writing us...
std::shared_ptr< ROOT::NTupleSize_t > fRangeLenPtr
std::unique_ptr< RNTupleModel > fUserModel
The model that the user provided on creation. Used to create user-visible entries.
const RNTupleFillContext * fMainFillContext
Fill context of the main RNTuple being written (i.e. the RNTuple whose attributes we are).
ROOT::Internal::RNTupleLink Commit()
Commits the attributes written so far to disk and disables writing any new ones.
std::unique_ptr< REntry > CreateEntry()
Creates an REntry fit to pass to CommitRange(RNTupleAttrPendingRange range, REntry entry).
RNTupleAttrPendingRange BeginRange()
Begins an attribute range.
RNTupleAttrSetWriter(const RNTupleFillContext &mainFillContext, std::unique_ptr< ROOT::Internal::RPageSink > sink, std::unique_ptr< RNTupleModel > metaModel, std::unique_ptr< RNTupleModel > userModel, std::shared_ptr< ROOT::NTupleSize_t > rangeStartPtr, std::shared_ptr< ROOT::NTupleSize_t > rangeLenPtr)
const ROOT::RNTupleModel & GetModel() const
Returns the user-defined model used to create this attribute set.
std::shared_ptr< ROOT::NTupleSize_t > fRangeStartPtr
void CommitRange(RNTupleAttrPendingRange range)
Ends an attribute range and associates the current values of the fields of the attribute model's defa...
RNTupleFillContext fFillContext
Our own fill context.
const ROOT::RNTupleDescriptor & GetDescriptor() const
Returns the descriptor of the underlying attribute RNTuple.
The REntry is a collection of values in an RNTuple corresponding to a complete row in the data set.
Definition REntry.hxx:51
std::uint64_t GetModelId() const
Definition REntry.hxx:250
Base class for all ROOT issued exceptions.
Definition RError.hxx:79
The on-storage metadata of an RNTuple.
A context for filling entries (data) into clusters of an RNTuple.
std::unique_ptr< ROOT::Internal::RPageSink > fSink
The RNTupleModel encapulates the schema of an RNTuple.
An RNTuple that gets filled with entries (data) and writes them to storage.
ROOT::RLogChannel & NTupleLog()
Log channel for RNTuple diagnostics.
std::uint64_t DescriptorId_t
Distriniguishes elements of the same type within a descriptor, e.g. different fields.
std::uint64_t NTupleSize_t
Integer type long enough to hold the maximum number of entries in a column.
A pair of scoped + meta entry used by the RNTupleAttrSetWriter.