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