Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RPageStorageDaos.cxx
Go to the documentation of this file.
1/// \file RPageStorageDaos.cxx
2/// \author Javier Lopez-Gomez <j.lopez@cern.ch>
3/// \date 2020-11-03
4/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
5/// is welcome!
6
7/*************************************************************************
8 * Copyright (C) 1995-2021, Rene Brun and Fons Rademakers. *
9 * All rights reserved. *
10 * *
11 * For the licensing terms see $ROOTSYS/LICENSE. *
12 * For the list of contributors see $ROOTSYS/README/CREDITS. *
13 *************************************************************************/
14
15#include <ROOT/RCluster.hxx>
16#include <ROOT/RLogger.hxx>
18#include <ROOT/RNTupleModel.hxx>
21#include <ROOT/RNTupleTypes.hxx>
22#include <ROOT/RNTupleUtils.hxx>
23#include <ROOT/RNTupleZip.hxx>
24#include <ROOT/RPage.hxx>
26#include <ROOT/RPagePool.hxx>
27#include <ROOT/RDaos.hxx>
29#include <ROOT/RVersion.hxx>
30
31#include <TError.h>
32
33#include <algorithm>
34#include <cstdio>
35#include <cstdlib>
36#include <cstring>
37#include <limits>
38#include <mutex>
39#include <tuple>
40#include <utility>
41#include <regex>
42#include <cassert>
43
44namespace {
53
54struct RDaosKey {
55 daos_obj_id_t fOid;
56 DistributionKey_t fDkey;
57 AttributeKey_t fAkey;
58};
59
60/// \brief Pre-defined keys for object store. `kDistributionKeyDefault` is the distribution key for all objects,
61/// `kAttributeKeyDefault` is the attribute key for all objects but anchor, header, footer.
62/// `kAttributeKey{Anchor,Header,Footer}` are the respective attribute keys for anchor/header/footer metadata elements.
63static constexpr DistributionKey_t kDistributionKeyDefault = 0x5a3c69f0cafe4a11;
64static constexpr AttributeKey_t kAttributeKeyDefault = 0x4243544b53444229;
65static constexpr AttributeKey_t kAttributeKeyAnchor = 0x4243544b5344422a;
66static constexpr AttributeKey_t kAttributeKeyHeader = 0x4243544b5344422b;
67static constexpr AttributeKey_t kAttributeKeyFooter = 0x4243544b5344422c;
68
69/// \brief Pre-defined 64 LSb of the OIDs for ntuple metadata (holds anchor/header/footer) and clusters' pagelists.
70static constexpr decltype(daos_obj_id_t::lo) kOidLowMetadata = -1;
71static constexpr decltype(daos_obj_id_t::lo) kOidLowPageList = -2;
72
73/// Because the object class becomes part of the object ID (encoded in the system-reserved 32 bits), we have to
74/// hard-code the object class for the anchor. Otherwise, we would need ask the user to specify the correct object
75/// class in the RNTupleReadOptions when trying to open a previously written data set, which is not really acceptable.
76/// The object class set in the RNTupleWriteOptions thus applies to all objects except the anchor.
77static constexpr daos_oclass_id_t kCidAnchor = OC_UNKNOWN;
78
79RDaosKey GetPageDaosKey(ROOT::Experimental::Internal::ntuple_index_t ntplId, long unsigned pageCount)
80{
81 return RDaosKey{daos_obj_id_t{static_cast<decltype(daos_obj_id_t::lo)>(pageCount),
82 static_cast<decltype(daos_obj_id_t::hi)>(ntplId)},
83 kDistributionKeyDefault, kAttributeKeyDefault};
84}
85
86struct RDaosURI {
87 /// \brief Label of the DAOS pool
88 std::string fPoolLabel;
89 /// \brief Label of the container for this RNTuple
90 std::string fContainerLabel;
91};
92
93/**
94 \brief Parse a DAOS RNTuple URI of the form 'daos://pool_id/container_id'.
95*/
96RDaosURI ParseDaosURI(std::string_view uri)
97{
98 std::regex re("daos://([^/]+)/(.+)");
99 std::cmatch m;
100 if (!std::regex_match(uri.data(), m, re))
101 throw ROOT::RException(R__FAIL("Invalid DAOS pool URI."));
102 return {m[1], m[2]};
103}
104
105/// \brief Helper structure concentrating the functionality required to locate an ntuple within a DAOS container.
106/// It includes a hashing function that converts the RNTuple's name into a 32-bit identifier; this value is used to
107/// index the subspace for the ntuple among all objects in the container. A zero-value hash value is reserved for
108/// storing any future metadata related to container-wide management; a zero-index ntuple is thus disallowed and
109/// remapped to "1". Once the index is computed, `InitNTupleDescriptorBuilder()` can be called to return a
110/// partially-filled builder with the ntuple's anchor, header and footer, lacking only pagelists. Upon that call,
111/// a copy of the anchor is stored in `fAnchor`.
112struct RDaosContainerNTupleLocator {
113 std::string fName{};
114 ntuple_index_t fIndex{};
115 std::optional<ROOT::Experimental::Internal::RDaosNTupleAnchor> fAnchor;
116 static const ntuple_index_t kReservedIndex = 0;
117
118 RDaosContainerNTupleLocator() = default;
119 explicit RDaosContainerNTupleLocator(const std::string &ntupleName) : fName(ntupleName), fIndex(Hash(ntupleName)) {}
120
121 bool IsValid() { return fAnchor.has_value() && fAnchor->fNBytesHeader; }
122 [[nodiscard]] ntuple_index_t GetIndex() const { return fIndex; };
123 static ntuple_index_t Hash(const std::string &ntupleName)
124 {
125 // Convert string to numeric representation via `std::hash`.
126 uint64_t h = std::hash<std::string>{}(ntupleName);
127 // Fold the hash into 32-bit using `boost::hash_combine()` algorithm and magic number.
128 auto seed = static_cast<uint32_t>(h >> 32);
129 seed ^= static_cast<uint32_t>(h & 0xffffffff) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
130 auto hash = static_cast<ntuple_index_t>(seed);
131 return (hash == kReservedIndex) ? kReservedIndex + 1 : hash;
132 }
133
134 int InitNTupleDescriptorBuilder(ROOT::Experimental::Internal::RDaosContainer &cont,
136 {
137 std::unique_ptr<unsigned char[]> buffer;
138 auto &anchor = fAnchor.emplace();
139 int err;
140
142 daos_obj_id_t oidMetadata{kOidLowMetadata, static_cast<decltype(daos_obj_id_t::hi)>(this->GetIndex())};
143
144 buffer = MakeUninitArray<unsigned char>(anchorSize);
145 if ((err = cont.ReadSingleAkey(buffer.get(), anchorSize, oidMetadata, kDistributionKeyDefault,
146 kAttributeKeyAnchor, kCidAnchor))) {
147 return err;
148 }
149
150 anchor.Deserialize(buffer.get(), anchorSize).Unwrap();
151
152 builder.SetVersion(anchor.fVersionEpoch, anchor.fVersionMajor, anchor.fVersionMinor, anchor.fVersionPatch);
153 builder.SetOnDiskHeaderSize(anchor.fNBytesHeader);
154 builder.AddToOnDiskFooterSize(anchor.fNBytesFooter);
155
156 return 0;
157 }
158
159 static std::pair<RDaosContainerNTupleLocator, ROOT::Internal::RNTupleDescriptorBuilder>
160 LocateNTuple(ROOT::Experimental::Internal::RDaosContainer &cont, const std::string &ntupleName)
161 {
162 auto result = std::make_pair(RDaosContainerNTupleLocator(ntupleName), ROOT::Internal::RNTupleDescriptorBuilder());
163
164 auto &loc = result.first;
165 auto &builder = result.second;
166
167 loc.InitNTupleDescriptorBuilder(cont, builder);
168 return result;
169 }
170};
171
172} // anonymous namespace
173
174////////////////////////////////////////////////////////////////////////////////
175
193
195ROOT::Experimental::Internal::RDaosNTupleAnchor::Deserialize(const void *buffer, std::uint32_t bufSize)
196{
197 if (bufSize < 32)
198 return R__FAIL("DAOS anchor too short");
199
200 auto bytes = reinterpret_cast<const unsigned char *>(buffer);
202 if (fVersionAnchor != RDaosNTupleAnchor().fVersionAnchor) {
203 return R__FAIL("unsupported DAOS anchor version: " + std::to_string(fVersionAnchor));
204 }
205
214 auto result = RNTupleSerializer::DeserializeString(bytes, bufSize - 32, fObjClass);
215 if (!result)
216 return R__FORWARD_ERROR(result);
217 return result.Unwrap() + 32;
218}
219
224
225////////////////////////////////////////////////////////////////////////////////
226
227ROOT::Experimental::Internal::RPageSinkDaos::RPageSinkDaos(std::string_view ntupleName, std::string_view uri,
228 const ROOT::RNTupleWriteOptions &options)
229 : RPagePersistentSink(ntupleName, options), fURI(uri)
230{
231 static std::once_flag once;
232 std::call_once(once, []() {
233 R__LOG_WARNING(ROOT::Internal::NTupleLog()) << "The DAOS backend is experimental and still under development. "
234 << "Do not store real data with this version of RNTuple!";
235 });
236 EnableDefaultMetrics("RPageSinkDaos");
237}
238
240
241void ROOT::Experimental::Internal::RPageSinkDaos::InitImpl(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
246 auto args = ParseDaosURI(fURI);
247 auto pool = std::make_unique<RDaosPool>(args.fPoolLabel);
248
249 fDaosContainer = std::make_unique<RDaosContainer>(std::move(pool), args.fContainerLabel, /*create =*/true);
250 fDaosContainer->SetDefaultObjectClass(fNTupleAnchor.fObjClass);
251
252 auto [locator, _] = RDaosContainerNTupleLocator::LocateNTuple(*fDaosContainer, fNTupleName);
253 fNTupleIndex = locator.GetIndex();
254
255 auto zipBuffer = MakeUninitArray<unsigned char>(length);
256 auto szZipHeader =
257 RNTupleCompressor::Zip(serializedHeader, length, GetWriteOptions().GetCompression(), zipBuffer.get());
258 WriteNTupleHeader(zipBuffer.get(), szZipHeader, length);
259}
260
263 const RPageStorage::RSealedPage &sealedPage)
264{
265 auto pageId = fPageId.fetch_add(1);
266
267 {
268 Detail::RNTupleAtomicTimer timer(fCounters->fTimeWallWrite, fCounters->fTimeCpuWrite);
269 RDaosKey daosKey = GetPageDaosKey(fNTupleIndex, pageId);
270 fDaosContainer->WriteSingleAkey(sealedPage.GetBuffer(), sealedPage.GetBufferSize(), daosKey.fOid, daosKey.fDkey,
271 daosKey.fAkey);
272 }
273
276 result.SetNBytesOnStorage(sealedPage.GetDataSize());
277 result.SetPosition(ROOT::RNTupleLocatorObject64{pageId});
278 fCounters->fNPageCommitted.Inc();
279 fCounters->fSzWritePayload.Add(sealedPage.GetBufferSize());
280 fNBytesCurrentCluster += sealedPage.GetBufferSize();
281 return result;
282}
283
284std::vector<ROOT::RNTupleLocator>
285ROOT::Experimental::Internal::RPageSinkDaos::CommitSealedPageVImpl(std::span<RPageStorage::RSealedPageGroup> ranges,
286 const std::vector<bool> &mask)
287{
289 std::vector<RNTupleLocator> locators;
290 auto nPages = mask.size();
291 locators.reserve(nPages);
292
293 int64_t payloadSz = 0;
294
295 /// Aggregate batch of requests by object ID and distribution key, determined by the ntuple-DAOS mapping
296 for (auto &range : ranges) {
297 for (auto sealedPageIt = range.fFirst; sealedPageIt != range.fLast; ++sealedPageIt) {
298 const RPageStorage::RSealedPage &s = *sealedPageIt;
299
300 const auto pageId = fPageId.fetch_add(1);
301
302 d_iov_t pageIov;
303 d_iov_set(&pageIov, const_cast<void *>(s.GetBuffer()), s.GetBufferSize());
304
305 RDaosKey daosKey = GetPageDaosKey(fNTupleIndex, pageId);
306 auto odPair = RDaosContainer::ROidDkeyPair{daosKey.fOid, daosKey.fDkey};
307 auto [it, ret] = writeRequests.emplace(odPair, RDaosContainer::RWOperation(odPair));
308 it->second.Insert(daosKey.fAkey, pageIov);
309
310 RNTupleLocator locator;
312 locator.SetNBytesOnStorage(s.GetDataSize());
314 locators.push_back(locator);
315
316 payloadSz += s.GetBufferSize();
317 }
318 }
319 fNBytesCurrentCluster += payloadSz;
320
321 {
322 Detail::RNTupleAtomicTimer timer(fCounters->fTimeWallWrite, fCounters->fTimeCpuWrite);
323 if (int err = fDaosContainer->WriteV(writeRequests))
324 throw ROOT::RException(R__FAIL("WriteV: error" + std::string(d_errstr(err))));
325 }
326
327 fCounters->fNPageCommitted.Add(nPages);
328 fCounters->fSzWritePayload.Add(payloadSz);
329
330 return locators;
331}
332
334{
335 return std::exchange(fNBytesCurrentCluster, 0);
336}
337
340 std::uint32_t length)
341{
342 auto bufPageListZip = MakeUninitArray<unsigned char>(length);
343 auto szPageListZip =
344 RNTupleCompressor::Zip(serializedPageList, length, GetWriteOptions().GetCompression(), bufPageListZip.get());
345
346 auto offsetData = fClusterGroupId.fetch_add(1);
347 // clang-format off
348 fDaosContainer->WriteSingleAkey(
349 bufPageListZip.get(),
350 szPageListZip,
351 daos_obj_id_t{kOidLowPageList, static_cast<decltype(daos_obj_id_t::hi)>(fNTupleIndex)},
352 kDistributionKeyDefault,
353 offsetData);
354 // clang-format on
357 result.SetNBytesOnStorage(szPageListZip);
358 result.SetPosition(RNTupleLocatorObject64{offsetData});
359 fCounters->fSzWritePayload.Add(static_cast<int64_t>(szPageListZip));
360 return result;
361}
362
364ROOT::Experimental::Internal::RPageSinkDaos::CommitDatasetImpl(unsigned char *serializedFooter, std::uint32_t length)
365{
366 auto bufFooterZip = MakeUninitArray<unsigned char>(length);
367 auto szFooterZip =
368 RNTupleCompressor::Zip(serializedFooter, length, GetWriteOptions().GetCompression(), bufFooterZip.get());
369 WriteNTupleFooter(bufFooterZip.get(), szFooterZip, length);
370 WriteNTupleAnchor();
371
372 // TODO: return the proper anchor locator+length
373 return {};
374}
375
376void ROOT::Experimental::Internal::RPageSinkDaos::WriteNTupleHeader(const void *data, size_t nbytes, size_t lenHeader)
377{
378 fDaosContainer->WriteSingleAkey(
379 data, nbytes, daos_obj_id_t{kOidLowMetadata, static_cast<decltype(daos_obj_id_t::hi)>(fNTupleIndex)},
380 kDistributionKeyDefault, kAttributeKeyHeader);
381 fNTupleAnchor.fLenHeader = lenHeader;
382 fNTupleAnchor.fNBytesHeader = nbytes;
383}
384
385void ROOT::Experimental::Internal::RPageSinkDaos::WriteNTupleFooter(const void *data, size_t nbytes, size_t lenFooter)
386{
387 fDaosContainer->WriteSingleAkey(
388 data, nbytes, daos_obj_id_t{kOidLowMetadata, static_cast<decltype(daos_obj_id_t::hi)>(fNTupleIndex)},
389 kDistributionKeyDefault, kAttributeKeyFooter);
390 fNTupleAnchor.fLenFooter = lenFooter;
391 fNTupleAnchor.fNBytesFooter = nbytes;
392}
393
395{
396 const auto ntplSize = RDaosNTupleAnchor::GetSize();
397 auto buffer = MakeUninitArray<unsigned char>(ntplSize);
398 fNTupleAnchor.Serialize(buffer.get());
399 fDaosContainer->WriteSingleAkey(
400 buffer.get(), ntplSize, daos_obj_id_t{kOidLowMetadata, static_cast<decltype(daos_obj_id_t::hi)>(fNTupleIndex)},
401 kDistributionKeyDefault, kAttributeKeyAnchor, kCidAnchor);
402}
403
404std::unique_ptr<ROOT::Internal::RPageSink>
406 const ROOT::RNTupleWriteOptions & /*opts*/) const
407{
408 throw ROOT::RException(R__FAIL("cloning a DAOS sink is not implemented yet"));
409}
410
411////////////////////////////////////////////////////////////////////////////////
412
413ROOT::Experimental::Internal::RPageSourceDaos::RPageSourceDaos(std::string_view ntupleName, std::string_view uri,
414 const ROOT::RNTupleReadOptions &options)
415 : RPageSource(ntupleName, options), fURI(uri)
416{
417 EnableDefaultMetrics("RPageSourceDaos");
418
419 auto args = ParseDaosURI(uri);
420 auto pool = std::make_unique<RDaosPool>(args.fPoolLabel);
421 fDaosContainer = std::make_unique<RDaosContainer>(std::move(pool), args.fContainerLabel);
422}
423
425{
426 StopClusterPoolBackgroundThread();
427}
428
430{
431 RDaosContainerNTupleLocator ntupleLocator;
432 std::tie(ntupleLocator, fDescriptorBuilder) =
433 RDaosContainerNTupleLocator::LocateNTuple(*fDaosContainer, fNTupleName);
434 if (!ntupleLocator.IsValid()) {
435 throw ROOT::RException(
436 R__FAIL("LoadStructureImpl: requested ntuple '" + fNTupleName + "' is not present in DAOS container."));
437 }
438 fAnchor = *ntupleLocator.fAnchor;
439 fNTupleIndex = ntupleLocator.GetIndex();
440
441 fDaosContainer->SetDefaultObjectClass(fAnchor.fObjClass);
442
443 // Reserve enough space for the compressed and the uncompressed header/footer (see AttachImpl)
444 const auto bufSize =
445 fAnchor.fNBytesHeader + fAnchor.fNBytesFooter + std::max(fAnchor.fLenHeader, fAnchor.fLenFooter);
446 fStructureBuffer.fBuffer = MakeUninitArray<unsigned char>(bufSize);
447 fStructureBuffer.fPtrHeader = fStructureBuffer.fBuffer.get();
448 fStructureBuffer.fPtrFooter = fStructureBuffer.fBuffer.get() + fAnchor.fNBytesHeader;
449
450 int err;
451 daos_obj_id_t oidMetadata{kOidLowMetadata, static_cast<decltype(daos_obj_id_t::hi)>(fNTupleIndex)};
452
453 if ((err = fDaosContainer->ReadSingleAkey(fStructureBuffer.fPtrHeader, fAnchor.fNBytesHeader, oidMetadata,
454 kDistributionKeyDefault, kAttributeKeyHeader))) {
455 throw ROOT::RException(R__FAIL("LoadStructureImpl: cannot load header: " + std::to_string(err)));
456 }
457
458 if ((err = fDaosContainer->ReadSingleAkey(fStructureBuffer.fPtrFooter, fAnchor.fNBytesFooter, oidMetadata,
459 kDistributionKeyDefault, kAttributeKeyFooter))) {
460 throw ROOT::RException(R__FAIL("LoadStructureImpl: cannot load footer: " + std::to_string(err)));
461 }
462}
463
465{
466 auto unzipBuf = reinterpret_cast<unsigned char *>(fStructureBuffer.fPtrFooter) + fAnchor.fNBytesFooter;
467
468 RNTupleDecompressor::Unzip(fStructureBuffer.fPtrHeader, fAnchor.fNBytesHeader, fAnchor.fLenHeader, unzipBuf);
469 RNTupleSerializer::DeserializeHeader(unzipBuf, fAnchor.fLenHeader, fDescriptorBuilder);
470
471 RNTupleDecompressor::Unzip(fStructureBuffer.fPtrFooter, fAnchor.fNBytesFooter, fAnchor.fLenFooter, unzipBuf);
472 RNTupleSerializer::DeserializeFooter(unzipBuf, fAnchor.fLenFooter, fDescriptorBuilder);
473
474 if (fDescriptorBuilder.GetDescriptor().GetName() != fNTupleName) {
475 // Hash already taken by a differently-named ntuple.
476 throw ROOT::RException(R__FAIL("LocateNTuple: ntuple name '" + fNTupleName + "' unavailable in this container."));
477 }
478
479 return fDescriptorBuilder.MoveDescriptor();
480}
481
483 unsigned char *buffer)
484{
485 std::lock_guard lockGuard(fContainerLock);
486 daos_obj_id_t oidPageList{kOidLowPageList, static_cast<decltype(daos_obj_id_t::hi)>(fNTupleIndex)};
487 fDaosContainer->ReadSingleAkey(buffer, locator.GetNBytesOnStorage(), oidPageList, kDistributionKeyDefault,
488 locator.GetPosition<RNTupleLocatorObject64>().GetLocation());
489}
490
492{
493 return fDaosContainer->GetDefaultObjectClass().ToString();
494}
495
497 RSealedPage &sealedPage)
498{
499 std::lock_guard lockGuard(fContainerLock);
500 RDaosKey daosKey = GetPageDaosKey(fNTupleIndex, locator.GetPosition<RNTupleLocatorObject64>().GetLocation());
501 fDaosContainer->ReadSingleAkey(const_cast<void *>(sealedPage.GetBuffer()), sealedPage.GetBufferSize(), daosKey.fOid,
502 daosKey.fDkey, daosKey.fAkey);
503}
504
505std::unique_ptr<ROOT::Internal::RPageSource> ROOT::Experimental::Internal::RPageSourceDaos::CloneImpl() const
506{
507 auto clone = std::make_unique<RPageSourceDaos>(fNTupleName, fURI, fOptions);
508 clone->fAnchor = fAnchor;
509 clone->fNTupleIndex = fNTupleIndex;
510 if (!fAnchor.fObjClass.empty())
511 clone->fDaosContainer->SetDefaultObjectClass(fAnchor.fObjClass);
512 return clone;
513}
514
515std::vector<std::unique_ptr<RCluster>>
517{
518 struct RDaosSealedPageLocator {
519 ROOT::DescriptorId_t fClusterId = 0;
520 ROOT::DescriptorId_t fColumnId = 0;
521 ROOT::NTupleSize_t fPageNo = 0;
522 std::uint64_t fPageId = 0;
523 std::uint64_t fDataSize = 0; // page payload
524 std::uint64_t fBufferSize = 0; // page payload + checksum (if available)
525 };
526
527 // Prepares read requests for a single cluster; `readRequests` is modified by this function. Requests are coalesced
528 // by OID and distribution key.
529 // TODO(jalopezg): this may be a private member function; that, however, requires additional changes given that
530 // `RDaosContainer::MultiObjectRWOperation_t` cannot be forward-declared
531 auto fnPrepareSingleCluster = [&](const RCluster::RKey &clusterKey,
533 auto clusterId = clusterKey.fClusterId;
534 std::vector<RDaosSealedPageLocator> onDiskPages;
535
536 unsigned clusterBufSz = 0, nPages = 0;
537 auto pageZeroMap = std::make_unique<ROOT::Internal::ROnDiskPageMap>();
538 PrepareLoadCluster(
539 clusterKey, *pageZeroMap,
540 [&](ROOT::DescriptorId_t physicalColumnId, ROOT::NTupleSize_t pageNo,
541 const ROOT::RClusterDescriptor::RPageInfo &pageInfo) {
542 const auto &pageLocator = pageInfo.GetLocator();
543 const auto pageId = pageLocator.GetPosition<RNTupleLocatorObject64>().GetLocation();
544 const auto pageBufferSize = pageLocator.GetNBytesOnStorage() + pageInfo.HasChecksum() * kNBytesPageChecksum;
545 onDiskPages.emplace_back(RDaosSealedPageLocator{clusterId, physicalColumnId, pageNo, pageId,
546 pageLocator.GetNBytesOnStorage(), pageBufferSize});
547
548 ++nPages;
549 clusterBufSz += pageBufferSize;
550 });
551
552 auto clusterBuffer = new unsigned char[clusterBufSz];
553 auto pageMap =
554 std::make_unique<ROOT::Internal::ROnDiskPageMapHeap>(std::unique_ptr<unsigned char[]>(clusterBuffer));
555
556 // Fill the cluster page map and the read requests for the RDaosContainer::ReadV() call
557 for (const auto &sealedLoc : onDiskPages) {
558 ROOT::Internal::ROnDiskPage::Key key(sealedLoc.fColumnId, sealedLoc.fPageNo);
559 pageMap->Register(key, ROOT::Internal::ROnDiskPage(clusterBuffer, sealedLoc.fBufferSize));
560
561 // Prepare new read request batched up by object ID and distribution key
562 d_iov_t iov;
563 d_iov_set(&iov, clusterBuffer, sealedLoc.fBufferSize);
564
565 RDaosKey daosKey = GetPageDaosKey(fNTupleIndex, sealedLoc.fPageId);
566 auto odPair = RDaosContainer::ROidDkeyPair{daosKey.fOid, daosKey.fDkey};
567 auto [itReq, ret] = readRequests.emplace(odPair, RDaosContainer::RWOperation(odPair));
568 itReq->second.Insert(daosKey.fAkey, iov);
569
570 clusterBuffer += sealedLoc.fBufferSize;
571 }
572 fCounters->fNPageRead.Add(nPages);
573 fCounters->fSzReadPayload.Add(clusterBufSz);
574
575 auto cluster = std::make_unique<RCluster>(clusterId);
576 cluster->Adopt(std::move(pageMap));
577 cluster->Adopt(std::move(pageZeroMap));
578 for (auto colId : clusterKey.fPhysicalColumnSet)
579 cluster->SetColumnAvailable(colId);
580 return cluster;
581 };
582
583 fCounters->fNClusterLoaded.Add(clusterKeys.size());
584
585 std::vector<std::unique_ptr<ROOT::Internal::RCluster>> clusters;
587 for (auto key : clusterKeys) {
588 clusters.emplace_back(fnPrepareSingleCluster(key, readRequests));
589 }
590
591 {
592 Detail::RNTupleAtomicTimer timer(fCounters->fTimeWallRead, fCounters->fTimeCpuRead);
593 std::lock_guard lockGuard(fContainerLock);
594 if (int err = fDaosContainer->ReadV(readRequests))
595 throw ROOT::RException(R__FAIL("ReadV: error" + std::string(d_errstr(err))));
596 }
597 fCounters->fNReadV.Inc();
598 fCounters->fNRead.Add(readRequests.size());
599
600 return clusters;
601}
602
603std::unique_ptr<ROOT::Internal::RPageSource>
#define R__FORWARD_ERROR(res)
Short-hand to return an RResult<T> in an error state (i.e. after checking)
Definition RError.hxx:326
#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:322
#define R__LOG_WARNING(...)
Definition RLogger.hxx:357
#define h(i)
Definition RSha256.hxx:106
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 mask
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
UInt_t Hash(const TString &s)
Definition TString.h:504
#define _(A, B)
Definition cfortran.h:112
Record wall time and CPU time between construction and destruction.
A RDaosContainer provides read/write access to objects in a given container.
Definition RDaos.hxx:155
RDaosObject::DistributionKey_t DistributionKey_t
Definition RDaos.hxx:158
std::unordered_map< ROidDkeyPair, RWOperation, ROidDkeyPair::Hash > MultiObjectRWOperation_t
Definition RDaos.hxx:229
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::AttributeKey_t AttributeKey_t
Definition RDaos.hxx:159
std::unique_ptr< ROOT::Internal::RPageSink > CloneAsHidden(std::string_view name, const ROOT::RNTupleWriteOptions &opts) const final
Creates a new sink with the same underlying storage as this but writing to a different RNTuple named ...
std::vector< RNTupleLocator > CommitSealedPageVImpl(std::span< RPageStorage::RSealedPageGroup > ranges, const std::vector< bool > &mask) final
Vector commit of preprocessed pages.
void WriteNTupleFooter(const void *data, size_t nbytes, size_t lenFooter)
std::uint64_t StageClusterImpl() final
Returns the number of bytes written to storage (excluding metadata)
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...
void WriteNTupleHeader(const void *data, size_t nbytes, size_t lenHeader)
void InitImpl(unsigned char *serializedHeader, std::uint32_t length) final
RPageSinkDaos(std::string_view ntupleName, std::string_view uri, const ROOT::RNTupleWriteOptions &options)
RNTupleLocator CommitSealedPageImpl(ROOT::DescriptorId_t physicalColumnId, const RPageStorage::RSealedPage &sealedPage) final
ROOT::RNTupleDescriptor AttachImpl() final
LoadStructureImpl() has been called before AttachImpl() is called
std::string GetObjectClass() const
Return the object class used for user data OIDs in this ntuple.
std::unique_ptr< RPageSource > CloneImpl() const final
The cloned page source creates a new connection to the pool/container.
void LoadSealedPageImpl(const RNTupleLocator &locator, RSealedPage &sealedPage) final
std::vector< std::unique_ptr< ROOT::Internal::RCluster > > LoadClusters(std::span< ROOT::Internal::RCluster::RKey > clusterKeys) final
Populates all the pages of the given cluster ids and columns; it is possible that some columns do not...
void LoadPageListImpl(const RNTupleLocator &locator, unsigned char *buffer) final
void LoadStructureImpl() final
Fills fStructureBuffer with the compressed header and footer.
std::unique_ptr< RPageSource > OpenWithDifferentAnchor(const ROOT::Internal::RNTupleLink &anchorLink, const ROOT::RNTupleReadOptions &options={}) final
Creates a new PageSource using the same underlying file as this but referring to a different RNTuple,...
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 ROOT::RNTupleReadOptions &options)
DAOS-specific user-tunable settings for storing ntuples.
An in-memory subset of the packed and compressed pages of a cluster.
Definition RCluster.hxx:147
Helper class to compress data blocks in the ROOT compression frame format.
static std::size_t Zip(const void *from, std::size_t nbytes, int compression, void *to)
Returns the size of the compressed data, written into the provided output buffer.
Helper class to uncompress data blocks in the ROOT compression frame format.
static void Unzip(const void *from, size_t nbytes, size_t dataLen, void *to)
The nbytes parameter provides the size ls of the from buffer.
A helper class for piece-wise construction of an RNTupleDescriptor.
void SetVersion(std::uint16_t versionEpoch, std::uint16_t versionMajor, std::uint16_t versionMinor, std::uint16_t versionPatch)
void AddToOnDiskFooterSize(std::uint64_t size)
The real footer size also include the page list envelopes.
A helper class for serializing and deserialization of the RNTuple binary format.
static RResult< std::uint32_t > DeserializeString(const void *buffer, std::uint64_t bufSize, std::string &val)
static std::uint32_t SerializeUInt32(std::uint32_t val, void *buffer)
static std::uint32_t DeserializeUInt32(const void *buffer, std::uint32_t &val)
static std::uint32_t SerializeUInt16(std::uint16_t val, void *buffer)
static RResult< void > DeserializeFooter(const void *buffer, std::uint64_t bufSize, ROOT::Internal::RNTupleDescriptorBuilder &descBuilder)
static std::uint32_t SerializeString(const std::string &val, void *buffer)
static std::uint32_t DeserializeUInt16(const void *buffer, std::uint16_t &val)
static RResult< void > DeserializeHeader(const void *buffer, std::uint64_t bufSize, ROOT::Internal::RNTupleDescriptorBuilder &descBuilder)
static std::uint32_t DeserializeUInt64(const void *buffer, std::uint64_t &val)
static std::uint32_t SerializeUInt64(std::uint64_t val, void *buffer)
A page as being stored on disk, that is packed and compressed.
Definition RCluster.hxx:40
Base class for a sink with a physical storage backend.
void EnableDefaultMetrics(const std::string &prefix)
Enables the default set of metrics provided by RPageSink.
Abstract interface to read data from an ntuple.
void EnableDefaultMetrics(const std::string &prefix)
Enables the default set of metrics provided by RPageSource.
Base class for all ROOT issued exceptions.
Definition RError.hxx:78
The on-storage metadata of an RNTuple.
RNTupleLocator payload that is common for object stores using 64bit location information.
std::uint64_t GetLocation() const
Generic information about the physical location of data.
std::uint64_t GetNBytesOnStorage() const
T GetPosition() const
Note that for GetPosition() / SetPosition(), the locator type must correspond (kTypeFile,...
void SetType(ELocatorType type)
void SetPosition(std::uint64_t position)
void SetNBytesOnStorage(std::uint64_t nBytesOnStorage)
Common user-tunable settings for reading RNTuples.
Common user-tunable settings for storing RNTuples.
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:222
const char * d_errstr(int rc)
static void d_iov_set(d_iov_t *iov, void *buf, size_t size)
Definition daos.h:50
@ OC_UNKNOWN
Definition daos.h:109
uint16_t daos_oclass_id_t
Definition daos.h:135
ROOT::RLogChannel & NTupleLog()
Log channel for RNTuple diagnostics.
std::unique_ptr< T[]> MakeUninitArray(std::size_t size)
Make an array of default-initialized elements.
std::uint64_t DescriptorId_t
Distriniguishes elements of the same type within a descriptor, e.g. different fields.
std::uint64_t NTupleSize_t
Integer type long enough to hold the maximum number of entries in a column.
A pair of <object ID, distribution key> that can be used to issue a fetch/update request for multiple...
Definition RDaos.hxx:164
Describes a read/write operation on multiple attribute keys under the same object ID and distribution...
Definition RDaos.hxx:188
Entry point for an RNTuple in a DAOS container.
std::uint32_t fNBytesFooter
The size of the compressed ntuple footer.
std::uint64_t fVersionAnchor
Allows for evolving the struct in future versions.
std::string fObjClass
The object class for user data OIDs, e.g. SX
std::uint16_t fVersionEpoch
Version of the binary format supported by the writer.
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 fLenFooter
The size of the uncompressed ntuple footer.
std::uint32_t fNBytesHeader
The size of the compressed ntuple header.
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:106
The identifiers that specifies the content of a (partial) cluster.
Definition RCluster.hxx:151
ROOT::DescriptorId_t fClusterId
Definition RCluster.hxx:152
On-disk pages within a page source are identified by the column and page number.
Definition RCluster.hxx:50
A sealed page contains the bytes of a page as written to storage (packed & compressed).
Information about a single page in the context of a cluster's page range.
const RNTupleLocator & GetLocator() const
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