Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-15 09:11:45

0001 /// \file ROOT/RPage.hxx
0002 /// \ingroup NTuple
0003 /// \author Jakob Blomer <jblomer@cern.ch>
0004 /// \date 2018-10-09
0005 
0006 /*************************************************************************
0007  * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers.               *
0008  * All rights reserved.                                                  *
0009  *                                                                       *
0010  * For the licensing terms see $ROOTSYS/LICENSE.                         *
0011  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
0012  *************************************************************************/
0013 
0014 #ifndef ROOT_RPage
0015 #define ROOT_RPage
0016 
0017 #include <ROOT/RNTupleUtil.hxx>
0018 
0019 #include <cassert>
0020 #include <cstddef>
0021 #include <cstdint>
0022 #include <memory>
0023 
0024 namespace ROOT {
0025 namespace Internal {
0026 
0027 class RPageAllocator;
0028 class RPageRef;
0029 
0030 // clang-format off
0031 /**
0032 \class ROOT::Internal::RPage
0033 \ingroup NTuple
0034 \brief A page is a slice of a column that is mapped into memory
0035 
0036 The page provides an opaque memory buffer for uncompressed, unpacked data. It does not interpret
0037 the contents but it does now about the size (and thus the number) of the elements inside as well as the element
0038 number range within the backing column/cluster.
0039 For reading, pages are allocated and filled by the page source and then registered with the page pool.
0040 For writing, the page sink allocates uninitialized pages of a given size.
0041 The page has a pointer to its memory allocator so that it can release itself.
0042 */
0043 // clang-format on
0044 class RPage {
0045    friend class RPageRef;
0046 
0047 public:
0048    static constexpr size_t kPageZeroSize = 64 * 1024;
0049 
0050    /**
0051     * Stores information about the cluster in which this page resides.
0052     */
0053    class RClusterInfo {
0054    private:
0055       /// The cluster number
0056       ROOT::DescriptorId_t fId = 0;
0057       /// The first element index of the column in this cluster
0058       ROOT::NTupleSize_t fIndexOffset = 0;
0059 
0060    public:
0061       RClusterInfo() = default;
0062       RClusterInfo(ROOT::NTupleSize_t id, ROOT::NTupleSize_t indexOffset) : fId(id), fIndexOffset(indexOffset) {}
0063       ROOT::NTupleSize_t GetId() const { return fId; }
0064       ROOT::NTupleSize_t GetIndexOffset() const { return fIndexOffset; }
0065    };
0066 
0067 private:
0068    void *fBuffer = nullptr;
0069    /// The allocator used to allocate fBuffer. Can be null if the buffer doesn't need to be freed.
0070    RPageAllocator *fPageAllocator = nullptr;
0071    std::uint32_t fElementSize = 0;
0072    std::uint32_t fNElements = 0;
0073    /// The capacity of the page in number of elements
0074    std::uint32_t fMaxElements = 0;
0075    ROOT::NTupleSize_t fRangeFirst = 0;
0076    RClusterInfo fClusterInfo;
0077 
0078 public:
0079    RPage() = default;
0080    RPage(void *buffer, RPageAllocator *pageAllocator, std::uint32_t elementSize, std::uint32_t maxElements)
0081       : fBuffer(buffer), fPageAllocator(pageAllocator), fElementSize(elementSize), fMaxElements(maxElements)
0082    {}
0083    RPage(const RPage &) = delete;
0084    RPage &operator=(const RPage &) = delete;
0085    RPage(RPage &&other)
0086    {
0087       fBuffer = other.fBuffer;
0088       fPageAllocator = other.fPageAllocator;
0089       fElementSize = other.fElementSize;
0090       fNElements = other.fNElements;
0091       fMaxElements = other.fMaxElements;
0092       fRangeFirst = other.fRangeFirst;
0093       fClusterInfo = other.fClusterInfo;
0094       other.fPageAllocator = nullptr;
0095    }
0096    RPage &operator=(RPage &&other)
0097    {
0098       if (this != &other) {
0099          std::swap(fBuffer, other.fBuffer);
0100          std::swap(fPageAllocator, other.fPageAllocator);
0101          std::swap(fElementSize, other.fElementSize);
0102          std::swap(fNElements, other.fNElements);
0103          std::swap(fMaxElements, other.fMaxElements);
0104          std::swap(fRangeFirst, other.fRangeFirst);
0105          std::swap(fClusterInfo, other.fClusterInfo);
0106       }
0107       return *this;
0108    }
0109    ~RPage();
0110 
0111    /// The space taken by column elements in the buffer
0112    std::size_t GetNBytes() const
0113    {
0114       return static_cast<std::size_t>(fElementSize) * static_cast<std::size_t>(fNElements);
0115    }
0116    std::size_t GetCapacity() const
0117    {
0118       return static_cast<std::size_t>(fElementSize) * static_cast<std::size_t>(fMaxElements);
0119    }
0120    std::uint32_t GetElementSize() const { return fElementSize; }
0121    std::uint32_t GetNElements() const { return fNElements; }
0122    std::uint32_t GetMaxElements() const { return fMaxElements; }
0123    ROOT::NTupleSize_t GetGlobalRangeFirst() const { return fRangeFirst; }
0124    ROOT::NTupleSize_t GetGlobalRangeLast() const { return fRangeFirst + ROOT::NTupleSize_t(fNElements) - 1; }
0125    ROOT::NTupleSize_t GetLocalRangeFirst() const { return fRangeFirst - fClusterInfo.GetIndexOffset(); }
0126    ROOT::NTupleSize_t GetLocalRangeLast() const { return GetLocalRangeFirst() + ROOT::NTupleSize_t(fNElements) - 1; }
0127    const RClusterInfo& GetClusterInfo() const { return fClusterInfo; }
0128 
0129    bool Contains(ROOT::NTupleSize_t globalIndex) const
0130    {
0131       return (globalIndex >= fRangeFirst) && (globalIndex < fRangeFirst + ROOT::NTupleSize_t(fNElements));
0132    }
0133 
0134    bool Contains(RNTupleLocalIndex localIndex) const
0135    {
0136       if (fClusterInfo.GetId() != localIndex.GetClusterId())
0137          return false;
0138       auto clusterRangeFirst = fRangeFirst - fClusterInfo.GetIndexOffset();
0139       return (localIndex.GetIndexInCluster() >= clusterRangeFirst) &&
0140              (localIndex.GetIndexInCluster() < clusterRangeFirst + fNElements);
0141    }
0142 
0143    void* GetBuffer() const { return fBuffer; }
0144    /// Increases the number elements in the page. The caller is responsible to respect the page capacity,
0145    /// i.e. to ensure that fNElements + nElements <= fMaxElements.
0146    /// Returns a pointer after the last element, which is used during writing in anticipation of the caller filling
0147    /// nElements in the page.
0148    /// When reading a page from disk, GrowUnchecked is used to set the actual number of elements. In this case, the
0149    /// return value is ignored.
0150    void *GrowUnchecked(std::uint32_t nElements)
0151    {
0152       assert(fNElements + nElements <= fMaxElements);
0153       auto offset = GetNBytes();
0154       fNElements += nElements;
0155       return static_cast<unsigned char *>(fBuffer) + offset;
0156    }
0157    /// Seek the page to a certain position of the column
0158    void SetWindow(const ROOT::NTupleSize_t rangeFirst, const RClusterInfo &clusterInfo)
0159    {
0160       fClusterInfo = clusterInfo;
0161       fRangeFirst = rangeFirst;
0162    }
0163    /// Forget all currently stored elements (size == 0) and set a new starting index.
0164    void Reset(ROOT::NTupleSize_t rangeFirst)
0165    {
0166       fNElements = 0;
0167       fRangeFirst = rangeFirst;
0168    }
0169    void ResetCluster(const RClusterInfo &clusterInfo) { fNElements = 0; fClusterInfo = clusterInfo; }
0170 
0171    /// Return a pointer to the page zero buffer used if there is no on-disk data for a particular deferred column
0172    static const void *GetPageZeroBuffer();
0173 
0174    bool IsNull() const { return fBuffer == nullptr; }
0175    bool IsEmpty() const { return fNElements == 0; }
0176    bool operator ==(const RPage &other) const { return fBuffer == other.fBuffer; }
0177    bool operator !=(const RPage &other) const { return !(*this == other); }
0178 }; // class RPage
0179 
0180 } // namespace Internal
0181 } // namespace ROOT
0182 
0183 #endif