Skip to content

Commit dc266ee

Browse files
committed
[ntuple] implement LoadStructureImpl() for DAOS
Make use of the dedicated callback that loads the compressed header and footer, instead of leaving it squashed in AttachImpl().
1 parent 2ac56be commit dc266ee

3 files changed

Lines changed: 56 additions & 37 deletions

File tree

tree/ntuple/inc/ROOT/RPageStorage.hxx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -744,6 +744,7 @@ protected:
744744

745745
ROOT::RNTupleReadOptions fOptions;
746746

747+
/// Fills fStructureBuffer with the compressed header and footer
747748
virtual void LoadStructureImpl() = 0;
748749
/// `LoadStructureImpl()` has been called before `AttachImpl()` is called
749750
virtual ROOT::RNTupleDescriptor AttachImpl(ROOT::Internal::RNTupleSerializer::EDescriptorDeserializeMode mode) = 0;

tree/ntuple/inc/ROOT/RPageStorageDaos.hxx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,12 +155,13 @@ private:
155155
/// A URI to a DAOS pool of the form 'daos://pool-label/container-label'
156156
std::string fURI;
157157

158+
RDaosNTupleAnchor fAnchor;
158159
ROOT::Internal::RNTupleDescriptorBuilder fDescriptorBuilder;
159160

160161
void LoadSealedPageImpl(const RNTupleLocator &locator, RSealedPage &sealedPage) final;
161162

162163
protected:
163-
void LoadStructureImpl() final {}
164+
void LoadStructureImpl() final;
164165
ROOT::RNTupleDescriptor AttachImpl(ROOT::Internal::RNTupleSerializer::EDescriptorDeserializeMode mode) final;
165166
/// The cloned page source creates a new connection to the pool/container.
166167
std::unique_ptr<RPageSource> CloneImpl() const final;

tree/ntuple/src/RPageStorageDaos.cxx

Lines changed: 53 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include <cstdlib>
3636
#include <cstring>
3737
#include <limits>
38+
#include <tuple>
3839
#include <utility>
3940
#include <regex>
4041
#include <cassert>
@@ -129,7 +130,7 @@ struct RDaosContainerNTupleLocator {
129130
int InitNTupleDescriptorBuilder(ROOT::Experimental::Internal::RDaosContainer &cont,
130131
ROOT::Internal::RNTupleDescriptorBuilder &builder)
131132
{
132-
std::unique_ptr<unsigned char[]> buffer, zipBuffer;
133+
std::unique_ptr<unsigned char[]> buffer;
133134
auto &anchor = fAnchor.emplace();
134135
int err;
135136

@@ -146,22 +147,7 @@ struct RDaosContainerNTupleLocator {
146147

147148
builder.SetVersion(anchor.fVersionEpoch, anchor.fVersionMajor, anchor.fVersionMinor, anchor.fVersionPatch);
148149
builder.SetOnDiskHeaderSize(anchor.fNBytesHeader);
149-
buffer = MakeUninitArray<unsigned char>(anchor.fLenHeader);
150-
zipBuffer = MakeUninitArray<unsigned char>(anchor.fNBytesHeader);
151-
if ((err = cont.ReadSingleAkey(zipBuffer.get(), anchor.fNBytesHeader, oidMetadata, kDistributionKeyDefault,
152-
kAttributeKeyHeader, kCidMetadata)))
153-
return err;
154-
RNTupleDecompressor::Unzip(zipBuffer.get(), anchor.fNBytesHeader, anchor.fLenHeader, buffer.get());
155-
RNTupleSerializer::DeserializeHeader(buffer.get(), anchor.fLenHeader, builder);
156-
157150
builder.AddToOnDiskFooterSize(anchor.fNBytesFooter);
158-
buffer = MakeUninitArray<unsigned char>(anchor.fLenFooter);
159-
zipBuffer = MakeUninitArray<unsigned char>(anchor.fNBytesFooter);
160-
if ((err = cont.ReadSingleAkey(zipBuffer.get(), anchor.fNBytesFooter, oidMetadata, kDistributionKeyDefault,
161-
kAttributeKeyFooter, kCidMetadata)))
162-
return err;
163-
RNTupleDecompressor::Unzip(zipBuffer.get(), anchor.fNBytesFooter, anchor.fLenFooter, buffer.get());
164-
RNTupleSerializer::DeserializeFooter(buffer.get(), anchor.fLenFooter, builder);
165151

166152
return 0;
167153
}
@@ -174,13 +160,7 @@ struct RDaosContainerNTupleLocator {
174160
auto &loc = result.first;
175161
auto &builder = result.second;
176162

177-
if (int err = loc.InitNTupleDescriptorBuilder(cont, builder); !err) {
178-
if (ntupleName.empty() || ntupleName != builder.GetDescriptor().GetName()) {
179-
// Hash already taken by a differently-named ntuple.
180-
throw ROOT::RException(
181-
R__FAIL("LocateNTuple: ntuple name '" + ntupleName + "' unavailable in this container."));
182-
}
183-
}
163+
loc.InitNTupleDescriptorBuilder(cont, builder);
184164
return result;
185165
}
186166
};
@@ -455,27 +435,64 @@ ROOT::Experimental::Internal::RPageSourceDaos::~RPageSourceDaos()
455435
StopClusterPoolBackgroundThread();
456436
}
457437

438+
void ROOT::Experimental::Internal::RPageSourceDaos::LoadStructureImpl()
439+
{
440+
RDaosContainerNTupleLocator ntupleLocator;
441+
std::tie(ntupleLocator, fDescriptorBuilder) =
442+
RDaosContainerNTupleLocator::LocateNTuple(*fDaosContainer, fNTupleName);
443+
if (!ntupleLocator.IsValid()) {
444+
throw ROOT::RException(
445+
R__FAIL("LoadStructureImpl: requested ntuple '" + fNTupleName + "' is not present in DAOS container."));
446+
}
447+
fAnchor = *ntupleLocator.fAnchor;
448+
fNTupleIndex = ntupleLocator.GetIndex();
449+
450+
auto oclass = RDaosObject::ObjClassId(fAnchor.fObjClass);
451+
if (oclass.IsUnknown())
452+
throw ROOT::RException(R__FAIL("LoadStructureImpl: unknown object class " + fAnchor.fObjClass));
453+
fDaosContainer->SetDefaultObjectClass(oclass);
454+
455+
// Reserve enough space for the compressed and the uncompressed header/footer (see AttachImpl)
456+
const auto bufSize =
457+
fAnchor.fNBytesHeader + fAnchor.fNBytesFooter + std::max(fAnchor.fLenHeader, fAnchor.fLenFooter);
458+
fStructureBuffer.fBuffer = MakeUninitArray<unsigned char>(bufSize);
459+
fStructureBuffer.fPtrHeader = fStructureBuffer.fBuffer.get();
460+
fStructureBuffer.fPtrFooter = fStructureBuffer.fBuffer.get() + fAnchor.fNBytesHeader;
461+
462+
int err;
463+
daos_obj_id_t oidMetadata{kOidLowMetadata, static_cast<decltype(daos_obj_id_t::hi)>(fNTupleIndex)};
464+
465+
if ((err = fDaosContainer->ReadSingleAkey(fStructureBuffer.fPtrHeader, fAnchor.fNBytesHeader, oidMetadata,
466+
kDistributionKeyDefault, kAttributeKeyHeader, kCidMetadata))) {
467+
throw ROOT::RException(R__FAIL("LoadStructureImpl: cannot load header: " + std::to_string(err)));
468+
}
469+
470+
if ((err = fDaosContainer->ReadSingleAkey(fStructureBuffer.fPtrFooter, fAnchor.fNBytesFooter, oidMetadata,
471+
kDistributionKeyDefault, kAttributeKeyFooter, kCidMetadata))) {
472+
throw ROOT::RException(R__FAIL("LoadStructureImpl: cannot load footer: " + std::to_string(err)));
473+
}
474+
}
475+
458476
ROOT::RNTupleDescriptor
459477
ROOT::Experimental::Internal::RPageSourceDaos::AttachImpl(RNTupleSerializer::EDescriptorDeserializeMode mode)
460478
{
461-
ROOT::RNTupleDescriptor ntplDesc;
462-
std::unique_ptr<unsigned char[]> buffer, zipBuffer;
479+
auto unzipBuf = reinterpret_cast<unsigned char *>(fStructureBuffer.fPtrFooter) + fAnchor.fNBytesFooter;
463480

464-
auto [locator, descBuilder] = RDaosContainerNTupleLocator::LocateNTuple(*fDaosContainer, fNTupleName);
465-
if (!locator.IsValid())
466-
throw ROOT::RException(
467-
R__FAIL("Attach: requested ntuple '" + fNTupleName + "' is not present in DAOS container."));
481+
RNTupleDecompressor::Unzip(fStructureBuffer.fPtrHeader, fAnchor.fNBytesHeader, fAnchor.fLenHeader, unzipBuf);
482+
RNTupleSerializer::DeserializeHeader(unzipBuf, fAnchor.fLenHeader, fDescriptorBuilder);
468483

469-
auto oclass = RDaosObject::ObjClassId(locator.fAnchor->fObjClass);
470-
if (oclass.IsUnknown())
471-
throw ROOT::RException(R__FAIL("Attach: unknown object class " + locator.fAnchor->fObjClass));
484+
RNTupleDecompressor::Unzip(fStructureBuffer.fPtrFooter, fAnchor.fNBytesFooter, fAnchor.fLenFooter, unzipBuf);
485+
RNTupleSerializer::DeserializeFooter(unzipBuf, fAnchor.fLenFooter, fDescriptorBuilder);
472486

473-
fDaosContainer->SetDefaultObjectClass(oclass);
474-
fNTupleIndex = locator.GetIndex();
475-
daos_obj_id_t oidPageList{kOidLowPageList, static_cast<decltype(daos_obj_id_t::hi)>(fNTupleIndex)};
487+
if (fDescriptorBuilder.GetDescriptor().GetName() != fNTupleName) {
488+
// Hash already taken by a differently-named ntuple.
489+
throw ROOT::RException(R__FAIL("LocateNTuple: ntuple name '" + fNTupleName + "' unavailable in this container."));
490+
}
476491

477-
auto desc = descBuilder.MoveDescriptor();
492+
auto desc = fDescriptorBuilder.MoveDescriptor();
478493

494+
std::unique_ptr<unsigned char[]> buffer, zipBuffer;
495+
daos_obj_id_t oidPageList{kOidLowPageList, static_cast<decltype(daos_obj_id_t::hi)>(fNTupleIndex)};
479496
for (const auto &cgDesc : desc.GetClusterGroupIterable()) {
480497
buffer = MakeUninitArray<unsigned char>(cgDesc.GetPageListLength());
481498
zipBuffer = MakeUninitArray<unsigned char>(cgDesc.GetPageListLocator().GetNBytesOnStorage());

0 commit comments

Comments
 (0)