Logo ROOT  
Reference Guide
Loading...
Searching...
No Matches
RPageStorage.hxx
Go to the documentation of this file.
1/// \file ROOT/RPageStorage.hxx
2/// \author Jakob Blomer <jblomer@cern.ch>
3/// \date 2018-07-19
4
5/*************************************************************************
6 * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. *
7 * All rights reserved. *
8 * *
9 * For the licensing terms see $ROOTSYS/LICENSE. *
10 * For the list of contributors see $ROOTSYS/README/CREDITS. *
11 *************************************************************************/
12
13#ifndef ROOT_RPageStorage
14#define ROOT_RPageStorage
15
16#include <ROOT/RError.hxx>
17#include <ROOT/RCluster.hxx>
18#include <ROOT/RClusterPool.hxx>
25#include <ROOT/RNTupleTypes.hxx>
26#include <ROOT/RPage.hxx>
27#include <ROOT/RPagePool.hxx>
28#include <ROOT/RSpan.hxx>
29#include <string_view>
30
31#include <atomic>
32#include <cassert>
33#include <cstddef>
34#include <deque>
35#include <functional>
36#include <map>
37#include <memory>
38#include <mutex>
39#include <set>
40#include <shared_mutex>
41#include <unordered_map>
42#include <unordered_set>
43#include <vector>
44
45namespace ROOT {
46
47class RNTupleModel;
48
49namespace Internal {
50
51class RPageAllocator;
52class RColumn;
54
59
60// clang-format off
61/**
62\class ROOT::Internal::RPageStorage
63\ingroup NTuple
64\brief Common functionality of an ntuple storage for both reading and writing
65
66The RPageStore provides access to a storage container that keeps the bits of pages and clusters comprising
67an ntuple. Concrete implementations can use a TFile, a raw file, an object store, and so on.
68*/
69// clang-format on
71public:
72 /// The page checksum is a 64bit xxhash3
73 static constexpr std::size_t kNBytesPageChecksum = sizeof(std::uint64_t);
74
75 /// The interface of a task scheduler to schedule page (de)compression tasks
77 public:
78 virtual ~RTaskScheduler() = default;
79 /// Take a callable that represents a task
80 virtual void AddTask(const std::function<void(void)> &taskFunc) = 0;
81 /// Blocks until all scheduled tasks finished
82 virtual void Wait() = 0;
83 };
84
85 /// A sealed page contains the bytes of a page as written to storage (packed & compressed). It is used
86 /// as an input to UnsealPages() as well as to transfer pages between different storage media.
87 /// RSealedPage does _not_ own the buffer it is pointing to in order to not interfere with the memory management
88 /// of concrete page sink and page source implementations.
89 struct RSealedPage {
90 private:
91 const void *fBuffer = nullptr;
92 std::size_t fBufferSize = 0; ///< Size of the page payload and the trailing checksum (if available)
93 std::uint32_t fNElements = 0;
94 bool fHasChecksum = false; ///< If set, the last 8 bytes of the buffer are the xxhash of the rest of the buffer
95
96 public:
97 RSealedPage() = default;
98 RSealedPage(const void *buffer, std::size_t bufferSize, std::uint32_t nElements, bool hasChecksum = false)
99 : fBuffer(buffer), fBufferSize(bufferSize), fNElements(nElements), fHasChecksum(hasChecksum)
100 {
101 }
102 RSealedPage(const RSealedPage &other) = default;
103 RSealedPage &operator=(const RSealedPage &other) = default;
104 RSealedPage(RSealedPage &&other) = default;
105 RSealedPage &operator=(RSealedPage &&other) = default;
106
107 const void *GetBuffer() const { return fBuffer; }
108 void SetBuffer(const void *buffer) { fBuffer = buffer; }
109
110 std::size_t GetDataSize() const
111 {
114 }
115 std::size_t GetBufferSize() const { return fBufferSize; }
116 void SetBufferSize(std::size_t bufferSize) { fBufferSize = bufferSize; }
117
118 std::uint32_t GetNElements() const { return fNElements; }
119 void SetNElements(std::uint32_t nElements) { fNElements = nElements; }
120
121 bool GetHasChecksum() const { return fHasChecksum; }
122 void SetHasChecksum(bool hasChecksum) { fHasChecksum = hasChecksum; }
123
124 void ChecksumIfEnabled();
126 /// Returns a failure if the sealed page has no checksum
128 };
129
130 using SealedPageSequence_t = std::deque<RSealedPage>;
131 /// A range of sealed pages referring to the same column that can be used for vector commit
134 SealedPageSequence_t::const_iterator fFirst;
135 SealedPageSequence_t::const_iterator fLast;
136
137 RSealedPageGroup() = default;
138 RSealedPageGroup(ROOT::DescriptorId_t d, SealedPageSequence_t::const_iterator b,
139 SealedPageSequence_t::const_iterator e)
141 {
142 }
143 };
144
145protected:
147
148 /// For the time being, we will use the heap allocator for all sources and sinks. This may change in the future.
149 std::unique_ptr<ROOT::Internal::RPageAllocator> fPageAllocator;
150
151 std::string fNTupleName;
154 {
155 if (!fTaskScheduler)
156 return;
157 fTaskScheduler->Wait();
158 }
159
160public:
161 explicit RPageStorage(std::string_view name);
162 RPageStorage(const RPageStorage &other) = delete;
163 RPageStorage &operator=(const RPageStorage &other) = delete;
164 RPageStorage(RPageStorage &&other) = default;
166 virtual ~RPageStorage();
167
168 /// Whether the concrete implementation is a sink or a source
170
174
175 /// Returns true for a valid column handle; fColumn and fPhysicalId should always either both
176 /// be valid or both be invalid.
177 explicit operator bool() const { return fPhysicalId != ROOT::kInvalidDescriptorId && fColumn; }
178 };
179 /// The column handle identifies a column with the current open page storage
181
182 /// Register a new column. When reading, the column must exist in the ntuple on disk corresponding to the metadata.
183 /// When writing, every column can only be attached once.
185 /// Unregisters a column. A page source decreases the reference counter for the corresponding active column.
186 /// For a page sink, dropping columns is currently a no-op.
187 virtual void DropColumn(ColumnHandle_t columnHandle) = 0;
188 ROOT::DescriptorId_t GetColumnId(ColumnHandle_t columnHandle) const { return columnHandle.fPhysicalId; }
189
190 /// Returns the default metrics object. Subclasses might alternatively provide their own metrics object by
191 /// overriding this.
193
194 /// Returns the NTuple name.
195 const std::string &GetNTupleName() const { return fNTupleName; }
196
197 void SetTaskScheduler(RTaskScheduler *taskScheduler) { fTaskScheduler = taskScheduler; }
198}; // class RPageStorage
199
200// clang-format off
201/**
202\class ROOT::Internal::RWritePageMemoryManager
203\ingroup NTuple
204\brief Helper to maintain a memory budget for the write pages of a set of columns
205
206The memory manager keeps track of the sum of bytes used by the write pages of a set of columns.
207It will flush (and shrink) large pages of other columns on the attempt to expand a page.
208*/
209// clang-format on
211private:
212 struct RColumnInfo {
214 std::size_t fCurrentPageSize = 0;
215 std::size_t fInitialPageSize = 0;
216
217 bool operator>(const RColumnInfo &other) const;
218 };
219
220 /// Sum of all the write page sizes (their capacity) of the columns in `fColumnsSortedByPageSize`
221 std::size_t fCurrentAllocatedBytes = 0;
222 /// Maximum allowed value for `fCurrentAllocatedBytes`, set from RNTupleWriteOptions::fPageBufferBudget
223 std::size_t fMaxAllocatedBytes = 0;
224 /// All columns that called `ReservePage()` (hence `TryUpdate()`) at least once,
225 /// sorted by their current write page size from large to small
226 std::set<RColumnInfo, std::greater<RColumnInfo>> fColumnsSortedByPageSize;
227
228 /// Flush columns in order of allocated write page size until the sum of all write page allocations
229 /// leaves space for at least targetAvailableSize bytes. Only use columns with a write page size larger
230 /// than pageSizeLimit.
231 bool TryEvict(std::size_t targetAvailableSize, std::size_t pageSizeLimit);
232
233public:
234 explicit RWritePageMemoryManager(std::size_t maxAllocatedBytes) : fMaxAllocatedBytes(maxAllocatedBytes) {}
235
236 /// Try to register the new write page size for the given column. Flush large columns to make space, if necessary.
237 /// If not enough space is available after all (sum of write pages would be larger than fMaxAllocatedBytes),
238 /// return false.
239 bool TryUpdate(ROOT::Internal::RColumn &column, std::size_t newWritePageSize);
240};
241
242// clang-format off
243/**
244\class ROOT::Internal::RPageSink
245\ingroup NTuple
246\brief Abstract interface to write data into an ntuple
247
248The page sink takes the list of columns and afterwards a series of page commits and cluster commits.
249The user is responsible to commit clusters at a consistent point, i.e. when all pages corresponding to data
250up to the given entry number are committed.
251
252An object of this class may either be a wrapper (for example a RPageSinkBuf) or a "persistent" sink,
253inheriting from RPagePersistentSink.
254*/
255// clang-format on
256class RPageSink : public RPageStorage {
257public:
258 using Callback_t = std::function<void(RPageSink &)>;
259
260 /// Cluster that was staged, but not yet logically appended to the RNTuple
274
275protected:
276 std::unique_ptr<ROOT::RNTupleWriteOptions> fOptions;
277
278 /// Flag if sink was initialized
279 bool fIsInitialized = false;
280
281 /// Helper for streaming a page. This is commonly used in derived, concrete page sinks. Note that if
282 /// compressionSetting is 0 (uncompressed) and the page is mappable and not checksummed, the returned sealed page
283 /// will point directly to the input page buffer. Otherwise, the sealed page references fSealPageBuffer. Thus,
284 /// the buffer pointed to by the RSealedPage should never be freed.
286
287private:
288 std::vector<Callback_t> fOnDatasetCommitCallbacks;
289 std::vector<unsigned char> fSealPageBuffer; ///< Used as destination buffer in the simple SealPage overload
290
291 /// Used in ReservePage to maintain the page buffer budget
293
294public:
295 RPageSink(std::string_view ntupleName, const ROOT::RNTupleWriteOptions &options);
296
297 RPageSink(const RPageSink &) = delete;
298 RPageSink &operator=(const RPageSink &) = delete;
299 RPageSink(RPageSink &&) = default;
301 ~RPageSink() override;
302
304 /// Returns the sink's write options.
306
307 void DropColumn(ColumnHandle_t /*columnHandle*/) final {}
308
309 bool IsInitialized() const { return fIsInitialized; }
310
311 /// Return the RNTupleDescriptor being constructed.
312 virtual const ROOT::RNTupleDescriptor &GetDescriptor() const = 0;
313
314 virtual ROOT::NTupleSize_t GetNEntries() const = 0;
315
316 /// Physically creates the storage container to hold the ntuple (e.g., a keys a TFile or an S3 bucket)
317 /// Init() associates column handles to the columns referenced by the model
318 void Init(RNTupleModel &model)
319 {
320 if (fIsInitialized) {
321 throw RException(R__FAIL("already initialized"));
322 }
323 InitImpl(model);
324 fIsInitialized = true;
325 }
326
327protected:
328 virtual void InitImpl(RNTupleModel &model) = 0;
330
331public:
332 /// Parameters for the SealPage() method
334 const ROOT::Internal::RPage *fPage = nullptr; ///< Input page to be sealed
336 nullptr; ///< Corresponds to the page's elements, for size calculation etc.
337 std::uint32_t fCompressionSettings = 0; ///< Compression algorithm and level to apply
338 /// Adds a 8 byte little-endian xxhash3 checksum to the page payload. The buffer has to be large enough to
339 /// to store the additional 8 bytes.
340 bool fWriteChecksum = true;
341 /// If false, the output buffer must not point to the input page buffer, which would otherwise be an option
342 /// if the page is mappable and should not be compressed
343 bool fAllowAlias = false;
344 /// Location for sealed output. The memory buffer has to be large enough.
345 void *fBuffer = nullptr;
346 };
347
348 /// Seal a page using the provided info.
349 static RSealedPage SealPage(const RSealPageConfig &config);
350
351 /// Incorporate incremental changes to the model into the ntuple descriptor. This happens, e.g. if new fields were
352 /// added after the initial call to `RPageSink::Init(RNTupleModel &)`.
353 /// `firstEntry` specifies the global index for the first stored element in the added columns.
354 virtual void UpdateSchema(const ROOT::Internal::RNTupleModelChangeset &changeset, ROOT::NTupleSize_t firstEntry) = 0;
355 /// Adds an extra type information record to schema. The extra type information will be written to the
356 /// extension header. The information in the record will be merged with the existing information, e.g.
357 /// duplicate streamer info records will be removed. This method is called by the "on commit dataset" callback
358 /// registered by specific fields (e.g., streamer field) and during merging.
359 virtual void UpdateExtraTypeInfo(const ROOT::RExtraTypeInfoDescriptor &extraTypeInfo) = 0;
360
361 /// Commits a suppressed column for the current cluster. Can be called anytime before CommitCluster().
362 /// For any given column and cluster, there must be no calls to both CommitSuppressedColumn() and page commits.
363 virtual void CommitSuppressedColumn(ColumnHandle_t columnHandle) = 0;
364 /// Write a page to the storage. The column must have been added before.
365 virtual void CommitPage(ColumnHandle_t columnHandle, const ROOT::Internal::RPage &page) = 0;
366 /// Write a preprocessed page to storage. The column must have been added before.
367 virtual void
368 CommitSealedPage(ROOT::DescriptorId_t physicalColumnId, const RPageStorage::RSealedPage &sealedPage) = 0;
369 /// Write a vector of preprocessed pages to storage. The corresponding columns must have been added before.
370 virtual void CommitSealedPageV(std::span<RPageStorage::RSealedPageGroup> ranges) = 0;
371 /// Stage the current cluster and create a new one for the following data.
372 /// Returns the object that must be passed to CommitStagedClusters to logically append the staged cluster to the
373 /// ntuple descriptor.
375 /// Commit staged clusters, logically appending them to the ntuple descriptor.
376 virtual void CommitStagedClusters(std::span<RStagedCluster> clusters) = 0;
377 /// Finalize the current cluster and create a new one for the following data.
378 /// Returns the number of bytes written to storage (excluding metadata).
379 virtual std::uint64_t CommitCluster(ROOT::NTupleSize_t nNewEntries)
380 {
381 RStagedCluster stagedClusters[] = {StageCluster(nNewEntries)};
382 CommitStagedClusters(stagedClusters);
383 return stagedClusters[0].fNBytesWritten;
384 }
385 /// Write out the page locations (page list envelope) for all the committed clusters since the last call of
386 /// CommitClusterGroup (or the beginning of writing).
387 virtual void CommitClusterGroup() = 0;
388
389 /// Creates a new sink with the same underlying storage as this but writing to a different
390 /// RNTuple named `name`. Only one of the two sinks can safely write at the same time.
391 /// The RNTuple written by this cloned sink will be stored in a hidden key (this is a convenient assumption we
392 /// make now since this method is only used to create attribute RNTuples).
393 virtual std::unique_ptr<RPageSink> CloneAsHidden(std::string_view name, const RNTupleWriteOptions &opts) const = 0;
394
395 /// Adds the given anchor information (name + locator) into the main RNTuple's descriptor as an attribute set
396 /// linked to it with the given name.
397 /// The attribute set must have already been written to storage via RNTupleAttrSetWriter::Commit().
398 /// Note that, by RNTuple specs, this is only legal to call on a non-attribute RNTuple's sink.
399 virtual void CommitAttributeSet(std::string_view attrSetName, const RNTupleLink &attrAnchorInfo) = 0;
400
401 /// The registered callback is executed at the beginning of CommitDataset();
403 /// Run the registered callbacks and finalize the current cluster and the entrire data set.
405
406 /// Get a new, empty page for the given column that can be filled with up to nElements;
407 /// nElements must be larger than zero.
408 virtual ROOT::Internal::RPage ReservePage(ColumnHandle_t columnHandle, std::size_t nElements);
409
410 /// An RAII wrapper used to synchronize a page sink. See GetSinkGuard().
412 std::mutex *fLock;
413
414 public:
415 explicit RSinkGuard(std::mutex *lock) : fLock(lock)
416 {
417 if (fLock != nullptr) {
418 fLock->lock();
419 }
420 }
421 RSinkGuard(const RSinkGuard &) = delete;
422 RSinkGuard &operator=(const RSinkGuard &) = delete;
423 RSinkGuard(RSinkGuard &&) = delete;
426 {
427 if (fLock != nullptr) {
428 fLock->unlock();
429 }
430 }
431 };
432
434 {
435 // By default, there is no lock and the guard does nothing.
436 return RSinkGuard(nullptr);
437 }
438}; // class RPageSink
439
440// clang-format off
441/**
442\class ROOT::Internal::RPagePersistentSink
443\ingroup NTuple
444\brief Base class for a sink with a physical storage backend
445*/
446// clang-format on
448private:
449 /// Used to map the IDs of the descriptor to the physical IDs issued during header/footer serialization
451
452 /// Remembers the starting cluster id for the next cluster group
453 std::uint64_t fNextClusterInGroup = 0;
454 /// Used to calculate the number of entries in the current cluster
456 /// Keeps track of the number of elements in the currently open cluster. Indexed by column id.
457 std::vector<ROOT::RClusterDescriptor::RColumnRange> fOpenColumnRanges;
458 /// Keeps track of the written pages in the currently open cluster. Indexed by column id.
459 std::vector<ROOT::RClusterDescriptor::RPageRange> fOpenPageRanges;
460
461 /// Union of the streamer info records that are sent from streamer fields to the sink before committing the dataset.
463
464protected:
465 /// Set of optional features supported by the persistent sink
466 struct RFeatures {
467 bool fCanMergePages = false;
468 };
469
472
473 /// Default I/O performance counters that get registered in fMetrics
483 std::unique_ptr<RCounters> fCounters;
484
485 virtual void InitImpl(unsigned char *serializedHeader, std::uint32_t length) = 0;
486
488 virtual RNTupleLocator
490 /// Vector commit of preprocessed pages. The `ranges` array specifies a range of sealed pages to be
491 /// committed for each column. The returned vector contains, in order, the RNTupleLocator for each
492 /// page on each range in `ranges`, i.e. the first N entries refer to the N pages in `ranges[0]`,
493 /// followed by M entries that refer to the M pages in `ranges[1]`, etc.
494 /// The mask allows to skip writing out certain pages. The vector has the size of all the pages.
495 /// For every `false` value in the mask, the corresponding locator is skipped (missing) in the output vector.
496 /// The default is to call `CommitSealedPageImpl` for each page; derived classes may provide an
497 /// optimized implementation though.
498 virtual std::vector<RNTupleLocator>
499 CommitSealedPageVImpl(std::span<RPageStorage::RSealedPageGroup> ranges, const std::vector<bool> &mask);
500 /// Returns the number of bytes written to storage (excluding metadata)
501 virtual std::uint64_t StageClusterImpl() = 0;
502 /// Returns the locator of the page list envelope of the given buffer that contains the serialized page list.
503 /// Typically, the implementation takes care of compressing and writing the provided buffer.
504 virtual RNTupleLocator CommitClusterGroupImpl(unsigned char *serializedPageList, std::uint32_t length) = 0;
505 virtual RNTupleLink CommitDatasetImpl(unsigned char *serializedFooter, std::uint32_t length) = 0;
506
507 /// Enables the default set of metrics provided by RPageSink. `prefix` will be used as the prefix for
508 /// the counters registered in the internal RNTupleMetrics object.
509 /// This set of counters can be extended by a subclass by calling `fMetrics.MakeCounter<...>()`.
510 ///
511 /// A subclass using the default set of metrics is always responsible for updating the counters
512 /// appropriately, e.g. `fCounters->fNPageCommited.Inc()`
513 void EnableDefaultMetrics(const std::string &prefix);
514
515public:
516 RPagePersistentSink(std::string_view ntupleName, const ROOT::RNTupleWriteOptions &options);
517
522 ~RPagePersistentSink() override;
523
524 /// Guess the concrete derived page source from the location
525 static std::unique_ptr<RPageSink> Create(std::string_view ntupleName, std::string_view location,
527
529
530 const ROOT::RNTupleDescriptor &GetDescriptor() const final { return fDescriptorBuilder.GetDescriptor(); }
531
533
534 /// Updates the descriptor and calls InitImpl() that handles the backend-specific details (file, DAOS, etc.)
535 void InitImpl(RNTupleModel &model) final;
536 void UpdateSchema(const ROOT::Internal::RNTupleModelChangeset &changeset, ROOT::NTupleSize_t firstEntry) override;
537 void UpdateExtraTypeInfo(const ROOT::RExtraTypeInfoDescriptor &extraTypeInfo) final;
538
539 /// Initialize sink based on an existing descriptor and fill into the descriptor builder, optionally copying over
540 /// the descriptor's clusters to this sink's descriptor.
541 /// \return The model created from the new sink's descriptor. This model should be kept alive
542 /// for at least as long as the sink.
543 [[nodiscard]] std::unique_ptr<RNTupleModel>
544 InitFromDescriptor(const ROOT::RNTupleDescriptor &descriptor, bool copyClusters);
545
546 void CommitSuppressedColumn(ColumnHandle_t columnHandle) final;
547 void CommitPage(ColumnHandle_t columnHandle, const ROOT::Internal::RPage &page) final;
548 void CommitSealedPage(ROOT::DescriptorId_t physicalColumnId, const RPageStorage::RSealedPage &sealedPage) final;
549 void CommitSealedPageV(std::span<RPageStorage::RSealedPageGroup> ranges) final;
550 RStagedCluster StageCluster(ROOT::NTupleSize_t nNewEntries) final;
551 void CommitStagedClusters(std::span<RStagedCluster> clusters) final;
552 void CommitClusterGroup() final;
553 void CommitAttributeSet(std::string_view attrSetName, const RNTupleLink &attrAnchorInfo) final;
554 /// \return The locator and length of the written anchor.
556}; // class RPagePersistentSink
557
558// clang-format off
559/**
560\class ROOT::Internal::RPageSource
561\ingroup NTuple
562\brief Abstract interface to read data from an ntuple
563
564The page source is initialized with the columns of interest. Alias columns from projected fields are mapped to the
565corresponding physical columns. Pages from the columns of interest can then be mapped into memory.
566The page source also gives access to the ntuple's metadata.
567*/
568// clang-format on
569class RPageSource : public RPageStorage {
570public:
571 /// Used in SetEntryRange / GetEntryRange
572 struct REntryRange {
575
576 /// Returns true if the given cluster has entries within the entry range
577 bool IntersectsWith(const ROOT::RClusterDescriptor &clusterDesc) const;
578 };
579
580 /// An RAII wrapper used for the read-only access to `RPageSource::fDescriptor`. See `GetExclDescriptorGuard()``.
583 std::shared_mutex &fLock;
584
585 public:
586 RSharedDescriptorGuard(const ROOT::RNTupleDescriptor &desc, std::shared_mutex &lock)
587 : fDescriptor(desc), fLock(lock)
588 {
589 fLock.lock_shared();
590 }
595 ~RSharedDescriptorGuard() { fLock.unlock_shared(); }
597 const ROOT::RNTupleDescriptor &GetRef() const { return fDescriptor; }
598 };
599
600 /// An RAII wrapper used for the writable access to `RPageSource::fDescriptor`. See `GetSharedDescriptorGuard()`.
603 std::shared_mutex &fLock;
604
605 public:
606 RExclDescriptorGuard(ROOT::RNTupleDescriptor &desc, std::shared_mutex &lock) : fDescriptor(desc), fLock(lock)
607 {
608 fLock.lock();
609 }
615 {
616 fDescriptor.IncGeneration();
617 fLock.unlock();
618 }
620 void MoveIn(ROOT::RNTupleDescriptor desc) { fDescriptor = std::move(desc); }
621 };
622
623private:
625 mutable std::shared_mutex fDescriptorLock;
626 REntryRange fEntryRange; ///< Used by the cluster pool to prevent reading beyond the given range
627 bool fHasStructure = false; ///< Set to true once `LoadStructure()` is called
628 bool fIsAttached = false; ///< Set to true once `Attach()` is called
629 bool fHasStreamerInfosRegistered = false; ///< Set to true when RegisterStreamerInfos() is called.
630
631 /// Remembers the last cluster id from which a page was requested
633 /// Clusters from where pages got preloaded in UnzipClusterImpl(), ordered by first entry number
634 /// of the clusters. If the last used cluster changes in LoadPage(), all unused pages from
635 /// previous clusters are evicted from the page pool. Pinned clusters won't be evicted.
636 std::map<ROOT::NTupleSize_t, ROOT::DescriptorId_t> fPreloadedClusters;
637
638 /// Does nothing if fLastUsedCluster == clusterId. Otherwise, updated fLastUsedCluster
639 /// and evict unused paged from the page pool of all previous clusters.
640 /// Must not be called when the descriptor guard is taken.
642
643protected:
644 /// Default I/O performance counters that get registered in `fMetrics`
664
665 /// Keeps track of the requested physical column IDs and their in-memory target type via a column element identifier.
666 /// When using alias columns (projected fields), physical columns may be requested multiple times.
668 public:
673
674 private:
675 /// Maps physical column IDs to all the requested in-memory representations.
676 /// A pair of physical column ID and in-memory representation can be requested multiple times, which is
677 /// indicated by the reference counter.
678 /// We can only have a handful of possible in-memory representations for a given column,
679 /// so it is fine to search them linearly.
680 std::unordered_map<ROOT::DescriptorId_t, std::vector<RColumnInfo>> fColumnInfos;
681
682 public:
686 bool HasColumnInfos(ROOT::DescriptorId_t physicalColumnId) const
687 {
688 return fColumnInfos.count(physicalColumnId) > 0;
689 }
690 const std::vector<RColumnInfo> &GetColumnInfos(ROOT::DescriptorId_t physicalColumnId) const
691 {
692 return fColumnInfos.at(physicalColumnId);
693 }
694 };
695
696 /// Summarizes cluster-level information that are necessary to load a certain page.
697 /// Used by LoadPageImpl().
700 /// Location of the page on disk
702 /// The first element number of the page's column in the given cluster
703 std::uint64_t fColumnOffset = 0;
704 };
705
706 std::unique_ptr<RCounters> fCounters;
707
709 /// The active columns are implicitly defined by the model fields or views
711 /// Pinned clusters and their $2 * (cluster bunch size) - 1$ successors will not be evicted from the cluster pool.
712 /// Pages of pinned clusters won't be evicted from the page pool.
713 std::unordered_set<ROOT::DescriptorId_t> fPinnedClusters;
714
715 /// The cluster pool asynchronously preloads the next few clusters. Note that derived classes should call
716 /// fClusterPool.StopBackgroundThread() in their destructor so that the I/O background thread does not call
717 /// methods from the destructed derived class.
719 /// Pages that are unzipped with IMT are staged into the page pool
721
722 virtual void LoadStructureImpl() = 0;
723 /// `LoadStructureImpl()` has been called before `AttachImpl()` is called
725 /// Returns a new, unattached page source for the same data set
726 virtual std::unique_ptr<RPageSource> CloneImpl() const = 0;
727 // Only called if a task scheduler is set. No-op be default.
728 virtual void UnzipClusterImpl(ROOT::Internal::RCluster *cluster);
729 // Returns a page from storage if not found in the page pool. Should be able to handle zero page locators.
731 LoadPageImpl(ColumnHandle_t columnHandle, const RClusterInfo &clusterInfo, ROOT::NTupleSize_t idxInCluster) = 0;
732
733 /// Prepare a page range read for the column set in `clusterKey`. Specifically, pages referencing the
734 /// `kTypePageZero` locator are filled in `pageZeroMap`; otherwise, `perPageFunc` is called for each page. This is
735 /// commonly used as part of `LoadClusters()` in derived classes.
739 perPageFunc);
740
741 /// Enables the default set of metrics provided by RPageSource. `prefix` will be used as the prefix for
742 /// the counters registered in the internal RNTupleMetrics object.
743 /// A subclass using the default set of metrics is responsible for updating the counters
744 /// appropriately, e.g. `fCounters->fNRead.Inc()`
745 /// Alternatively, a subclass might provide its own RNTupleMetrics object by overriding the
746 /// `GetMetrics()` member function.
747 void EnableDefaultMetrics(const std::string &prefix);
748
749 /// Note that the underlying lock is not recursive. See `GetSharedDescriptorGuard()` for further information.
751
752public:
753 RPageSource(std::string_view ntupleName, const ROOT::RNTupleReadOptions &fOptions);
754 RPageSource(const RPageSource &) = delete;
758 ~RPageSource() override;
759 /// Guess the concrete derived page source from the file name (location)
760 static std::unique_ptr<RPageSource> Create(std::string_view ntupleName, std::string_view location,
762 /// Open the same storage multiple time, e.g. for reading in multiple threads.
763 /// If the source is already attached, the clone will be attached, too. The clone will use, however,
764 /// it's own connection to the underlying storage (e.g., file descriptor, XRootD handle, etc.)
765 std::unique_ptr<RPageSource> Clone() const;
766
767 /// Helper for unstreaming a page. This is commonly used in derived, concrete page sources. The implementation
768 /// currently always makes a memory copy, even if the sealed page is uncompressed and in the final memory layout.
769 /// The optimization of directly mapping pages is left to the concrete page source implementations.
773
776
777 /// Takes the read lock for the descriptor. Multiple threads can take the lock concurrently.
778 /// The underlying `std::shared_mutex`, however, is neither read nor write recursive:
779 /// within one thread, only one lock (shared or exclusive) must be acquired at the same time. This requires special
780 /// care in sections protected by `GetSharedDescriptorGuard()` and `GetExclDescriptorGuard()` especially to avoid
781 /// that the locks are acquired indirectly. As a general guideline, no other
782 /// method of the page source should be called (directly or indirectly) in a guarded section.
787
789 void DropColumn(ColumnHandle_t columnHandle) override;
790
791 /// Loads header and footer without decompressing or deserializing them. This can be used to asynchronously open
792 /// a file in the background. The method is idempotent and it is called as a first step in `Attach()`.
793 /// Pages sources may or may not make use of splitting loading and processing metadata.
794 /// Therefore, `LoadStructure()` may do nothing and defer loading the metadata to `Attach()`.
795 void LoadStructure();
796 /// Open the physical storage container and deserialize header and footer
800 ROOT::NTupleSize_t GetNElements(ColumnHandle_t columnHandle);
801
802 /// Promise to only read from the given entry range. If set, prevents the cluster pool from reading-ahead beyond
803 /// the given range. The range needs to be within `[0, GetNEntries())`.
804 void SetEntryRange(const REntryRange &range);
806
807 /// Allocates and fills a page that contains the index-th element. The default implementation searches
808 /// the page and calls LoadPageImpl(). Returns a default-constructed RPage for suppressed columns.
809 virtual ROOT::Internal::RPageRef LoadPage(ColumnHandle_t columnHandle, ROOT::NTupleSize_t globalIndex);
810 /// Another version of `LoadPage` that allows to specify cluster-relative indexes.
811 /// Returns a default-constructed RPage for suppressed columns.
812 virtual ROOT::Internal::RPageRef LoadPage(ColumnHandle_t columnHandle, RNTupleLocalIndex localIndex);
813
814 /// Read the packed and compressed bytes of a page into the memory buffer provided by `sealedPage`. The sealed page
815 /// can be used subsequently in a call to `RPageSink::CommitSealedPage`.
816 /// The `fSize` and `fNElements` member of the sealedPage parameters are always set. If `sealedPage.fBuffer` is
817 /// `nullptr`, no data will be copied but the returned size information can be used by the caller to allocate a large
818 /// enough buffer and call `LoadSealedPage` again.
819 virtual void
820 LoadSealedPage(ROOT::DescriptorId_t physicalColumnId, RNTupleLocalIndex localIndex, RSealedPage &sealedPage) = 0;
821
822 /// Populates all the pages of the given cluster ids and columns; it is possible that some columns do not
823 /// contain any pages. The page source may load more columns than the minimal necessary set from `columns`.
824 /// To indicate which columns have been loaded, `LoadClusters()`` must mark them with `SetColumnAvailable()`.
825 /// That includes the ones from the `columns` that don't have pages; otherwise subsequent requests
826 /// for the cluster would assume an incomplete cluster and trigger loading again.
827 /// `LoadClusters()` is typically called from the I/O thread of a cluster pool, i.e. the method runs
828 /// concurrently to other methods of the page source.
829 virtual std::vector<std::unique_ptr<ROOT::Internal::RCluster>>
830 LoadClusters(std::span<ROOT::Internal::RCluster::RKey> clusterKeys) = 0;
831
832 /// Parallel decompression and unpacking of the pages in the given cluster. The unzipped pages are supposed
833 /// to be preloaded in a page pool attached to the source. The method is triggered by the cluster pool's
834 /// unzip thread. It is an optional optimization, the method can safely do nothing. In particular, the
835 /// actual implementation will only run if a task scheduler is set. In practice, a task scheduler is set
836 /// if implicit multi-threading is turned on.
838
839 /// Instructs the cluster pool and page pool to consider the given cluster as active (should stay cached).
840 void PinCluster(ROOT::DescriptorId_t clusterId) { fPinnedClusters.insert(clusterId); }
841 /// Allows the given cluster to be evicted from the cluster pool and page pool.
842 void UnpinCluster(ROOT::DescriptorId_t clusterId) { fPinnedClusters.erase(clusterId); }
843 const std::unordered_set<ROOT::DescriptorId_t> &GetPinnedClusters() const { return fPinnedClusters; }
844
845 // TODO(gparolini): for symmetry with SealPage(), we should either make this private or SealPage() public.
847 UnsealPage(const RSealedPage &sealedPage, const ROOT::Internal::RColumnElementBase &element);
848
849 /// Builds the streamer info records from the descriptor's extra type info section. This is necessary when
850 /// connecting streamer fields so that emulated classes can be read.
851 void RegisterStreamerInfos();
852
853 /// Forces the loading of ROOT StreamerInfo from the underlying file. This currently only has an effect for
854 /// TFile-backed sources.
855 virtual void LoadStreamerInfo() = 0;
856
857 /// Creates a new PageSource using the same underlying file as this but referring to a different RNTuple,
858 /// described by `anchorLink`.
859 virtual std::unique_ptr<RPageSource> OpenWithDifferentAnchor(const ROOT::Internal::RNTupleLink &anchorLink,
860 const ROOT::RNTupleReadOptions &options = {}) = 0;
861}; // class RPageSource
862
863} // namespace Internal
864} // namespace ROOT
865
866#endif
#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 d(i)
Definition RSha256.hxx:102
#define b(i)
Definition RSha256.hxx:100
#define e(i)
Definition RSha256.hxx:103
char name[80]
Definition TGX11.cxx:148
A thread-safe integral performance counter.
A metric element that computes its floating point value from other counters.
A collection of Counter objects with a name, a unit, and a description.
Managed a set of clusters containing compressed and packed pages.
An in-memory subset of the packed and compressed pages of a cluster.
Definition RCluster.hxx:147
std::unordered_set< ROOT::DescriptorId_t > ColumnSet_t
Definition RCluster.hxx:149
A column element encapsulates the translation between basic C++ types and their column representation...
A column is a storage-backed array of a simple, fixed-size type, from which pages can be mapped into ...
Definition RColumn.hxx:37
A helper class for piece-wise construction of an RNTupleDescriptor.
The serialization context is used for the piecewise serialization of a descriptor.
std::map< Int_t, TVirtualStreamerInfo * > StreamerInfoMap_t
@ kForReading
Deserializes the descriptor and performs fixup on the suppressed column ranges and on clusters,...
A memory region that contains packed and compressed pages.
Definition RCluster.hxx:98
Abstract interface to allocate and release pages.
RStagedCluster StageCluster(ROOT::NTupleSize_t nNewEntries) final
Stage the current cluster and create a new one for the following data.
void UpdateSchema(const ROOT::Internal::RNTupleModelChangeset &changeset, ROOT::NTupleSize_t firstEntry) override
Incorporate incremental changes to the model into the ntuple descriptor.
void CommitSealedPage(ROOT::DescriptorId_t physicalColumnId, const RPageStorage::RSealedPage &sealedPage) final
Write a preprocessed page to storage. The column must have been added before.
RPagePersistentSink(RPagePersistentSink &&)=default
std::uint64_t fNextClusterInGroup
Remembers the starting cluster id for the next cluster group.
std::unique_ptr< RNTupleModel > InitFromDescriptor(const ROOT::RNTupleDescriptor &descriptor, bool copyClusters)
Initialize sink based on an existing descriptor and fill into the descriptor builder,...
void UpdateExtraTypeInfo(const ROOT::RExtraTypeInfoDescriptor &extraTypeInfo) final
Adds an extra type information record to schema.
void CommitAttributeSet(std::string_view attrSetName, const RNTupleLink &attrAnchorInfo) final
Adds the given anchor information (name + locator) into the main RNTuple's descriptor as an attribute...
ColumnHandle_t AddColumn(ROOT::DescriptorId_t fieldId, ROOT::Internal::RColumn &column) final
Register a new column.
ROOT::Internal::RNTupleDescriptorBuilder fDescriptorBuilder
RPagePersistentSink & operator=(RPagePersistentSink &&)=default
virtual std::vector< RNTupleLocator > CommitSealedPageVImpl(std::span< RPageStorage::RSealedPageGroup > ranges, const std::vector< bool > &mask)
Vector commit of preprocessed pages.
RPagePersistentSink(std::string_view ntupleName, const ROOT::RNTupleWriteOptions &options)
RPagePersistentSink & operator=(const RPagePersistentSink &)=delete
ROOT::NTupleSize_t GetNEntries() const final
RPagePersistentSink(const RPagePersistentSink &)=delete
void CommitSuppressedColumn(ColumnHandle_t columnHandle) final
Commits a suppressed column for the current cluster.
ROOT::Internal::RNTupleSerializer::RContext fSerializationContext
Used to map the IDs of the descriptor to the physical IDs issued during header/footer serialization.
ROOT::NTupleSize_t fPrevClusterNEntries
Used to calculate the number of entries in the current cluster.
virtual RNTupleLink CommitDatasetImpl(unsigned char *serializedFooter, std::uint32_t length)=0
virtual RNTupleLocator CommitClusterGroupImpl(unsigned char *serializedPageList, std::uint32_t length)=0
Returns the locator of the page list envelope of the given buffer that contains the serialized page l...
void CommitStagedClusters(std::span< RStagedCluster > clusters) final
Commit staged clusters, logically appending them to the ntuple descriptor.
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.
std::vector< ROOT::RClusterDescriptor::RPageRange > fOpenPageRanges
Keeps track of the written pages in the currently open cluster. Indexed by column id.
void CommitPage(ColumnHandle_t columnHandle, const ROOT::Internal::RPage &page) final
Write a page to the storage. The column must have been added before.
virtual void InitImpl(unsigned char *serializedHeader, std::uint32_t length)=0
const ROOT::RNTupleDescriptor & GetDescriptor() const final
Return the RNTupleDescriptor being constructed.
std::vector< ROOT::RClusterDescriptor::RColumnRange > fOpenColumnRanges
Keeps track of the number of elements in the currently open cluster. Indexed by column id.
std::unique_ptr< RCounters > fCounters
void CommitClusterGroup() final
Write out the page locations (page list envelope) for all the committed clusters since the last call ...
virtual RNTupleLocator CommitSealedPageImpl(ROOT::DescriptorId_t physicalColumnId, const RPageStorage::RSealedPage &sealedPage)=0
void CommitSealedPageV(std::span< RPageStorage::RSealedPageGroup > ranges) final
Write a vector of preprocessed pages to storage. The corresponding columns must have been added befor...
void EnableDefaultMetrics(const std::string &prefix)
Enables the default set of metrics provided by RPageSink.
ROOT::Internal::RNTupleSerializer::StreamerInfoMap_t fInfosOfStreamerFields
Union of the streamer info records that are sent from streamer fields to the sink before committing t...
virtual RNTupleLocator CommitPageImpl(ColumnHandle_t columnHandle, const ROOT::Internal::RPage &page)=0
virtual std::uint64_t StageClusterImpl()=0
Returns the number of bytes written to storage (excluding metadata).
A thread-safe cache of pages loaded from the page source.
Definition RPagePool.hxx:46
Reference to a page stored in the page pool.
An RAII wrapper used to synchronize a page sink. See GetSinkGuard().
RSinkGuard & operator=(const RSinkGuard &)=delete
RSinkGuard & operator=(RSinkGuard &&)=delete
RSinkGuard(const RSinkGuard &)=delete
virtual RNTupleLink CommitDatasetImpl()=0
RPageSink(RPageSink &&)=default
RNTupleLink CommitDataset()
Run the registered callbacks and finalize the current cluster and the entrire data set.
virtual void CommitSealedPage(ROOT::DescriptorId_t physicalColumnId, const RPageStorage::RSealedPage &sealedPage)=0
Write a preprocessed page to storage. The column must have been added before.
std::vector< unsigned char > fSealPageBuffer
Used as destination buffer in the simple SealPage overload.
virtual void CommitSuppressedColumn(ColumnHandle_t columnHandle)=0
Commits a suppressed column for the current cluster.
std::unique_ptr< ROOT::RNTupleWriteOptions > fOptions
void RegisterOnCommitDatasetCallback(Callback_t callback)
The registered callback is executed at the beginning of CommitDataset();.
std::vector< Callback_t > fOnDatasetCommitCallbacks
virtual ROOT::Internal::RPage ReservePage(ColumnHandle_t columnHandle, std::size_t nElements)
Get a new, empty page for the given column that can be filled with up to nElements; nElements must be...
const ROOT::RNTupleWriteOptions & GetWriteOptions() const
Returns the sink's write options.
virtual void CommitClusterGroup()=0
Write out the page locations (page list envelope) for all the committed clusters since the last call ...
virtual RStagedCluster StageCluster(ROOT::NTupleSize_t nNewEntries)=0
Stage the current cluster and create a new one for the following data.
virtual void CommitPage(ColumnHandle_t columnHandle, const ROOT::Internal::RPage &page)=0
Write a page to the storage. The column must have been added before.
RPageSink & operator=(const RPageSink &)=delete
EPageStorageType GetType() final
Whether the concrete implementation is a sink or a source.
void Init(RNTupleModel &model)
Physically creates the storage container to hold the ntuple (e.g., a keys a TFile or an S3 bucket) In...
virtual void UpdateExtraTypeInfo(const ROOT::RExtraTypeInfoDescriptor &extraTypeInfo)=0
Adds an extra type information record to schema.
virtual void CommitAttributeSet(std::string_view attrSetName, const RNTupleLink &attrAnchorInfo)=0
Adds the given anchor information (name + locator) into the main RNTuple's descriptor as an attribute...
RPageSink(const RPageSink &)=delete
virtual std::unique_ptr< RPageSink > CloneAsHidden(std::string_view name, const RNTupleWriteOptions &opts) const =0
Creates a new sink with the same underlying storage as this but writing to a different RNTuple named ...
virtual void CommitStagedClusters(std::span< RStagedCluster > clusters)=0
Commit staged clusters, logically appending them to the ntuple descriptor.
virtual std::uint64_t CommitCluster(ROOT::NTupleSize_t nNewEntries)
Finalize the current cluster and create a new one for the following data.
virtual void InitImpl(RNTupleModel &model)=0
virtual RSinkGuard GetSinkGuard()
std::function< void(RPageSink &)> Callback_t
virtual void UpdateSchema(const ROOT::Internal::RNTupleModelChangeset &changeset, ROOT::NTupleSize_t firstEntry)=0
Incorporate incremental changes to the model into the ntuple descriptor.
RSealedPage SealPage(const ROOT::Internal::RPage &page, const ROOT::Internal::RColumnElementBase &element)
Helper for streaming a page.
bool fIsInitialized
Flag if sink was initialized.
RPageSink(std::string_view ntupleName, const ROOT::RNTupleWriteOptions &options)
RPageSink & operator=(RPageSink &&)=default
virtual const ROOT::RNTupleDescriptor & GetDescriptor() const =0
Return the RNTupleDescriptor being constructed.
virtual void CommitSealedPageV(std::span< RPageStorage::RSealedPageGroup > ranges)=0
Write a vector of preprocessed pages to storage. The corresponding columns must have been added befor...
virtual ROOT::NTupleSize_t GetNEntries() const =0
RWritePageMemoryManager fWritePageMemoryManager
Used in ReservePage to maintain the page buffer budget.
void DropColumn(ColumnHandle_t) final
Unregisters a column.
Keeps track of the requested physical column IDs and their in-memory target type via a column element...
const std::vector< RColumnInfo > & GetColumnInfos(ROOT::DescriptorId_t physicalColumnId) const
std::unordered_map< ROOT::DescriptorId_t, std::vector< RColumnInfo > > fColumnInfos
Maps physical column IDs to all the requested in-memory representations.
void Insert(ROOT::DescriptorId_t physicalColumnId, ROOT::Internal::RColumnElementBase::RIdentifier elementId)
bool HasColumnInfos(ROOT::DescriptorId_t physicalColumnId) const
ROOT::Internal::RCluster::ColumnSet_t ToColumnSet() const
void Erase(ROOT::DescriptorId_t physicalColumnId, ROOT::Internal::RColumnElementBase::RIdentifier elementId)
An RAII wrapper used for the writable access to RPageSource::fDescriptor. See GetSharedDescriptorGuar...
void MoveIn(ROOT::RNTupleDescriptor desc)
RExclDescriptorGuard & operator=(const RExclDescriptorGuard &)=delete
ROOT::RNTupleDescriptor * operator->() const
RExclDescriptorGuard(RExclDescriptorGuard &&)=delete
RExclDescriptorGuard(ROOT::RNTupleDescriptor &desc, std::shared_mutex &lock)
RExclDescriptorGuard(const RExclDescriptorGuard &)=delete
RExclDescriptorGuard & operator=(RExclDescriptorGuard &&)=delete
An RAII wrapper used for the read-only access to RPageSource::fDescriptor. See `GetExclDescriptorGuar...
RSharedDescriptorGuard(const RSharedDescriptorGuard &)=delete
RSharedDescriptorGuard(RSharedDescriptorGuard &&)=delete
const ROOT::RNTupleDescriptor & GetRef() const
RSharedDescriptorGuard & operator=(const RSharedDescriptorGuard &)=delete
const ROOT::RNTupleDescriptor * operator->() const
RSharedDescriptorGuard(const ROOT::RNTupleDescriptor &desc, std::shared_mutex &lock)
RSharedDescriptorGuard & operator=(RSharedDescriptorGuard &&)=delete
Abstract interface to read data from an ntuple.
ROOT::Internal::RClusterPool fClusterPool
The cluster pool asynchronously preloads the next few clusters.
const std::unordered_set< ROOT::DescriptorId_t > & GetPinnedClusters() const
RPageSource & operator=(RPageSource &&)=delete
EPageStorageType GetType() final
Whether the concrete implementation is a sink or a source.
RPageSource & operator=(const RPageSource &)=delete
ROOT::DescriptorId_t fLastUsedCluster
Remembers the last cluster id from which a page was requested.
RExclDescriptorGuard GetExclDescriptorGuard()
Note that the underlying lock is not recursive. See GetSharedDescriptorGuard() for further informatio...
ROOT::RNTupleReadOptions fOptions
void UnzipCluster(ROOT::Internal::RCluster *cluster)
Populates all the pages of the given cluster ids and columns; it is possible that some columns do not...
REntryRange GetEntryRange() const
const RSharedDescriptorGuard GetSharedDescriptorGuard() const
Takes the read lock for the descriptor.
std::map< ROOT::NTupleSize_t, ROOT::DescriptorId_t > fPreloadedClusters
Clusters from where pages got preloaded in UnzipClusterImpl(), ordered by first entry number of the c...
void PrepareLoadCluster(const ROOT::Internal::RCluster::RKey &clusterKey, ROOT::Internal::ROnDiskPageMap &pageZeroMap, std::function< void(ROOT::DescriptorId_t, ROOT::NTupleSize_t, const ROOT::RClusterDescriptor::RPageInfo &)> perPageFunc)
Prepare a page range read for the column set in clusterKey.
bool fHasStreamerInfosRegistered
Set to true when RegisterStreamerInfos() is called.
REntryRange fEntryRange
Used by the cluster pool to prevent reading beyond the given range.
void UpdateLastUsedCluster(ROOT::DescriptorId_t clusterId)
Does nothing if fLastUsedCluster == clusterId.
virtual ROOT::Internal::RPageRef LoadPageImpl(ColumnHandle_t columnHandle, const RClusterInfo &clusterInfo, ROOT::NTupleSize_t idxInCluster)=0
virtual std::unique_ptr< RPageSource > CloneImpl() const =0
Returns a new, unattached page source for the same data set.
void UnpinCluster(ROOT::DescriptorId_t clusterId)
Allows the given cluster to be evicted from the cluster pool and page pool.
std::unique_ptr< RCounters > fCounters
std::unordered_set< ROOT::DescriptorId_t > fPinnedClusters
Pinned clusters and their $2 * (cluster bunch size) - 1$ successors will not be evicted from the clus...
virtual void LoadStructureImpl()=0
ROOT::RNTupleDescriptor fDescriptor
void PinCluster(ROOT::DescriptorId_t clusterId)
Instructs the cluster pool and page pool to consider the given cluster as active (should stay cached)...
ROOT::Internal::RPagePool fPagePool
Pages that are unzipped with IMT are staged into the page pool.
virtual ROOT::RNTupleDescriptor AttachImpl(ROOT::Internal::RNTupleSerializer::EDescriptorDeserializeMode mode)=0
LoadStructureImpl() has been called before AttachImpl() is called
std::shared_mutex fDescriptorLock
virtual void UnzipClusterImpl(ROOT::Internal::RCluster *cluster)
RPageSource(RPageSource &&)=delete
virtual std::unique_ptr< RPageSource > OpenWithDifferentAnchor(const ROOT::Internal::RNTupleLink &anchorLink, const ROOT::RNTupleReadOptions &options={})=0
Creates a new PageSource using the same underlying file as this but referring to a different RNTuple,...
virtual void LoadStreamerInfo()=0
Forces the loading of ROOT StreamerInfo from the underlying file.
RPageSource(std::string_view ntupleName, const ROOT::RNTupleReadOptions &fOptions)
RPageSource(const RPageSource &)=delete
std::unique_ptr< RPageSource > Clone() const
Open the same storage multiple time, e.g.
const ROOT::RNTupleReadOptions & GetReadOptions() const
RActivePhysicalColumns fActivePhysicalColumns
The active columns are implicitly defined by the model fields or views.
bool fIsAttached
Set to true once Attach() is called.
virtual void LoadSealedPage(ROOT::DescriptorId_t physicalColumnId, RNTupleLocalIndex localIndex, RSealedPage &sealedPage)=0
Read the packed and compressed bytes of a page into the memory buffer provided by sealedPage.
static RResult< ROOT::Internal::RPage > UnsealPage(const RSealedPage &sealedPage, const ROOT::Internal::RColumnElementBase &element, ROOT::Internal::RPageAllocator &pageAlloc)
Helper for unstreaming a page.
bool fHasStructure
Set to true once LoadStructure() is called.
The interface of a task scheduler to schedule page (de)compression tasks.
virtual void Wait()=0
Blocks until all scheduled tasks finished.
virtual void AddTask(const std::function< void(void)> &taskFunc)=0
Take a callable that represents a task.
virtual ColumnHandle_t AddColumn(ROOT::DescriptorId_t fieldId, ROOT::Internal::RColumn &column)=0
Register a new column.
void SetTaskScheduler(RTaskScheduler *taskScheduler)
RPageStorage(const RPageStorage &other)=delete
virtual ROOT::Experimental::Detail::RNTupleMetrics & GetMetrics()
Returns the default metrics object.
RPageStorage & operator=(const RPageStorage &other)=delete
ROOT::DescriptorId_t GetColumnId(ColumnHandle_t columnHandle) const
virtual void DropColumn(ColumnHandle_t columnHandle)=0
Unregisters a column.
RPageStorage & operator=(RPageStorage &&other)=default
std::unique_ptr< ROOT::Internal::RPageAllocator > fPageAllocator
For the time being, we will use the heap allocator for all sources and sinks. This may change in the ...
static constexpr std::size_t kNBytesPageChecksum
The page checksum is a 64bit xxhash3.
std::deque< RSealedPage > SealedPageSequence_t
virtual EPageStorageType GetType()=0
Whether the concrete implementation is a sink or a source.
RColumnHandle ColumnHandle_t
The column handle identifies a column with the current open page storage.
RPageStorage(RPageStorage &&other)=default
ROOT::Experimental::Detail::RNTupleMetrics fMetrics
RPageStorage(std::string_view name)
const std::string & GetNTupleName() const
Returns the NTuple name.
A page is a slice of a column that is mapped into memory.
Definition RPage.hxx:43
Helper to maintain a memory budget for the write pages of a set of columns.
std::size_t fCurrentAllocatedBytes
Sum of all the write page sizes (their capacity) of the columns in fColumnsSortedByPageSize.
std::size_t fMaxAllocatedBytes
Maximum allowed value for fCurrentAllocatedBytes, set from RNTupleWriteOptions::fPageBufferBudget.
bool TryEvict(std::size_t targetAvailableSize, std::size_t pageSizeLimit)
Flush columns in order of allocated write page size until the sum of all write page allocations leave...
bool TryUpdate(ROOT::Internal::RColumn &column, std::size_t newWritePageSize)
Try to register the new write page size for the given column.
RWritePageMemoryManager(std::size_t maxAllocatedBytes)
std::set< RColumnInfo, std::greater< RColumnInfo > > fColumnsSortedByPageSize
All columns that called ReservePage() (hence TryUpdate()) at least once, sorted by their current writ...
Records the partition of data into pages for a particular column in a particular cluster.
Metadata for RNTuple clusters.
Base class for all ROOT issued exceptions.
Definition RError.hxx:78
Field specific extra type information from the header / extenstion header.
The on-storage metadata of an RNTuple.
Addresses a column element or field item relative to a particular cluster, instead of a global NTuple...
Generic information about the physical location of data.
The RNTupleModel encapulates the schema of an RNTuple.
Common user-tunable settings for reading RNTuples.
Common user-tunable settings for storing RNTuples.
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
STL class.
std::uint64_t DescriptorId_t
Distriniguishes elements of the same type within a descriptor, e.g. different fields.
constexpr NTupleSize_t kInvalidNTupleIndex
std::uint64_t NTupleSize_t
Integer type long enough to hold the maximum number of entries in a column.
constexpr DescriptorId_t kInvalidDescriptorId
The identifiers that specifies the content of a (partial) cluster.
Definition RCluster.hxx:151
Every concrete RColumnElement type is identified by its on-disk type (column type) and the in-memory ...
The incremental changes to a RNTupleModel.
Default I/O performance counters that get registered in fMetrics.
ROOT::Experimental::Detail::RNTupleAtomicCounter & fSzWritePayload
ROOT::Experimental::Detail::RNTupleTickCounter< ROOT::Experimental::Detail::RNTupleAtomicCounter > & fTimeCpuWrite
ROOT::Experimental::Detail::RNTupleAtomicCounter & fTimeWallWrite
ROOT::Experimental::Detail::RNTupleTickCounter< ROOT::Experimental::Detail::RNTupleAtomicCounter > & fTimeCpuZip
ROOT::Experimental::Detail::RNTupleAtomicCounter & fTimeWallZip
ROOT::Experimental::Detail::RNTupleAtomicCounter & fSzZip
ROOT::Experimental::Detail::RNTupleAtomicCounter & fNPageCommitted
Set of optional features supported by the persistent sink.
Parameters for the SealPage() method.
bool fWriteChecksum
Adds a 8 byte little-endian xxhash3 checksum to the page payload.
std::uint32_t fCompressionSettings
Compression algorithm and level to apply.
void * fBuffer
Location for sealed output. The memory buffer has to be large enough.
const ROOT::Internal::RPage * fPage
Input page to be sealed.
bool fAllowAlias
If false, the output buffer must not point to the input page buffer, which would otherwise be an opti...
const ROOT::Internal::RColumnElementBase * fElement
Corresponds to the page's elements, for size calculation etc.
ROOT::RClusterDescriptor::RPageRange fPageRange
Cluster that was staged, but not yet logically appended to the RNTuple.
std::vector< RColumnInfo > fColumnInfos
ROOT::Internal::RColumnElementBase::RIdentifier fElementId
Summarizes cluster-level information that are necessary to load a certain page.
std::uint64_t fColumnOffset
The first element number of the page's column in the given cluster.
ROOT::RClusterDescriptor::RPageInfoExtended fPageInfo
Location of the page on disk.
Default I/O performance counters that get registered in fMetrics.
ROOT::Experimental::Detail::RNTupleAtomicCounter & fNPageUnsealed
ROOT::Experimental::Detail::RNTupleAtomicCounter & fNRead
ROOT::Experimental::Detail::RNTupleAtomicCounter & fTimeWallRead
ROOT::Experimental::Detail::RNTupleAtomicCounter & fSzReadOverhead
ROOT::Experimental::Detail::RNTupleCalcPerf & fCompressionRatio
ROOT::Experimental::Detail::RNTupleCalcPerf & fFractionReadOverhead
ROOT::Experimental::Detail::RNTupleAtomicCounter & fNReadV
ROOT::Experimental::Detail::RNTupleAtomicCounter & fNClusterLoaded
ROOT::Experimental::Detail::RNTupleAtomicCounter & fTimeWallUnzip
ROOT::Experimental::Detail::RNTupleAtomicCounter & fNPageRead
ROOT::Experimental::Detail::RNTupleAtomicCounter & fSzReadPayload
ROOT::Experimental::Detail::RNTupleCalcPerf & fBandwidthReadCompressed
ROOT::Experimental::Detail::RNTupleTickCounter< ROOT::Experimental::Detail::RNTupleAtomicCounter > & fTimeCpuUnzip
ROOT::Experimental::Detail::RNTupleTickCounter< ROOT::Experimental::Detail::RNTupleAtomicCounter > & fTimeCpuRead
ROOT::Experimental::Detail::RNTupleCalcPerf & fBandwidthReadUncompressed
ROOT::Experimental::Detail::RNTupleCalcPerf & fBandwidthUnzip
ROOT::Experimental::Detail::RNTupleAtomicCounter & fSzUnzip
Used in SetEntryRange / GetEntryRange.
bool IntersectsWith(const ROOT::RClusterDescriptor &clusterDesc) const
Returns true if the given cluster has entries within the entry range.
SealedPageSequence_t::const_iterator fFirst
SealedPageSequence_t::const_iterator fLast
RSealedPageGroup(ROOT::DescriptorId_t d, SealedPageSequence_t::const_iterator b, SealedPageSequence_t::const_iterator e)
A sealed page contains the bytes of a page as written to storage (packed & compressed).
RSealedPage(const void *buffer, std::size_t bufferSize, std::uint32_t nElements, bool hasChecksum=false)
RResult< void > VerifyChecksumIfEnabled() const
RSealedPage(const RSealedPage &other)=default
bool fHasChecksum
If set, the last 8 bytes of the buffer are the xxhash of the rest of the buffer.
RSealedPage & operator=(RSealedPage &&other)=default
void SetNElements(std::uint32_t nElements)
RSealedPage(RSealedPage &&other)=default
RResult< std::uint64_t > GetChecksum() const
Returns a failure if the sealed page has no checksum.
RSealedPage & operator=(const RSealedPage &other)=default
void SetBufferSize(std::size_t bufferSize)
std::size_t fBufferSize
Size of the page payload and the trailing checksum (if available).
bool operator>(const RColumnInfo &other) const
Additional information about a page in an in-memory RPageRange.
Information about a single page in the context of a cluster's page range.