Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
RPage.hxx
Go to the documentation of this file.
1 /// \file ROOT/RPage.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_RPage
17 #define ROOT7_RPage
18 
19 #include <ROOT/RNTupleUtil.hxx>
20 
21 #include <cstddef>
22 #include <cstdint>
23 
24 namespace ROOT {
25 namespace Experimental {
26 
27 namespace Detail {
28 
29 // clang-format off
30 /**
31 \class ROOT::Experimental::Detail::RPage
32 \ingroup NTuple
33 \brief A page is a slice of a column that is mapped into memory
34 
35 The page provides an opaque memory buffer for uncompressed, unpacked data. It does not interpret
36 the contents but it does now about the size (and thus the number) of the elements inside as well as the element
37 number range within the backing column/cluster. The memory buffer is not managed by the page. It is normally registered
38 with the page pool and allocated/freed by the page storage.
39 */
40 // clang-format on
41 class RPage {
42 public:
43  /**
44  * Stores information about the cluster in which this page resides.
45  */
46  class RClusterInfo {
47  private:
48  /// The cluster number
49  DescriptorId_t fId = 0;
50  /// The first element index of the column in this cluster
51  NTupleSize_t fIndexOffset = 0;
52  public:
53  RClusterInfo() = default;
54  RClusterInfo(NTupleSize_t id, NTupleSize_t indexOffset) : fId(id), fIndexOffset(indexOffset) {}
55  NTupleSize_t GetId() const { return fId; }
56  NTupleSize_t GetIndexOffset() const { return fIndexOffset; }
57  };
58 
59 private:
60  ColumnId_t fColumnId;
61  void *fBuffer;
62  ClusterSize_t::ValueType fCapacity;
63  ClusterSize_t::ValueType fElementSize;
64  ClusterSize_t::ValueType fNElements;
65  NTupleSize_t fRangeFirst;
66  RClusterInfo fClusterInfo;
67 
68 public:
69  RPage() : fColumnId(kInvalidColumnId), fBuffer(nullptr), fCapacity(0), fElementSize(0), fNElements(0), fRangeFirst(0)
70  {}
71  RPage(ColumnId_t columnId, void* buffer, ClusterSize_t::ValueType capacity, ClusterSize_t::ValueType elementSize)
72  : fColumnId(columnId), fBuffer(buffer), fCapacity(capacity), fElementSize(elementSize), fNElements(0),
73  fRangeFirst(0)
74  {}
75  ~RPage() = default;
76 
77  ColumnId_t GetColumnId() { return fColumnId; }
78  /// The total space available in the page
79  ClusterSize_t::ValueType GetCapacity() const { return fCapacity; }
80  /// The space taken by column elements in the buffer
81  ClusterSize_t::ValueType GetSize() const { return fElementSize * fNElements; }
82  ClusterSize_t::ValueType GetElementSize() const { return fElementSize; }
83  ClusterSize_t::ValueType GetNElements() const { return fNElements; }
84  NTupleSize_t GetGlobalRangeFirst() const { return fRangeFirst; }
85  NTupleSize_t GetGlobalRangeLast() const { return fRangeFirst + NTupleSize_t(fNElements) - 1; }
86  ClusterSize_t::ValueType GetClusterRangeFirst() const { return fRangeFirst - fClusterInfo.GetIndexOffset(); }
87  ClusterSize_t::ValueType GetClusterRangeLast() const {
88  return GetClusterRangeFirst() + NTupleSize_t(fNElements) - 1;
89  }
90  const RClusterInfo& GetClusterInfo() const { return fClusterInfo; }
91 
92  bool Contains(NTupleSize_t globalIndex) const {
93  return (globalIndex >= fRangeFirst) && (globalIndex < fRangeFirst + NTupleSize_t(fNElements));
94  }
95 
96  bool Contains(const RClusterIndex &clusterIndex) const {
97  if (fClusterInfo.GetId() != clusterIndex.GetClusterId())
98  return false;
99  auto clusterRangeFirst = ClusterSize_t(fRangeFirst - fClusterInfo.GetIndexOffset());
100  return (clusterIndex.GetIndex() >= clusterRangeFirst) &&
101  (clusterIndex.GetIndex() < clusterRangeFirst + fNElements);
102  }
103 
104  void* GetBuffer() const { return fBuffer; }
105  /// Return a pointer after the last element that has space for nElements new elements. If there is not enough capacity,
106  /// return nullptr
107  void* TryGrow(ClusterSize_t::ValueType nElements) {
108  auto offset = GetSize();
109  auto nbyte = nElements * fElementSize;
110  if (offset + nbyte > fCapacity) {
111  return nullptr;
112  }
113  fNElements += nElements;
114  return static_cast<unsigned char *>(fBuffer) + offset;
115  }
116  /// Seek the page to a certain position of the column
117  void SetWindow(const NTupleSize_t rangeFirst, const RClusterInfo &clusterInfo) {
118  fClusterInfo = clusterInfo;
119  fRangeFirst = rangeFirst;
120  }
121  /// Forget all currently stored elements (size == 0) and set a new starting index.
122  void Reset(NTupleSize_t rangeFirst) { fNElements = 0; fRangeFirst = rangeFirst; }
123  void ResetCluster(const RClusterInfo &clusterInfo) { fNElements = 0; fClusterInfo = clusterInfo; }
124 
125  bool IsNull() const { return fBuffer == nullptr; }
126  bool operator ==(const RPage &other) const { return fBuffer == other.fBuffer; }
127  bool operator !=(const RPage &other) const { return !(*this == other); }
128 };
129 
130 } // namespace Detail
131 
132 } // namespace Experimental
133 } // namespace ROOT
134 
135 #endif