File indexing completed on 2025-09-16 09:08:35
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef ROOT_RPagePool
0015 #define ROOT_RPagePool
0016
0017 #include <ROOT/RPage.hxx>
0018 #include <ROOT/RPageAllocator.hxx>
0019 #include <ROOT/RNTupleUtil.hxx>
0020
0021 #include <cstddef>
0022 #include <map>
0023 #include <mutex>
0024 #include <typeindex>
0025 #include <typeinfo>
0026 #include <unordered_map>
0027 #include <unordered_set>
0028 #include <vector>
0029
0030 namespace ROOT {
0031 namespace Internal {
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044 class RPagePool {
0045 friend class RPageRef;
0046
0047 public:
0048
0049
0050 struct RKey {
0051 ROOT::DescriptorId_t fColumnId = ROOT::kInvalidDescriptorId;
0052 std::type_index fInMemoryType = std::type_index(typeid(void));
0053
0054 bool operator==(const RKey &other) const
0055 {
0056 return this->fColumnId == other.fColumnId && this->fInMemoryType == other.fInMemoryType;
0057 }
0058
0059 bool operator!=(const RKey &other) const { return !(*this == other); }
0060 };
0061
0062 private:
0063
0064 struct RKeyHasher {
0065
0066 std::size_t operator()(const RKey &k) const
0067 {
0068 auto seed = std::hash<ROOT::DescriptorId_t>()(k.fColumnId);
0069 return seed ^ (std::hash<std::type_index>()(k.fInMemoryType) + 0x9e3779b9 + (seed << 6) + (seed >> 2));
0070 }
0071 };
0072
0073
0074 struct REntry {
0075 RPage fPage;
0076 RKey fKey;
0077 std::int64_t fRefCounter = 0;
0078 };
0079
0080
0081
0082
0083 struct RPagePosition {
0084 ROOT::NTupleSize_t fGlobalFirstElement = ROOT::kInvalidNTupleIndex;
0085 RNTupleLocalIndex fClusterFirstElement;
0086
0087 bool operator<(const RPagePosition &other) const
0088 {
0089 if ((fGlobalFirstElement != ROOT::kInvalidNTupleIndex) &&
0090 (other.fGlobalFirstElement != ROOT::kInvalidNTupleIndex)) {
0091 return fGlobalFirstElement < other.fGlobalFirstElement;
0092 }
0093
0094 assert(fClusterFirstElement.GetClusterId() != ROOT::kInvalidDescriptorId &&
0095 fClusterFirstElement.GetIndexInCluster() != ROOT::kInvalidNTupleIndex);
0096 assert(other.fClusterFirstElement.GetClusterId() != ROOT::kInvalidDescriptorId &&
0097 other.fClusterFirstElement.GetIndexInCluster() != ROOT::kInvalidNTupleIndex);
0098 if (fClusterFirstElement.GetClusterId() == other.fClusterFirstElement.GetClusterId())
0099 return fClusterFirstElement.GetIndexInCluster() < other.fClusterFirstElement.GetIndexInCluster();
0100 return fClusterFirstElement.GetClusterId() < other.fClusterFirstElement.GetClusterId();
0101 }
0102
0103
0104 explicit RPagePosition(const RPage &page)
0105 : fGlobalFirstElement(page.GetGlobalRangeFirst()),
0106 fClusterFirstElement({page.GetClusterInfo().GetId(), page.GetLocalRangeFirst()})
0107 {
0108 }
0109
0110
0111 explicit RPagePosition(ROOT::NTupleSize_t globalIndex) : fGlobalFirstElement(globalIndex) {}
0112 explicit RPagePosition(RNTupleLocalIndex localIndex) : fClusterFirstElement(localIndex) {}
0113 };
0114
0115 std::vector<REntry> fEntries;
0116
0117 std::unordered_map<void *, std::size_t> fLookupByBuffer;
0118
0119
0120
0121
0122 std::unordered_map<RKey, std::map<RPagePosition, std::size_t>, RKeyHasher> fLookupByKey;
0123
0124
0125
0126
0127 std::unordered_map<ROOT::DescriptorId_t, std::unordered_set<void *>> fUnusedPages;
0128 std::mutex fLock;
0129
0130
0131 REntry &AddPage(RPage page, const RKey &key, std::int64_t initialRefCounter);
0132
0133
0134
0135
0136 void ReleasePage(const RPage &page);
0137
0138
0139 void RemoveFromUnusedPages(const RPage &page);
0140
0141
0142 void ErasePage(std::size_t entryIdx, decltype(fLookupByBuffer)::iterator lookupByBufferItr);
0143
0144 public:
0145 RPagePool() = default;
0146 RPagePool(const RPagePool&) = delete;
0147 RPagePool& operator =(const RPagePool&) = delete;
0148 ~RPagePool() = default;
0149
0150
0151
0152 RPageRef RegisterPage(RPage page, RKey key);
0153
0154
0155 void PreloadPage(RPage page, RKey key);
0156
0157
0158 void Evict(ROOT::DescriptorId_t clusterId);
0159
0160
0161 RPageRef GetPage(RKey key, ROOT::NTupleSize_t globalIndex);
0162 RPageRef GetPage(RKey key, RNTupleLocalIndex localIndex);
0163 };
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174 class RPageRef {
0175 friend class RPagePool;
0176
0177 RPage fPage;
0178 RPagePool *fPagePool = nullptr;
0179
0180
0181 RPageRef(const RPage &page, RPagePool *pagePool) : fPagePool(pagePool)
0182 {
0183
0184 fPage.fBuffer = page.fBuffer;
0185 fPage.fElementSize = page.fElementSize;
0186 fPage.fNElements = page.fNElements;
0187 fPage.fMaxElements = page.fMaxElements;
0188 fPage.fRangeFirst = page.fRangeFirst;
0189 fPage.fClusterInfo = page.fClusterInfo;
0190 }
0191
0192 public:
0193 RPageRef() = default;
0194 RPageRef(const RPageRef &other) = delete;
0195 RPageRef &operator=(const RPageRef &other) = delete;
0196
0197 RPageRef(RPageRef &&other) : RPageRef(other.fPage, other.fPagePool) { other.fPagePool = nullptr; }
0198
0199 RPageRef &operator=(RPageRef &&other)
0200 {
0201 if (this != &other) {
0202 std::swap(fPage, other.fPage);
0203 std::swap(fPagePool, other.fPagePool);
0204 }
0205 return *this;
0206 }
0207
0208 ~RPageRef()
0209 {
0210 if (fPagePool)
0211 fPagePool->ReleasePage(fPage);
0212 }
0213
0214 const RPage &Get() const { return fPage; }
0215 };
0216
0217 }
0218 }
0219
0220 #endif