Logo ROOT  
Reference Guide
 
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
Loading...
Searching...
No Matches
RNTupleModel.cxx
Go to the documentation of this file.
1/// \file RNTupleModel.cxx
2/// \ingroup NTuple
3/// \author Jakob Blomer <jblomer@cern.ch>
4/// \date 2018-10-15
5
6/*************************************************************************
7 * Copyright (C) 1995-2019, 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
14#include <ROOT/RError.hxx>
15#include <ROOT/RField.hxx>
16#include <ROOT/RFieldToken.hxx>
17#include <ROOT/RNTupleModel.hxx>
19#include <ROOT/StringUtils.hxx>
20
21#include <atomic>
22#include <cstdlib>
23#include <memory>
24#include <utility>
25
26namespace {
27std::uint64_t GetNewModelId()
28{
29 static std::atomic<std::uint64_t> gLastModelId = 0;
30 return ++gLastModelId;
31}
32} // anonymous namespace
33
35{
36 if (model.IsExpired()) {
37 throw RException(R__FAIL("invalid use of expired model"));
38 }
39 return *model.fFieldZero;
40}
41
43{
44 if (model.IsExpired()) {
45 throw RException(R__FAIL("invalid use of expired model"));
46 }
47 return *model.fProjectedFields;
48}
49
50//------------------------------------------------------------------------------
51
54{
55 auto source = fieldMap.at(target);
56
57 if (!target->GetColumnRepresentatives()[0].empty()) {
58 const auto representative = target->GetColumnRepresentatives()[0][0];
59 // If the user is trying to add a projected field upon which they called SetTruncated() or SetQuantized(),
60 // they probably have the wrong expectations about what should happen. Warn them about it.
63 << "calling SetQuantized() or SetTruncated() on a projected field has no effect, as the on-disk "
64 "representation of the value is decided by the projection source field. Reading back the field will "
65 "yield the correct values, but the value range and bits of precision you set on the projected field "
66 "will be ignored.";
67 }
68 }
69
70 const bool hasCompatibleStructure = (source->GetStructure() == target->GetStructure()) ||
71 ((source->GetStructure() == ROOT::ENTupleStructure::kCollection) &&
72 dynamic_cast<const ROOT::RCardinalityField *>(target));
74 return R__FAIL("field mapping structural mismatch: " + source->GetFieldName() + " --> " + target->GetFieldName());
75 if ((source->GetStructure() == ROOT::ENTupleStructure::kLeaf) ||
76 (source->GetStructure() == ROOT::ENTupleStructure::kStreamer)) {
77 if (target->GetTypeName() != source->GetTypeName())
78 return R__FAIL("field mapping type mismatch: " + source->GetFieldName() + " --> " + target->GetFieldName());
79 }
80
81 auto fnHasArrayParent = [](const ROOT::RFieldBase &f) -> bool {
82 auto parent = f.GetParent();
83 while (parent) {
84 if (parent->GetNRepetitions() > 0)
85 return true;
86 parent = parent->GetParent();
87 }
88 return false;
89 };
91 return R__FAIL("unsupported field mapping across fixed-size arrays");
92 }
93
94 // We support projections only across records and collections. In the following, we check that the projected
95 // field is on the same path of collection fields in the field tree than the source field.
96
97 // Finds the first non-record parent field of the input field
98 auto fnBreakPoint = [](const ROOT::RFieldBase *f) -> const ROOT::RFieldBase * {
99 auto parent = f->GetParent();
100 while (parent) {
101 if ((parent->GetStructure() != ROOT::ENTupleStructure::kRecord) &&
102 (parent->GetStructure() != ROOT::ENTupleStructure::kLeaf)) {
103 return parent;
104 }
105 parent = parent->GetParent();
106 }
107 // We reached the zero field
108 return nullptr;
109 };
110
111 // If source or target has a variant or reference as a parent, error out
114 return R__FAIL("unsupported field mapping (source structure)");
117 return R__FAIL("unsupported field mapping (target structure)");
118
120 // Source and target have no collections as parent
121 return RResult<void>::Success();
122 }
125 // Source and target are children of the same collection
126 return RResult<void>::Success();
127 }
128 if (auto it = fieldMap.find(targetBreakPoint); it != fieldMap.end() && it->second == sourceBreakPoint) {
129 // The parent collection of parent is mapped to the parent collection of the source
130 return RResult<void>::Success();
131 }
132 // Source and target are children of different collections
133 return R__FAIL("field mapping structure mismatch: " + source->GetFieldName() + " --> " + target->GetFieldName());
134 }
135
136 // Either source or target have no collection as a parent, but the other one has; that doesn't fit
137 return R__FAIL("field mapping structure mismatch: " + source->GetFieldName() + " --> " + target->GetFieldName());
138}
139
141ROOT::Internal::RProjectedFields::Add(std::unique_ptr<ROOT::RFieldBase> field, const FieldMap_t &fieldMap)
142{
143 auto result = EnsureValidMapping(field.get(), fieldMap);
144 if (!result)
145 return R__FORWARD_ERROR(result);
146 for (const auto &f : *field) {
147 result = EnsureValidMapping(&f, fieldMap);
148 if (!result)
149 return R__FORWARD_ERROR(result);
150 }
151
152 fFieldMap.insert(fieldMap.begin(), fieldMap.end());
153 fFieldZero->Attach(std::move(field));
154 return RResult<void>::Success();
155}
156
158{
159 if (auto it = fFieldMap.find(target); it != fFieldMap.end())
160 return it->second;
161 return nullptr;
162}
163
164std::unique_ptr<ROOT::Internal::RProjectedFields>
166{
167 auto cloneFieldZero =
168 std::unique_ptr<ROOT::RFieldZero>(static_cast<ROOT::RFieldZero *>(fFieldZero->Clone("").release()));
169 auto clone = std::unique_ptr<RProjectedFields>(new RProjectedFields(std::move(cloneFieldZero)));
170 clone->fModel = &newModel;
171 // TODO(jblomer): improve quadratic search to re-wire the field mappings given the new model and the cloned
172 // projected fields. Not too critical as we generally expect a limited number of projected fields
173 for (const auto &[k, v] : fFieldMap) {
174 for (const auto &f : clone->GetFieldZero()) {
175 if (f.GetQualifiedFieldName() == k->GetQualifiedFieldName()) {
176 clone->fFieldMap[&f] = &newModel.GetConstField(v->GetQualifiedFieldName());
177 break;
178 }
179 }
180 }
181 return clone;
182}
183
185 : fWriter(writer), fOpenChangeset(fWriter.GetUpdatableModel())
186{
187}
188
190{
191 fOpenChangeset.fModel.Unfreeze();
192 // We set the model ID to zero until CommitUpdate(). That prevents calls to RNTupleWriter::Fill() in the middle
193 // of updates
194 std::swap(fOpenChangeset.fModel.fModelId, fNewModelId);
195}
196
198{
199 fOpenChangeset.fModel.Freeze();
200 std::swap(fOpenChangeset.fModel.fModelId, fNewModelId);
201 if (fOpenChangeset.IsEmpty())
202 return;
203 Internal::RNTupleModelChangeset toCommit{fOpenChangeset.fModel};
204 std::swap(fOpenChangeset.fAddedFields, toCommit.fAddedFields);
205 std::swap(fOpenChangeset.fAddedProjectedFields, toCommit.fAddedProjectedFields);
206 fWriter.GetSink().UpdateSchema(toCommit, fWriter.GetNEntries());
207}
208
209void ROOT::Internal::RNTupleModelChangeset::AddField(std::unique_ptr<ROOT::RFieldBase> field)
210{
211 auto fieldp = field.get();
212 fModel.AddField(std::move(field));
213 fAddedFields.emplace_back(fieldp);
214}
215
216void ROOT::RNTupleModel::RUpdater::AddField(std::unique_ptr<ROOT::RFieldBase> field)
217{
218 fOpenChangeset.AddField(std::move(field));
219}
220
223{
224 auto fieldp = field.get();
225 auto result = fModel.AddProjectedField(std::move(field), mapping);
226 if (result)
227 fAddedProjectedFields.emplace_back(fieldp);
229}
230
233{
234 return R__FORWARD_RESULT(fOpenChangeset.AddProjectedField(std::move(field), std::move(mapping)));
235}
236
238{
240 if (!nameValid) {
241 nameValid.Throw();
242 }
243 if (fieldName.empty()) {
244 throw RException(R__FAIL("name cannot be empty string \"\""));
245 }
246 auto fieldNameStr = std::string(fieldName);
247 if (fFieldNames.count(fieldNameStr) > 0)
248 throw RException(R__FAIL("field name '" + fieldNameStr + "' already exists in NTuple model"));
249}
250
252{
253 if (IsFrozen())
254 throw RException(R__FAIL("invalid attempt to modify frozen model"));
255}
256
258{
259 if (IsBare())
260 throw RException(R__FAIL("invalid attempt to use default entry of bare model"));
261}
262
263ROOT::RNTupleModel::RNTupleModel(std::unique_ptr<ROOT::RFieldZero> fieldZero)
265{
266}
267
268std::unique_ptr<ROOT::RNTupleModel> ROOT::RNTupleModel::CreateBare()
269{
270 return CreateBare(std::make_unique<ROOT::RFieldZero>());
271}
272
273std::unique_ptr<ROOT::RNTupleModel> ROOT::RNTupleModel::CreateBare(std::unique_ptr<ROOT::RFieldZero> fieldZero)
274{
275 auto model = std::unique_ptr<RNTupleModel>(new RNTupleModel(std::move(fieldZero)));
276 model->fProjectedFields = std::make_unique<Internal::RProjectedFields>(*model);
277 return model;
278}
279
280std::unique_ptr<ROOT::RNTupleModel> ROOT::RNTupleModel::Create()
281{
282 return Create(std::make_unique<ROOT::RFieldZero>());
283}
284
285std::unique_ptr<ROOT::RNTupleModel> ROOT::RNTupleModel::Create(std::unique_ptr<ROOT::RFieldZero> fieldZero)
286{
287 auto model = CreateBare(std::move(fieldZero));
288 model->fDefaultEntry = std::unique_ptr<ROOT::REntry>(new ROOT::REntry(model->fModelId, model->fSchemaId));
289 return model;
290}
291
292std::unique_ptr<ROOT::RNTupleModel> ROOT::RNTupleModel::Clone() const
293{
294 auto cloneModel = std::unique_ptr<RNTupleModel>(new RNTupleModel(
295 std::unique_ptr<ROOT::RFieldZero>(static_cast<ROOT::RFieldZero *>(fFieldZero->Clone("").release()))));
296 cloneModel->fModelId = GetNewModelId();
297 // For a frozen model, we can keep the schema id because adding new fields is forbidden. It is reset in Unfreeze()
298 // if called by the user.
299 if (IsFrozen()) {
300 cloneModel->fSchemaId = fSchemaId;
301 } else {
302 cloneModel->fSchemaId = cloneModel->fModelId;
303 }
304 cloneModel->fModelState = (fModelState == EState::kExpired) ? EState::kFrozen : fModelState;
305 cloneModel->fFieldNames = fFieldNames;
306 cloneModel->fDescription = fDescription;
307 cloneModel->fProjectedFields = fProjectedFields->Clone(*cloneModel);
308 cloneModel->fRegisteredSubfields = fRegisteredSubfields;
309 if (fDefaultEntry) {
310 cloneModel->fDefaultEntry =
311 std::unique_ptr<ROOT::REntry>(new ROOT::REntry(cloneModel->fModelId, cloneModel->fSchemaId));
312 for (const auto &f : cloneModel->fFieldZero->GetMutableSubfields()) {
313 cloneModel->fDefaultEntry->AddValue(f->CreateValue());
314 }
315 for (const auto &f : cloneModel->fRegisteredSubfields) {
316 cloneModel->AddSubfield(f, *cloneModel->fDefaultEntry);
317 }
318 }
319 return cloneModel;
320}
321
323{
324 if (fieldName.empty())
325 return nullptr;
326
327 auto *field = static_cast<ROOT::RFieldBase *>(fFieldZero.get());
328 for (auto subfieldName : ROOT::Split(fieldName, ".")) {
329 const auto subfields = field->GetMutableSubfields();
330 auto it = std::find_if(subfields.begin(), subfields.end(),
331 [&](const auto *f) { return f->GetFieldName() == subfieldName; });
332 if (it != subfields.end()) {
333 field = *it;
334 } else {
335 field = nullptr;
336 break;
337 }
338 }
339
340 return field;
341}
342
343void ROOT::RNTupleModel::AddField(std::unique_ptr<ROOT::RFieldBase> field)
344{
345 EnsureNotFrozen();
346 if (!field)
347 throw RException(R__FAIL("null field"));
348 EnsureValidFieldName(field->GetFieldName());
349
350 if (fDefaultEntry)
351 fDefaultEntry->AddValue(field->CreateValue());
352 fFieldNames.insert(field->GetFieldName());
353 fFieldZero->Attach(std::move(field));
354}
355
357 bool initializeValue) const
358{
359 auto field = FindField(qualifiedFieldName);
360 if (initializeValue)
361 entry.AddValue(field->CreateValue());
362 else
363 entry.AddValue(field->BindValue(nullptr));
364}
365
367{
368 if (qualifiedFieldName.empty())
369 throw RException(R__FAIL("no field name provided"));
370
371 if (fFieldNames.find(std::string(qualifiedFieldName)) != fFieldNames.end()) {
372 throw RException(
373 R__FAIL("cannot register top-level field \"" + std::string(qualifiedFieldName) + "\" as a subfield"));
374 }
375
376 if (fRegisteredSubfields.find(std::string(qualifiedFieldName)) != fRegisteredSubfields.end())
377 throw RException(R__FAIL("subfield \"" + std::string(qualifiedFieldName) + "\" already registered"));
378
379 EnsureNotFrozen();
380
381 auto *field = FindField(qualifiedFieldName);
382 if (!field) {
383 throw RException(R__FAIL("could not find subfield \"" + std::string(qualifiedFieldName) + "\" in model"));
384 }
385
386 auto parent = field->GetParent();
387 while (parent && !parent->GetFieldName().empty()) {
388 if (parent->GetStructure() == ROOT::ENTupleStructure::kCollection || parent->GetNRepetitions() > 0 ||
389 parent->GetStructure() == ROOT::ENTupleStructure::kVariant) {
390 throw RException(R__FAIL(
391 "registering a subfield as part of a collection, fixed-sized array or std::variant is not supported"));
392 }
393 parent = parent->GetParent();
394 }
395
396 if (fDefaultEntry)
397 AddSubfield(qualifiedFieldName, *fDefaultEntry);
398 fRegisteredSubfields.emplace(qualifiedFieldName);
399}
400
403{
404 EnsureNotFrozen();
405 if (!field)
406 return R__FAIL("null field");
407 auto fieldName = field->GetFieldName();
408
410 auto sourceField = FindField(mapping(fieldName));
411 if (!sourceField)
412 return R__FAIL("no such field: " + mapping(fieldName));
413 fieldMap[field.get()] = sourceField;
414 for (const auto &subField : *field) {
415 sourceField = FindField(mapping(subField.GetQualifiedFieldName()));
416 if (!sourceField)
417 return R__FAIL("no such field: " + mapping(subField.GetQualifiedFieldName()));
419 }
420
421 EnsureValidFieldName(fieldName);
422 auto result = fProjectedFields->Add(std::move(field), fieldMap);
423 if (!result) {
424 return R__FORWARD_ERROR(result);
425 }
426 fFieldNames.insert(fieldName);
427 return RResult<void>::Success();
428}
429
431{
432 if (IsFrozen())
433 throw RException(R__FAIL("invalid attempt to get mutable zero field of frozen model"));
434 return *fFieldZero;
435}
436
438{
439 if (IsFrozen())
440 throw RException(R__FAIL("invalid attempt to get mutable field of frozen model"));
441 auto f = FindField(fieldName);
442 if (!f)
443 throw RException(R__FAIL("invalid field: " + std::string(fieldName)));
444
445 return *f;
446}
447
449{
450 auto f = FindField(fieldName);
451 if (!f)
452 throw RException(R__FAIL("invalid field: " + std::string(fieldName)));
453
454 return *f;
455}
456
458{
459 EnsureNotBare();
460 return *fDefaultEntry;
461}
462
464{
465 if (!IsFrozen())
466 throw RException(R__FAIL("invalid attempt to get default entry of unfrozen model"));
467 EnsureNotBare();
468 return *fDefaultEntry;
469}
470
471std::unique_ptr<ROOT::REntry> ROOT::RNTupleModel::CreateEntry() const
472{
473 switch (fModelState) {
474 case EState::kBuilding: throw RException(R__FAIL("invalid attempt to create entry of unfrozen model"));
475 case EState::kExpired: throw RException(R__FAIL("invalid attempt to create entry of expired model"));
476 case EState::kFrozen: break;
477 }
478
479 auto entry = std::unique_ptr<ROOT::REntry>(new ROOT::REntry(fModelId, fSchemaId));
480 for (const auto &f : fFieldZero->GetMutableSubfields()) {
481 entry->AddValue(f->CreateValue());
482 }
483 for (const auto &f : fRegisteredSubfields) {
484 AddSubfield(f, *entry);
485 }
486 return entry;
487}
488
489std::unique_ptr<ROOT::REntry> ROOT::RNTupleModel::CreateBareEntry() const
490{
491 switch (fModelState) {
492 case EState::kBuilding: throw RException(R__FAIL("invalid attempt to create entry of unfrozen model"));
493 case EState::kExpired: throw RException(R__FAIL("invalid attempt to create entry of expired model"));
494 case EState::kFrozen: break;
495 }
496
497 auto entry = std::unique_ptr<ROOT::REntry>(new ROOT::REntry(fModelId, fSchemaId));
498 for (const auto &f : fFieldZero->GetMutableSubfields()) {
499 entry->AddValue(f->BindValue(nullptr));
500 }
501 for (const auto &f : fRegisteredSubfields) {
502 AddSubfield(f, *entry, false /* initializeValue */);
503 }
504 return entry;
505}
506
507std::unique_ptr<ROOT::Experimental::Detail::RRawPtrWriteEntry> ROOT::RNTupleModel::CreateRawPtrWriteEntry() const
508{
509 switch (fModelState) {
510 case EState::kBuilding: throw RException(R__FAIL("invalid attempt to create entry of unfrozen model"));
511 case EState::kExpired: throw RException(R__FAIL("invalid attempt to create entry of expired model"));
512 case EState::kFrozen: break;
513 }
514
515 auto entry = std::unique_ptr<Experimental::Detail::RRawPtrWriteEntry>(
516 new Experimental::Detail::RRawPtrWriteEntry(fModelId, fSchemaId));
517 for (const auto &f : fFieldZero->GetMutableSubfields()) {
518 entry->AddField(*f);
519 }
520 // fRegisteredSubfields are not relevant for writing
521 return entry;
522}
523
525{
526 const auto &topLevelFields = fFieldZero->GetConstSubfields();
527 auto it = std::find_if(topLevelFields.begin(), topLevelFields.end(),
528 [&fieldName](const ROOT::RFieldBase *f) { return f->GetFieldName() == fieldName; });
529
530 if (it == topLevelFields.end()) {
531 throw RException(R__FAIL("invalid field name: " + std::string(fieldName)));
532 }
533 return ROOT::RFieldToken(std::distance(topLevelFields.begin(), it), fSchemaId);
534}
535
537{
538 switch (fModelState) {
539 case EState::kBuilding: throw RException(R__FAIL("invalid attempt to create bulk of unfrozen model"));
540 case EState::kExpired: throw RException(R__FAIL("invalid attempt to create bulk of expired model"));
541 case EState::kFrozen: break;
542 }
543
544 auto f = FindField(fieldName);
545 if (!f)
546 throw RException(R__FAIL("no such field: " + std::string(fieldName)));
547 return f->CreateBulk();
548}
549
551{
552 switch (fModelState) {
553 case EState::kExpired: return;
554 case EState::kBuilding: throw RException(R__FAIL("invalid attempt to expire unfrozen model"));
555 case EState::kFrozen: break;
556 }
557
558 // Ensure that Fill() does not work anymore
559 fModelId = 0;
560 fModelState = EState::kExpired;
561}
562
564{
565 switch (fModelState) {
566 case EState::kBuilding: return;
567 case EState::kExpired: throw RException(R__FAIL("invalid attempt to unfreeze expired model"));
568 case EState::kFrozen: break;
569 }
570
571 fModelId = GetNewModelId();
572 fSchemaId = fModelId;
573 if (fDefaultEntry) {
574 fDefaultEntry->fModelId = fModelId;
575 fDefaultEntry->fSchemaId = fSchemaId;
576 }
577 fModelState = EState::kBuilding;
578}
579
581{
582 if (fModelState == EState::kExpired)
583 throw RException(R__FAIL("invalid attempt to freeze expired model"));
584
585 fModelState = EState::kFrozen;
586}
587
589{
590 EnsureNotFrozen();
591 fDescription = std::string(description);
592}
593
595{
596 std::size_t bytes = 0;
597 std::size_t minPageBufferSize = 0;
598
599 // Start with the size of the page buffers used to fill a persistent sink
600 std::size_t nColumns = 0;
601 for (auto &&field : *fFieldZero) {
602 for (const auto &r : field.GetColumnRepresentatives()) {
603 nColumns += r.size();
604 minPageBufferSize += r.size() * options.GetInitialUnzippedPageSize();
605 }
606 }
607 bytes = std::min(options.GetPageBufferBudget(), nColumns * options.GetMaxUnzippedPageSize());
608
609 // If using buffered writing with RPageSinkBuf, we create a clone of the model and keep at least
610 // the compressed pages in memory.
611 if (options.GetUseBufferedWrite()) {
613 // Use the target cluster size as an estimate for all compressed pages combined.
615 int compression = options.GetCompression();
617 // With IMT, compression happens asynchronously which means that the uncompressed pages also stay around. Use a
618 // compression factor of 2x as a very rough estimate.
619 bytes += 2 * options.GetApproxZippedClusterSize();
620 }
621 }
622
623 return bytes;
624}
#define R__FORWARD_ERROR(res)
Short-hand to return an RResult<T> in an error state (i.e. after checking)
Definition RError.hxx:303
#define R__FORWARD_RESULT(res)
Short-hand to return an RResult<T> value from a subroutine to the calling stack frame.
Definition RError.hxx:301
#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:358
#define f(i)
Definition RSha256.hxx:104
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t target
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t r
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t bytes
A container of const raw pointers, corresponding to a row in the data set.
Container for the projected fields of an RNTupleModel.
const ROOT::RFieldBase * GetSourceField(const ROOT::RFieldBase *target) const
std::unordered_map< const ROOT::RFieldBase *, const ROOT::RFieldBase * > FieldMap_t
The map keys are the projected target fields, the map values are the backing source fields Note that ...
RResult< void > Add(std::unique_ptr< ROOT::RFieldBase > field, const FieldMap_t &fieldMap)
Adds a new projected field.
std::unique_ptr< RProjectedFields > Clone(const RNTupleModel &newModel) const
Clones this container and all the projected fields it owns.
RResult< void > EnsureValidMapping(const ROOT::RFieldBase *target, const FieldMap_t &fieldMap)
Asserts that the passed field is a valid target of the source field provided in the field map.
An artificial field that transforms an RNTuple column that contains the offset of collections into co...
Definition RField.hxx:310
The REntry is a collection of values in an ntuple corresponding to a complete row in the data set.
Definition REntry.hxx:54
Base class for all ROOT issued exceptions.
Definition RError.hxx:79
Points to an array of objects with RNTuple I/O support, used for bulk reading.
A field translates read and write calls from/to underlying columns to/from tree values.
const RFieldBase * GetParent() const
A field token identifies a (sub)field in an entry.
The container field for an ntuple model, which itself has no physical representation.
Definition RField.hxx:54
void CommitUpdate()
Commit changes since the last call to BeginUpdate().
RResult< void > AddProjectedField(std::unique_ptr< ROOT::RFieldBase > field, FieldMappingFunc_t mapping)
RUpdater(ROOT::RNTupleWriter &writer)
void AddField(std::unique_ptr< ROOT::RFieldBase > field)
void BeginUpdate()
Begin a new set of alterations to the underlying model.
The RNTupleModel encapulates the schema of an RNTuple.
std::unique_ptr< REntry > CreateEntry() const
Creates a new entry with default values for each field.
RNTupleModel(std::unique_ptr< ROOT::RFieldZero > fieldZero)
void AddSubfield(std::string_view fieldName, ROOT::REntry &entry, bool initializeValue=true) const
Add a subfield to the provided entry.
std::unique_ptr< RNTupleModel > Clone() const
std::uint64_t fModelId
Every model has a unique ID to distinguish it from other models.
void EnsureValidFieldName(std::string_view fieldName)
Checks that user-provided field names are valid in the context of this RNTupleModel.
ROOT::RFieldZero & GetMutableFieldZero()
Retrieves the field zero of this model, i.e.
std::size_t EstimateWriteMemoryUsage(const ROOT::RNTupleWriteOptions &options=ROOT::RNTupleWriteOptions()) const
Estimate the memory usage for this model during writing.
void Unfreeze()
Transitions an RNTupleModel from the frozen state back to the building state, invalidating all previo...
REntry & GetDefaultEntry()
Retrieves the default entry of this model.
void EnsureNotFrozen() const
Throws an RException if fFrozen is true.
void AddField(std::unique_ptr< ROOT::RFieldBase > field)
Adds a field whose type is not known at compile time.
static std::unique_ptr< RNTupleModel > Create()
bool IsFrozen() const
void SetDescription(std::string_view description)
std::unique_ptr< Experimental::Detail::RRawPtrWriteEntry > CreateRawPtrWriteEntry() const
std::unique_ptr< Internal::RProjectedFields > fProjectedFields
The set of projected top-level fields.
RResult< void > AddProjectedField(std::unique_ptr< ROOT::RFieldBase > field, FieldMappingFunc_t mapping)
Adds a top-level field based on existing fields.
ROOT::RFieldToken GetToken(std::string_view fieldName) const
Creates a token to be used in REntry methods to address a field present in the entry.
std::unordered_set< std::string > fFieldNames
Keeps track of which field names are taken, including projected field names.
std::unique_ptr< ROOT::RFieldZero > fFieldZero
Hierarchy of fields consisting of simple types and collections (sub trees)
void EnsureNotBare() const
Throws an RException if fDefaultEntry is nullptr.
void RegisterSubfield(std::string_view qualifiedFieldName)
Register a subfield so it can be accessed directly from entries belonging to the model.
ROOT::RFieldBase * FindField(std::string_view fieldName) const
The field name can be a top-level field or a nested field. Returns nullptr if the field is not in the...
void Freeze()
Transitions an RNTupleModel from the building state to the frozen state, disabling adding additional ...
ROOT::RFieldBase & GetMutableField(std::string_view fieldName)
Retrieves the field with fully-qualified name fieldName.
static std::unique_ptr< RNTupleModel > CreateBare()
Creates a "bare model", i.e. an RNTupleModel with no default entry.
std::function< std::string(const std::string &)> FieldMappingFunc_t
User-provided function that describes the mapping of existing source fields to projected fields in te...
void Expire()
Transitions an RNTupleModel from the frozen state to the expired state, invalidating all previously c...
bool IsExpired() const
std::uint64_t fSchemaId
Models have a separate schema ID to remember that the clone of a frozen model still has the same sche...
ROOT::RFieldBase::RBulk CreateBulk(std::string_view fieldName) const
Calls the given field's CreateBulk() method. Throws an RException if no field with the given name exi...
const ROOT::RFieldBase & GetConstField(std::string_view fieldName) const
std::unique_ptr< REntry > CreateBareEntry() const
Creates a "bare entry", i.e.
Common user-tunable settings for storing RNTuples.
std::size_t GetPageBufferBudget() const
std::size_t GetApproxZippedClusterSize() const
std::size_t GetMaxUnzippedPageSize() const
std::uint32_t GetCompression() const
EImplicitMT GetUseImplicitMT() const
std::size_t GetInitialUnzippedPageSize() const
An RNTuple that gets filled with entries (data) and writes them to storage.
const_iterator begin() const
const_iterator end() const
The class is used as a return type for operations that can fail; wraps a value of type T or an RError...
Definition RError.hxx:197
ROOT::RFieldZero & GetFieldZeroOfModel(RNTupleModel &model)
RResult< void > EnsureValidNameForRNTuple(std::string_view name, std::string_view where)
Check whether a given string is a valid name according to the RNTuple specification.
ROOT::RLogChannel & NTupleLog()
Log channel for RNTuple diagnostics.
RProjectedFields & GetProjectedFieldsOfModel(RNTupleModel &model)
std::vector< std::string > Split(std::string_view str, std::string_view delims, bool skipEmpty=false)
Splits a string at each character in delims.
The incremental changes to a RNTupleModel
void AddField(std::unique_ptr< ROOT::RFieldBase > field)
ROOT::RResult< void > AddProjectedField(std::unique_ptr< ROOT::RFieldBase > field, RNTupleModel::FieldMappingFunc_t mapping)