Logo ROOT  
Reference Guide
RPageSinkBuf.hxx
Go to the documentation of this file.
1/// \file ROOT/RPageSinkBuf.hxx
2/// \ingroup NTuple ROOT7
3/// \author Jakob Blomer <jblomer@cern.ch>
4/// \author Max Orok <maxwellorok@gmail.com>
5/// \date 2021-03-17
6/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
7/// is welcome!
8
9/*************************************************************************
10 * Copyright (C) 1995-2021, Rene Brun and Fons Rademakers. *
11 * All rights reserved. *
12 * *
13 * For the licensing terms see $ROOTSYS/LICENSE. *
14 * For the list of contributors see $ROOTSYS/README/CREDITS. *
15 *************************************************************************/
16
17#ifndef ROOT7_RPageSinkBuf
18#define ROOT7_RPageSinkBuf
19
21#include <ROOT/RPageStorage.hxx>
22
23#include <deque>
24#include <iterator>
25#include <memory>
26#include <tuple>
27
28namespace ROOT {
29namespace Experimental {
30namespace Detail {
31
32// clang-format off
33/**
34\class ROOT::Experimental::Detail::RPageSinkBuf
35\ingroup NTuple
36\brief Wrapper sink that coalesces cluster column page writes
37*
38* TODO(jblomer): The interplay of derived class and RPageSink is not yet optimally designed for page storage wrapper
39* classes like this one. Header and footer serialization, e.g., are done twice. To be revised.
40*/
41// clang-format on
42class RPageSinkBuf : public RPageSink {
43private:
44 /// A buffered column. The column is not responsible for RPage memory management (i.e.
45 /// ReservePage/ReleasePage), which is handled by the enclosing RPageSinkBuf.
46 class RColumnBuf {
47 public:
48 struct RPageZipItem {
50 // Compression scratch buffer for fSealedPage.
51 std::unique_ptr<unsigned char[]> fBuf;
53 explicit RPageZipItem(RPage page)
54 : fPage(page), fBuf(nullptr) {}
55 bool IsSealed() const { return fSealedPage != nullptr; }
57 fBuf = std::make_unique<unsigned char[]>(fPage.GetNBytes());
58 }
59 };
60 public:
61 RColumnBuf() = default;
62 RColumnBuf(const RColumnBuf&) = delete;
63 RColumnBuf& operator=(const RColumnBuf&) = delete;
64 RColumnBuf(RColumnBuf&&) = default;
66 ~RColumnBuf() = default;
67
68 using iterator = std::deque<RPageZipItem>::iterator;
69 /// Returns an iterator to the newly buffered page. The iterator remains
70 /// valid until the return value of DrainBufferedPages() is destroyed.
72 RPageStorage::ColumnHandle_t columnHandle, const RPage &page)
73 {
74 if (!fCol) {
75 fCol = columnHandle;
76 }
77 // Safety: Insertion at the end of a deque never invalidates existing
78 // iterators.
79 fBufferedPages.push_back(RPageZipItem(page));
80 return std::prev(fBufferedPages.end());
81 }
82 const RPageStorage::ColumnHandle_t &GetHandle() const { return fCol; }
83 bool HasSealedPagesOnly() const { return fBufferedPages.size() && fBufferedPages.size() == fSealedPages.size(); }
85
86 using BufferedPages_t = std::tuple<std::deque<RPageZipItem>, RPageStorage::SealedPageSequence_t>;
87 // When the return value of DrainBufferedPages() is destroyed, all iterators
88 // returned by GetBuffer are invalidated.
90 {
91 BufferedPages_t drained;
92 std::swap(fBufferedPages, std::get<decltype(fBufferedPages)>(drained));
93 std::swap(fSealedPages, std::get<decltype(fSealedPages)>(drained));
94 return drained;
95 }
96
97 // The returned iterator points to a default-constructed RSealedPage. This iterator can be used
98 // to fill in data after sealing.
99 RPageStorage::SealedPageSequence_t::iterator RegisterSealedPage()
100 {
101 return fSealedPages.emplace(std::end(fSealedPages));
102 }
103
104 private:
106 // Using a deque guarantees that element iterators are never invalidated
107 // by appends to the end of the iterator by BufferPage.
108 std::deque<RPageZipItem> fBufferedPages;
109 // Pages that have been already sealed by a concurrent task. A vector commit can be issued if all
110 // buffered pages have been sealed.
112 };
113
114private:
115 /// I/O performance counters that get registered in fMetrics
116 struct RCounters {
118 };
119 std::unique_ptr<RCounters> fCounters;
121 /// The inner sink, responsible for actually performing I/O.
122 std::unique_ptr<RPageSink> fInnerSink;
123 /// The buffered page sink maintains a copy of the RNTupleModel for the inner sink.
124 /// For the unbuffered case, the RNTupleModel is instead managed by a RNTupleWriter.
125 std::unique_ptr<RNTupleModel> fInnerModel;
126 /// Vector of buffered column pages. Indexed by column id.
127 std::vector<RColumnBuf> fBufferedColumns;
128
129protected:
130 void CreateImpl(const RNTupleModel &model, unsigned char *serializedHeader, std::uint32_t length) final;
131 RNTupleLocator CommitPageImpl(ColumnHandle_t columnHandle, const RPage &page) final;
132 RNTupleLocator CommitSealedPageImpl(DescriptorId_t columnId, const RSealedPage &sealedPage) final;
133 std::uint64_t CommitClusterImpl(NTupleSize_t nEntries) final;
134 RNTupleLocator CommitClusterGroupImpl(unsigned char *serializedPageList, std::uint32_t length) final;
135 void CommitDatasetImpl(unsigned char *serializedFooter, std::uint32_t length) final;
136
137public:
138 explicit RPageSinkBuf(std::unique_ptr<RPageSink> inner);
139 RPageSinkBuf(const RPageSinkBuf&) = delete;
143 virtual ~RPageSinkBuf() = default;
144
145 RPage ReservePage(ColumnHandle_t columnHandle, std::size_t nElements) final;
146 void ReleasePage(RPage &page) final;
147
148 RNTupleMetrics &GetMetrics() final { return fMetrics; }
149};
150
151} // namespace Detail
152} // namespace Experimental
153} // namespace ROOT
154
155#endif
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 length
A collection of Counter objects with a name, a unit, and a description.
A non thread-safe integral performance counter.
const RPageStorage::ColumnHandle_t & GetHandle() const
iterator BufferPage(RPageStorage::ColumnHandle_t columnHandle, const RPage &page)
Returns an iterator to the newly buffered page.
RColumnBuf & operator=(const RColumnBuf &)=delete
const RPageStorage::SealedPageSequence_t & GetSealedPages() const
RPageStorage::SealedPageSequence_t::iterator RegisterSealedPage()
RColumnBuf & operator=(RColumnBuf &&)=default
RPageStorage::SealedPageSequence_t fSealedPages
std::deque< RPageZipItem >::iterator iterator
std::tuple< std::deque< RPageZipItem >, RPageStorage::SealedPageSequence_t > BufferedPages_t
Wrapper sink that coalesces cluster column page writes.
RNTupleLocator CommitSealedPageImpl(DescriptorId_t columnId, const RSealedPage &sealedPage) final
RPageSinkBuf(std::unique_ptr< RPageSink > inner)
void ReleasePage(RPage &page) final
Every page store needs to be able to free pages it handed out.
std::unique_ptr< RCounters > fCounters
RPageSinkBuf(RPageSinkBuf &&)=default
RPage ReservePage(ColumnHandle_t columnHandle, std::size_t nElements) final
Get a new, empty page for the given column that can be filled with up to nElements.
RPageSinkBuf & operator=(RPageSinkBuf &&)=default
RPageSinkBuf(const RPageSinkBuf &)=delete
std::unique_ptr< RPageSink > fInnerSink
The inner sink, responsible for actually performing I/O.
RNTupleMetrics & GetMetrics() final
Returns the default metrics object. Subclasses might alternatively provide their own metrics object b...
RPageSinkBuf & operator=(const RPageSinkBuf &)=delete
std::vector< RColumnBuf > fBufferedColumns
Vector of buffered column pages. Indexed by column id.
void CommitDatasetImpl(unsigned char *serializedFooter, std::uint32_t length) final
std::uint64_t CommitClusterImpl(NTupleSize_t nEntries) final
Returns the number of bytes written to storage (excluding metadata)
RNTupleLocator CommitClusterGroupImpl(unsigned char *serializedPageList, std::uint32_t length) final
Returns the locator of the page list envelope of the given buffer that contains the serialized page l...
void CreateImpl(const RNTupleModel &model, unsigned char *serializedHeader, std::uint32_t length) final
std::unique_ptr< RNTupleModel > fInnerModel
The buffered page sink maintains a copy of the RNTupleModel for the inner sink.
RNTupleLocator CommitPageImpl(ColumnHandle_t columnHandle, const RPage &page) final
Abstract interface to write data into an ntuple.
std::deque< RSealedPage > SealedPageSequence_t
A page is a slice of a column that is mapped into memory.
Definition: RPage.hxx:41
ClusterSize_t::ValueType GetNBytes() const
The space taken by column elements in the buffer.
Definition: RPage.hxx:81
The RNTupleModel encapulates the schema of an ntuple.
void swap(RDirectoryEntry &e1, RDirectoryEntry &e2) noexcept
std::uint64_t NTupleSize_t
Integer type long enough to hold the maximum number of entries in a column.
Definition: RNTupleUtil.hxx:47
std::uint64_t DescriptorId_t
Distriniguishes elements of the same type within a descriptor, e.g. different fields.
Definition: RNTupleUtil.hxx:83
This file contains a specialised ROOT message handler to test for diagnostic in unit tests.
I/O performance counters that get registered in fMetrics.
A sealed page contains the bytes of a page as written to storage (packed & compressed).
Generic information about the physical location of data.