Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RFieldBase.hxx
Go to the documentation of this file.
1/// \file ROOT/RFieldBase.hxx
2/// \ingroup NTuple ROOT7
3/// \author Jakob Blomer <jblomer@cern.ch>
4/// \date 2018-10-09
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/*************************************************************************
9 * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. *
10 * All rights reserved. *
11 * *
12 * For the licensing terms see $ROOTSYS/LICENSE. *
13 * For the list of contributors see $ROOTSYS/README/CREDITS. *
14 *************************************************************************/
15
16#ifndef ROOT7_RFieldBase
17#define ROOT7_RFieldBase
18
19#include <ROOT/RColumn.hxx>
21#include <ROOT/RNTupleRange.hxx>
22#include <ROOT/RNTupleUtil.hxx>
23
24#include <cstddef>
25#include <functional>
26#include <iterator>
27#include <memory>
28#include <new>
29#include <string>
30#include <string_view>
31#include <vector>
32
33namespace ROOT {
34namespace Experimental {
35
36class RClassField;
37class RFieldBase;
38class RNTupleJoinProcessor;
39
40namespace Internal {
41struct RFieldCallbackInjector;
42struct RFieldRepresentationModifier;
43class RPageSink;
44class RPageSource;
45// TODO(jblomer): find a better way to not have these methods in the RFieldBase public API
46void CallFlushColumnsOnField(RFieldBase &);
47void CallCommitClusterOnField(RFieldBase &);
48void CallConnectPageSinkOnField(RFieldBase &, RPageSink &, NTupleSize_t firstEntry = 0);
49void CallConnectPageSourceOnField(RFieldBase &, RPageSource &);
51CallFieldBaseCreate(const std::string &fieldName, const std::string &canonicalType, const std::string &typeAlias,
52 const RCreateFieldOptions &options, const RNTupleDescriptor *desc, DescriptorId_t fieldId);
53
54} // namespace Internal
55
56namespace Detail {
57class RFieldVisitor;
58} // namespace Detail
59
60// clang-format off
61/**
62\class ROOT::Experimental::RFieldBase
63\ingroup NTuple
64\brief A field translates read and write calls from/to underlying columns to/from tree values
65
66A field is a serializable C++ type or a container for a collection of sub fields. The RFieldBase and its
67type-safe descendants provide the object to column mapper. They map C++ objects to primitive columns. The
68mapping is trivial for simple types such as 'double'. Complex types resolve to multiple primitive columns.
69The field knows based on its type and the field name the type(s) and name(s) of the columns.
70
71Note: the class hierarchy starting at RFieldBase is not meant to be extended by user-provided child classes.
72This is and can only be partially enforced through C++.
73*/
74// clang-format on
76 friend class ROOT::Experimental::RClassField; // to mark members as artificial
77 friend class ROOT::Experimental::RNTupleJoinProcessor; // needs ConstructValue
78 friend struct ROOT::Experimental::Internal::RFieldCallbackInjector; // used for unit tests
85 Internal::CallFieldBaseCreate(const std::string &fieldName, const std::string &canonicalType,
86 const std::string &typeAlias, const RCreateFieldOptions &options,
88
89 using ReadCallback_t = std::function<void(void *)>;
90
91protected:
92 /// A functor to release the memory acquired by CreateValue (memory and constructor).
93 /// This implementation works for types with a trivial destructor. More complex fields implement a derived deleter.
94 /// The deleter is operational without the field object and thus can be used to destruct/release a value after
95 /// the field has been destructed.
96 class RDeleter {
97 public:
98 virtual ~RDeleter() = default;
99 virtual void operator()(void *objPtr, bool dtorOnly)
100 {
101 if (!dtorOnly)
102 operator delete(objPtr);
103 }
104 };
105
106 /// A deleter for templated RFieldBase descendents where the value type is known.
107 template <typename T>
108 class RTypedDeleter : public RDeleter {
109 public:
110 void operator()(void *objPtr, bool dtorOnly) final
111 {
112 std::destroy_at(static_cast<T *>(objPtr));
114 }
115 };
116
117 // We cannot directly use RFieldBase::RDeleter as a shared pointer deleter due to splicing. We use this
118 // wrapper class to store a polymorphic pointer to the actual deleter.
120 std::unique_ptr<RFieldBase::RDeleter> fDeleter;
121 void operator()(void *objPtr) { fDeleter->operator()(objPtr, false /* dtorOnly*/); }
122 explicit RSharedPtrDeleter(std::unique_ptr<RFieldBase::RDeleter> deleter) : fDeleter(std::move(deleter)) {}
123 };
124
125public:
126 static constexpr std::uint32_t kInvalidTypeVersion = -1U;
127 enum {
128 /// No constructor needs to be called, i.e. any bit pattern in the allocated memory represents a valid type
129 /// A trivially constructible field has a no-op ConstructValue() implementation
131 /// The type is cleaned up just by freeing its memory. I.e. the destructor performs a no-op.
133 /// A field of a fundamental type that can be directly mapped via `RField<T>::Map()`, i.e. maps as-is to a single
134 /// column
136 /// The TClass checksum is set and valid
138 /// This field is an instance of RInvalidField and can be safely static_cast to it
140 /// This field is a user defined type that was missing dictionaries and was reconstructed from the on-disk
141 /// information
143
144 /// Shorthand for types that are both trivially constructible and destructible
146 };
147
148 using ColumnRepresentation_t = std::vector<ENTupleColumnType>;
149
150 /// During its lifetime, a field undergoes the following possible state transitions:
151 ///
152 /// [*] --> Unconnected --> ConnectedToSink ----
153 /// | | |
154 /// | --> ConnectedToSource ---> [*]
155 /// | |
156 /// -------------------------------
157 enum class EState {
161 };
162
163 /// Some fields have multiple possible column representations, e.g. with or without split encoding.
164 /// All column representations supported for writing also need to be supported for reading. In addition,
165 /// fields can support extra column representations for reading only, e.g. a 64bit integer reading from a
166 /// 32bit column.
167 /// The defined column representations must be supported by corresponding column packing/unpacking implementations,
168 /// i.e. for the example above, the unpacking of 32bit ints to 64bit pages must be implemented in RColumnElement.hxx
170 public:
171 /// A list of column representations
172 using Selection_t = std::vector<ColumnRepresentation_t>;
173
176
177 /// The first column list from fSerializationTypes is the default for writing.
181
182 private:
184 /// The union of the serialization types and the deserialization extra types. Duplicates the serialization types
185 /// list but the benenfit is that GetDeserializationTypes does not need to compile the list.
187 }; // class RColumnRepresentations
188
189 class RValue;
190 class RBulk;
191
192private:
193 /// The field name relative to its parent field
194 std::string fName;
195 /// The C++ type captured by this field
196 std::string fType;
197 /// The role of this field in the data model structure
199 /// For fixed sized arrays, the array length
200 std::size_t fNRepetitions;
201 /// A field qualifies as simple if it is mappable (which implies it has a single principal column),
202 /// and it is not an artificial field and has no post-read callback
204 /// A field that is not backed on disk but computed, e.g. a default-constructed missing field or
205 /// a field whose data is created by I/O customization rules. Subfields of artificial fields are
206 /// artificial, too.
207 bool fIsArtificial = false;
208 /// When the columns are connected to a page source or page sink, the field represents a field id in the
209 /// corresponding RNTuple descriptor. This on-disk ID is set in RPageSink::Create() for writing and by
210 /// RFieldDescriptor::CreateField() when recreating a field / model from the stored descriptor.
212 /// Free text set by the user
213 std::string fDescription;
214 /// Changed by ConnectTo[Sink,Source], reset by Clone()
216
218 {
219 for (const auto &func : fReadCallbacks)
220 func(target);
221 }
222
223 /// Translate an entry index to a column element index of the principal column and viceversa. These functions
224 /// take into account the role and number of repetitions on each level of the field hierarchy as follows:
225 /// - Top level fields: element index == entry index
226 /// - Record fields propagate their principal column index to the principal columns of direct descendant fields
227 /// - Collection and variant fields set the principal column index of their childs to 0
228 ///
229 /// The column element index also depends on the number of repetitions of each field in the hierarchy, e.g., given a
230 /// field with type `std::array<std::array<float, 4>, 2>`, this function returns 8 for the inner-most field.
232
233 /// Flushes data from active columns
234 void FlushColumns();
235 /// Flushes data from active columns to disk and calls CommitClusterImpl
236 void CommitCluster();
237 /// Fields and their columns live in the void until connected to a physical page storage. Only once connected, data
238 /// can be read or written. In order to find the field in the page storage, the field's on-disk ID has to be set.
239 /// \param firstEntry The global index of the first entry with on-disk data for the connected field
241 /// Connects the field and its sub field tree to the given page source. Once connected, data can be read.
242 /// Only unconnected fields may be connected, i.e. the method is not idempotent. The field ID has to be set prior to
243 /// calling this function. For sub fields, a field ID may or may not be set. If the field ID is unset, it will be
244 /// determined using the page source descriptor, based on the parent field ID and the sub field name.
246
248 {
249 fIsSimple = false;
250 fIsArtificial = true;
251 for (auto &field : fSubFields) {
252 field->SetArtificial();
253 }
254 }
255
256protected:
257 /// Input parameter to ReadBulk() and ReadBulkImpl(). See RBulk class for more information
258 struct RBulkSpec;
259
260 /// Collections and classes own sub fields
261 std::vector<std::unique_ptr<RFieldBase>> fSubFields;
262 /// Sub fields point to their mother field
264 /// All fields that have columns have a distinct main column. E.g., for simple fields (float, int, ...), the
265 /// principal column corresponds to the field type. For collection fields except fixed-sized arrays,
266 /// the main column is the offset field. Class fields have no column of their own.
267 /// When reading, points to any column of the column team of the active representation. Usually, this is just
268 /// the first column.
269 /// When writing, points to the first column index of the currently active (not suppressed) column representation.
271 /// Some fields have a second column in its column representation. In this case, fAuxiliaryColumn points into
272 /// fAvailableColumns to the column that immediately follows the column fPrincipalColumn points to.
274 /// The columns are connected either to a sink or to a source (not to both); they are owned by the field.
275 /// Contains all columns of all representations in order of representation and column index.
276 std::vector<std::unique_ptr<Internal::RColumn>> fAvailableColumns;
277 /// Properties of the type that allow for optimizations of collections of that type
278 std::uint32_t fTraits = 0;
279 /// A typedef or using name that was used when creating the field
280 std::string fTypeAlias;
281 /// List of functions to be called after reading a value
282 std::vector<ReadCallback_t> fReadCallbacks;
283 /// C++ type version cached from the descriptor after a call to `ConnectPageSource()`
285 /// TClass checksum cached from the descriptor after a call to `ConnectPageSource()`. Only set
286 /// for classes with dictionaries.
287 std::uint32_t fOnDiskTypeChecksum = 0;
288 /// Pointers into the static vector GetColumnRepresentations().GetSerializationTypes() when
289 /// SetColumnRepresentatives is called. Otherwise (if empty) GetColumnRepresentatives() returns a vector
290 /// with a single element, the default representation. Always empty for artificial fields.
291 std::vector<std::reference_wrapper<const ColumnRepresentation_t>> fColumnRepresentatives;
292
293 /// Factory method for the field's type. The caller owns the returned pointer
294 void *CreateObjectRawPtr() const;
295
296 /// Helpers for generating columns. We use the fact that most fields have the same C++/memory types
297 /// for all their column representations.
298 /// Where possible, we call the helpers not from the header to reduce compilation time.
299 template <std::uint32_t ColumnIndexT, typename HeadT, typename... TailTs>
301 {
303 auto &column = fAvailableColumns.emplace_back(
304 Internal::RColumn::Create<HeadT>(representation[ColumnIndexT], ColumnIndexT, representationIndex));
305
306 // Initially, the first two columns become the active column representation
308 fPrincipalColumn = column.get();
309 } else if (representationIndex == 0 && !fAuxiliaryColumn) {
310 fAuxiliaryColumn = column.get();
311 } else {
312 // We currently have no fields with more than 2 columns in its column representation
314 }
315
316 if constexpr (sizeof...(TailTs))
318 }
319
320 /// For writing, use the currently set column representative
321 template <typename... ColumnCppTs>
323 {
324 if (fColumnRepresentatives.empty()) {
325 fAvailableColumns.reserve(sizeof...(ColumnCppTs));
326 GenerateColumnsImpl<0, ColumnCppTs...>(GetColumnRepresentations().GetSerializationDefault(), 0);
327 } else {
328 const auto N = fColumnRepresentatives.size();
329 fAvailableColumns.reserve(N * sizeof...(ColumnCppTs));
330 for (unsigned i = 0; i < N; ++i) {
332 }
333 }
334 }
335
336 /// For reading, use the on-disk column list
337 template <typename... ColumnCppTs>
339 {
340 std::uint16_t representationIndex = 0;
341 do {
343 if (onDiskTypes.empty())
344 break;
347 if (representationIndex > 0) {
348 for (std::size_t i = 0; i < sizeof...(ColumnCppTs); ++i) {
349 fAvailableColumns[i]->MergeTeams(
350 *fAvailableColumns[representationIndex * sizeof...(ColumnCppTs) + i].get());
351 }
352 }
354 } while (true);
355 }
356
357 /// Implementations in derived classes should return a static RColumnRepresentations object. The default
358 /// implementation does not attach any columns to the field.
359 virtual const RColumnRepresentations &GetColumnRepresentations() const;
360 /// Implementations in derived classes should create the backing columns corresponsing to the field type for
361 /// writing. The default implementation does not attach any columns to the field.
362 virtual void GenerateColumns() {}
363 /// Implementations in derived classes should create the backing columns corresponsing to the field type for reading.
364 /// The default implementation does not attach any columns to the field. The method should check, using the page
365 /// source and fOnDiskId, if the column types match and throw if they don't.
366 virtual void GenerateColumns(const RNTupleDescriptor & /*desc*/) {}
367 /// Returns the on-disk column types found in the provided descriptor for fOnDiskId and the given
368 /// representation index. If there are no columns for the given representation index, return an empty
369 /// ColumnRepresentation_t list. Otherwise, the returned reference points into the static array returned by
370 /// GetColumnRepresentations().
371 /// Throws an exception if the types on disk don't match any of the deserialization types from
372 /// GetColumnRepresentations().
374 EnsureCompatibleColumnTypes(const RNTupleDescriptor &desc, std::uint16_t representationIndex) const;
375 /// When connecting a field to a page sink, the field's default column representation is subject
376 /// to adjustment according to the write options. E.g., if compression is turned off, encoded columns
377 /// are changed to their unencoded counterparts.
378 void AutoAdjustColumnTypes(const RNTupleWriteOptions &options);
379
380 /// Called by Clone(), which additionally copies the on-disk ID
381 virtual std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const = 0;
382
383 /// Constructs value in a given location of size at least GetValueSize(). Called by the base class' CreateValue().
384 virtual void ConstructValue(void *where) const = 0;
385 virtual std::unique_ptr<RDeleter> GetDeleter() const { return std::make_unique<RDeleter>(); }
386 /// Allow derived classes to call ConstructValue(void *) and GetDeleter on other (sub) fields.
387 static void CallConstructValueOn(const RFieldBase &other, void *where) { other.ConstructValue(where); }
388 static std::unique_ptr<RDeleter> GetDeleterOf(const RFieldBase &other) { return other.GetDeleter(); }
389
390 /// Operations on values of complex types, e.g. ones that involve multiple columns or for which no direct
391 /// column type exists.
392 virtual std::size_t AppendImpl(const void *from);
393 virtual void ReadGlobalImpl(NTupleSize_t globalIndex, void *to);
394 virtual void ReadInClusterImpl(RNTupleLocalIndex localIndex, void *to);
395
396 /// Write the given value into columns. The value object has to be of the same type as the field.
397 /// Returns the number of uncompressed bytes written.
398 std::size_t Append(const void *from);
399
400 /// Populate a single value with data from the field. The memory location pointed to by to needs to be of the
401 /// fitting type. The fast path is conditioned by the field qualifying as simple, i.e. maps as-is
402 /// to a single column and has no read callback.
404 {
405 if (fIsSimple)
406 return (void)fPrincipalColumn->Read(globalIndex, to);
407
408 if (!fIsArtificial) {
411 else
413 }
414 if (R__unlikely(!fReadCallbacks.empty()))
416 }
417
418 /// Populate a single value with data from the field. The memory location pointed to by to needs to be of the
419 /// fitting type. The fast path is conditioned by the field qualifying as simple, i.e. maps as-is
420 /// to a single column and has no read callback.
422 {
423 if (fIsSimple)
424 return (void)fPrincipalColumn->Read(localIndex, to);
425
426 if (!fIsArtificial) {
429 else
431 }
432 if (R__unlikely(!fReadCallbacks.empty()))
434 }
435
436 /// General implementation of bulk read. Loop over the required range and read values that are required
437 /// and not already present. Derived classes may implement more optimized versions of this method.
438 /// See ReadBulk() for the return value.
439 virtual std::size_t ReadBulkImpl(const RBulkSpec &bulkSpec);
440
441 /// Returns the number of newly available values, that is the number of bools in bulkSpec.fMaskAvail that
442 /// flipped from false to true. As a special return value, kAllSet can be used if all values are read
443 /// independent from the masks.
444 std::size_t ReadBulk(const RBulkSpec &bulkSpec);
445
446 /// Allow derived classes to call Append and Read on other (sub) fields.
447 static std::size_t CallAppendOn(RFieldBase &other, const void *from) { return other.Append(from); }
449 static void CallReadOn(RFieldBase &other, NTupleSize_t globalIndex, void *to) { other.Read(globalIndex, to); }
450 static void *CallCreateObjectRawPtrOn(RFieldBase &other) { return other.CreateObjectRawPtr(); }
451
452 /// Fields may need direct access to the principal column of their sub fields, e.g. in RRVecField::ReadBulk
453 static Internal::RColumn *GetPrincipalColumnOf(const RFieldBase &other) { return other.fPrincipalColumn; }
454
455 /// Set a user-defined function to be called after reading a value, giving a chance to inspect and/or modify the
456 /// value object.
457 /// Returns an index that can be used to remove the callback.
458 size_t AddReadCallback(ReadCallback_t func);
459 void RemoveReadCallback(size_t idx);
460
461 // Perform housekeeping tasks for global to cluster-local index translation
462 virtual void CommitClusterImpl() {}
463 // The field can indicate that it needs to register extra type information in the on-disk schema.
464 // In this case, a callback from the page sink to the field will be registered on connect, so that the
465 // extra type information can be collected when the dataset gets committed.
466 virtual bool HasExtraTypeInfo() const { return false; }
467 // The page sink's callback when the data set gets committed will call this method to get the field's extra
468 // type information. This has to happen at the end of writing because the type information may change depending
469 // on the data that's written, e.g. for polymorphic types in the streamer field.
471
472 /// Add a new subfield to the list of nested fields
473 void Attach(std::unique_ptr<RFieldBase> child);
474
475 /// Called by `ConnectPageSource()` before connecting; derived classes may override this as appropriate
477
478 /// Called by `ConnectPageSource()` once connected; derived classes may override this as appropriate
479 virtual void OnConnectPageSource() {}
480
481 /// Factory method to resurrect a field from the stored on-disk type information. This overload takes an already
482 /// normalized type name and type alias.
483 /// `desc` and `fieldId` must be passed if `options.fEmulateUnknownTypes` is true, otherwise they can be left blank.
484 /// TODO(jalopezg): this overload may eventually be removed leaving only the `RFieldBase::Create()` that takes a
485 /// single type name
487 Create(const std::string &fieldName, const std::string &canonicalType, const std::string &typeAlias,
488 const RCreateFieldOptions &options = {}, const RNTupleDescriptor *desc = nullptr,
489 DescriptorId_t fieldId = kInvalidDescriptorId);
490
491 /// Same as the above overload of Create, but infers the normalized type name and the canonical type name from
492 /// `typeName`.
493 static RResult<std::unique_ptr<RFieldBase>> Create(const std::string &fieldName, const std::string &typeName,
494 const RCreateFieldOptions &options, const RNTupleDescriptor *desc,
495 DescriptorId_t fieldId);
496
497public:
498 template <bool IsConstT>
499 class RSchemaIteratorTemplate;
502
503 // This is used in CreateObject and is specialized for void
504 template <typename T>
506 using deleter = std::default_delete<T>;
507 };
508
509 /// Used in the return value of the Check() method
511 std::string fFieldName; ///< Qualified field name causing the error
512 std::string fTypeName; ///< Type name corresponding to the (sub) field
513 std::string fErrMsg; ///< Cause of the failure, e.g. unsupported type
514 };
515
516 /// The constructor creates the underlying column objects and connects them to either a sink or a source.
517 /// If `isSimple` is `true`, the trait `kTraitMappable` is automatically set on construction. However, the
518 /// field might be demoted to non-simple if a post-read callback is set.
519 RFieldBase(std::string_view name, std::string_view type, ENTupleStructure structure, bool isSimple,
520 std::size_t nRepetitions = 0);
521 RFieldBase(const RFieldBase &) = delete;
522 RFieldBase(RFieldBase &&) = default;
523 RFieldBase &operator=(const RFieldBase &) = delete;
525 virtual ~RFieldBase() = default;
526
527 /// Copies the field and its sub fields using a possibly new name and a new, unconnected set of columns
528 std::unique_ptr<RFieldBase> Clone(std::string_view newName) const;
529
530 /// Factory method to resurrect a field from the stored on-disk type information
532 Create(const std::string &fieldName, const std::string &typeName);
533
534 /// Checks if the given type is supported by RNTuple. In case of success, the result vector is empty.
535 /// Otherwise there is an error record for each failing sub field (sub type).
536 static std::vector<RCheckResult> Check(const std::string &fieldName, const std::string &typeName);
537
538 /// Generates an object of the field type and allocates new initialized memory according to the type.
539 /// Implemented at the end of this header because the implementation is using RField<T>::TypeName()
540 /// The returned object can be released with `delete`, i.e. it is valid to call
541 /// auto ptr = field->CreateObject();
542 /// delete ptr.release();
543 ///
544 /// Note that CreateObject<void> is supported. The returned unique_ptr has a custom deleter that reports an error
545 /// if it is called. The intended use of the returned unique_ptr<void> is to call `release()`. In this way, the
546 /// transfer of pointer ownership is explicit.
547 template <typename T>
548 std::unique_ptr<T, typename RCreateObjectDeleter<T>::deleter> CreateObject() const;
549 /// Generates an object of the field type and wraps the created object in a shared pointer and returns it an RValue
550 /// connected to the field.
552 /// The returned bulk is initially empty; RBulk::ReadBulk will construct the array of values
554 /// Creates a value from a memory location with an already constructed object
555 RValue BindValue(std::shared_ptr<void> objPtr);
556 /// Creates the list of direct child values given a value for this field. E.g. a single value for the
557 /// correct variant or all the elements of a collection. The default implementation assumes no sub values
558 /// and returns an empty vector.
559 virtual std::vector<RValue> SplitValue(const RValue &value) const;
560 /// The number of bytes taken by a value of the appropriate type
561 virtual size_t GetValueSize() const = 0;
562 /// As a rule of thumb, the alignment is equal to the size of the type. There are, however, various exceptions
563 /// to this rule depending on OS and CPU architecture. So enforce the alignment to be explicitly spelled out.
564 virtual size_t GetAlignment() const = 0;
565 std::uint32_t GetTraits() const { return fTraits; }
566 bool HasReadCallbacks() const { return !fReadCallbacks.empty(); }
567
568 const std::string &GetFieldName() const { return fName; }
569 /// Returns the field name and parent field names separated by dots ("grandparent.parent.child")
570 std::string GetQualifiedFieldName() const;
571 const std::string &GetTypeName() const { return fType; }
572 const std::string &GetTypeAlias() const { return fTypeAlias; }
574 std::size_t GetNRepetitions() const { return fNRepetitions; }
575 const RFieldBase *GetParent() const { return fParent; }
576 std::vector<RFieldBase *> GetSubFields();
577 std::vector<const RFieldBase *> GetSubFields() const;
578 bool IsSimple() const { return fIsSimple; }
579 bool IsArtificial() const { return fIsArtificial; }
580 /// Get the field's description
581 const std::string &GetDescription() const { return fDescription; }
582 void SetDescription(std::string_view description);
583 EState GetState() const { return fState; }
584
587
588 /// Returns the fColumnRepresentative pointee or, if unset (always the case for artificial fields), the field's
589 /// default representative
591 /// Fixes a column representative. This can only be done _before_ connecting the field to a page sink.
592 /// Otherwise, or if the provided representation is not in the list of GetColumnRepresentations,
593 /// an exception is thrown
595 /// Whether or not an explicit column representative was set
597
598 /// Indicates an evolution of the mapping scheme from C++ type to columns
599 virtual std::uint32_t GetFieldVersion() const { return 0; }
600 /// Indicates an evolution of the C++ type itself
601 virtual std::uint32_t GetTypeVersion() const { return 0; }
602 /// Return the current TClass reported checksum of this class. Only valid if kTraitTypeChecksum is set.
603 virtual std::uint32_t GetTypeChecksum() const { return 0; }
604 /// Return the C++ type version stored in the field descriptor; only valid after a call to `ConnectPageSource()`
605 std::uint32_t GetOnDiskTypeVersion() const { return fOnDiskTypeVersion; }
606 /// Return checksum stored in the field descriptor; only valid after a call to `ConnectPageSource()`,
607 /// if the field stored a type checksum
608 std::uint32_t GetOnDiskTypeChecksum() const { return fOnDiskTypeChecksum; }
609
616
617 virtual void AcceptVisitor(Detail::RFieldVisitor &visitor) const;
618}; // class RFieldBase
619
620/// Iterates over the sub tree of fields in depth-first search order
621template <bool IsConstT>
623private:
624 struct Position {
625 using FieldPtr_t = std::conditional_t<IsConstT, const RFieldBase *, RFieldBase *>;
626 Position() : fFieldPtr(nullptr), fIdxInParent(-1) {}
630 };
631 /// The stack of nodes visited when walking down the tree of fields
632 std::vector<Position> fStack;
633
634public:
636 using iterator_category = std::forward_iterator_tag;
637 using difference_type = std::ptrdiff_t;
638 using value_type = std::conditional_t<IsConstT, const RFieldBase, RFieldBase>;
639 using pointer = std::conditional_t<IsConstT, const RFieldBase *, RFieldBase *>;
640 using reference = std::conditional_t<IsConstT, const RFieldBase &, RFieldBase &>;
641
645 /// Given that the iterator points to a valid field which is not the end iterator, go to the next field
646 /// in depth-first search order
647 void Advance()
648 {
649 auto itr = fStack.rbegin();
650 if (!itr->fFieldPtr->fSubFields.empty()) {
651 fStack.emplace_back(Position(itr->fFieldPtr->fSubFields[0].get(), 0));
652 return;
653 }
654
655 unsigned int nextIdxInParent = ++(itr->fIdxInParent);
656 while (nextIdxInParent >= itr->fFieldPtr->fParent->fSubFields.size()) {
657 if (fStack.size() == 1) {
658 itr->fFieldPtr = itr->fFieldPtr->fParent;
659 itr->fIdxInParent = -1;
660 return;
661 }
662 fStack.pop_back();
663 itr = fStack.rbegin();
664 nextIdxInParent = ++(itr->fIdxInParent);
665 }
666 itr->fFieldPtr = itr->fFieldPtr->fParent->fSubFields[nextIdxInParent].get();
667 }
668
669 iterator operator++(int) /* postfix */
670 {
671 auto r = *this;
672 Advance();
673 return r;
674 }
675 iterator &operator++() /* prefix */
676 {
677 Advance();
678 return *this;
679 }
680 reference operator*() const { return *fStack.back().fFieldPtr; }
681 pointer operator->() const { return fStack.back().fFieldPtr; }
682 bool operator==(const iterator &rh) const { return fStack.back().fFieldPtr == rh.fStack.back().fFieldPtr; }
683 bool operator!=(const iterator &rh) const { return fStack.back().fFieldPtr != rh.fStack.back().fFieldPtr; }
684};
685
686/// Points to an object with RNTuple I/O support and keeps a pointer to the corresponding field.
687/// Only fields can create RValue objects through generation, binding or splitting.
689 friend class RFieldBase;
690
691private:
692 RFieldBase *fField = nullptr; ///< The field that created the RValue
693 std::shared_ptr<void> fObjPtr; ///< Set by Bind() or by RFieldBase::CreateValue(), SplitValue() or BindValue()
694
695 RValue(RFieldBase *field, std::shared_ptr<void> objPtr) : fField(field), fObjPtr(objPtr) {}
696
697public:
698 RValue(const RValue &) = default;
699 RValue &operator=(const RValue &) = default;
700 RValue(RValue &&other) = default;
702 ~RValue() = default;
703
704 std::size_t Append() { return fField->Append(fObjPtr.get()); }
707 void Bind(std::shared_ptr<void> objPtr) { fObjPtr = objPtr; }
708 void BindRawPtr(void *rawPtr);
709 /// Replace the current object pointer by a pointer to a new object constructed by the field
710 void EmplaceNew() { fObjPtr = fField->CreateValue().GetPtr<void>(); }
711
712 template <typename T>
713 std::shared_ptr<T> GetPtr() const
714 {
715 return std::static_pointer_cast<T>(fObjPtr);
716 }
717
718 template <typename T>
719 const T &GetRef() const
720 {
721 return *static_cast<T *>(fObjPtr.get());
722 }
723
724 const RFieldBase &GetField() const { return *fField; }
725};
726
728 /// As a return value of ReadBulk and ReadBulkImpl(), indicates that the full bulk range was read
729 /// independent of the provided masks.
730 static const std::size_t kAllSet = std::size_t(-1);
731
732 RNTupleLocalIndex fFirstIndex; ///< Start of the bulk range
733 std::size_t fCount = 0; ///< Size of the bulk range
734 /// A bool array of size fCount, indicating the required values in the requested range
735 const bool *fMaskReq = nullptr;
736 bool *fMaskAvail = nullptr; ///< A bool array of size fCount, indicating the valid values in fValues
737 /// The destination area, which has to be a big enough array of valid objects of the correct type
738 void *fValues = nullptr;
739 /// Reference to memory owned by the RBulk class. The field implementing BulkReadImpl may use fAuxData
740 /// as memory that stays persistent between calls.
741 std::vector<unsigned char> *fAuxData = nullptr;
742};
743
744/// Similar to RValue but manages an array of consecutive values. Bulks have to come from the same cluster.
745/// Bulk I/O works with two bit masks: the mask of all the available entries in the current bulk and the mask
746/// of the required entries in a bulk read. The idea is that a single bulk may serve multiple read operations
747/// on the same range, where in each read operation a different subset of values is required.
748/// The memory of the value array is managed by the RBulk class.
750private:
751 friend class RFieldBase;
752
753 RFieldBase *fField = nullptr; ///< The field that created the array of values
754 std::unique_ptr<RFieldBase::RDeleter> fDeleter; /// Cached deleter of fField
755 void *fValues = nullptr; ///< Pointer to the start of the array
756 std::size_t fValueSize = 0; ///< Cached copy of fField->GetValueSize()
757 std::size_t fCapacity = 0; ///< The size of the array memory block in number of values
758 std::size_t fSize = 0; ///< The number of available values in the array (provided their mask is set)
759 bool fIsAdopted = false; ///< True if the user provides the memory buffer for fValues
760 std::unique_ptr<bool[]> fMaskAvail; ///< Masks invalid values in the array
761 std::size_t fNValidValues = 0; ///< The sum of non-zero elements in the fMask
762 RNTupleLocalIndex fFirstIndex; ///< Index of the first value of the array
763 /// Reading arrays of complex values may require additional memory, for instance for the elements of
764 /// arrays of vectors. A pointer to the fAuxData array is passed to the field's BulkRead method.
765 /// The RBulk class does not modify the array in-between calls to the field's BulkRead method.
766 std::vector<unsigned char> fAuxData;
767
768 void ReleaseValues();
769 /// Sets a new range for the bulk. If there is enough capacity, the fValues array will be reused.
770 /// Otherwise a new array is allocated. After reset, fMaskAvail is false for all values.
771 void Reset(RNTupleLocalIndex firstIndex, std::size_t size);
772 void CountValidValues();
773
775 {
776 if (firstIndex.GetClusterId() != fFirstIndex.GetClusterId())
777 return false;
778 return (firstIndex.GetIndexInCluster() >= fFirstIndex.GetIndexInCluster()) &&
779 ((firstIndex.GetIndexInCluster() + size) <= (fFirstIndex.GetIndexInCluster() + fSize));
780 }
781
782 void *GetValuePtrAt(std::size_t idx) const { return reinterpret_cast<unsigned char *>(fValues) + idx * fValueSize; }
783
787
788public:
789 ~RBulk();
790 RBulk(const RBulk &) = delete;
791 RBulk &operator=(const RBulk &) = delete;
792 RBulk(RBulk &&other);
794
795 // Sets fValues and fSize/fCapacity to the given values. The capacity is specified in number of values.
796 // Once a buffer is adopted, an attempt to read more values then available throws an exception.
797 void AdoptBuffer(void *buf, std::size_t capacity);
798
799 /// Reads 'size' values from the associated field, starting from 'firstIndex'. Note that the index is given
800 /// relative to a certain cluster. The return value points to the array of read objects.
801 /// The 'maskReq' parameter is a bool array of at least 'size' elements. Only objects for which the mask is
802 /// true are guaranteed to be read in the returned value array. A 'nullptr' means to read all elements.
803 void *ReadBulk(RNTupleLocalIndex firstIndex, const bool *maskReq, std::size_t size)
804 {
807
808 // We may read a sub range of the currently available range
809 auto offset = firstIndex.GetIndexInCluster() - fFirstIndex.GetIndexInCluster();
810
811 if (fNValidValues == fSize)
812 return GetValuePtrAt(offset);
813
815 bulkSpec.fFirstIndex = firstIndex;
816 bulkSpec.fCount = size;
817 bulkSpec.fMaskReq = maskReq;
818 bulkSpec.fMaskAvail = &fMaskAvail[offset];
819 bulkSpec.fValues = GetValuePtrAt(offset);
820 bulkSpec.fAuxData = &fAuxData;
821 auto nRead = fField->ReadBulk(bulkSpec);
822 if (nRead == RBulkSpec::kAllSet) {
823 if ((offset == 0) && (size == fSize)) {
825 } else {
827 }
828 } else {
830 }
831 return GetValuePtrAt(offset);
832 }
833
834 /// Overload to read all elements in the given cluster range.
835 void *ReadBulk(RNTupleClusterRange range) { return ReadBulk(*range.begin(), nullptr, range.size()); }
836};
837
838namespace Internal {
839// At some point, RFieldBase::OnClusterCommit() may allow for a user-defined callback to change the
840// column representation. For now, we inject this for testing and internal use only.
843 {
844 R__ASSERT(newRepresentationIdx < field.fColumnRepresentatives.size());
845 const auto N = field.fColumnRepresentatives[0].get().size();
846 R__ASSERT(N >= 1 && N <= 2);
847 R__ASSERT(field.fPrincipalColumn);
848 field.fPrincipalColumn = field.fAvailableColumns[newRepresentationIdx * N].get();
849 if (field.fAuxiliaryColumn) {
850 R__ASSERT(N == 2);
851 field.fAuxiliaryColumn = field.fAvailableColumns[newRepresentationIdx * N + 1].get();
852 }
853 }
854};
855} // namespace Internal
856
857} // namespace Experimental
858} // namespace ROOT
859
860#endif
#define R__unlikely(expr)
Definition RConfig.hxx:602
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
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
#define N
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 offset
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 Int_t Int_t Window_t child
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
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 Atom_t Time_t type
char name[80]
Definition TGX11.cxx:110
Abstract base class for classes implementing the visitor design pattern.
A column is a storage-backed array of a simple, fixed-size type, from which pages can be mapped into ...
Definition RColumn.hxx:40
void Read(const NTupleSize_t globalIndex, void *to)
Definition RColumn.hxx:161
Abstract interface to write data into an ntuple.
Abstract interface to read data from an ntuple.
The field for a class with dictionary.
Definition RField.hxx:115
Field specific extra type information from the header / extenstion header.
Similar to RValue but manages an array of consecutive values.
bool fIsAdopted
True if the user provides the memory buffer for fValues.
void Reset(RNTupleLocalIndex firstIndex, std::size_t size)
Sets a new range for the bulk.
RFieldBase * fField
The field that created the array of values.
RNTupleLocalIndex fFirstIndex
Index of the first value of the array.
std::vector< unsigned char > fAuxData
Reading arrays of complex values may require additional memory, for instance for the elements of arra...
std::size_t fCapacity
The size of the array memory block in number of values.
std::unique_ptr< bool[]> fMaskAvail
Masks invalid values in the array.
std::size_t fValueSize
Cached copy of fField->GetValueSize()
void AdoptBuffer(void *buf, std::size_t capacity)
void * GetValuePtrAt(std::size_t idx) const
RBulk & operator=(const RBulk &)=delete
void * ReadBulk(RNTupleClusterRange range)
Overload to read all elements in the given cluster range.
void * ReadBulk(RNTupleLocalIndex firstIndex, const bool *maskReq, std::size_t size)
Reads 'size' values from the associated field, starting from 'firstIndex'.
std::size_t fNValidValues
The sum of non-zero elements in the fMask.
bool ContainsRange(RNTupleLocalIndex firstIndex, std::size_t size) const
std::size_t fSize
The number of available values in the array (provided their mask is set)
void * fValues
Cached deleter of fField.
std::unique_ptr< RFieldBase::RDeleter > fDeleter
Some fields have multiple possible column representations, e.g.
std::vector< ColumnRepresentation_t > Selection_t
A list of column representations.
Selection_t fDeserializationTypes
The union of the serialization types and the deserialization extra types.
const ColumnRepresentation_t & GetSerializationDefault() const
The first column list from fSerializationTypes is the default for writing.
A functor to release the memory acquired by CreateValue (memory and constructor).
virtual void operator()(void *objPtr, bool dtorOnly)
Iterates over the sub tree of fields in depth-first search order.
std::conditional_t< IsConstT, const RFieldBase *, RFieldBase * > pointer
std::vector< Position > fStack
The stack of nodes visited when walking down the tree of fields.
void Advance()
Given that the iterator points to a valid field which is not the end iterator, go to the next field i...
std::conditional_t< IsConstT, const RFieldBase, RFieldBase > value_type
std::conditional_t< IsConstT, const RFieldBase &, RFieldBase & > reference
A deleter for templated RFieldBase descendents where the value type is known.
void operator()(void *objPtr, bool dtorOnly) final
Points to an object with RNTuple I/O support and keeps a pointer to the corresponding field.
RValue & operator=(RValue &&other)=default
void Read(RNTupleLocalIndex localIndex)
void Read(NTupleSize_t globalIndex)
RFieldBase * fField
The field that created the RValue.
RValue & operator=(const RValue &)=default
const RFieldBase & GetField() const
void EmplaceNew()
Replace the current object pointer by a pointer to a new object constructed by the field.
std::shared_ptr< void > fObjPtr
Set by Bind() or by RFieldBase::CreateValue(), SplitValue() or BindValue()
std::shared_ptr< T > GetPtr() const
void Bind(std::shared_ptr< void > objPtr)
RValue(RFieldBase *field, std::shared_ptr< void > objPtr)
A field translates read and write calls from/to underlying columns to/from tree values.
static constexpr std::uint32_t kInvalidTypeVersion
RBulk CreateBulk()
The returned bulk is initially empty; RBulk::ReadBulk will construct the array of values.
const std::string & GetTypeAlias() const
const RFieldBase * GetParent() const
void Read(RNTupleLocalIndex localIndex, void *to)
Populate a single value with data from the field.
virtual void GenerateColumns()
Implementations in derived classes should create the backing columns corresponsing to the field type ...
std::uint32_t fTraits
Properties of the type that allow for optimizations of collections of that type.
void Attach(std::unique_ptr< RFieldBase > child)
Add a new subfield to the list of nested fields.
bool HasDefaultColumnRepresentative() const
Whether or not an explicit column representative was set.
std::uint32_t fOnDiskTypeVersion
C++ type version cached from the descriptor after a call to ConnectPageSource()
std::uint32_t GetOnDiskTypeChecksum() const
Return checksum stored in the field descriptor; only valid after a call to ConnectPageSource(),...
void AutoAdjustColumnTypes(const RNTupleWriteOptions &options)
When connecting a field to a page sink, the field's default column representation is subject to adjus...
RFieldBase & operator=(RFieldBase &&)=default
void SetColumnRepresentatives(const RColumnRepresentations::Selection_t &representatives)
Fixes a column representative.
ENTupleStructure fStructure
The role of this field in the data model structure.
std::vector< RFieldBase * > GetSubFields()
static std::vector< RCheckResult > Check(const std::string &fieldName, const std::string &typeName)
Checks if the given type is supported by RNTuple.
virtual void GenerateColumns(const RNTupleDescriptor &)
Implementations in derived classes should create the backing columns corresponsing to the field type ...
std::vector< ENTupleColumnType > ColumnRepresentation_t
virtual bool HasExtraTypeInfo() const
std::function< void(void *)> ReadCallback_t
EState fState
Changed by ConnectTo[Sink,Source], reset by Clone()
std::string fTypeAlias
A typedef or using name that was used when creating the field.
const std::string & GetDescription() const
Get the field's description.
const std::string & GetFieldName() const
RSchemaIteratorTemplate< false > RSchemaIterator
ENTupleStructure GetStructure() const
const std::string & GetTypeName() const
RFieldBase(RFieldBase &&)=default
virtual void AcceptVisitor(Detail::RFieldVisitor &visitor) const
std::string fDescription
Free text set by the user.
virtual void ReadInClusterImpl(RNTupleLocalIndex localIndex, void *to)
static Internal::RColumn * GetPrincipalColumnOf(const RFieldBase &other)
Fields may need direct access to the principal column of their sub fields, e.g. in RRVecField::ReadBu...
friend struct ROOT::Experimental::Internal::RFieldCallbackInjector
std::size_t fNRepetitions
For fixed sized arrays, the array length.
RFieldBase & operator=(const RFieldBase &)=delete
RFieldBase * fParent
Sub fields point to their mother field.
std::unique_ptr< T, typename RCreateObjectDeleter< T >::deleter > CreateObject() const
Generates an object of the field type and allocates new initialized memory according to the type.
Definition RField.hxx:469
void FlushColumns()
Flushes data from active columns.
static std::size_t CallAppendOn(RFieldBase &other, const void *from)
Allow derived classes to call Append and Read on other (sub) fields.
static std::unique_ptr< RDeleter > GetDeleterOf(const RFieldBase &other)
Internal::RColumn * fAuxiliaryColumn
Some fields have a second column in its column representation.
void ConnectPageSink(Internal::RPageSink &pageSink, NTupleSize_t firstEntry=0)
Fields and their columns live in the void until connected to a physical page storage.
DescriptorId_t fOnDiskId
When the columns are connected to a page source or page sink, the field represents a field id in the ...
virtual std::size_t AppendImpl(const void *from)
Operations on values of complex types, e.g.
void Read(NTupleSize_t globalIndex, void *to)
Populate a single value with data from the field.
bool fIsSimple
A field qualifies as simple if it is mappable (which implies it has a single principal column),...
static void CallReadOn(RFieldBase &other, RNTupleLocalIndex localIndex, void *to)
RConstSchemaIterator cend() const
virtual RExtraTypeInfoDescriptor GetExtraTypeInfo() const
std::vector< std::reference_wrapper< const ColumnRepresentation_t > > fColumnRepresentatives
Pointers into the static vector GetColumnRepresentations().GetSerializationTypes() when SetColumnRepr...
std::uint32_t GetOnDiskTypeVersion() const
Return the C++ type version stored in the field descriptor; only valid after a call to ConnectPageSou...
std::string GetQualifiedFieldName() const
Returns the field name and parent field names separated by dots ("grandparent.parent....
virtual std::uint32_t GetTypeVersion() const
Indicates an evolution of the C++ type itself.
void GenerateColumnsImpl(const RNTupleDescriptor &desc)
For reading, use the on-disk column list.
virtual std::size_t ReadBulkImpl(const RBulkSpec &bulkSpec)
General implementation of bulk read.
void GenerateColumnsImpl(const ColumnRepresentation_t &representation, std::uint16_t representationIndex)
Helpers for generating columns.
virtual std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const =0
Called by Clone(), which additionally copies the on-disk ID.
std::size_t Append(const void *from)
Write the given value into columns.
RFieldBase(const RFieldBase &)=delete
@ kTraitTrivialType
Shorthand for types that are both trivially constructible and destructible.
@ kTraitEmulatedField
This field is a user defined type that was missing dictionaries and was reconstructed from the on-dis...
@ kTraitTriviallyConstructible
No constructor needs to be called, i.e.
@ kTraitMappable
A field of a fundamental type that can be directly mapped via RField<T>::Map(), i....
@ kTraitTypeChecksum
The TClass checksum is set and valid.
@ kTraitTriviallyDestructible
The type is cleaned up just by freeing its memory. I.e. the destructor performs a no-op.
@ kTraitInvalidField
This field is an instance of RInvalidField and can be safely static_cast to it.
bool fIsArtificial
A field that is not backed on disk but computed, e.g.
virtual void BeforeConnectPageSource(Internal::RPageSource &)
Called by ConnectPageSource() before connecting; derived classes may override this as appropriate.
void RemoveReadCallback(size_t idx)
void * CreateObjectRawPtr() const
Factory method for the field's type. The caller owns the returned pointer.
virtual std::uint32_t GetTypeChecksum() const
Return the current TClass reported checksum of this class. Only valid if kTraitTypeChecksum is set.
void CommitCluster()
Flushes data from active columns to disk and calls CommitClusterImpl.
const ColumnRepresentation_t & EnsureCompatibleColumnTypes(const RNTupleDescriptor &desc, std::uint16_t representationIndex) const
Returns the on-disk column types found in the provided descriptor for fOnDiskId and the given represe...
void ConnectPageSource(Internal::RPageSource &pageSource)
Connects the field and its sub field tree to the given page source.
RValue CreateValue()
Generates an object of the field type and wraps the created object in a shared pointer and returns it...
std::unique_ptr< RFieldBase > Clone(std::string_view newName) const
Copies the field and its sub fields using a possibly new name and a new, unconnected set of columns.
std::size_t ReadBulk(const RBulkSpec &bulkSpec)
Returns the number of newly available values, that is the number of bools in bulkSpec....
virtual std::unique_ptr< RDeleter > GetDeleter() const
virtual std::uint32_t GetFieldVersion() const
Indicates an evolution of the mapping scheme from C++ type to columns.
virtual void ConstructValue(void *where) const =0
Constructs value in a given location of size at least GetValueSize(). Called by the base class' Creat...
RConstSchemaIterator cbegin() const
RSchemaIteratorTemplate< true > RConstSchemaIterator
size_t AddReadCallback(ReadCallback_t func)
Set a user-defined function to be called after reading a value, giving a chance to inspect and/or mod...
virtual std::vector< RValue > SplitValue(const RValue &value) const
Creates the list of direct child values given a value for this field.
std::vector< std::unique_ptr< Internal::RColumn > > fAvailableColumns
The columns are connected either to a sink or to a source (not to both); they are owned by the field.
void SetOnDiskId(DescriptorId_t id)
std::size_t GetNRepetitions() const
RColumnRepresentations::Selection_t GetColumnRepresentatives() const
Returns the fColumnRepresentative pointee or, if unset (always the case for artificial fields),...
virtual ~RFieldBase()=default
std::uint32_t GetTraits() const
static void * CallCreateObjectRawPtrOn(RFieldBase &other)
std::string fName
The field name relative to its parent field.
virtual size_t GetAlignment() const =0
As a rule of thumb, the alignment is equal to the size of the type.
void InvokeReadCallbacks(void *target)
std::uint32_t fOnDiskTypeChecksum
TClass checksum cached from the descriptor after a call to ConnectPageSource().
virtual void OnConnectPageSource()
Called by ConnectPageSource() once connected; derived classes may override this as appropriate.
static void CallReadOn(RFieldBase &other, NTupleSize_t globalIndex, void *to)
static void CallConstructValueOn(const RFieldBase &other, void *where)
Allow derived classes to call ConstructValue(void *) and GetDeleter on other (sub) fields.
std::vector< std::unique_ptr< RFieldBase > > fSubFields
Collections and classes own sub fields.
std::string fType
The C++ type captured by this field.
static RResult< std::unique_ptr< RFieldBase > > Create(const std::string &fieldName, const std::string &canonicalType, const std::string &typeAlias, const RCreateFieldOptions &options={}, const RNTupleDescriptor *desc=nullptr, DescriptorId_t fieldId=kInvalidDescriptorId)
Factory method to resurrect a field from the stored on-disk type information.
Internal::RColumn * fPrincipalColumn
All fields that have columns have a distinct main column.
DescriptorId_t GetOnDiskId() const
virtual size_t GetValueSize() const =0
The number of bytes taken by a value of the appropriate type.
EState
During its lifetime, a field undergoes the following possible state transitions:
std::vector< ReadCallback_t > fReadCallbacks
List of functions to be called after reading a value.
void SetDescription(std::string_view description)
NTupleSize_t EntryToColumnElementIndex(NTupleSize_t globalIndex) const
Translate an entry index to a column element index of the principal column and viceversa.
RValue BindValue(std::shared_ptr< void > objPtr)
Creates a value from a memory location with an already constructed object.
virtual void ReadGlobalImpl(NTupleSize_t globalIndex, void *to)
void GenerateColumnsImpl()
For writing, use the currently set column representative.
RFieldBase(std::string_view name, std::string_view type, ENTupleStructure structure, bool isSimple, std::size_t nRepetitions=0)
The constructor creates the underlying column objects and connects them to either a sink or a source.
virtual const RColumnRepresentations & GetColumnRepresentations() const
Implementations in derived classes should return a static RColumnRepresentations object.
Used to loop over entries of collections in a single cluster.
The on-storage meta-data of an ntuple.
Processor specializiation for horizontally concatenated RNTuples (joins).
Addresses a column element or field item relative to a particular cluster, instead of a global NTuple...
Common user-tunable settings for storing ntuples.
const_iterator begin() 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
void CallConnectPageSinkOnField(RFieldBase &, RPageSink &, NTupleSize_t firstEntry=0)
ROOT::RResult< std::unique_ptr< ROOT::Experimental::RFieldBase > > CallFieldBaseCreate(const std::string &fieldName, const std::string &canonicalType, const std::string &typeAlias, const RCreateFieldOptions &options, const RNTupleDescriptor *desc, DescriptorId_t fieldId)
void CallFlushColumnsOnField(RFieldBase &)
void CallConnectPageSourceOnField(RFieldBase &, RPageSource &)
void CallCommitClusterOnField(RFieldBase &)
std::uint64_t NTupleSize_t
Integer type long enough to hold the maximum number of entries in a column.
std::uint64_t DescriptorId_t
Distriniguishes elements of the same type within a descriptor, e.g. different fields.
ENTupleStructure
The fields in the ntuple model tree can carry different structural information about the type system.
constexpr DescriptorId_t kInvalidDescriptorId
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
static void SetPrimaryColumnRepresentation(RFieldBase &field, std::uint16_t newRepresentationIdx)
void * fValues
The destination area, which has to be a big enough array of valid objects of the correct type.
RNTupleLocalIndex fFirstIndex
Start of the bulk range.
const bool * fMaskReq
A bool array of size fCount, indicating the required values in the requested range.
bool * fMaskAvail
A bool array of size fCount, indicating the valid values in fValues.
std::size_t fCount
Size of the bulk range.
std::vector< unsigned char > * fAuxData
Reference to memory owned by the RBulk class.
static const std::size_t kAllSet
As a return value of ReadBulk and ReadBulkImpl(), indicates that the full bulk range was read indepen...
Used in the return value of the Check() method.
std::string fFieldName
Qualified field name causing the error.
std::string fTypeName
Type name corresponding to the (sub) field.
std::string fErrMsg
Cause of the failure, e.g. unsupported type.
std::conditional_t< IsConstT, const RFieldBase *, RFieldBase * > FieldPtr_t
RSharedPtrDeleter(std::unique_ptr< RFieldBase::RDeleter > deleter)
std::unique_ptr< RFieldBase::RDeleter > fDeleter