File indexing completed on 2026-11-01 10:27:00
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef ROOT_RPageStorage
0015 #define ROOT_RPageStorage
0016
0017 #include <ROOT/RError.hxx>
0018 #include <ROOT/RCluster.hxx>
0019 #include <ROOT/RClusterPool.hxx>
0020 #include <ROOT/RColumnElementBase.hxx>
0021 #include <ROOT/RNTupleDescriptor.hxx>
0022 #include <ROOT/RNTupleMetrics.hxx>
0023 #include <ROOT/RNTupleReadOptions.hxx>
0024 #include <ROOT/RNTupleSerialize.hxx>
0025 #include <ROOT/RNTupleWriteOptions.hxx>
0026 #include <ROOT/RNTupleTypes.hxx>
0027 #include <ROOT/RPage.hxx>
0028 #include <ROOT/RPagePool.hxx>
0029 #include <ROOT/RSpan.hxx>
0030 #include <string_view>
0031
0032 #include <atomic>
0033 #include <cassert>
0034 #include <cstddef>
0035 #include <deque>
0036 #include <functional>
0037 #include <map>
0038 #include <memory>
0039 #include <mutex>
0040 #include <set>
0041 #include <shared_mutex>
0042 #include <unordered_map>
0043 #include <unordered_set>
0044 #include <vector>
0045
0046 namespace ROOT {
0047
0048 class RNTupleModel;
0049
0050 namespace Internal {
0051
0052 class RPageAllocator;
0053 class RColumn;
0054 struct RNTupleModelChangeset;
0055
0056 enum class EPageStorageType {
0057 kSink,
0058 kSource,
0059 };
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071 class RPageStorage {
0072 public:
0073
0074 static constexpr std::size_t kNBytesPageChecksum = sizeof(std::uint64_t);
0075
0076
0077 class RTaskScheduler {
0078 public:
0079 virtual ~RTaskScheduler() = default;
0080
0081 virtual void AddTask(const std::function<void(void)> &taskFunc) = 0;
0082
0083 virtual void Wait() = 0;
0084 };
0085
0086
0087
0088
0089
0090 struct RSealedPage {
0091 private:
0092 const void *fBuffer = nullptr;
0093 std::size_t fBufferSize = 0;
0094 std::uint32_t fNElements = 0;
0095 bool fHasChecksum = false;
0096
0097 public:
0098 RSealedPage() = default;
0099 RSealedPage(const void *buffer, std::size_t bufferSize, std::uint32_t nElements, bool hasChecksum = false)
0100 : fBuffer(buffer), fBufferSize(bufferSize), fNElements(nElements), fHasChecksum(hasChecksum)
0101 {
0102 }
0103 RSealedPage(const RSealedPage &other) = default;
0104 RSealedPage &operator=(const RSealedPage &other) = default;
0105 RSealedPage(RSealedPage &&other) = default;
0106 RSealedPage &operator=(RSealedPage &&other) = default;
0107
0108 const void *GetBuffer() const { return fBuffer; }
0109 void SetBuffer(const void *buffer) { fBuffer = buffer; }
0110
0111 std::size_t GetDataSize() const
0112 {
0113 assert(fBufferSize >= fHasChecksum * kNBytesPageChecksum);
0114 return fBufferSize - fHasChecksum * kNBytesPageChecksum;
0115 }
0116 std::size_t GetBufferSize() const { return fBufferSize; }
0117 void SetBufferSize(std::size_t bufferSize) { fBufferSize = bufferSize; }
0118
0119 std::uint32_t GetNElements() const { return fNElements; }
0120 void SetNElements(std::uint32_t nElements) { fNElements = nElements; }
0121
0122 bool GetHasChecksum() const { return fHasChecksum; }
0123 void SetHasChecksum(bool hasChecksum) { fHasChecksum = hasChecksum; }
0124
0125 void ChecksumIfEnabled();
0126 RResult<void> VerifyChecksumIfEnabled() const;
0127
0128 RResult<std::uint64_t> GetChecksum() const;
0129 };
0130
0131 using SealedPageSequence_t = std::deque<RSealedPage>;
0132
0133 struct RSealedPageGroup {
0134 ROOT::DescriptorId_t fPhysicalColumnId;
0135 SealedPageSequence_t::const_iterator fFirst;
0136 SealedPageSequence_t::const_iterator fLast;
0137
0138 RSealedPageGroup() = default;
0139 RSealedPageGroup(ROOT::DescriptorId_t d, SealedPageSequence_t::const_iterator b,
0140 SealedPageSequence_t::const_iterator e)
0141 : fPhysicalColumnId(d), fFirst(b), fLast(e)
0142 {
0143 }
0144 };
0145
0146 protected:
0147 ROOT::Experimental::Detail::RNTupleMetrics fMetrics;
0148
0149
0150 std::unique_ptr<ROOT::Internal::RPageAllocator> fPageAllocator;
0151
0152 std::string fNTupleName;
0153 RTaskScheduler *fTaskScheduler = nullptr;
0154 void WaitForAllTasks()
0155 {
0156 if (!fTaskScheduler)
0157 return;
0158 fTaskScheduler->Wait();
0159 }
0160
0161 public:
0162 explicit RPageStorage(std::string_view name);
0163 RPageStorage(const RPageStorage &other) = delete;
0164 RPageStorage &operator=(const RPageStorage &other) = delete;
0165 RPageStorage(RPageStorage &&other) = default;
0166 RPageStorage &operator=(RPageStorage &&other) = default;
0167 virtual ~RPageStorage();
0168
0169
0170 virtual EPageStorageType GetType() = 0;
0171
0172 struct RColumnHandle {
0173 ROOT::DescriptorId_t fPhysicalId = ROOT::kInvalidDescriptorId;
0174 ROOT::Internal::RColumn *fColumn = nullptr;
0175
0176
0177
0178 explicit operator bool() const { return fPhysicalId != ROOT::kInvalidDescriptorId && fColumn; }
0179 };
0180
0181 using ColumnHandle_t = RColumnHandle;
0182
0183
0184
0185 virtual ColumnHandle_t AddColumn(ROOT::DescriptorId_t fieldId, ROOT::Internal::RColumn &column) = 0;
0186
0187
0188 virtual void DropColumn(ColumnHandle_t columnHandle) = 0;
0189 ROOT::DescriptorId_t GetColumnId(ColumnHandle_t columnHandle) const { return columnHandle.fPhysicalId; }
0190
0191
0192
0193 virtual ROOT::Experimental::Detail::RNTupleMetrics &GetMetrics() { return fMetrics; }
0194
0195
0196 const std::string &GetNTupleName() const { return fNTupleName; }
0197
0198 void SetTaskScheduler(RTaskScheduler *taskScheduler) { fTaskScheduler = taskScheduler; }
0199 };
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211 class RWritePageMemoryManager {
0212 private:
0213 struct RColumnInfo {
0214 ROOT::Internal::RColumn *fColumn = nullptr;
0215 std::size_t fCurrentPageSize = 0;
0216 std::size_t fInitialPageSize = 0;
0217
0218 bool operator>(const RColumnInfo &other) const;
0219 };
0220
0221
0222 std::size_t fCurrentAllocatedBytes = 0;
0223
0224 std::size_t fMaxAllocatedBytes = 0;
0225
0226
0227 std::set<RColumnInfo, std::greater<RColumnInfo>> fColumnsSortedByPageSize;
0228
0229
0230
0231
0232 bool TryEvict(std::size_t targetAvailableSize, std::size_t pageSizeLimit);
0233
0234 public:
0235 explicit RWritePageMemoryManager(std::size_t maxAllocatedBytes) : fMaxAllocatedBytes(maxAllocatedBytes) {}
0236
0237
0238
0239
0240 bool TryUpdate(ROOT::Internal::RColumn &column, std::size_t newWritePageSize);
0241 };
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257 class RPageSink : public RPageStorage {
0258 public:
0259 using Callback_t = std::function<void(RPageSink &)>;
0260
0261
0262 struct RStagedCluster {
0263 std::uint64_t fNBytesWritten = 0;
0264 ROOT::NTupleSize_t fNEntries = 0;
0265
0266 struct RColumnInfo {
0267 ROOT::RClusterDescriptor::RPageRange fPageRange;
0268 ROOT::NTupleSize_t fNElements = ROOT::kInvalidNTupleIndex;
0269 std::uint32_t fCompressionSettings;
0270 bool fIsSuppressed = false;
0271 };
0272
0273 std::vector<RColumnInfo> fColumnInfos;
0274 };
0275
0276 protected:
0277 std::unique_ptr<ROOT::RNTupleWriteOptions> fOptions;
0278
0279
0280 bool fIsInitialized = false;
0281
0282
0283
0284
0285
0286 RSealedPage SealPage(const ROOT::Internal::RPage &page, const ROOT::Internal::RColumnElementBase &element);
0287
0288 private:
0289 std::vector<Callback_t> fOnDatasetCommitCallbacks;
0290 std::vector<unsigned char> fSealPageBuffer;
0291
0292
0293 RWritePageMemoryManager fWritePageMemoryManager;
0294
0295 public:
0296 RPageSink(std::string_view ntupleName, const ROOT::RNTupleWriteOptions &options);
0297
0298 RPageSink(const RPageSink &) = delete;
0299 RPageSink &operator=(const RPageSink &) = delete;
0300 RPageSink(RPageSink &&) = default;
0301 RPageSink &operator=(RPageSink &&) = default;
0302 ~RPageSink() override;
0303
0304 EPageStorageType GetType() final { return EPageStorageType::kSink; }
0305
0306 const ROOT::RNTupleWriteOptions &GetWriteOptions() const { return *fOptions; }
0307
0308 void DropColumn(ColumnHandle_t ) final {}
0309
0310 bool IsInitialized() const { return fIsInitialized; }
0311
0312
0313 virtual const ROOT::RNTupleDescriptor &GetDescriptor() const = 0;
0314
0315 virtual ROOT::NTupleSize_t GetNEntries() const = 0;
0316
0317
0318
0319 void Init(RNTupleModel &model)
0320 {
0321 if (fIsInitialized) {
0322 throw RException(R__FAIL("already initialized"));
0323 }
0324 InitImpl(model);
0325 fIsInitialized = true;
0326 }
0327
0328 protected:
0329 virtual void InitImpl(RNTupleModel &model) = 0;
0330 virtual RNTupleLink CommitDatasetImpl() = 0;
0331
0332 public:
0333
0334 struct RSealPageConfig {
0335 const ROOT::Internal::RPage *fPage = nullptr;
0336 const ROOT::Internal::RColumnElementBase *fElement =
0337 nullptr;
0338 std::uint32_t fCompressionSettings = 0;
0339
0340
0341 bool fWriteChecksum = true;
0342
0343
0344 bool fAllowAlias = false;
0345
0346 void *fBuffer = nullptr;
0347 };
0348
0349
0350 static RSealedPage SealPage(const RSealPageConfig &config);
0351
0352
0353
0354
0355 virtual void UpdateSchema(const ROOT::Internal::RNTupleModelChangeset &changeset, ROOT::NTupleSize_t firstEntry) = 0;
0356
0357
0358
0359
0360 virtual void UpdateExtraTypeInfo(const ROOT::RExtraTypeInfoDescriptor &extraTypeInfo) = 0;
0361
0362
0363
0364 virtual void CommitSuppressedColumn(ColumnHandle_t columnHandle) = 0;
0365
0366 virtual void CommitPage(ColumnHandle_t columnHandle, const ROOT::Internal::RPage &page) = 0;
0367
0368 virtual void
0369 CommitSealedPage(ROOT::DescriptorId_t physicalColumnId, const RPageStorage::RSealedPage &sealedPage) = 0;
0370
0371 virtual void CommitSealedPageV(std::span<RPageStorage::RSealedPageGroup> ranges) = 0;
0372
0373
0374
0375 virtual RStagedCluster StageCluster(ROOT::NTupleSize_t nNewEntries) = 0;
0376
0377 virtual void CommitStagedClusters(std::span<RStagedCluster> clusters) = 0;
0378
0379
0380 virtual std::uint64_t CommitCluster(ROOT::NTupleSize_t nNewEntries)
0381 {
0382 RStagedCluster stagedClusters[] = {StageCluster(nNewEntries)};
0383 CommitStagedClusters(stagedClusters);
0384 return stagedClusters[0].fNBytesWritten;
0385 }
0386
0387
0388 virtual void CommitClusterGroup() = 0;
0389
0390
0391
0392
0393
0394 virtual std::unique_ptr<RPageSink> CloneAsHidden(std::string_view name, const RNTupleWriteOptions &opts) const = 0;
0395
0396
0397
0398
0399
0400 virtual void CommitAttributeSet(std::string_view attrSetName, const RNTupleLink &attrAnchorInfo) = 0;
0401
0402
0403 void RegisterOnCommitDatasetCallback(Callback_t callback) { fOnDatasetCommitCallbacks.emplace_back(callback); }
0404
0405 RNTupleLink CommitDataset();
0406
0407
0408
0409 virtual ROOT::Internal::RPage ReservePage(ColumnHandle_t columnHandle, std::size_t nElements);
0410
0411
0412 class RSinkGuard {
0413 std::mutex *fLock;
0414
0415 public:
0416 explicit RSinkGuard(std::mutex *lock) : fLock(lock)
0417 {
0418 if (fLock != nullptr) {
0419 fLock->lock();
0420 }
0421 }
0422 RSinkGuard(const RSinkGuard &) = delete;
0423 RSinkGuard &operator=(const RSinkGuard &) = delete;
0424 RSinkGuard(RSinkGuard &&) = delete;
0425 RSinkGuard &operator=(RSinkGuard &&) = delete;
0426 ~RSinkGuard()
0427 {
0428 if (fLock != nullptr) {
0429 fLock->unlock();
0430 }
0431 }
0432 };
0433
0434 virtual RSinkGuard GetSinkGuard()
0435 {
0436
0437 return RSinkGuard(nullptr);
0438 }
0439 };
0440
0441
0442
0443
0444
0445
0446
0447
0448 class RPagePersistentSink : public RPageSink {
0449 private:
0450
0451 ROOT::Internal::RNTupleSerializer::RContext fSerializationContext;
0452
0453
0454 std::uint64_t fNextClusterInGroup = 0;
0455
0456 ROOT::NTupleSize_t fPrevClusterNEntries = 0;
0457
0458 std::vector<ROOT::RClusterDescriptor::RColumnRange> fOpenColumnRanges;
0459
0460 std::vector<ROOT::RClusterDescriptor::RPageRange> fOpenPageRanges;
0461
0462
0463 ROOT::Internal::RNTupleSerializer::StreamerInfoMap_t fInfosOfStreamerFields;
0464
0465 protected:
0466
0467 struct RFeatures {
0468 bool fCanMergePages = false;
0469 };
0470
0471 RFeatures fFeatures;
0472 ROOT::Internal::RNTupleDescriptorBuilder fDescriptorBuilder;
0473
0474
0475 struct RCounters {
0476 ROOT::Experimental::Detail::RNTupleAtomicCounter &fNPageCommitted;
0477 ROOT::Experimental::Detail::RNTupleAtomicCounter &fSzWritePayload;
0478 ROOT::Experimental::Detail::RNTupleAtomicCounter &fSzZip;
0479 ROOT::Experimental::Detail::RNTupleAtomicCounter &fTimeWallWrite;
0480 ROOT::Experimental::Detail::RNTupleAtomicCounter &fTimeWallZip;
0481 ROOT::Experimental::Detail::RNTupleTickCounter<ROOT::Experimental::Detail::RNTupleAtomicCounter> &fTimeCpuWrite;
0482 ROOT::Experimental::Detail::RNTupleTickCounter<ROOT::Experimental::Detail::RNTupleAtomicCounter> &fTimeCpuZip;
0483 };
0484 std::unique_ptr<RCounters> fCounters;
0485
0486 virtual void InitImpl(unsigned char *serializedHeader, std::uint32_t length) = 0;
0487
0488 virtual RNTupleLocator CommitPageImpl(ColumnHandle_t columnHandle, const ROOT::Internal::RPage &page) = 0;
0489 virtual RNTupleLocator
0490 CommitSealedPageImpl(ROOT::DescriptorId_t physicalColumnId, const RPageStorage::RSealedPage &sealedPage) = 0;
0491
0492
0493
0494
0495
0496
0497
0498
0499 virtual std::vector<RNTupleLocator>
0500 CommitSealedPageVImpl(std::span<RPageStorage::RSealedPageGroup> ranges, const std::vector<bool> &mask);
0501
0502 virtual std::uint64_t StageClusterImpl() = 0;
0503
0504
0505 virtual RNTupleLocator CommitClusterGroupImpl(unsigned char *serializedPageList, std::uint32_t length) = 0;
0506 virtual RNTupleLink CommitDatasetImpl(unsigned char *serializedFooter, std::uint32_t length) = 0;
0507
0508
0509
0510
0511
0512
0513
0514 void EnableDefaultMetrics(const std::string &prefix);
0515
0516 public:
0517 RPagePersistentSink(std::string_view ntupleName, const ROOT::RNTupleWriteOptions &options);
0518
0519 RPagePersistentSink(const RPagePersistentSink &) = delete;
0520 RPagePersistentSink &operator=(const RPagePersistentSink &) = delete;
0521 RPagePersistentSink(RPagePersistentSink &&) = default;
0522 RPagePersistentSink &operator=(RPagePersistentSink &&) = default;
0523 ~RPagePersistentSink() override;
0524
0525
0526 static std::unique_ptr<RPageSink> Create(std::string_view ntupleName, std::string_view location,
0527 const ROOT::RNTupleWriteOptions &options = ROOT::RNTupleWriteOptions());
0528
0529 ColumnHandle_t AddColumn(ROOT::DescriptorId_t fieldId, ROOT::Internal::RColumn &column) final;
0530
0531 const ROOT::RNTupleDescriptor &GetDescriptor() const final { return fDescriptorBuilder.GetDescriptor(); }
0532
0533 ROOT::NTupleSize_t GetNEntries() const final { return fPrevClusterNEntries; }
0534
0535
0536 void InitImpl(RNTupleModel &model) final;
0537 void UpdateSchema(const ROOT::Internal::RNTupleModelChangeset &changeset, ROOT::NTupleSize_t firstEntry) override;
0538 void UpdateExtraTypeInfo(const ROOT::RExtraTypeInfoDescriptor &extraTypeInfo) final;
0539
0540
0541
0542
0543
0544 [[nodiscard]] std::unique_ptr<RNTupleModel>
0545 InitFromDescriptor(const ROOT::RNTupleDescriptor &descriptor, bool copyClusters);
0546
0547 void CommitSuppressedColumn(ColumnHandle_t columnHandle) final;
0548 void CommitPage(ColumnHandle_t columnHandle, const ROOT::Internal::RPage &page) final;
0549 void CommitSealedPage(ROOT::DescriptorId_t physicalColumnId, const RPageStorage::RSealedPage &sealedPage) final;
0550 void CommitSealedPageV(std::span<RPageStorage::RSealedPageGroup> ranges) final;
0551 RStagedCluster StageCluster(ROOT::NTupleSize_t nNewEntries) final;
0552 void CommitStagedClusters(std::span<RStagedCluster> clusters) final;
0553 void CommitClusterGroup() final;
0554 void CommitAttributeSet(std::string_view attrSetName, const RNTupleLink &attrAnchorInfo) final;
0555
0556 RNTupleLink CommitDatasetImpl() final;
0557 };
0558
0559
0560
0561
0562
0563
0564
0565
0566
0567
0568
0569
0570 class RPageSource : public RPageStorage {
0571 public:
0572
0573 struct REntryRange {
0574 ROOT::NTupleSize_t fFirstEntry = ROOT::kInvalidNTupleIndex;
0575 ROOT::NTupleSize_t fNEntries = 0;
0576
0577
0578 bool IntersectsWith(const ROOT::RClusterDescriptor &clusterDesc) const;
0579 };
0580
0581
0582 class RSharedDescriptorGuard {
0583 const ROOT::RNTupleDescriptor &fDescriptor;
0584 std::shared_mutex &fLock;
0585
0586 public:
0587 RSharedDescriptorGuard(const ROOT::RNTupleDescriptor &desc, std::shared_mutex &lock)
0588 : fDescriptor(desc), fLock(lock)
0589 {
0590 fLock.lock_shared();
0591 }
0592 RSharedDescriptorGuard(const RSharedDescriptorGuard &) = delete;
0593 RSharedDescriptorGuard &operator=(const RSharedDescriptorGuard &) = delete;
0594 RSharedDescriptorGuard(RSharedDescriptorGuard &&) = delete;
0595 RSharedDescriptorGuard &operator=(RSharedDescriptorGuard &&) = delete;
0596 ~RSharedDescriptorGuard() { fLock.unlock_shared(); }
0597 const ROOT::RNTupleDescriptor *operator->() const { return &fDescriptor; }
0598 const ROOT::RNTupleDescriptor &GetRef() const { return fDescriptor; }
0599 };
0600
0601
0602 class RExclDescriptorGuard {
0603 ROOT::RNTupleDescriptor &fDescriptor;
0604 std::shared_mutex &fLock;
0605
0606 public:
0607 RExclDescriptorGuard(ROOT::RNTupleDescriptor &desc, std::shared_mutex &lock) : fDescriptor(desc), fLock(lock)
0608 {
0609 fLock.lock();
0610 }
0611 RExclDescriptorGuard(const RExclDescriptorGuard &) = delete;
0612 RExclDescriptorGuard &operator=(const RExclDescriptorGuard &) = delete;
0613 RExclDescriptorGuard(RExclDescriptorGuard &&) = delete;
0614 RExclDescriptorGuard &operator=(RExclDescriptorGuard &&) = delete;
0615 ~RExclDescriptorGuard()
0616 {
0617 fDescriptor.IncGeneration();
0618 fLock.unlock();
0619 }
0620 ROOT::RNTupleDescriptor *operator->() const { return &fDescriptor; }
0621 void MoveIn(ROOT::RNTupleDescriptor desc) { fDescriptor = std::move(desc); }
0622 };
0623
0624 private:
0625 ROOT::RNTupleDescriptor fDescriptor;
0626 mutable std::shared_mutex fDescriptorLock;
0627 REntryRange fEntryRange;
0628 bool fHasStructure = false;
0629 bool fIsAttached = false;
0630 bool fHasStreamerInfosRegistered = false;
0631
0632
0633 ROOT::DescriptorId_t fLastUsedCluster = ROOT::kInvalidDescriptorId;
0634
0635
0636
0637 std::map<ROOT::NTupleSize_t, ROOT::DescriptorId_t> fPreloadedClusters;
0638
0639
0640
0641
0642 void UpdateLastUsedCluster(ROOT::DescriptorId_t clusterId);
0643
0644 protected:
0645
0646 struct RCounters {
0647 ROOT::Experimental::Detail::RNTupleAtomicCounter &fNReadV;
0648 ROOT::Experimental::Detail::RNTupleAtomicCounter &fNRead;
0649 ROOT::Experimental::Detail::RNTupleAtomicCounter &fSzReadPayload;
0650 ROOT::Experimental::Detail::RNTupleAtomicCounter &fSzReadOverhead;
0651 ROOT::Experimental::Detail::RNTupleAtomicCounter &fSzUnzip;
0652 ROOT::Experimental::Detail::RNTupleAtomicCounter &fNClusterLoaded;
0653 ROOT::Experimental::Detail::RNTupleAtomicCounter &fNPageRead;
0654 ROOT::Experimental::Detail::RNTupleAtomicCounter &fNPageUnsealed;
0655 ROOT::Experimental::Detail::RNTupleAtomicCounter &fTimeWallRead;
0656 ROOT::Experimental::Detail::RNTupleAtomicCounter &fTimeWallUnzip;
0657 ROOT::Experimental::Detail::RNTupleTickCounter<ROOT::Experimental::Detail::RNTupleAtomicCounter> &fTimeCpuRead;
0658 ROOT::Experimental::Detail::RNTupleTickCounter<ROOT::Experimental::Detail::RNTupleAtomicCounter> &fTimeCpuUnzip;
0659 ROOT::Experimental::Detail::RNTupleCalcPerf &fBandwidthReadUncompressed;
0660 ROOT::Experimental::Detail::RNTupleCalcPerf &fBandwidthReadCompressed;
0661 ROOT::Experimental::Detail::RNTupleCalcPerf &fBandwidthUnzip;
0662 ROOT::Experimental::Detail::RNTupleCalcPerf &fFractionReadOverhead;
0663 ROOT::Experimental::Detail::RNTupleCalcPerf &fCompressionRatio;
0664 };
0665
0666
0667
0668 class RActivePhysicalColumns {
0669 public:
0670 struct RColumnInfo {
0671 ROOT::Internal::RColumnElementBase::RIdentifier fElementId;
0672 std::size_t fRefCounter = 0;
0673 };
0674
0675 private:
0676
0677
0678
0679
0680
0681 std::unordered_map<ROOT::DescriptorId_t, std::vector<RColumnInfo>> fColumnInfos;
0682
0683 public:
0684 void Insert(ROOT::DescriptorId_t physicalColumnId, ROOT::Internal::RColumnElementBase::RIdentifier elementId);
0685 void Erase(ROOT::DescriptorId_t physicalColumnId, ROOT::Internal::RColumnElementBase::RIdentifier elementId);
0686 ROOT::Internal::RCluster::ColumnSet_t ToColumnSet() const;
0687 bool HasColumnInfos(ROOT::DescriptorId_t physicalColumnId) const
0688 {
0689 return fColumnInfos.count(physicalColumnId) > 0;
0690 }
0691 const std::vector<RColumnInfo> &GetColumnInfos(ROOT::DescriptorId_t physicalColumnId) const
0692 {
0693 return fColumnInfos.at(physicalColumnId);
0694 }
0695 };
0696
0697
0698
0699 struct RClusterInfo {
0700 ROOT::DescriptorId_t fClusterId = 0;
0701
0702 ROOT::RClusterDescriptor::RPageInfoExtended fPageInfo;
0703
0704 std::uint64_t fColumnOffset = 0;
0705 };
0706
0707 std::unique_ptr<RCounters> fCounters;
0708
0709 ROOT::RNTupleReadOptions fOptions;
0710
0711 RActivePhysicalColumns fActivePhysicalColumns;
0712
0713
0714 std::unordered_set<ROOT::DescriptorId_t> fPinnedClusters;
0715
0716
0717
0718
0719 ROOT::Internal::RClusterPool fClusterPool;
0720
0721 ROOT::Internal::RPagePool fPagePool;
0722
0723 virtual void LoadStructureImpl() = 0;
0724
0725 virtual ROOT::RNTupleDescriptor AttachImpl(ROOT::Internal::RNTupleSerializer::EDescriptorDeserializeMode mode) = 0;
0726
0727 virtual std::unique_ptr<RPageSource> CloneImpl() const = 0;
0728
0729 virtual void UnzipClusterImpl(ROOT::Internal::RCluster *cluster);
0730
0731 virtual ROOT::Internal::RPageRef
0732 LoadPageImpl(ColumnHandle_t columnHandle, const RClusterInfo &clusterInfo, ROOT::NTupleSize_t idxInCluster) = 0;
0733
0734
0735
0736
0737 void PrepareLoadCluster(
0738 const ROOT::Internal::RCluster::RKey &clusterKey, ROOT::Internal::ROnDiskPageMap &pageZeroMap,
0739 std::function<void(ROOT::DescriptorId_t, ROOT::NTupleSize_t, const ROOT::RClusterDescriptor::RPageInfo &)>
0740 perPageFunc);
0741
0742
0743
0744
0745
0746
0747
0748 void EnableDefaultMetrics(const std::string &prefix);
0749
0750
0751 RExclDescriptorGuard GetExclDescriptorGuard() { return RExclDescriptorGuard(fDescriptor, fDescriptorLock); }
0752
0753 public:
0754 RPageSource(std::string_view ntupleName, const ROOT::RNTupleReadOptions &fOptions);
0755 RPageSource(const RPageSource &) = delete;
0756 RPageSource &operator=(const RPageSource &) = delete;
0757 RPageSource(RPageSource &&) = delete;
0758 RPageSource &operator=(RPageSource &&) = delete;
0759 ~RPageSource() override;
0760
0761 static std::unique_ptr<RPageSource> Create(std::string_view ntupleName, std::string_view location,
0762 const ROOT::RNTupleReadOptions &options = ROOT::RNTupleReadOptions());
0763
0764
0765
0766 std::unique_ptr<RPageSource> Clone() const;
0767
0768
0769
0770
0771 RResult<ROOT::Internal::RPage> static UnsealPage(const RSealedPage &sealedPage,
0772 const ROOT::Internal::RColumnElementBase &element,
0773 ROOT::Internal::RPageAllocator &pageAlloc);
0774
0775 EPageStorageType GetType() final { return EPageStorageType::kSource; }
0776 const ROOT::RNTupleReadOptions &GetReadOptions() const { return fOptions; }
0777
0778
0779
0780
0781
0782
0783
0784 const RSharedDescriptorGuard GetSharedDescriptorGuard() const
0785 {
0786 return RSharedDescriptorGuard(fDescriptor, fDescriptorLock);
0787 }
0788
0789 ColumnHandle_t AddColumn(ROOT::DescriptorId_t fieldId, ROOT::Internal::RColumn &column) override;
0790 void DropColumn(ColumnHandle_t columnHandle) override;
0791
0792
0793
0794
0795
0796 void LoadStructure();
0797
0798 void Attach(ROOT::Internal::RNTupleSerializer::EDescriptorDeserializeMode mode =
0799 ROOT::Internal::RNTupleSerializer::EDescriptorDeserializeMode::kForReading);
0800 ROOT::NTupleSize_t GetNEntries();
0801 ROOT::NTupleSize_t GetNElements(ColumnHandle_t columnHandle);
0802
0803
0804
0805 void SetEntryRange(const REntryRange &range);
0806 REntryRange GetEntryRange() const { return fEntryRange; }
0807
0808
0809
0810 virtual ROOT::Internal::RPageRef LoadPage(ColumnHandle_t columnHandle, ROOT::NTupleSize_t globalIndex);
0811
0812
0813 virtual ROOT::Internal::RPageRef LoadPage(ColumnHandle_t columnHandle, RNTupleLocalIndex localIndex);
0814
0815
0816
0817
0818
0819
0820 virtual void
0821 LoadSealedPage(ROOT::DescriptorId_t physicalColumnId, RNTupleLocalIndex localIndex, RSealedPage &sealedPage) = 0;
0822
0823
0824
0825
0826
0827
0828
0829
0830 virtual std::vector<std::unique_ptr<ROOT::Internal::RCluster>>
0831 LoadClusters(std::span<ROOT::Internal::RCluster::RKey> clusterKeys) = 0;
0832
0833
0834
0835
0836
0837
0838 void UnzipCluster(ROOT::Internal::RCluster *cluster);
0839
0840
0841 void PinCluster(ROOT::DescriptorId_t clusterId) { fPinnedClusters.insert(clusterId); }
0842
0843 void UnpinCluster(ROOT::DescriptorId_t clusterId) { fPinnedClusters.erase(clusterId); }
0844 const std::unordered_set<ROOT::DescriptorId_t> &GetPinnedClusters() const { return fPinnedClusters; }
0845
0846
0847 RResult<ROOT::Internal::RPage>
0848 UnsealPage(const RSealedPage &sealedPage, const ROOT::Internal::RColumnElementBase &element);
0849
0850
0851
0852 void RegisterStreamerInfos();
0853
0854
0855
0856 virtual void LoadStreamerInfo() = 0;
0857
0858
0859
0860 virtual std::unique_ptr<RPageSource> OpenWithDifferentAnchor(const ROOT::Internal::RNTupleLink &anchorLink,
0861 const ROOT::RNTupleReadOptions &options = {}) = 0;
0862 };
0863
0864 }
0865 }
0866
0867 #endif