Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:10:47

0001 /// \file ROOT/RPage.hxx
0002 /// \ingroup NTuple ROOT7
0003 /// \author Jakob Blomer <jblomer@cern.ch>
0004 /// \date 2018-10-09
0005 /// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
0006 /// is welcome!
0007 
0008 /*************************************************************************
0009  * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers.               *
0010  * All rights reserved.                                                  *
0011  *                                                                       *
0012  * For the licensing terms see $ROOTSYS/LICENSE.                         *
0013  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
0014  *************************************************************************/
0015 
0016 #ifndef ROOT7_RPage
0017 #define ROOT7_RPage
0018 
0019 #include <ROOT/RNTupleUtil.hxx>
0020 
0021 #include <cstddef>
0022 #include <cstdint>
0023 #include <memory>
0024 
0025 namespace ROOT {
0026 namespace Experimental {
0027 namespace Internal {
0028 
0029 // clang-format off
0030 /**
0031 \class ROOT::Experimental::Internal::RPage
0032 \ingroup NTuple
0033 \brief A page is a slice of a column that is mapped into memory
0034 
0035 The page provides an opaque memory buffer for uncompressed, unpacked data. It does not interpret
0036 the contents but it does now about the size (and thus the number) of the elements inside as well as the element
0037 number range within the backing column/cluster. The memory buffer is not managed by the page. It is normally registered
0038 with the page pool and allocated/freed by the page storage.
0039 */
0040 // clang-format on
0041 class RPage {
0042 public:
0043    static constexpr size_t kPageZeroSize = 64 * 1024;
0044 
0045    /**
0046     * Stores information about the cluster in which this page resides.
0047     */
0048    class RClusterInfo {
0049    private:
0050       /// The cluster number
0051       DescriptorId_t fId = 0;
0052       /// The first element index of the column in this cluster
0053       NTupleSize_t fIndexOffset = 0;
0054    public:
0055       RClusterInfo() = default;
0056       RClusterInfo(NTupleSize_t id, NTupleSize_t indexOffset) : fId(id), fIndexOffset(indexOffset) {}
0057       NTupleSize_t GetId() const { return fId; }
0058       NTupleSize_t GetIndexOffset() const { return fIndexOffset; }
0059    };
0060 
0061 private:
0062    ColumnId_t fColumnId;
0063    void *fBuffer;
0064    std::uint32_t fElementSize;
0065    std::uint32_t fNElements;
0066    /// The capacity of the page in number of elements
0067    std::uint32_t fMaxElements;
0068    NTupleSize_t fRangeFirst;
0069    RClusterInfo fClusterInfo;
0070 
0071 public:
0072    RPage()
0073       : fColumnId(kInvalidColumnId), fBuffer(nullptr), fElementSize(0), fNElements(0), fMaxElements(0), fRangeFirst(0)
0074    {}
0075    RPage(ColumnId_t columnId, void* buffer, ClusterSize_t::ValueType elementSize, ClusterSize_t::ValueType maxElements)
0076       : fColumnId(columnId), fBuffer(buffer), fElementSize(elementSize), fNElements(0), fMaxElements(maxElements),
0077         fRangeFirst(0)
0078    {}
0079    ~RPage() = default;
0080 
0081    ColumnId_t GetColumnId() const { return fColumnId; }
0082    /// The space taken by column elements in the buffer
0083    std::uint32_t GetNBytes() const { return fElementSize * fNElements; }
0084    std::uint32_t GetNElements() const { return fNElements; }
0085    std::uint32_t GetMaxElements() const { return fMaxElements; }
0086    NTupleSize_t GetGlobalRangeFirst() const { return fRangeFirst; }
0087    NTupleSize_t GetGlobalRangeLast() const { return fRangeFirst + NTupleSize_t(fNElements) - 1; }
0088    ClusterSize_t::ValueType GetClusterRangeFirst() const { return fRangeFirst - fClusterInfo.GetIndexOffset(); }
0089    ClusterSize_t::ValueType GetClusterRangeLast() const {
0090       return GetClusterRangeFirst() + NTupleSize_t(fNElements) - 1;
0091    }
0092    const RClusterInfo& GetClusterInfo() const { return fClusterInfo; }
0093 
0094    bool Contains(NTupleSize_t globalIndex) const {
0095       return (globalIndex >= fRangeFirst) && (globalIndex < fRangeFirst + NTupleSize_t(fNElements));
0096    }
0097 
0098    bool Contains(RClusterIndex clusterIndex) const
0099    {
0100       if (fClusterInfo.GetId() != clusterIndex.GetClusterId())
0101          return false;
0102       auto clusterRangeFirst = ClusterSize_t(fRangeFirst - fClusterInfo.GetIndexOffset());
0103       return (clusterIndex.GetIndex() >= clusterRangeFirst) &&
0104              (clusterIndex.GetIndex() < clusterRangeFirst + fNElements);
0105    }
0106 
0107    void* GetBuffer() const { return fBuffer; }
0108    /// Called during writing: returns a pointer after the last element and increases the element counter
0109    /// in anticipation of the caller filling nElements in the page. It is the responsibility of the caller
0110    /// to prevent page overflows, i.e. that fNElements + nElements <= fMaxElements
0111    void* GrowUnchecked(ClusterSize_t::ValueType nElements) {
0112       auto offset = GetNBytes();
0113       fNElements += nElements;
0114       return static_cast<unsigned char *>(fBuffer) + offset;
0115    }
0116    /// Seek the page to a certain position of the column
0117    void SetWindow(const NTupleSize_t rangeFirst, const RClusterInfo &clusterInfo) {
0118       fClusterInfo = clusterInfo;
0119       fRangeFirst = rangeFirst;
0120    }
0121    /// Forget all currently stored elements (size == 0) and set a new starting index.
0122    void Reset(NTupleSize_t rangeFirst) { fNElements = 0; fRangeFirst = rangeFirst; }
0123    void ResetCluster(const RClusterInfo &clusterInfo) { fNElements = 0; fClusterInfo = clusterInfo; }
0124 
0125    /// Used by virtual page sources to map the physical column and cluster IDs to ther virtual counterparts
0126    void ChangeIds(DescriptorId_t columnId, DescriptorId_t clusterId)
0127    {
0128       fColumnId = columnId;
0129       fClusterInfo = RClusterInfo(clusterId, fClusterInfo.GetIndexOffset());
0130    }
0131 
0132    /// Make a 'zero' page for column `columnId` (that is comprised of 0x00 bytes only). The caller is responsible for
0133    /// invoking `GrowUnchecked()` and `SetWindow()` as appropriate.
0134    static RPage MakePageZero(ColumnId_t columnId, ClusterSize_t::ValueType elementSize)
0135    {
0136       return RPage{columnId, const_cast<void *>(GetPageZeroBuffer()), elementSize,
0137                    /*maxElements=*/(kPageZeroSize / elementSize)};
0138    }
0139    /// Return a pointer to the page zero buffer used if there is no on-disk data for a particular deferred column
0140    static const void *GetPageZeroBuffer();
0141 
0142    bool IsNull() const { return fBuffer == nullptr; }
0143    bool IsPageZero() const { return fBuffer == GetPageZeroBuffer(); }
0144    bool IsEmpty() const { return fNElements == 0; }
0145    bool operator ==(const RPage &other) const { return fBuffer == other.fBuffer; }
0146    bool operator !=(const RPage &other) const { return !(*this == other); }
0147 }; // class RPage
0148 
0149 } // namespace Internal
0150 } // namespace Experimental
0151 } // namespace ROOT
0152 
0153 #endif