33static constexpr const char* kKeySeparator =
"_";
34static constexpr const char* kKeyNTupleFooter =
"NTPLF";
35static constexpr const char* kKeyNTupleHeader =
"NTPLH";
36static constexpr const char* kKeyPagePayload =
"NTPLP";
43 , fMetrics(
"RPageSinkRoot")
47 "Do not store real data with this version of RNTuple!";
48 fFile = std::unique_ptr<TFile>(
TFile::Open(std::string(path).c_str(),
"RECREATE"));
60 fDirectory = fFile->mkdir(fNTupleName.c_str());
62 const auto &descriptor = fDescriptorBuilder.GetDescriptor();
63 auto szHeader = descriptor.SerializeHeader(
nullptr);
64 auto buffer =
new unsigned char[szHeader];
65 descriptor.SerializeHeader(buffer);
67 fDirectory->WriteObject(&blob, kKeyNTupleHeader);
74 unsigned char *buffer =
reinterpret_cast<unsigned char *
>(page.
GetBuffer());
75 auto packedBytes = page.
GetSize();
80 packedBytes = (page.
GetNElements() * element->GetBitsOnStorage() + 7) / 8;
81 buffer =
new unsigned char[packedBytes];
86 std::string keyName = std::string(kKeyPagePayload) +
87 std::to_string(fLastClusterId) + kKeySeparator +
88 std::to_string(fLastPageIdx);
89 fDirectory->WriteObject(&pagePayload, keyName.c_str());
113 const auto &descriptor = fDescriptorBuilder.GetDescriptor();
114 auto szFooter = descriptor.SerializeFooter(
nullptr);
115 auto buffer =
new unsigned char[szFooter];
116 descriptor.SerializeFooter(buffer);
118 fDirectory->WriteObject(&footerBlob, kKeyNTupleFooter);
126 nElements = kDefaultElementsPerPage;
128 return fPageAllocator->NewPage(columnHandle.
fId, elementSize, nElements);
133 fPageAllocator->DeletePage(page);
141 ColumnId_t columnId,
void *mem, std::size_t elementSize, std::size_t nElements)
143 RPage newPage(columnId, mem, elementSize * nElements, elementSize);
165 , fMetrics(
"RPageSourceRoot")
167 , fPagePool(std::make_shared<
RPagePool>())
169 fFile = std::unique_ptr<TFile>(
TFile::Open(std::string(path).c_str(),
"READ"));
182 fDirectory = fFile->GetDirectory(fNTupleName.c_str());
185 auto keyRawNTupleHeader = fDirectory->GetKey(kKeyNTupleHeader);
188 free(ntupleRawHeader->fContent);
189 delete ntupleRawHeader;
191 auto keyRawNTupleFooter = fDirectory->GetKey(kKeyNTupleFooter);
194 free(ntupleRawFooter->fContent);
195 delete ntupleRawFooter;
204 auto columnId = columnHandle.
fId;
205 auto clusterId = clusterDescriptor.
GetId();
206 const auto &pageRange = clusterDescriptor.
GetPageRange(columnId);
210 decltype(clusterIndex) firstInPage = 0;
211 for (
const auto &
pi : pageRange.fPageInfos) {
212 if (firstInPage +
pi.fNElements > clusterIndex) {
216 firstInPage +=
pi.fNElements;
223 std::string keyName = std::string(kKeyPagePayload) +
224 std::to_string(clusterId) + kKeySeparator +
226 auto pageKey = fDirectory->GetKey(keyName.c_str());
229 unsigned char *buffer = pagePayload->
fContent;
231 auto elementSize = element->
GetSize();
232 if (!element->IsMappable()) {
233 auto pageSize = elementSize * pageInfo.
fNElements;
234 buffer =
reinterpret_cast<unsigned char *
>(
malloc(pageSize));
236 element->Unpack(buffer, pagePayload->fContent, pageInfo.
fNElements);
237 free(pagePayload->fContent);
238 pagePayload->fContent = buffer;
239 pagePayload->fSize = pageSize;
243 auto newPage = fPageAllocator->NewPage(columnId, pagePayload->fContent, elementSize, pageInfo.
fNElements);
245 fPagePool->RegisterPage(newPage,
257 auto columnId = columnHandle.
fId;
258 auto cachedPage = fPagePool->GetPage(columnId, globalIndex);
259 if (!cachedPage.IsNull())
262 auto clusterId = fDescriptor.FindClusterId(columnId, globalIndex);
264 const auto &clusterDescriptor = fDescriptor.GetClusterDescriptor(clusterId);
265 auto selfOffset = clusterDescriptor.GetColumnRange(columnId).fFirstElementIndex;
267 return PopulatePageFromCluster(columnHandle, clusterDescriptor, globalIndex - selfOffset);
275 auto index = clusterIndex.
GetIndex();
276 auto columnId = columnHandle.
fId;
277 auto cachedPage = fPagePool->GetPage(columnId, clusterIndex);
278 if (!cachedPage.IsNull())
282 const auto &clusterDescriptor = fDescriptor.GetClusterDescriptor(clusterId);
283 return PopulatePageFromCluster(columnHandle, clusterDescriptor, index);
288 fPagePool->ReturnPage(page);
293 return std::make_unique<RPageSourceRoot>(fNTupleName, fFile->GetName(), fOptions);
#define R__WARNING_HERE(GROUP)
virtual bool IsMappable() const
Derived, typed classes tell whether the on-storage layout is bitwise identical to the memory layout.
std::size_t GetSize() const
RColumnElementBase * GetElement() const
Uses standard C++ memory allocation for the column data pages.
Adopts the memory returned by TKey->ReadObject()
static RPage NewPage(ColumnId_t columnId, void *mem, std::size_t elementSize, std::size_t nElements)
static void DeletePage(const RPage &page, ROOT::Experimental::Internal::RNTupleBlob *payload)
A closure that can free the memory associated with a mapped page.
A thread-safe cache of column pages.
void DoCreate(const RNTupleModel &model) final
RClusterDescriptor::RLocator DoCommitCluster(NTupleSize_t nEntries) final
std::unique_ptr< TFile > fFile
Currently, an ntuple is stored as a directory in a TFile.
void ReleasePage(RPage &page) final
Every page store needs to be able to free pages it handed out.
RPageSinkRoot(std::string_view ntupleName, std::string_view path, const RNTupleWriteOptions &options)
RClusterDescriptor::RLocator DoCommitPage(ColumnHandle_t columnHandle, const RPage &page) final
RPage ReservePage(ColumnHandle_t columnHandle, std::size_t nElements=0) final
Get a new, empty page for the given column that can be filled with up to nElements.
void DoCommitDataset() final
Abstract interface to write data into an ntuple.
const RNTupleWriteOptions fOptions
std::unique_ptr< TFile > fFile
Currently, an ntuple is stored as a directory in a TFile.
RPage PopulatePage(ColumnHandle_t columnHandle, NTupleSize_t globalIndex) final
Allocates and fills a page that contains the index-th element.
std::unique_ptr< RPageSource > Clone() const final
Open the same storage multiple time, e.g. for reading in multiple threads.
virtual ~RPageSourceRoot()
RPageSourceRoot(std::string_view ntupleName, std::string_view path, const RNTupleReadOptions &options)
RPage PopulatePageFromCluster(ColumnHandle_t columnHandle, const RClusterDescriptor &clusterDescriptor, ClusterSize_t::ValueType clusterIndex)
void ReleasePage(RPage &page) final
Every page store needs to be able to free pages it handed out.
RNTupleDescriptor DoAttach() final
Abstract interface to read data from an ntuple.
Stores information about the cluster in which this page resides.
A page is a slice of a column that is mapped into memory.
ClusterSize_t::ValueType GetNElements() const
void * TryGrow(ClusterSize_t::ValueType nElements)
Return a pointer after the last element that has space for nElements new elements.
ClusterSize_t::ValueType GetSize() const
The space taken by column elements in the buffer.
Meta-data for a set of ntuple clusters.
const RPageRange & GetPageRange(DescriptorId_t columnId) const
const RColumnRange & GetColumnRange(DescriptorId_t columnId) const
DescriptorId_t GetId() const
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
A helper class for piece-wise construction of an RNTupleDescriptor.
RNTupleDescriptor MoveDescriptor()
void SetFromHeader(void *headerBuffer)
void AddClustersFromFooter(void *footerBuffer)
The on-storage meta-data of an ntuple.
The RNTupleModel encapulates the schema of an ntuple.
Common user-tunable settings for reading ntuples.
Common user-tunable settings for storing ntuples.
int GetCompression() const
static TFile * Open(const char *name, Option_t *option="", const char *ftitle="", Int_t compress=ROOT::RCompressionSetting::EDefaults::kUseCompiledDefault, Int_t netopt=0)
Create / open a file.
basic_string_view< char > string_view
std::uint64_t NTupleSize_t
Integer type long enough to hold the maximum number of entries in a column.
std::int64_t ColumnId_t
Uniquely identifies a physical column within the scope of the current process, used to tag pages.
constexpr DescriptorId_t kInvalidDescriptorId
static constexpr double pi
NTupleSize_t fFirstElementIndex
A 64bit element index.
Generic information about the physical location of data.
std::uint32_t fBytesOnStorage