Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RPageSourceFriends.cxx
Go to the documentation of this file.
1/// \file RPageSourceFriends.cxx
2/// \ingroup NTuple ROOT7
3/// \author Jakob Blomer <jblomer@cern.ch>
4/// \date 2019-08-10
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-2020, 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#include <ROOT/RCluster.hxx>
17#include <ROOT/RError.hxx>
18#include <ROOT/RLogger.hxx>
21
22#include <utility>
23
25 std::string_view ntupleName, std::span<std::unique_ptr<RPageSource>> sources)
26 : RPageSource(ntupleName, RNTupleReadOptions())
27 , fMetrics(std::string(ntupleName))
28{
29 for (auto &s : sources) {
30 fSources.emplace_back(std::move(s));
31 fMetrics.ObserveMetrics(fSources.back()->GetMetrics());
32 }
33}
34
36
38 std::size_t originIdx,
39 const RFieldDescriptor &originField,
40 DescriptorId_t virtualParent,
41 const std::string &virtualName)
42{
43 auto virtualFieldId = fNextId++;
44 auto virtualField = RFieldDescriptorBuilder(originField)
45 .FieldId(virtualFieldId)
46 .FieldName(virtualName)
47 .MakeDescriptor().Unwrap();
48 fBuilder.AddField(virtualField);
49 fBuilder.AddFieldLink(virtualParent, virtualFieldId);
50 fIdBiMap.Insert({originIdx, originField.GetId()}, virtualFieldId);
51
52 for (const auto &f : originDesc.GetFieldIterable(originField))
53 AddVirtualField(originDesc, originIdx, f, virtualFieldId, f.GetFieldName());
54
55 for (const auto &c: originDesc.GetColumnIterable(originField)) {
56 auto physicalId = c.IsAliasColumn() ? fIdBiMap.GetVirtualId({originIdx, c.GetPhysicalId()}) : fNextId;
57 fBuilder.AddColumn(fNextId, physicalId, virtualFieldId, c.GetModel(), c.GetIndex());
58 fIdBiMap.Insert({originIdx, c.GetLogicalId()}, fNextId);
59 fNextId++;
60 }
61}
62
63
65{
66 fBuilder.SetNTuple(fNTupleName, "");
67 fBuilder.AddField(RFieldDescriptorBuilder()
68 .FieldId(0)
70 .MakeDescriptor()
71 .Unwrap());
72
73 for (std::size_t i = 0; i < fSources.size(); ++i) {
74 fSources[i]->Attach();
75
76 if (fSources[i]->GetNEntries() != fSources[0]->GetNEntries()) {
77 fNextId = 1;
78 fIdBiMap.Clear();
79 fBuilder.Reset();
80 throw RException(R__FAIL("mismatch in the number of entries of friend RNTuples"));
81 }
82
83 auto descriptorGuard = fSources[i]->GetSharedDescriptorGuard();
84 for (unsigned j = 0; j < i; ++j) {
85 if (fSources[j]->GetSharedDescriptorGuard()->GetName() == descriptorGuard->GetName()) {
86 fNextId = 1;
87 fIdBiMap.Clear();
88 fBuilder.Reset();
89 throw RException(R__FAIL("duplicate names of friend RNTuples"));
90 }
91 }
92 AddVirtualField(descriptorGuard.GetRef(), i, descriptorGuard->GetFieldZero(), 0, descriptorGuard->GetName());
93
94 for (const auto &c : descriptorGuard->GetClusterIterable()) {
95 RClusterDescriptorBuilder clusterBuilder(fNextId, c.GetFirstEntryIndex(), c.GetNEntries());
96 for (auto originColumnId : c.GetColumnIds()) {
97 DescriptorId_t virtualColumnId = fIdBiMap.GetVirtualId({i, originColumnId});
98
99 auto pageRange = c.GetPageRange(originColumnId).Clone();
100 pageRange.fPhysicalColumnId = virtualColumnId;
101
102 auto firstElementIndex = c.GetColumnRange(originColumnId).fFirstElementIndex;
103 auto compressionSettings = c.GetColumnRange(originColumnId).fCompressionSettings;
104
105 clusterBuilder.CommitColumnRange(virtualColumnId, firstElementIndex, compressionSettings, pageRange);
106 }
107 fBuilder.AddClusterWithDetails(clusterBuilder.MoveDescriptor().Unwrap());
108 fIdBiMap.Insert({i, c.GetId()}, fNextId);
109 fNextId++;
110 }
111 }
112
113 fBuilder.EnsureValidDescriptor();
114 return fBuilder.MoveDescriptor();
115}
116
117
118std::unique_ptr<ROOT::Experimental::Detail::RPageSource>
120{
121 std::vector<std::unique_ptr<RPageSource>> cloneSources;
122 for (const auto &f : fSources)
123 cloneSources.emplace_back(f->Clone());
124 return std::make_unique<RPageSourceFriends>(fNTupleName, cloneSources);
125}
126
127
130{
131 auto originFieldId = fIdBiMap.GetOriginId(fieldId);
132 fSources[originFieldId.fSourceIdx]->AddColumn(originFieldId.fId, column);
133 return RPageSource::AddColumn(fieldId, column);
134}
135
137{
138 RPageSource::DropColumn(columnHandle);
139 auto originColumnId = fIdBiMap.GetOriginId(columnHandle.fPhysicalId);
140 columnHandle.fPhysicalId = originColumnId.fId;
141 fSources[originColumnId.fSourceIdx]->DropColumn(columnHandle);
142}
143
144
147 ColumnHandle_t columnHandle, NTupleSize_t globalIndex)
148{
149 auto virtualColumnId = columnHandle.fPhysicalId;
150 auto originColumnId = fIdBiMap.GetOriginId(virtualColumnId);
151 columnHandle.fPhysicalId = originColumnId.fId;
152
153 auto page = fSources[originColumnId.fSourceIdx]->PopulatePage(columnHandle, globalIndex);
154
155 auto virtualClusterId = fIdBiMap.GetVirtualId({originColumnId.fSourceIdx, page.GetClusterInfo().GetId()});
156 page.ChangeIds(virtualColumnId, virtualClusterId);
157
158 return page;
159}
160
161
164 ColumnHandle_t columnHandle, const RClusterIndex &clusterIndex)
165{
166 auto virtualColumnId = columnHandle.fPhysicalId;
167 auto originColumnId = fIdBiMap.GetOriginId(virtualColumnId);
168 RClusterIndex originClusterIndex(
169 fIdBiMap.GetOriginId(clusterIndex.GetClusterId()).fId,
170 clusterIndex.GetIndex());
171 columnHandle.fPhysicalId = originColumnId.fId;
172
173 auto page = fSources[originColumnId.fSourceIdx]->PopulatePage(columnHandle, originClusterIndex);
174
175 page.ChangeIds(virtualColumnId, clusterIndex.GetClusterId());
176 return page;
177}
178
180 const RClusterIndex &clusterIndex,
181 RSealedPage &sealedPage)
182{
183 auto originColumnId = fIdBiMap.GetOriginId(physicalColumnId);
184 RClusterIndex originClusterIndex(
185 fIdBiMap.GetOriginId(clusterIndex.GetClusterId()).fId,
186 clusterIndex.GetIndex());
187
188 fSources[originColumnId.fSourceIdx]->LoadSealedPage(physicalColumnId, originClusterIndex, sealedPage);
189}
190
191
193{
194 if (page.IsNull())
195 return;
196 auto sourceIdx = fIdBiMap.GetOriginId(page.GetClusterInfo().GetId()).fSourceIdx;
197 fSources[sourceIdx]->ReleasePage(page);
198}
199
200
201std::vector<std::unique_ptr<ROOT::Experimental::Detail::RCluster>>
203{
204 // The virtual friends page source does not pre-load any clusters itself. However, the underlying page sources
205 // that are combined may well do it.
206 return std::vector<std::unique_ptr<ROOT::Experimental::Detail::RCluster>>(clusterKeys.size());
207}
#define R__FAIL(msg)
Short-hand to return an RResult<T> in an error state; the RError is implicitly converted into RResult...
Definition RError.hxx:303
#define f(i)
Definition RSha256.hxx:104
#define c(i)
Definition RSha256.hxx:101
void ObserveMetrics(RNTupleMetrics &observee)
void LoadSealedPage(DescriptorId_t physicalColumnId, const RClusterIndex &clusterIndex, RSealedPage &sealedPage) final
Read the packed and compressed bytes of a page into the memory buffer provided by selaedPage.
std::unique_ptr< RPageSource > Clone() const final
Open the same storage multiple time, e.g. for reading in multiple threads.
void ReleasePage(RPage &page) final
Every page store needs to be able to free pages it handed out.
std::vector< std::unique_ptr< RPageSource > > fSources
std::vector< std::unique_ptr< RCluster > > LoadClusters(std::span< RCluster::RKey > clusterKeys) final
Populates all the pages of the given cluster ids and columns; it is possible that some columns do not...
void AddVirtualField(const RNTupleDescriptor &originDesc, std::size_t originIdx, const RFieldDescriptor &originField, DescriptorId_t virtualParent, const std::string &virtualName)
RPage PopulatePage(ColumnHandle_t columnHandle, NTupleSize_t globalIndex) final
Allocates and fills a page that contains the index-th element.
RPageSourceFriends(std::string_view ntupleName, std::span< std::unique_ptr< RPageSource > > sources)
void DropColumn(ColumnHandle_t columnHandle) final
Unregisters a column.
ColumnHandle_t AddColumn(DescriptorId_t fieldId, const RColumn &column) final
Register a new column.
Abstract interface to read data from an ntuple.
void DropColumn(ColumnHandle_t columnHandle) override
Unregisters a column.
ColumnHandle_t AddColumn(DescriptorId_t fieldId, const RColumn &column) override
Register a new column.
A page is a slice of a column that is mapped into memory.
Definition RPage.hxx:42
const RClusterInfo & GetClusterInfo() const
Definition RPage.hxx:94
A helper class for piece-wise construction of an RClusterDescriptor.
RResult< void > CommitColumnRange(DescriptorId_t physicalId, std::uint64_t firstElementIndex, std::uint32_t compressionSettings, const RClusterDescriptor::RPageRange &pageRange)
RResult< RClusterDescriptor > MoveDescriptor()
Move out the full cluster descriptor including page locations.
Addresses a column element or field item relative to a particular cluster, instead of a global NTuple...
DescriptorId_t GetClusterId() const
ClusterSize_t::ValueType GetIndex() const
Base class for all ROOT issued exceptions.
Definition RError.hxx:78
A helper class for piece-wise construction of an RFieldDescriptor.
RFieldDescriptorBuilder & FieldName(const std::string &fieldName)
RResult< RFieldDescriptor > MakeDescriptor() const
Attempt to make a field descriptor.
RFieldDescriptorBuilder & FieldId(DescriptorId_t fieldId)
Meta-data stored for every field of an ntuple.
The on-storage meta-data of an ntuple.
RFieldDescriptorIterable GetFieldIterable(const RFieldDescriptor &fieldDesc) const
RColumnDescriptorIterable GetColumnIterable() const
Common user-tunable settings for reading ntuples.
std::uint64_t NTupleSize_t
Integer type long enough to hold the maximum number of entries in a column.
std::uint64_t DescriptorId_t
Distriniguishes elements of the same type within a descriptor, e.g. different fields.
A sealed page contains the bytes of a page as written to storage (packed & compressed).