Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RPageStorageDaos.cxx
Go to the documentation of this file.
1/// \file RPageStorageDaos.cxx
2/// \ingroup NTuple ROOT7
3/// \author Javier Lopez-Gomez <j.lopez@cern.ch>
4/// \date 2020-11-03
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-2021, 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/RClusterPool.hxx>
18#include <ROOT/RField.hxx>
19#include <ROOT/RLogger.hxx>
21#include <ROOT/RNTupleModel.hxx>
23#include <ROOT/RNTupleUtil.hxx>
24#include <ROOT/RNTupleZip.hxx>
25#include <ROOT/RPage.hxx>
27#include <ROOT/RPagePool.hxx>
28#include <ROOT/RDaos.hxx>
30
31#include <RVersion.h>
32#include <TError.h>
33
34#include <algorithm>
35#include <cstdio>
36#include <cstdlib>
37#include <limits>
38#include <utility>
39#include <regex>
40#include <cassert>
41
42namespace {
45
46/// \brief RNTuple page-DAOS mappings
47enum EDaosMapping { kOidPerCluster, kOidPerPage };
48
49struct RDaosKey {
50 daos_obj_id_t fOid;
51 DistributionKey_t fDkey;
52 AttributeKey_t fAkey;
53};
54
55/// \brief Pre-defined keys for object store. `kDistributionKeyDefault` is the distribution key for metadata and
56/// pagelist values; optionally it can be used for ntuple pages (if under the `kOidPerPage` mapping strategy).
57/// `kAttributeKeyDefault` is the attribute key for ntuple pages under `kOidPerPage`.
58/// `kAttributeKey{Anchor,Header,Footer}` are the respective attribute keys for anchor/header/footer metadata elements.
59static constexpr DistributionKey_t kDistributionKeyDefault = 0x5a3c69f0cafe4a11;
60static constexpr AttributeKey_t kAttributeKeyDefault = 0x4243544b53444229;
61static constexpr AttributeKey_t kAttributeKeyAnchor = 0x4243544b5344422a;
62static constexpr AttributeKey_t kAttributeKeyHeader = 0x4243544b5344422b;
63static constexpr AttributeKey_t kAttributeKeyFooter = 0x4243544b5344422c;
64
65/// \brief Pre-defined 64 LSb of the OIDs for ntuple metadata (holds anchor/header/footer) and clusters' pagelists.
66static constexpr decltype(daos_obj_id_t::lo) kOidLowMetadata = -1;
67static constexpr decltype(daos_obj_id_t::lo) kOidLowPageList = -2;
68
69static constexpr daos_oclass_id_t kCidMetadata = OC_SX;
70
71static constexpr EDaosMapping kDefaultDaosMapping = kOidPerCluster;
72
73template <EDaosMapping mapping>
74RDaosKey GetPageDaosKey(ROOT::Experimental::Detail::ntuple_index_t ntplId, long unsigned clusterId,
75 long unsigned columnId, long unsigned pageCount)
76{
77 if constexpr (mapping == kOidPerCluster) {
78 return RDaosKey{daos_obj_id_t{static_cast<decltype(daos_obj_id_t::lo)>(clusterId),
79 static_cast<decltype(daos_obj_id_t::hi)>(ntplId)},
80 static_cast<DistributionKey_t>(columnId), static_cast<AttributeKey_t>(pageCount)};
81 } else if constexpr (mapping == kOidPerPage) {
82 return RDaosKey{daos_obj_id_t{static_cast<decltype(daos_obj_id_t::lo)>(pageCount),
83 static_cast<decltype(daos_obj_id_t::hi)>(ntplId)},
84 kDistributionKeyDefault, kAttributeKeyDefault};
85 }
86}
87
88struct RDaosURI {
89 /// \brief Label of the DAOS pool
90 std::string fPoolLabel;
91 /// \brief Label of the container for this RNTuple
92 std::string fContainerLabel;
93};
94
95/**
96 \brief Parse a DAOS RNTuple URI of the form 'daos://pool_id/container_id'.
97*/
98RDaosURI ParseDaosURI(std::string_view uri)
99{
100 std::regex re("daos://([^/]+)/(.+)");
101 std::cmatch m;
102 if (!std::regex_match(uri.data(), m, re))
103 throw ROOT::Experimental::RException(R__FAIL("Invalid DAOS pool URI."));
104 return {m[1], m[2]};
105}
106
107/// \brief Unpacks a 64-bit RNTuple page locator address for object stores into a pair of 32-bit values:
108/// the attribute key under which the cage is stored and the offset within that cage to access the page.
109std::pair<uint32_t, uint32_t> DecodeDaosPagePosition(const ROOT::Experimental::RNTupleLocatorObject64 &address)
110{
111 auto position = static_cast<uint32_t>(address.fLocation & 0xFFFFFFFF);
112 auto offset = static_cast<uint32_t>(address.fLocation >> 32);
113 return {position, offset};
114}
115
116/// \brief Packs an attribute key together with an offset within its contents into a single 64-bit address.
117/// The offset is kept in the MSb half and defaults to zero, which is the case when caging is disabled.
118ROOT::Experimental::RNTupleLocatorObject64 EncodeDaosPagePosition(uint64_t position, uint64_t offset = 0)
119{
120 uint64_t address = (position & 0xFFFFFFFF) | (offset << 32);
122}
123} // namespace
124
125////////////////////////////////////////////////////////////////////////////////
126
128{
129 using RNTupleSerializer = ROOT::Experimental::Internal::RNTupleSerializer;
130 if (buffer != nullptr) {
131 auto bytes = reinterpret_cast<unsigned char *>(buffer);
132 bytes += RNTupleSerializer::SerializeUInt32(fVersion, bytes);
133 bytes += RNTupleSerializer::SerializeUInt32(fNBytesHeader, bytes);
134 bytes += RNTupleSerializer::SerializeUInt32(fLenHeader, bytes);
135 bytes += RNTupleSerializer::SerializeUInt32(fNBytesFooter, bytes);
136 bytes += RNTupleSerializer::SerializeUInt32(fLenFooter, bytes);
137 bytes += RNTupleSerializer::SerializeString(fObjClass, bytes);
138 }
139 return RNTupleSerializer::SerializeString(fObjClass, nullptr) + 20;
140}
141
143ROOT::Experimental::Detail::RDaosNTupleAnchor::Deserialize(const void *buffer, std::uint32_t bufSize)
144{
145 if (bufSize < 20)
146 return R__FAIL("DAOS anchor too short");
147
148 using RNTupleSerializer = ROOT::Experimental::Internal::RNTupleSerializer;
149 auto bytes = reinterpret_cast<const unsigned char *>(buffer);
150 bytes += RNTupleSerializer::DeserializeUInt32(bytes, fVersion);
151 bytes += RNTupleSerializer::DeserializeUInt32(bytes, fNBytesHeader);
152 bytes += RNTupleSerializer::DeserializeUInt32(bytes, fLenHeader);
153 bytes += RNTupleSerializer::DeserializeUInt32(bytes, fNBytesFooter);
154 bytes += RNTupleSerializer::DeserializeUInt32(bytes, fLenFooter);
155 auto result = RNTupleSerializer::DeserializeString(bytes, bufSize - 20, fObjClass);
156 if (!result)
157 return R__FORWARD_ERROR(result);
158 return result.Unwrap() + 20;
159}
160
162{
163 return RDaosNTupleAnchor().Serialize(nullptr) +
165}
166
170{
171 std::unique_ptr<unsigned char[]> buffer, zipBuffer;
172 auto &anchor = fAnchor.emplace();
173 int err;
174
176 daos_obj_id_t oidMetadata{kOidLowMetadata, static_cast<decltype(daos_obj_id_t::hi)>(this->GetIndex())};
177
178 buffer = std::make_unique<unsigned char[]>(anchorSize);
179 if ((err = cont.ReadSingleAkey(buffer.get(), anchorSize, oidMetadata, kDistributionKeyDefault, kAttributeKeyAnchor,
180 kCidMetadata)))
181 return err;
182
183 anchor.Deserialize(buffer.get(), anchorSize).Unwrap();
184
185 builder.SetOnDiskHeaderSize(anchor.fNBytesHeader);
186 buffer = std::make_unique<unsigned char[]>(anchor.fLenHeader);
187 zipBuffer = std::make_unique<unsigned char[]>(anchor.fNBytesHeader);
188 if ((err = cont.ReadSingleAkey(zipBuffer.get(), anchor.fNBytesHeader, oidMetadata, kDistributionKeyDefault,
189 kAttributeKeyHeader, kCidMetadata)))
190 return err;
191 decompressor.Unzip(zipBuffer.get(), anchor.fNBytesHeader, anchor.fLenHeader, buffer.get());
192 ROOT::Experimental::Internal::RNTupleSerializer::DeserializeHeaderV1(buffer.get(), anchor.fLenHeader, builder);
193
194 builder.AddToOnDiskFooterSize(anchor.fNBytesFooter);
195 buffer = std::make_unique<unsigned char[]>(anchor.fLenFooter);
196 zipBuffer = std::make_unique<unsigned char[]>(anchor.fNBytesFooter);
197 if ((err = cont.ReadSingleAkey(zipBuffer.get(), anchor.fNBytesFooter, oidMetadata, kDistributionKeyDefault,
198 kAttributeKeyFooter, kCidMetadata)))
199 return err;
200 decompressor.Unzip(zipBuffer.get(), anchor.fNBytesFooter, anchor.fLenFooter, buffer.get());
201 ROOT::Experimental::Internal::RNTupleSerializer::DeserializeFooterV1(buffer.get(), anchor.fLenFooter, builder);
202
203 return 0;
204}
205
206std::pair<ROOT::Experimental::Detail::RDaosContainerNTupleLocator, ROOT::Experimental::RNTupleDescriptorBuilder>
208 const std::string &ntupleName,
209 RNTupleDecompressor &decompressor)
210{
211 auto result = std::make_pair(RDaosContainerNTupleLocator(ntupleName), RNTupleDescriptorBuilder());
212
213 auto &loc = result.first;
214 auto &builder = result.second;
215
216 if (int err = loc.InitNTupleDescriptorBuilder(cont, decompressor, builder); !err) {
217 if (ntupleName.empty() || ntupleName != builder.GetDescriptor().GetName()) {
218 // Hash already taken by a differently-named ntuple.
220 R__FAIL("LocateNTuple: ntuple name '" + ntupleName + "' unavailable in this container."));
221 }
222 }
223 return result;
224}
225
226////////////////////////////////////////////////////////////////////////////////
227
228ROOT::Experimental::Detail::RPageSinkDaos::RPageSinkDaos(std::string_view ntupleName, std::string_view uri,
229 const RNTupleWriteOptions &options)
230 : RPageSink(ntupleName, options), fPageAllocator(std::make_unique<RPageAllocatorHeap>()), fURI(uri)
231{
232 R__LOG_WARNING(NTupleLog()) << "The DAOS backend is experimental and still under development. "
233 << "Do not store real data with this version of RNTuple!";
234 fCompressor = std::make_unique<RNTupleCompressor>();
235 EnableDefaultMetrics("RPageSinkDaos");
236}
237
239
241 unsigned char *serializedHeader, std::uint32_t length)
242{
243 auto opts = dynamic_cast<RNTupleWriteOptionsDaos *>(fOptions.get());
244 fNTupleAnchor.fObjClass = opts ? opts->GetObjectClass() : RNTupleWriteOptionsDaos().GetObjectClass();
245 auto oclass = RDaosObject::ObjClassId(fNTupleAnchor.fObjClass);
246 if (oclass.IsUnknown())
247 throw ROOT::Experimental::RException(R__FAIL("Unknown object class " + fNTupleAnchor.fObjClass));
248
249 size_t cageSz = opts ? opts->GetMaxCageSize() : RNTupleWriteOptionsDaos().GetMaxCageSize();
250 size_t pageSz = opts ? opts->GetApproxUnzippedPageSize() : RNTupleWriteOptionsDaos().GetApproxUnzippedPageSize();
251 fCageSizeLimit = std::max(cageSz, pageSz);
252
253 auto args = ParseDaosURI(fURI);
254 auto pool = std::make_shared<RDaosPool>(args.fPoolLabel);
255
256 fDaosContainer = std::make_unique<RDaosContainer>(pool, args.fContainerLabel, /*create =*/true);
257 fDaosContainer->SetDefaultObjectClass(oclass);
258
259 RNTupleDecompressor decompressor;
260 auto [locator, _] = RDaosContainerNTupleLocator::LocateNTuple(*fDaosContainer, fNTupleName, decompressor);
261 fNTupleIndex = locator.GetIndex();
262
263 auto zipBuffer = std::make_unique<unsigned char[]>(length);
264 auto szZipHeader = fCompressor->Zip(serializedHeader, length, GetWriteOptions().GetCompression(),
265 RNTupleCompressor::MakeMemCopyWriter(zipBuffer.get()));
266 WriteNTupleHeader(zipBuffer.get(), szZipHeader, length);
267}
268
271{
272 auto element = columnHandle.fColumn->GetElement();
273 RPageStorage::RSealedPage sealedPage;
274 {
275 RNTupleAtomicTimer timer(fCounters->fTimeWallZip, fCounters->fTimeCpuZip);
276 sealedPage = SealPage(page, *element, GetWriteOptions().GetCompression());
277 }
278
279 fCounters->fSzZip.Add(page.GetNBytes());
280 return CommitSealedPageImpl(columnHandle.fPhysicalId, sealedPage);
281}
282
285 const RPageStorage::RSealedPage &sealedPage)
286{
287 auto offsetData = fPageId.fetch_add(1);
288 DescriptorId_t clusterId = fDescriptorBuilder.GetDescriptor().GetNClusters();
289
290 {
291 RNTupleAtomicTimer timer(fCounters->fTimeWallWrite, fCounters->fTimeCpuWrite);
292 RDaosKey daosKey = GetPageDaosKey<kDefaultDaosMapping>(fNTupleIndex, clusterId, physicalColumnId, offsetData);
293 fDaosContainer->WriteSingleAkey(sealedPage.fBuffer, sealedPage.fSize, daosKey.fOid, daosKey.fDkey, daosKey.fAkey);
294 }
295
297 result.fPosition = EncodeDaosPagePosition(offsetData);
298 result.fBytesOnStorage = sealedPage.fSize;
300 fCounters->fNPageCommitted.Inc();
301 fCounters->fSzWritePayload.Add(sealedPage.fSize);
302 fNBytesCurrentCluster += sealedPage.fSize;
303 return result;
304}
305
306std::vector<ROOT::Experimental::RNTupleLocator>
307ROOT::Experimental::Detail::RPageSinkDaos::CommitSealedPageVImpl(std::span<RPageStorage::RSealedPageGroup> ranges)
308{
310 std::vector<ROOT::Experimental::RNTupleLocator> locators;
311 int64_t nPages =
312 std::accumulate(ranges.begin(), ranges.end(), 0, [](int64_t c, const RPageStorage::RSealedPageGroup &r) {
313 return c + std::distance(r.fFirst, r.fLast);
314 });
315 locators.reserve(nPages);
316
317 const uint32_t maxCageSz = fCageSizeLimit;
318 const bool useCaging = fCageSizeLimit > 0;
319 const std::uint8_t locatorFlags = useCaging ? Internal::EDaosLocatorFlags::kCagedPage : 0;
320
321 DescriptorId_t clusterId = fDescriptorBuilder.GetDescriptor().GetNClusters();
322 int64_t payloadSz = 0;
323 std::size_t positionOffset;
324 uint32_t positionIndex;
325
326 /// Aggregate batch of requests by object ID and distribution key, determined by the ntuple-DAOS mapping
327 for (auto &range : ranges) {
328 positionOffset = 0;
329 /// Under caging, the atomic page counter is fetch-incremented for every column range to get the position of its
330 /// first cage and indicate the next one, also ensuring subsequent pages of different columns do not end up caged
331 /// together. This increment is not necessary in the absence of caging, as each page is trivially caged.
332 positionIndex = useCaging ? fPageId.fetch_add(1) : fPageId.load();
333
334 for (auto sealedPageIt = range.fFirst; sealedPageIt != range.fLast; ++sealedPageIt) {
335
336 const RPageStorage::RSealedPage &s = *sealedPageIt;
337
338 if (positionOffset + s.fSize > maxCageSz) {
339 positionOffset = 0;
340 positionIndex = fPageId.fetch_add(1);
341 }
342
343 d_iov_t pageIov;
344 d_iov_set(&pageIov, const_cast<void *>(s.fBuffer), s.fSize);
345
346 RDaosKey daosKey =
347 GetPageDaosKey<kDefaultDaosMapping>(fNTupleIndex, clusterId, range.fPhysicalColumnId, positionIndex);
348 auto odPair = RDaosContainer::ROidDkeyPair{daosKey.fOid, daosKey.fDkey};
349 auto [it, ret] = writeRequests.emplace(odPair, RDaosContainer::RWOperation(odPair));
350 it->second.Insert(daosKey.fAkey, pageIov);
351
352 RNTupleLocator locator;
353 locator.fPosition = EncodeDaosPagePosition(positionIndex, positionOffset);
354 locator.fBytesOnStorage = s.fSize;
356 locator.fReserved = locatorFlags;
357 locators.push_back(locator);
358
359 positionOffset += s.fSize;
360 payloadSz += s.fSize;
361 }
362 }
363 fNBytesCurrentCluster += payloadSz;
364
365 {
366 RNTupleAtomicTimer timer(fCounters->fTimeWallWrite, fCounters->fTimeCpuWrite);
367 if (int err = fDaosContainer->WriteV(writeRequests))
368 throw ROOT::Experimental::RException(R__FAIL("WriteV: error" + std::string(d_errstr(err))));
369 }
370
371 fCounters->fNPageCommitted.Add(nPages);
372 fCounters->fSzWritePayload.Add(payloadSz);
373
374 return locators;
375}
376
377std::uint64_t
379{
380 return std::exchange(fNBytesCurrentCluster, 0);
381}
382
385 std::uint32_t length)
386{
387 auto bufPageListZip = std::make_unique<unsigned char[]>(length);
388 auto szPageListZip = fCompressor->Zip(serializedPageList, length, GetWriteOptions().GetCompression(),
389 RNTupleCompressor::MakeMemCopyWriter(bufPageListZip.get()));
390
391 auto offsetData = fClusterGroupId.fetch_add(1);
392 fDaosContainer->WriteSingleAkey(
393 bufPageListZip.get(), szPageListZip,
394 daos_obj_id_t{kOidLowPageList, static_cast<decltype(daos_obj_id_t::hi)>(fNTupleIndex)}, kDistributionKeyDefault,
395 offsetData, kCidMetadata);
397 result.fPosition = RNTupleLocatorObject64{offsetData};
398 result.fBytesOnStorage = szPageListZip;
400 fCounters->fSzWritePayload.Add(static_cast<int64_t>(szPageListZip));
401 return result;
402}
403
404void ROOT::Experimental::Detail::RPageSinkDaos::CommitDatasetImpl(unsigned char *serializedFooter, std::uint32_t length)
405{
406 auto bufFooterZip = std::make_unique<unsigned char[]>(length);
407 auto szFooterZip = fCompressor->Zip(serializedFooter, length, GetWriteOptions().GetCompression(),
408 RNTupleCompressor::MakeMemCopyWriter(bufFooterZip.get()));
409 WriteNTupleFooter(bufFooterZip.get(), szFooterZip, length);
410 WriteNTupleAnchor();
411}
412
413void ROOT::Experimental::Detail::RPageSinkDaos::WriteNTupleHeader(const void *data, size_t nbytes, size_t lenHeader)
414{
415 fDaosContainer->WriteSingleAkey(
416 data, nbytes, daos_obj_id_t{kOidLowMetadata, static_cast<decltype(daos_obj_id_t::hi)>(fNTupleIndex)},
417 kDistributionKeyDefault, kAttributeKeyHeader, kCidMetadata);
418 fNTupleAnchor.fLenHeader = lenHeader;
419 fNTupleAnchor.fNBytesHeader = nbytes;
420}
421
422void ROOT::Experimental::Detail::RPageSinkDaos::WriteNTupleFooter(const void *data, size_t nbytes, size_t lenFooter)
423{
424 fDaosContainer->WriteSingleAkey(
425 data, nbytes, daos_obj_id_t{kOidLowMetadata, static_cast<decltype(daos_obj_id_t::hi)>(fNTupleIndex)},
426 kDistributionKeyDefault, kAttributeKeyFooter, kCidMetadata);
427 fNTupleAnchor.fLenFooter = lenFooter;
428 fNTupleAnchor.fNBytesFooter = nbytes;
429}
430
432{
433 const auto ntplSize = RDaosNTupleAnchor::GetSize();
434 auto buffer = std::make_unique<unsigned char[]>(ntplSize);
435 fNTupleAnchor.Serialize(buffer.get());
436 fDaosContainer->WriteSingleAkey(
437 buffer.get(), ntplSize, daos_obj_id_t{kOidLowMetadata, static_cast<decltype(daos_obj_id_t::hi)>(fNTupleIndex)},
438 kDistributionKeyDefault, kAttributeKeyAnchor, kCidMetadata);
439}
440
443{
444 if (nElements == 0)
445 throw RException(R__FAIL("invalid call: request empty page"));
446 auto elementSize = columnHandle.fColumn->GetElement()->GetSize();
447 return fPageAllocator->NewPage(columnHandle.fPhysicalId, elementSize, nElements);
448}
449
451{
452 fPageAllocator->DeletePage(page);
453}
454
455////////////////////////////////////////////////////////////////////////////////
456
457ROOT::Experimental::Detail::RPageSourceDaos::RPageSourceDaos(std::string_view ntupleName, std::string_view uri,
458 const RNTupleReadOptions &options)
459 : RPageSource(ntupleName, options),
460 fPagePool(std::make_shared<RPagePool>()),
461 fURI(uri),
462 fClusterPool(std::make_unique<RClusterPool>(*this, options.GetClusterBunchSize()))
463{
464 fDecompressor = std::make_unique<RNTupleDecompressor>();
465 EnableDefaultMetrics("RPageSourceDaos");
466
467 auto args = ParseDaosURI(uri);
468 auto pool = std::make_shared<RDaosPool>(args.fPoolLabel);
469 fDaosContainer = std::make_unique<RDaosContainer>(pool, args.fContainerLabel);
470}
471
473
475{
477 std::unique_ptr<unsigned char[]> buffer, zipBuffer;
478
479 auto [locator, descBuilder] =
480 RDaosContainerNTupleLocator::LocateNTuple(*fDaosContainer, fNTupleName, *fDecompressor);
481 if (!locator.IsValid())
483 R__FAIL("Attach: requested ntuple '" + fNTupleName + "' is not present in DAOS container."));
484
485 auto oclass = RDaosObject::ObjClassId(locator.fAnchor->fObjClass);
486 if (oclass.IsUnknown())
487 throw ROOT::Experimental::RException(R__FAIL("Attach: unknown object class " + locator.fAnchor->fObjClass));
488
489 fDaosContainer->SetDefaultObjectClass(oclass);
490 fNTupleIndex = locator.GetIndex();
491
492 ntplDesc = descBuilder.MoveDescriptor();
493 daos_obj_id_t oidPageList{kOidLowPageList, static_cast<decltype(daos_obj_id_t::hi)>(fNTupleIndex)};
494
495 for (const auto &cgDesc : ntplDesc.GetClusterGroupIterable()) {
496 buffer = std::make_unique<unsigned char[]>(cgDesc.GetPageListLength());
497 zipBuffer = std::make_unique<unsigned char[]>(cgDesc.GetPageListLocator().fBytesOnStorage);
498 fDaosContainer->ReadSingleAkey(
499 zipBuffer.get(), cgDesc.GetPageListLocator().fBytesOnStorage, oidPageList, kDistributionKeyDefault,
500 cgDesc.GetPageListLocator().GetPosition<RNTupleLocatorObject64>().fLocation, kCidMetadata);
501 fDecompressor->Unzip(zipBuffer.get(), cgDesc.GetPageListLocator().fBytesOnStorage, cgDesc.GetPageListLength(),
502 buffer.get());
503
504 auto clusters = RClusterGroupDescriptorBuilder::GetClusterSummaries(ntplDesc, cgDesc.GetId());
505 Internal::RNTupleSerializer::DeserializePageListV1(buffer.get(), cgDesc.GetPageListLength(), clusters);
506 for (std::size_t i = 0; i < clusters.size(); ++i) {
507 ntplDesc.AddClusterDetails(clusters[i].MoveDescriptor().Unwrap());
508 }
509 }
510
511 return ntplDesc;
512}
513
515{
516 return fDaosContainer->GetDefaultObjectClass().ToString();
517}
518
520 const RClusterIndex &clusterIndex,
521 RSealedPage &sealedPage)
522{
523 const auto clusterId = clusterIndex.GetClusterId();
524
526 {
527 auto descriptorGuard = GetSharedDescriptorGuard();
528 const auto &clusterDescriptor = descriptorGuard->GetClusterDescriptor(clusterId);
529 pageInfo = clusterDescriptor.GetPageRange(physicalColumnId).Find(clusterIndex.GetIndex());
530 }
531
534 R__FAIL("accessing caged pages is only supported in conjunction with cluster cache"));
535 }
536
537 const auto bytesOnStorage = pageInfo.fLocator.fBytesOnStorage;
538 sealedPage.fSize = bytesOnStorage;
539 sealedPage.fNElements = pageInfo.fNElements;
540 if (!sealedPage.fBuffer)
541 return;
543 RDaosKey daosKey = GetPageDaosKey<kDefaultDaosMapping>(
544 fNTupleIndex, clusterId, physicalColumnId, pageInfo.fLocator.GetPosition<RNTupleLocatorObject64>().fLocation);
545 fDaosContainer->ReadSingleAkey(const_cast<void *>(sealedPage.fBuffer), bytesOnStorage, daosKey.fOid,
546 daosKey.fDkey, daosKey.fAkey);
547 } else {
548 memcpy(const_cast<void *>(sealedPage.fBuffer), RPage::GetPageZeroBuffer(), bytesOnStorage);
549 }
550}
551
554 const RClusterInfo &clusterInfo,
555 ClusterSize_t::ValueType idxInCluster)
556{
557 const auto columnId = columnHandle.fPhysicalId;
558 const auto clusterId = clusterInfo.fClusterId;
559 const auto &pageInfo = clusterInfo.fPageInfo;
560
561 const auto element = columnHandle.fColumn->GetElement();
562 const auto elementSize = element->GetSize();
563 const auto bytesOnStorage = pageInfo.fLocator.fBytesOnStorage;
564
565 const void *sealedPageBuffer = nullptr; // points either to directReadBuffer or to a read-only page in the cluster
566 std::unique_ptr<unsigned char[]> directReadBuffer; // only used if cluster pool is turned off
567
568 if (pageInfo.fLocator.fType == RNTupleLocator::kTypePageZero) {
569 auto pageZero = RPage::MakePageZero(columnId, elementSize);
570 pageZero.GrowUnchecked(pageInfo.fNElements);
571 pageZero.SetWindow(clusterInfo.fColumnOffset + pageInfo.fFirstInPage,
572 RPage::RClusterInfo(clusterId, clusterInfo.fColumnOffset));
573 fPagePool->RegisterPage(pageZero, RPageDeleter([](const RPage &, void *) {}, nullptr));
574 return pageZero;
575 }
576
577 if (fOptions.GetClusterCache() == RNTupleReadOptions::EClusterCache::kOff) {
578 if (pageInfo.fLocator.fReserved & Internal::EDaosLocatorFlags::kCagedPage) {
580 R__FAIL("accessing caged pages is only supported in conjunction with cluster cache"));
581 }
582
583 directReadBuffer = std::unique_ptr<unsigned char[]>(new unsigned char[bytesOnStorage]);
584 RDaosKey daosKey = GetPageDaosKey<kDefaultDaosMapping>(
585 fNTupleIndex, clusterId, columnId, pageInfo.fLocator.GetPosition<RNTupleLocatorObject64>().fLocation);
586 fDaosContainer->ReadSingleAkey(directReadBuffer.get(), bytesOnStorage, daosKey.fOid, daosKey.fDkey,
587 daosKey.fAkey);
588 fCounters->fNPageLoaded.Inc();
589 fCounters->fNRead.Inc();
590 fCounters->fSzReadPayload.Add(bytesOnStorage);
591 sealedPageBuffer = directReadBuffer.get();
592 } else {
593 if (!fCurrentCluster || (fCurrentCluster->GetId() != clusterId) || !fCurrentCluster->ContainsColumn(columnId))
594 fCurrentCluster = fClusterPool->GetCluster(clusterId, fActivePhysicalColumns.ToColumnSet());
595 R__ASSERT(fCurrentCluster->ContainsColumn(columnId));
596
597 auto cachedPage = fPagePool->GetPage(columnId, RClusterIndex(clusterId, idxInCluster));
598 if (!cachedPage.IsNull())
599 return cachedPage;
600
601 ROnDiskPage::Key key(columnId, pageInfo.fPageNo);
602 auto onDiskPage = fCurrentCluster->GetOnDiskPage(key);
603 R__ASSERT(onDiskPage && (bytesOnStorage == onDiskPage->GetSize()));
604 sealedPageBuffer = onDiskPage->GetAddress();
605 }
606
607 RPage newPage;
608 {
609 RNTupleAtomicTimer timer(fCounters->fTimeWallUnzip, fCounters->fTimeCpuUnzip);
610 newPage = UnsealPage({sealedPageBuffer, bytesOnStorage, pageInfo.fNElements}, *element, columnId);
611 fCounters->fSzUnzip.Add(elementSize * pageInfo.fNElements);
612 }
613
614 newPage.SetWindow(clusterInfo.fColumnOffset + pageInfo.fFirstInPage,
615 RPage::RClusterInfo(clusterId, clusterInfo.fColumnOffset));
616 fPagePool->RegisterPage(
617 newPage,
618 RPageDeleter([](const RPage &page, void * /*userData*/) { RPageAllocatorHeap::DeletePage(page); }, nullptr));
619 fCounters->fNPagePopulated.Inc();
620 return newPage;
621}
622
625{
626 const auto columnId = columnHandle.fPhysicalId;
627 auto cachedPage = fPagePool->GetPage(columnId, globalIndex);
628 if (!cachedPage.IsNull())
629 return cachedPage;
630
631 std::uint64_t idxInCluster;
632 RClusterInfo clusterInfo;
633 {
634 auto descriptorGuard = GetSharedDescriptorGuard();
635 clusterInfo.fClusterId = descriptorGuard->FindClusterId(columnId, globalIndex);
637
638 const auto &clusterDescriptor = descriptorGuard->GetClusterDescriptor(clusterInfo.fClusterId);
639 clusterInfo.fColumnOffset = clusterDescriptor.GetColumnRange(columnId).fFirstElementIndex;
640 R__ASSERT(clusterInfo.fColumnOffset <= globalIndex);
641 idxInCluster = globalIndex - clusterInfo.fColumnOffset;
642 clusterInfo.fPageInfo = clusterDescriptor.GetPageRange(columnId).Find(idxInCluster);
643 }
644 return PopulatePageFromCluster(columnHandle, clusterInfo, idxInCluster);
645}
646
649 const RClusterIndex &clusterIndex)
650{
651 const auto clusterId = clusterIndex.GetClusterId();
652 const auto idxInCluster = clusterIndex.GetIndex();
653 const auto columnId = columnHandle.fPhysicalId;
654 auto cachedPage = fPagePool->GetPage(columnId, clusterIndex);
655 if (!cachedPage.IsNull())
656 return cachedPage;
657
658 R__ASSERT(clusterId != kInvalidDescriptorId);
659 RClusterInfo clusterInfo;
660 {
661 auto descriptorGuard = GetSharedDescriptorGuard();
662 const auto &clusterDescriptor = descriptorGuard->GetClusterDescriptor(clusterId);
663 clusterInfo.fClusterId = clusterId;
664 clusterInfo.fColumnOffset = clusterDescriptor.GetColumnRange(columnId).fFirstElementIndex;
665 clusterInfo.fPageInfo = clusterDescriptor.GetPageRange(columnId).Find(idxInCluster);
666 }
667
668 return PopulatePageFromCluster(columnHandle, clusterInfo, idxInCluster);
669}
670
672{
673 fPagePool->ReturnPage(page);
674}
675
676std::unique_ptr<ROOT::Experimental::Detail::RPageSource> ROOT::Experimental::Detail::RPageSourceDaos::Clone() const
677{
678 auto clone = new RPageSourceDaos(fNTupleName, fURI, fOptions);
679 return std::unique_ptr<RPageSourceDaos>(clone);
680}
681
682std::vector<std::unique_ptr<ROOT::Experimental::Detail::RCluster>>
684{
685 struct RDaosSealedPageLocator {
686 DescriptorId_t fClusterId = 0;
687 DescriptorId_t fColumnId = 0;
688 NTupleSize_t fPageNo = 0;
689 std::uint64_t fPosition = 0;
690 std::uint64_t fCageOffset = 0;
691 std::uint64_t fSize = 0;
692 };
693
694 // Prepares read requests for a single cluster; `readRequests` is modified by this function. Requests are coalesced
695 // by OID and distribution key.
696 // TODO(jalopezg): this may be a private member function; that, however, requires additional changes given that
697 // `RDaosContainer::MultiObjectRWOperation_t` cannot be forward-declared
698 auto fnPrepareSingleCluster = [&](const RCluster::RKey &clusterKey,
700 auto clusterId = clusterKey.fClusterId;
701 // Group page locators by their position in the object store; with caging enabled, this facilitates the
702 // processing of cages' requests together into a single IOV to be populated.
703 std::unordered_map<std::uint32_t, std::vector<RDaosSealedPageLocator>> onDiskPages;
704
705 unsigned clusterBufSz = 0, nPages = 0;
706 auto pageZeroMap = std::make_unique<ROnDiskPageMap>();
707 PrepareLoadCluster(clusterKey, *pageZeroMap,
708 [&](DescriptorId_t physicalColumnId, NTupleSize_t pageNo,
710 const auto &pageLocator = pageInfo.fLocator;
711 uint32_t position, offset;
712 std::tie(position, offset) =
713 DecodeDaosPagePosition(pageLocator.GetPosition<RNTupleLocatorObject64>());
714 auto [itLoc, _] = onDiskPages.emplace(position, std::vector<RDaosSealedPageLocator>());
715
716 itLoc->second.push_back(
717 {clusterId, physicalColumnId, pageNo, position, offset, pageLocator.fBytesOnStorage});
718 ++nPages;
719 clusterBufSz += pageLocator.fBytesOnStorage;
720 });
721
722 auto clusterBuffer = new unsigned char[clusterBufSz];
723 auto pageMap = std::make_unique<ROnDiskPageMapHeap>(std::unique_ptr<unsigned char[]>(clusterBuffer));
724
725 auto cageBuffer = clusterBuffer;
726 // Fill the cluster page map and the read requests for the RDaosContainer::ReadV() call
727 for (auto &[cageIndex, pageVec] : onDiskPages) {
728 auto columnId = pageVec[0].fColumnId; // All pages in a cage belong to the same column
729 std::size_t cageSz = 0;
730
731 for (auto &s : pageVec) {
732 assert(columnId == s.fColumnId);
733 assert(cageIndex == s.fPosition);
734 // Register the on disk pages in a page map
735 ROnDiskPage::Key key(s.fColumnId, s.fPageNo);
736 pageMap->Register(key, ROnDiskPage(cageBuffer + s.fCageOffset, s.fSize));
737 cageSz += s.fSize;
738 }
739
740 // Prepare new read request batched up by object ID and distribution key
741 d_iov_t iov;
742 d_iov_set(&iov, cageBuffer, cageSz);
743
744 RDaosKey daosKey = GetPageDaosKey<kDefaultDaosMapping>(fNTupleIndex, clusterId, columnId, cageIndex);
745 auto odPair = RDaosContainer::ROidDkeyPair{daosKey.fOid, daosKey.fDkey};
746 auto [itReq, ret] = readRequests.emplace(odPair, RDaosContainer::RWOperation(odPair));
747 itReq->second.Insert(daosKey.fAkey, iov);
748
749 cageBuffer += cageSz;
750 }
751 fCounters->fNPageLoaded.Add(nPages);
752 fCounters->fSzReadPayload.Add(clusterBufSz);
753
754 auto cluster = std::make_unique<RCluster>(clusterId);
755 cluster->Adopt(std::move(pageMap));
756 cluster->Adopt(std::move(pageZeroMap));
757 for (auto colId : clusterKey.fPhysicalColumnSet)
758 cluster->SetColumnAvailable(colId);
759 return cluster;
760 };
761
762 fCounters->fNClusterLoaded.Add(clusterKeys.size());
763
764 std::vector<std::unique_ptr<ROOT::Experimental::Detail::RCluster>> clusters;
766 for (auto key : clusterKeys) {
767 clusters.emplace_back(fnPrepareSingleCluster(key, readRequests));
768 }
769
770 {
771 RNTupleAtomicTimer timer(fCounters->fTimeWallRead, fCounters->fTimeCpuRead);
772 if (int err = fDaosContainer->ReadV(readRequests))
773 throw ROOT::Experimental::RException(R__FAIL("ReadV: error" + std::string(d_errstr(err))));
774 }
775 fCounters->fNReadV.Inc();
776 fCounters->fNRead.Add(readRequests.size());
777
778 return clusters;
779}
780
782{
783 RNTupleAtomicTimer timer(fCounters->fTimeWallUnzip, fCounters->fTimeCpuUnzip);
784 fTaskScheduler->Reset();
785
786 const auto clusterId = cluster->GetId();
787 auto descriptorGuard = GetSharedDescriptorGuard();
788 const auto &clusterDescriptor = descriptorGuard->GetClusterDescriptor(clusterId);
789
790 std::vector<std::unique_ptr<RColumnElementBase>> allElements;
791
792 const auto &columnsInCluster = cluster->GetAvailPhysicalColumns();
793 for (const auto columnId : columnsInCluster) {
794 const auto &columnDesc = descriptorGuard->GetColumnDescriptor(columnId);
795
796 allElements.emplace_back(RColumnElementBase::Generate(columnDesc.GetModel().GetType()));
797
798 const auto &pageRange = clusterDescriptor.GetPageRange(columnId);
799 std::uint64_t pageNo = 0;
800 std::uint64_t firstInPage = 0;
801 for (const auto &pi : pageRange.fPageInfos) {
802 ROnDiskPage::Key key(columnId, pageNo);
803 auto onDiskPage = cluster->GetOnDiskPage(key);
804 R__ASSERT(onDiskPage && (onDiskPage->GetSize() == pi.fLocator.fBytesOnStorage));
805
806 auto taskFunc = [this, columnId, clusterId, firstInPage, onDiskPage, element = allElements.back().get(),
807 nElements = pi.fNElements,
808 indexOffset = clusterDescriptor.GetColumnRange(columnId).fFirstElementIndex]() {
809 auto newPage = UnsealPage({onDiskPage->GetAddress(), onDiskPage->GetSize(), nElements}, *element, columnId);
810 fCounters->fSzUnzip.Add(element->GetSize() * nElements);
811
812 newPage.SetWindow(indexOffset + firstInPage, RPage::RClusterInfo(clusterId, indexOffset));
813 fPagePool->PreloadPage(
814 newPage,
815 RPageDeleter([](const RPage &page, void * /*userData*/) { RPageAllocatorHeap::DeletePage(page); },
816 nullptr));
817 };
818
819 fTaskScheduler->AddTask(taskFunc);
820
821 firstInPage += pi.fNElements;
822 pageNo++;
823 } // for all pages in column
824 } // for all columns in cluster
825
826 fCounters->fNPagePopulated.Add(cluster->GetNOnDiskPages());
827
828 fTaskScheduler->Wait();
829}
size_t fSize
#define R__FORWARD_ERROR(res)
Short-hand to return an RResult<T> in an error state (i.e. after checking)
Definition RError.hxx:307
#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 R__LOG_WARNING(...)
Definition RLogger.hxx:363
#define c(i)
Definition RSha256.hxx:101
TObject * clone(const char *newname) const override
#define R__ASSERT(e)
Definition TError.h:118
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t r
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h length
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t bytes
#define _(A, B)
Definition cfortran.h:108
Managed a set of clusters containing compressed and packed pages.
An in-memory subset of the packed and compressed pages of a cluster.
Definition RCluster.hxx:155
const ColumnSet_t & GetAvailPhysicalColumns() const
Definition RCluster.hxx:199
const ROnDiskPage * GetOnDiskPage(const ROnDiskPage::Key &key) const
Definition RCluster.cxx:37
static std::unique_ptr< RColumnElementBase > Generate(EColumnType type)
If CppT == void, use the default C++ type for the given column type.
RColumnElementBase * GetElement() const
Definition RColumn.hxx:322
A RDaosContainer provides read/write access to objects in a given container.
Definition RDaos.hxx:157
std::unordered_map< ROidDkeyPair, RWOperation, ROidDkeyPair::Hash > MultiObjectRWOperation_t
Definition RDaos.hxx:231
int ReadSingleAkey(void *buffer, std::size_t length, daos_obj_id_t oid, DistributionKey_t dkey, AttributeKey_t akey, ObjClassId_t cid)
Read data from a single object attribute key to the given buffer.
Definition RDaos.cxx:208
RDaosObject::DistributionKey_t DistributionKey_t
Definition RDaos.hxx:160
RDaosObject::AttributeKey_t AttributeKey_t
Definition RDaos.hxx:161
static Writer_t MakeMemCopyWriter(unsigned char *dest)
Helper class to uncompress data blocks in the ROOT compression frame format.
void Unzip(const void *from, size_t nbytes, size_t dataLen, void *to)
The nbytes parameter provides the size ls of the from buffer.
Record wall time and CPU time between construction and destruction.
A page as being stored on disk, that is packed and compressed.
Definition RCluster.hxx:43
Uses standard C++ memory allocation for the column data pages.
static void DeletePage(const RPage &page)
Releases the memory pointed to by page and resets the page's information.
A closure that can free the memory associated with a mapped page.
A thread-safe cache of column pages.
Definition RPagePool.hxx:47
void ReleasePage(RPage &page) final
Every page store needs to be able to free pages it handed out.
RPageSinkDaos(std::string_view ntupleName, std::string_view uri, const RNTupleWriteOptions &options)
void WriteNTupleFooter(const void *data, size_t nbytes, size_t lenFooter)
void WriteNTupleHeader(const void *data, size_t nbytes, size_t lenHeader)
RNTupleLocator CommitClusterGroupImpl(unsigned char *serializedPageList, std::uint32_t length) final
Returns the locator of the page list envelope of the given buffer that contains the serialized page l...
std::uint64_t CommitClusterImpl(NTupleSize_t nEntries) final
Returns the number of bytes written to storage (excluding metadata)
void CommitDatasetImpl(unsigned char *serializedFooter, std::uint32_t length) final
RNTupleLocator CommitPageImpl(ColumnHandle_t columnHandle, const RPage &page) final
RNTupleLocator CommitSealedPageImpl(DescriptorId_t physicalColumnId, const RPageStorage::RSealedPage &sealedPage) final
void CreateImpl(const RNTupleModel &model, unsigned char *serializedHeader, std::uint32_t length) final
std::vector< RNTupleLocator > CommitSealedPageVImpl(std::span< RPageStorage::RSealedPageGroup > ranges) final
Vector commit of preprocessed pages.
RPage ReservePage(ColumnHandle_t columnHandle, std::size_t nElements) final
Get a new, empty page for the given column that can be filled with up to nElements.
Abstract interface to write data into an ntuple.
void EnableDefaultMetrics(const std::string &prefix)
Enables the default set of metrics provided by RPageSink.
std::unique_ptr< RNTupleCompressor > fCompressor
Helper to zip pages and header/footer; includes a 16MB (kMAXZIPBUF) zip buffer.
Storage provider that reads ntuple pages from a DAOS container.
std::unique_ptr< RDaosContainer > fDaosContainer
A container that stores object data (header/footer, pages, etc.)
RPageSourceDaos(std::string_view ntupleName, std::string_view uri, const RNTupleReadOptions &options)
void ReleasePage(RPage &page) final
Every page store needs to be able to free pages it handed out.
void UnzipClusterImpl(RCluster *cluster) final
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 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.
RPage PopulatePage(ColumnHandle_t columnHandle, NTupleSize_t globalIndex) final
Allocates and fills a page that contains the index-th element.
RPage PopulatePageFromCluster(ColumnHandle_t columnHandle, const RClusterInfo &clusterInfo, ClusterSize_t::ValueType idxInCluster)
std::string GetObjectClass() const
Return the object class used for user data OIDs in this ntuple.
std::unique_ptr< RPageSource > Clone() const final
The cloned page source creates a new connection to the pool/container.
Abstract interface to read data from an ntuple.
void EnableDefaultMetrics(const std::string &prefix)
Enables the default set of metrics provided by RPageSource.
std::unique_ptr< RNTupleDecompressor > fDecompressor
Helper to unzip pages and header/footer; comprises a 16MB (kMAXZIPBUF) unzip buffer.
Stores information about the cluster in which this page resides.
Definition RPage.hxx:49
A page is a slice of a column that is mapped into memory.
Definition RPage.hxx:42
std::uint32_t GetNBytes() const
The space taken by column elements in the buffer.
Definition RPage.hxx:84
static RPage MakePageZero(ColumnId_t columnId, ClusterSize_t::ValueType elementSize)
Make a 'zero' page for column columnId (that is comprised of 0x00 bytes only).
Definition RPage.hxx:135
void SetWindow(const NTupleSize_t rangeFirst, const RClusterInfo &clusterInfo)
Seek the page to a certain position of the column.
Definition RPage.hxx:118
static const void * GetPageZeroBuffer()
Return a pointer to the page zero buffer used if there is no on-disk data for a particular deferred c...
Definition RPage.cxx:23
A helper class for serializing and deserialization of the RNTuple binary format.
static RResult< void > DeserializePageListV1(const void *buffer, std::uint32_t bufSize, std::vector< RClusterDescriptorBuilder > &clusters)
static RResult< void > DeserializeFooterV1(const void *buffer, std::uint32_t bufSize, RNTupleDescriptorBuilder &descBuilder)
static RResult< void > DeserializeHeaderV1(const void *buffer, std::uint32_t bufSize, RNTupleDescriptorBuilder &descBuilder)
static std::vector< RClusterDescriptorBuilder > GetClusterSummaries(const RNTupleDescriptor &ntplDesc, DescriptorId_t clusterGroupId)
Used to prepare the cluster descriptor builders when loading the page locations for a certain cluster...
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 RNTupleDescriptor.
void AddToOnDiskFooterSize(std::uint64_t size)
The real footer size also include the page list envelopes.
The on-storage meta-data of an ntuple.
RClusterGroupDescriptorIterable GetClusterGroupIterable() const
RResult< void > AddClusterDetails(RClusterDescriptor &&clusterDesc)
Methods to load and drop cluster details.
The RNTupleModel encapulates the schema of an ntuple.
Common user-tunable settings for reading ntuples.
DAOS-specific user-tunable settings for storing ntuples.
Common user-tunable settings for storing ntuples.
The class is used as a return type for operations that can fail; wraps a value of type T or an RError...
Definition RError.hxx:207
const char * d_errstr(int rc)
@ OC_SX
Definition daos.h:129
static void d_iov_set(d_iov_t *iov, void *buf, size_t size)
Definition daos.h:50
uint16_t daos_oclass_id_t
Definition daos.h:135
RLogChannel & NTupleLog()
Log channel for RNTuple diagnostics.
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.
constexpr DescriptorId_t kInvalidDescriptorId
The identifiers that specifies the content of a (partial) cluster.
Definition RCluster.hxx:159
Helper structure concentrating the functionality required to locate an ntuple within a DAOS container...
int InitNTupleDescriptorBuilder(RDaosContainer &cont, RNTupleDecompressor &decompressor, RNTupleDescriptorBuilder &builder)
static std::pair< RDaosContainerNTupleLocator, RNTupleDescriptorBuilder > LocateNTuple(RDaosContainer &cont, const std::string &ntupleName, RNTupleDecompressor &decompressor)
A pair of <object ID, distribution key> that can be used to issue a fetch/update request for multiple...
Definition RDaos.hxx:166
Describes a read/write operation on multiple attribute keys under the same object ID and distribution...
Definition RDaos.hxx:190
Entry point for an RNTuple in a DAOS container.
std::uint32_t fNBytesFooter
The size of the compressed ntuple footer.
std::uint32_t fNBytesHeader
The size of the compressed ntuple header.
std::string fObjClass
The object class for user data OIDs, e.g. SX
std::uint32_t fVersion
Allows for evolving the struct in future versions.
RResult< std::uint32_t > Deserialize(const void *buffer, std::uint32_t bufSize)
std::uint32_t fLenHeader
The size of the uncompressed ntuple header.
std::uint32_t Serialize(void *buffer) const
std::uint32_t fLenFooter
The size of the uncompressed ntuple footer.
Wrap around a daos_oclass_id_t.
Definition RDaos.hxx:95
static constexpr std::size_t kOCNameMaxLength
This limit is currently not defined in any header and any call to daos_oclass_id2name() within DAOS u...
Definition RDaos.hxx:108
On-disk pages within a page source are identified by the column and page number.
Definition RCluster.hxx:53
Summarizes cluster-level information that are necessary to populate a certain page.
RClusterDescriptor::RPageRange::RPageInfoExtended fPageInfo
Location of the page on disk.
std::uint64_t fColumnOffset
The first element number of the page's column in the given cluster.
A range of sealed pages referring to the same column that can be used for vector commit.
A sealed page contains the bytes of a page as written to storage (packed & compressed).
We do not need to store the element size / uncompressed page size because we know to which column the...
std::uint32_t fNElements
The sum of the elements of all the pages must match the corresponding fNElements field in fColumnRang...
RNTupleLocator fLocator
The meaning of fLocator depends on the storage backend.
RNTupleLocator payload that is common for object stores using 64bit location information.
Generic information about the physical location of data.
std::uint8_t fReserved
Reserved for use by concrete storage backends.
ELocatorType fType
For non-disk locators, the value for the Type field.
std::variant< std::uint64_t, std::string, RNTupleLocatorObject64 > fPosition
Simple on-disk locators consisting of a 64-bit offset use variant type uint64_t; extended locators ha...
iovec for memory buffer
Definition daos.h:37
uint64_t hi
Definition daos.h:147
uint64_t lo
Definition daos.h:146
TMarker m
Definition textangle.C:8