|
|
|||
File indexing completed on 2026-08-16 09:21:19
0001 /// \file ROOT/RNTupleAttrWriting.hxx 0002 /// \ingroup NTuple ROOT7 0003 /// \author Giacomo Parolini <giacomo.parolini@cern.ch> 0004 /// \date 2026-01-27 0005 /// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback 0006 /// is welcome! 0007 0008 #ifndef ROOT7_RNTuple_Attr_Writing 0009 #define ROOT7_RNTuple_Attr_Writing 0010 0011 #include <memory> 0012 #include <string_view> 0013 0014 #include <ROOT/REntry.hxx> 0015 #include <ROOT/RNTupleFillContext.hxx> 0016 #include <ROOT/RNTupleUtils.hxx> 0017 0018 namespace ROOT { 0019 0020 class RNTupleModel; 0021 class RNTuple; 0022 class RNTupleWriter; 0023 0024 namespace Experimental { 0025 0026 class RNTupleAttrSetWriter; 0027 0028 namespace Internal { 0029 0030 // clang-format off 0031 /** 0032 \class ROOT::Experimental::Internal::RNTupleAttrEntry 0033 \ingroup NTuple 0034 \brief A pair of scoped + meta entry used by the RNTupleAttrSetWriter. 0035 0036 The meta entry is used to write the "meta fields" that are always present in an Attribute Set (start/len); the scoped 0037 entry is used to write the user-provided fields. 0038 */ 0039 // clang-format on 0040 struct RNTupleAttrEntry { 0041 REntry &fMetaEntry; 0042 REntry &fScopedEntry; 0043 ROOT::RNTupleModel &fMetaModel; 0044 0045 std::size_t Append(); 0046 ROOT::DescriptorId_t GetModelId() const { return fMetaEntry.GetModelId(); } 0047 }; 0048 0049 } // namespace Internal 0050 0051 // clang-format off 0052 /** 0053 \class ROOT::Experimental::RNTupleAttrPendingRange 0054 \ingroup NTuple 0055 \brief A not-yet-finalized Attribute Range used for writing 0056 0057 A range used for writing. It has a well-defined start but not a length/end yet. 0058 It is artificially made non-copyable in order to clarify the semantics of Begin/CommitRange. 0059 For the same reason, it can only be created by the AttrSetWriter. 0060 */ 0061 // clang-format on 0062 class RNTupleAttrPendingRange final { 0063 friend class ROOT::Experimental::RNTupleAttrSetWriter; 0064 0065 ROOT::NTupleSize_t fStart = 0; 0066 std::uint64_t fModelId = 0; 0067 bool fWasCommitted = false; 0068 0069 explicit RNTupleAttrPendingRange(ROOT::NTupleSize_t start, ROOT::DescriptorId_t modelId) 0070 : fStart(start), fModelId(modelId) 0071 { 0072 } 0073 0074 public: 0075 RNTupleAttrPendingRange() = default; 0076 RNTupleAttrPendingRange(const RNTupleAttrPendingRange &) = delete; 0077 RNTupleAttrPendingRange &operator=(const RNTupleAttrPendingRange &) = delete; 0078 0079 RNTupleAttrPendingRange(RNTupleAttrPendingRange &&other) { *this = std::move(other); } 0080 0081 // NOTE: explicitly implemented to make sure that 'other' gets invalidated upon move. 0082 RNTupleAttrPendingRange &operator=(RNTupleAttrPendingRange &&other) 0083 { 0084 if (&other != this) { 0085 std::swap(fStart, other.fStart); 0086 std::swap(fModelId, other.fModelId); 0087 other.fWasCommitted = true; 0088 fWasCommitted = false; 0089 } 0090 return *this; 0091 } 0092 0093 ~RNTupleAttrPendingRange() 0094 { 0095 if (R__unlikely(!fWasCommitted)) 0096 R__LOG_WARNING(ROOT::Internal::NTupleLog()) << "A pending attribute range was not committed! If CommitRange() " 0097 "is not explicitly called before closing the main " 0098 "Writer, the attributes will not be saved to storage!"; 0099 } 0100 0101 ROOT::NTupleSize_t GetStart() const 0102 { 0103 if (!IsValid()) 0104 throw ROOT::RException(R__FAIL("Tried to get the start of an invalid AttrPendingRange.")); 0105 return fStart; 0106 } 0107 0108 ROOT::DescriptorId_t GetModelId() const { return fModelId; } 0109 0110 /// Returns true if this PendingRange is valid 0111 operator bool() const { return IsValid(); } 0112 bool IsValid() const { return fModelId != 0; } 0113 }; 0114 0115 // clang-format off 0116 /** 0117 \class ROOT::Experimental::RNTupleAttrSetWriter 0118 \ingroup NTuple 0119 \brief Class used to write an RNTupleAttrSet in the context of an RNTupleWriter. 0120 0121 An Attribute Set is written as a separate RNTuple linked to the "main" RNTuple that created it. 0122 A RNTupleAttrSetWriter only lives as long as the RNTupleWriter that created it (or until CloseAttributeSet() is called). 0123 Users should not use this class directly but rather via RNTupleAttrSetWriterHandle, which is the type returned by 0124 RNTupleWriter::CreateAttributeSet(). 0125 0126 ~~~ {.cpp} 0127 // Writing attributes via RNTupleAttrSetWriter 0128 // ------------------------------------------- 0129 0130 // First define the schema of your Attribute Set: 0131 auto attrModel = ROOT::RNTupleModel::Create(); 0132 auto pMyAttr = attrModel->MakeField<std::string>("myAttr"); 0133 0134 // Then, assuming `writer` is an RNTupleWriter, create it: 0135 auto attrSet = writer->CreateAttributeSet(std::move(attrModel), "MyAttrSet"); 0136 0137 // Attributes are assigned to entry ranges. A range is started via BeginRange(): 0138 auto range = attrSet->BeginRange(); 0139 0140 // To assign actual attributes, you use the same interface as the main RNTuple: 0141 *pMyAttr = "This is my attribute for this range"; 0142 0143 // ... here you can fill your main RNTuple with data ... 0144 0145 // Once you're done, close the range. This will commit the attribute data and bind it to all data written 0146 // between BeginRange() and CommitRange(). 0147 attrSet->CommitRange(std::move(range)); 0148 0149 // You don't need to explicitly close the AttributeSet, but if you want to do so, use: 0150 // writer->CloseAttributeSet(std::move(attrSet)); 0151 ~~~ 0152 */ 0153 // clang-format on 0154 class RNTupleAttrSetWriter final { 0155 friend class ROOT::RNTupleWriter; 0156 0157 /// Our own fill context. 0158 RNTupleFillContext fFillContext; 0159 /// Fill context of the main RNTuple being written (i.e. the RNTuple whose attributes we are). 0160 const RNTupleFillContext *fMainFillContext = nullptr; 0161 /// The model that the user provided on creation. Used to create user-visible entries. 0162 std::unique_ptr<RNTupleModel> fUserModel; 0163 0164 // Cached values of the meta entry pointers. 0165 std::shared_ptr<ROOT::NTupleSize_t> fRangeStartPtr; 0166 std::shared_ptr<ROOT::NTupleSize_t> fRangeLenPtr; 0167 0168 /// Creates an RNTupleAttrSetWriter associated to the RNTupleWriter owning `mainFillContext` and writing 0169 /// using `sink`. `userModel` is the schema of the AttributeSet. 0170 static std::unique_ptr<RNTupleAttrSetWriter> Create(const RNTupleFillContext &mainFillContext, 0171 std::unique_ptr<ROOT::Internal::RPageSink> sink, 0172 std::unique_ptr<RNTupleModel> userModel); 0173 0174 RNTupleAttrSetWriter(const RNTupleFillContext &mainFillContext, std::unique_ptr<ROOT::Internal::RPageSink> sink, 0175 std::unique_ptr<RNTupleModel> metaModel, std::unique_ptr<RNTupleModel> userModel, 0176 std::shared_ptr<ROOT::NTupleSize_t> rangeStartPtr, 0177 std::shared_ptr<ROOT::NTupleSize_t> rangeLenPtr); 0178 0179 /// Commits the attributes written so far to disk and disables writing any new ones. 0180 ROOT::Internal::RNTupleLink Commit(); 0181 0182 public: 0183 /// Returns the descriptor of the underlying attribute RNTuple. This is **NOT** the same descriptor as the 0184 /// main RNTuple being written! 0185 const ROOT::RNTupleDescriptor &GetDescriptor() const { return fFillContext.fSink->GetDescriptor(); } 0186 /// Returns the user-defined model used to create this attribute set. 0187 const ROOT::RNTupleModel &GetModel() const { return *fUserModel; } 0188 0189 /// Begins an attribute range. All entries filled in the main RNTupleWriter between BeginRange and CommitRange 0190 /// will be associated with the set of values of the fields of this attribute set at the moment of CommitRange. 0191 /// Note that every attribute range must be explicitly committed for it to be stored on disk. 0192 /// \return An object describing the pending range, which must be passed back to CommitRange to end the attribute 0193 /// range 0194 [[nodiscard]] RNTupleAttrPendingRange BeginRange(); 0195 /// Ends an attribute range and associates the current values of the fields of the attribute model's default entry 0196 /// with all the main RNTuple entries filled since the BeginRange that created the given `range`. 0197 /// This is only valid if the model used to create this attribute set is not bare. 0198 void CommitRange(RNTupleAttrPendingRange range); 0199 /// Like CommitRange(RNTupleAttrPendingRange range) but uses the given entry rather than the default entry. 0200 /// The given entry must have been created by CreateEntry(). 0201 void CommitRange(RNTupleAttrPendingRange range, REntry &entry); 0202 0203 /// Creates an REntry fit to pass to CommitRange(RNTupleAttrPendingRange range, REntry entry). 0204 std::unique_ptr<REntry> CreateEntry() { return fUserModel->CreateEntry(); } 0205 }; 0206 0207 // clang-format off 0208 /** 0209 \class ROOT::Experimental::RNTupleAttrSetWriterHandle 0210 \ingroup NTuple 0211 \brief Non-owning handle to an RNTupleAttrSetWriter 0212 0213 RNTupleAttrSetWriter can only be used through an RNTupleAttrSetWriterHandle, a weak_ptr-like object that allows safe 0214 access to it. The lifetime of an attribute set writer is tied to its parent RNTupleWriter, so the handle handed out 0215 by RNTupleWriter::CreateAttributeSet is invalidated as soon as the parent writer is destructed. 0216 0217 */ 0218 // clang-format on 0219 class RNTupleAttrSetWriterHandle final { 0220 friend class ROOT::RNTupleWriter; 0221 0222 std::weak_ptr<RNTupleAttrSetWriter> fWriter; 0223 0224 explicit RNTupleAttrSetWriterHandle(const std::shared_ptr<RNTupleAttrSetWriter> &range) : fWriter(range) {} 0225 0226 public: 0227 RNTupleAttrSetWriterHandle(const RNTupleAttrSetWriterHandle &) = delete; 0228 RNTupleAttrSetWriterHandle &operator=(const RNTupleAttrSetWriterHandle &) = delete; 0229 RNTupleAttrSetWriterHandle(RNTupleAttrSetWriterHandle &&) = default; 0230 RNTupleAttrSetWriterHandle &operator=(RNTupleAttrSetWriterHandle &&other) = default; 0231 0232 /// Retrieves the underlying pointer to the AttrSetWriter, throwing if it's invalid. 0233 RNTupleAttrSetWriter *operator->() 0234 { 0235 auto ptr = fWriter.lock(); 0236 if (R__unlikely(!ptr)) 0237 throw ROOT::RException(R__FAIL("Tried to access invalid RNTupleAttrSetWriterHandle")); 0238 return ptr.get(); 0239 } 0240 }; 0241 0242 } // namespace Experimental 0243 } // namespace ROOT 0244 0245 #endif
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|