Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RNTupleWriter.cxx
Go to the documentation of this file.
1/// \file RNTupleReader.cxx
2/// \ingroup NTuple
3/// \author Jakob Blomer <jblomer@cern.ch>
4/// \date 2024-02-20
5
6/*************************************************************************
7 * Copyright (C) 1995-2024, Rene Brun and Fons Rademakers. *
8 * All rights reserved. *
9 * *
10 * For the licensing terms see $ROOTSYS/LICENSE. *
11 * For the list of contributors see $ROOTSYS/README/CREDITS. *
12 *************************************************************************/
13
15
16#include <ROOT/RLogger.hxx>
21#include <ROOT/RNTupleModel.hxx>
22#include <ROOT/RNTupleUtils.hxx>
24#include <ROOT/RPageSinkBuf.hxx>
25#include <ROOT/RPageStorage.hxx>
27#include <ROOT/RFile.hxx>
28
29#include <TFile.h>
30#include <TROOT.h>
31
32#include <utility>
33
34static bool IsReservedRNTupleAttrSetName(std::string_view name)
35{
36 return ROOT::StartsWith(name, "__");
37}
38
39ROOT::RNTupleWriter::RNTupleWriter(std::unique_ptr<ROOT::RNTupleModel> model,
40 std::unique_ptr<ROOT::Internal::RPageSink> sink)
41 : fFillContext(std::move(model), std::move(sink)), fMetrics("RNTupleWriter")
42{
43#ifdef R__USE_IMT
44 if (IsImplicitMTEnabled() &&
45 fFillContext.fSink->GetWriteOptions().GetUseImplicitMT() != ROOT::RNTupleWriteOptions::EImplicitMT::kOff) {
46 fFillContext.fZipTasks = std::make_unique<ROOT::Experimental::Internal::RNTupleImtTaskScheduler>();
47 fFillContext.fSink->SetTaskScheduler(fFillContext.fZipTasks.get());
48 }
49#endif
50 // Observe directly the sink's metrics to avoid an additional prefix from the fill context.
52}
53
55{
56 try {
57 CommitDataset();
58 } catch (const RException &err) {
59 R__LOG_ERROR(ROOT::Internal::NTupleLog()) << "failure committing ntuple: " << err.GetError().GetReport();
60 }
61}
62
63std::unique_ptr<ROOT::RNTupleWriter> ROOT::RNTupleWriter::Create(std::unique_ptr<ROOT::RNTupleModel> model,
64 std::unique_ptr<Internal::RPageSink> sink,
65 const ROOT::RNTupleWriteOptions &options)
66{
67 if (model->GetRegisteredSubfieldNames().size() > 0) {
68 throw RException(R__FAIL("cannot create an RNTupleWriter from a model with registered subfields"));
69 }
70 for (const auto &field : model->GetConstFieldZero()) {
72 throw RException(
73 R__FAIL("creating a RNTupleWriter from a model containing emulated fields is currently unsupported."));
74 }
75 if (options.GetUseBufferedWrite()) {
76 sink = std::make_unique<Internal::RPageSinkBuf>(std::move(sink));
77 }
78 return std::unique_ptr<RNTupleWriter>(new RNTupleWriter(std::move(model), std::move(sink)));
79}
80
81std::unique_ptr<ROOT::RNTupleWriter>
82ROOT::RNTupleWriter::Recreate(std::unique_ptr<ROOT::RNTupleModel> model, std::string_view ntupleName,
83 std::string_view storage, const ROOT::RNTupleWriteOptions &options)
84{
86 return Create(std::move(model), std::move(sink), options);
87}
88
89std::unique_ptr<ROOT::RNTupleWriter>
90ROOT::RNTupleWriter::Recreate(std::initializer_list<std::pair<std::string_view, std::string_view>> fields,
91 std::string_view ntupleName, std::string_view storage,
92 const ROOT::RNTupleWriteOptions &options)
93{
95 auto model = ROOT::RNTupleModel::Create();
96 for (const auto &fieldDesc : fields) {
97 std::string typeName(fieldDesc.first);
98 std::string fieldName(fieldDesc.second);
100 model->AddField(field.Unwrap());
101 }
102 return Create(std::move(model), std::move(sink), options);
103}
104
105std::unique_ptr<ROOT::RNTupleWriter>
106ROOT::RNTupleWriter::Append(std::unique_ptr<ROOT::RNTupleModel> model, std::string_view ntupleName,
108{
109 auto file = fileOrDirectory.GetFile();
110 if (!file) {
111 throw RException(R__FAIL("RNTupleWriter only supports writing to a ROOT file. Cannot write into a directory "
112 "that is not backed by a file"));
113 }
114 if (!file->IsBinary()) {
115 throw RException(R__FAIL("RNTupleWriter only supports writing to a ROOT file. Cannot write into " +
116 std::string(file->GetName())));
117 }
118 if (!file->IsWritable()) {
119 throw RException(R__FAIL("The file '" + std::string(file->GetName()) +
120 "' given to RNTupleWriter is not writable. Open it with 'UPDATE' or 'RECREATE' "
121 "if you want to write into it."));
122 }
123
124 auto sink = std::make_unique<Internal::RPageSinkFile>(ntupleName, fileOrDirectory, options);
125 return Create(std::move(model), std::move(sink), options);
126}
127
129{
130 if (GetNEntries() == fLastCommittedClusterGroup)
131 return;
132 fFillContext.fSink->CommitClusterGroup();
133 fLastCommittedClusterGroup = GetNEntries();
134}
135
137{
138 if (fFillContext.fModel->IsExpired()) {
139 throw RException(R__FAIL("invalid attempt to update expired model"));
140 }
141 return *fFillContext.fModel;
142}
143
145{
146 if (fFillContext.GetModel().IsExpired())
147 return;
148
149 CommitCluster(true /* commitClusterGroup */);
150
151 // Commit attributes
152 for (auto &attrSet : fAttributeSets) {
153 CloseAttributeSetImpl(*attrSet);
154 }
155
156 fFillContext.fSink->CommitDataset();
157 fFillContext.fModel->Expire();
158}
159
160std::unique_ptr<ROOT::RNTupleWriter>
161ROOT::Internal::CreateRNTupleWriter(std::unique_ptr<ROOT::RNTupleModel> model,
162 std::unique_ptr<ROOT::Internal::RPageSink> sink)
163{
164 return std::unique_ptr<ROOT::RNTupleWriter>(new ROOT::RNTupleWriter(std::move(model), std::move(sink)));
165}
166
167std::unique_ptr<ROOT::RNTupleWriter>
168ROOT::Experimental::RNTupleWriter_Append(std::unique_ptr<ROOT::RNTupleModel> model, std::string_view ntupleName,
170{
172 auto sink = std::make_unique<ROOT::Internal::RPageSinkFile>(ntupleBasename, file, ntupleDir, options);
173 return ROOT::RNTupleWriter::Create(std::move(model), std::move(sink), options);
174}
175
177ROOT::RNTupleWriter::CreateAttributeSet(std::unique_ptr<ROOT::RNTupleModel> model, std::string_view name,
179{
181 throw ROOT::RException(R__FAIL("Cannot create Attribute Set named \"" + std::string(name) +
182 "\": names starting with '__' are reserved for internal use."));
183 }
184
185 if (name.empty())
186 throw ROOT::RException(R__FAIL("cannot create an Attribute Set with an empty name"));
187
188 const RNTupleWriteOptions &opts = optsPtr != nullptr ? *optsPtr : fFillContext.fSink->GetWriteOptions();
189 auto attrSink = fFillContext.fSink->CloneAsHidden(name, opts);
190
191 std::string nameStr{name};
192 auto attrSet = Experimental::RNTupleAttrSetWriter::Create(fFillContext, std::move(attrSink), std::move(model));
193
194 // check for duplicates
195 auto existingIt = std::find_if(fAttributeSets.begin(), fAttributeSets.end(),
196 [&nameStr](const auto &set) { return set->GetDescriptor().GetName() == nameStr; });
197 if (existingIt != fAttributeSets.end())
198 throw ROOT::RException(R__FAIL(std::string("attempted to create an Attribute Set named '") + nameStr +
199 "', but one already exists with that name"));
200
201 auto &addedSet = fAttributeSets.emplace_back(std::move(attrSet));
203}
204
206{
207 auto attrAnchorInfo = attrSet.Commit();
208 fFillContext.fSink->CommitAttributeSet(attrSet.GetDescriptor().GetName(), attrAnchorInfo);
209}
210
212{
213 auto writer = handle.fWriter.lock();
214 if (writer) {
215 throw ROOT::RException(R__FAIL("Tried to close an invalid AttributeSetWriter"));
216 }
217
218 CloseAttributeSetImpl(*writer);
219
220 auto &attrSets = fAttributeSets;
221 for (auto it = attrSets.begin(), end = attrSets.end(); it != end; ++it) {
222 if (it->get() == writer.get()) {
223 attrSets.erase(it);
224 return;
225 }
226 }
227 // We must have erased the attribute set.
228 R__ASSERT(false);
229}
#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_ERROR(...)
Definition RLogger.hxx:357
static bool IsReservedRNTupleAttrSetName(std::string_view name)
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
#define R__ASSERT(e)
Checks condition e and reports a fatal error if it's false.
Definition TError.h:125
char name[80]
Definition TGX11.cxx:148
void ObserveMetrics(RNTupleMetrics &observee)
An interface to read from, or write to, a ROOT file, as well as performing other common operations.
Definition RFile.hxx:253
Non-owning handle to an RNTupleAttrSetWriter.
std::weak_ptr< RNTupleAttrSetWriter > fWriter
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...
static std::unique_ptr< RPageSink > Create(std::string_view ntupleName, std::string_view location, const ROOT::RNTupleWriteOptions &options=ROOT::RNTupleWriteOptions())
Guess the concrete derived page source from the location.
Base class for all ROOT issued exceptions.
Definition RError.hxx:79
const RError & GetError() const
Definition RError.hxx:84
@ kTraitEmulatedField
This field is a user defined type that was missing dictionaries and was reconstructed from the on-dis...
static RResult< std::unique_ptr< RFieldBase > > Create(const std::string &fieldName, const std::string &typeName, const ROOT::RCreateFieldOptions &options, const ROOT::RNTupleDescriptor *desc, ROOT::DescriptorId_t fieldId)
Factory method to resurrect a field from the stored on-disk type information.
std::unique_ptr< ROOT::Internal::RPageStorage::RTaskScheduler > fZipTasks
The page sink's parallel page compression scheduler if IMT is on.
std::unique_ptr< ROOT::Internal::RPageSink > fSink
The RNTupleModel encapulates the schema of an RNTuple.
static std::unique_ptr< RNTupleModel > Create()
Common user-tunable settings for storing RNTuples.
An RNTuple that gets filled with entries (data) and writes them to storage.
static std::unique_ptr< RNTupleWriter > Create(std::unique_ptr< ROOT::RNTupleModel > model, std::unique_ptr< Internal::RPageSink > sink, const ROOT::RNTupleWriteOptions &options)
Create a writer, potentially wrapping the sink in a RPageSinkBuf.
static std::unique_ptr< RNTupleWriter > Recreate(std::unique_ptr< ROOT::RNTupleModel > model, std::string_view ntupleName, std::string_view storage, const ROOT::RNTupleWriteOptions &options=ROOT::RNTupleWriteOptions())
Creates an RNTupleWriter backed by storage, overwriting it if one with the same URI exists.
Experimental::Detail::RNTupleMetrics fMetrics
RNTupleFillContext fFillContext
void CloseAttributeSet(ROOT::Experimental::RNTupleAttrSetWriterHandle handle)
Writes the given AttributeSet to the underlying storage and closes it.
ROOT::RNTupleModel & GetUpdatableModel()
ROOT::Experimental::RNTupleAttrSetWriterHandle CreateAttributeSet(std::unique_ptr< RNTupleModel > model, std::string_view name, const ROOT::RNTupleWriteOptions *options=nullptr)
Creates a new Attribute Set called name associated to this Writer and returns a non-owning pointer to...
static std::unique_ptr< RNTupleWriter > Append(std::unique_ptr< ROOT::RNTupleModel > model, std::string_view ntupleName, TDirectory &fileOrDirectory, const ROOT::RNTupleWriteOptions &options=ROOT::RNTupleWriteOptions())
Creates an RNTupleWriter that writes into an existing TFile or TDirectory, without overwriting its co...
RNTupleWriter(std::unique_ptr< ROOT::RNTupleModel > model, std::unique_ptr< Internal::RPageSink > sink)
void CommitDataset()
Closes the underlying file (page sink) and expires the model.
void CloseAttributeSetImpl(ROOT::Experimental::RNTupleAttrSetWriter &attrSet)
const_iterator begin() const
const_iterator end() const
Describe directory structure in memory.
Definition TDirectory.h:45
std::pair< std::string_view, std::string_view > DecomposePath(std::string_view path)
Given a "path-like" string (like foo/bar/baz), returns a pair { dirName, baseName }.
Definition RFile.cxx:194
std::unique_ptr< RNTupleWriter > RNTupleWriter_Append(std::unique_ptr< ROOT::RNTupleModel > model, std::string_view ntuplePath, ROOT::Experimental::RFile &file, const ROOT::RNTupleWriteOptions &options=ROOT::RNTupleWriteOptions())
Creates an RNTupleWriter that writes into the given file, appending to it.
ROOT::RLogChannel & NTupleLog()
Log channel for RNTuple diagnostics.
std::unique_ptr< RNTupleWriter > CreateRNTupleWriter(std::unique_ptr< ROOT::RNTupleModel > model, std::unique_ptr< Internal::RPageSink > sink)
Bool_t IsImplicitMTEnabled()
Returns true if the implicit multi-threading in ROOT is enabled.
Definition TROOT.cxx:675
bool StartsWith(std::string_view string, std::string_view prefix)