Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion tree/ntuple/inc/ROOT/RMiniFile.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ private:
/// what happens in `RNTupleFileWriter::WriteBlob()`.
std::uint64_t fMaxKeySize = 0;

/// Information about the streamer info record cache on file open from the TFile header. Used in LoadStreamerInfo.
std::uint64_t fSeekKeyInfo = 0;
std::uint64_t fNbytesKeyAndInfo = 0;

/// Used when the file container turns out to be a bare file
RResult<RNTuple> GetNTupleBare(std::string_view ntupleName);
/// Used when the file turns out to be a TFile container. The ntuplePath variable is either the ntuple name
Expand Down Expand Up @@ -96,7 +100,7 @@ public:
void ReadBuffer(void *buffer, size_t nbytes, std::uint64_t offset);
/// Like ReadBuffer but returns a RResult instead of throwing.
ROOT::RResult<void> TryReadBuffer(void *buffer, size_t nbytes, std::uint64_t offset);
/// Attempts to load the streamer info from the file.
/// Load the streamer info from the file into the global list of streamer infos
void LoadStreamerInfo();

std::uint64_t GetMaxKeySize() const { return fMaxKeySize; }
Expand Down
4 changes: 0 additions & 4 deletions tree/ntuple/inc/ROOT/RPageStorage.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -906,10 +906,6 @@ public:
/// connecting streamer fields so that emulated classes can be read.
void RegisterStreamerInfos();

/// Forces the loading of ROOT StreamerInfo from the underlying file. This currently only has an effect for
/// TFile-backed sources.
virtual void LoadStreamerInfo() = 0;

/// Creates a new PageSource using the same underlying file as this but referring to a different RNTuple,
/// described by `anchorLink`.
virtual std::unique_ptr<RPageSource> OpenWithDifferentAnchor(const ROOT::Internal::RNTupleLink &anchorLink,
Expand Down
2 changes: 0 additions & 2 deletions tree/ntuple/inc/ROOT/RPageStorageDaos.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,6 @@ public:
/// Return the object class used for user data OIDs in this ntuple.
std::string GetObjectClass() const;

void LoadStreamerInfo() final;

std::unique_ptr<RPageSource> OpenWithDifferentAnchor(const ROOT::Internal::RNTupleLink &anchorLink,
const ROOT::RNTupleReadOptions &options = {}) final;
}; // class RPageSourceDaos
Expand Down
2 changes: 0 additions & 2 deletions tree/ntuple/inc/ROOT/RPageStorageFile.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -189,8 +189,6 @@ public:

std::vector<std::unique_ptr<ROOT::Internal::RCluster>>
LoadClusters(std::span<ROOT::Internal::RCluster::RKey> clusterKeys) final;

void LoadStreamerInfo() final;
}; // class RPageSourceFile

} // namespace Internal
Expand Down
17 changes: 10 additions & 7 deletions tree/ntuple/src/RMiniFile.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -723,16 +723,15 @@ std::uint64_t ROOT::Internal::RMiniFileReader::SearchInDirectory(std::uint64_t &

void ROOT::Internal::RMiniFileReader::LoadStreamerInfo()
{
RTFHeader fileHeader;
ReadBuffer(&fileHeader, sizeof(fileHeader), 0);

const std::uint64_t seekKeyInfo = fileHeader.GetSeekInfo();
if (fIsBare == 0)
return;

RTFKey key;
ReadBuffer(&key, sizeof(key), seekKeyInfo);
ReadBuffer(&key, sizeof(key), fSeekKeyInfo);

const std::uint64_t nbytesInfo = fileHeader.GetNbytesInfo() - key.fKeyLen;
const std::uint64_t seekInfo = seekKeyInfo + key.fKeyLen;
R__ASSERT(fNbytesKeyAndInfo >= key.fKeyLen);
const std::uint64_t nbytesInfo = fNbytesKeyAndInfo - key.fKeyLen;
const std::uint64_t seekInfo = fSeekKeyInfo + key.fKeyLen;
const std::uint32_t uncompLenInfo = key.fObjLen;
auto streamerInfo = MakeUninitArray<char>(uncompLenInfo);
if (nbytesInfo == uncompLenInfo) {
Expand Down Expand Up @@ -770,6 +769,9 @@ ROOT::RResult<ROOT::RNTuple> ROOT::Internal::RMiniFileReader::GetNTupleProper(st
RTFHeader fileHeader;
ReadBuffer(&fileHeader, sizeof(fileHeader), 0);

fSeekKeyInfo = fileHeader.GetSeekInfo();
fNbytesKeyAndInfo = fileHeader.GetNbytesInfo();

RTFKey key;
RTFString name;
ReadBuffer(&key, sizeof(key), fileHeader.fBEGIN);
Expand Down Expand Up @@ -817,6 +819,7 @@ ROOT::RResult<ROOT::RNTuple> ROOT::Internal::RMiniFileReader::GetNTupleProper(st

const auto objNbytes = key.GetSize() - key.fKeyLen;
auto res = GetNTupleProperAtOffset(offset, objNbytes, key.fObjLen);

return res;
}

Expand Down
4 changes: 0 additions & 4 deletions tree/ntuple/src/RNTupleMerger.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -1393,10 +1393,6 @@ ROOT::RResult<void> RNTupleMerger::Merge(std::span<RPageSource *> sources, const

// Merge main loop
for (RPageSource *source : sources) {
// We need to make sure the streamer info from the source files is loaded otherwise we may not be able
// to build the streamer info of user-defined types unless we have their dictionaries available.
source->LoadStreamerInfo();

source->Attach(RNTupleSerializer::EDescriptorDeserializeMode::kForWriting);
auto srcDescriptor = source->GetSharedDescriptorGuard();
mergeData.fSrcDescriptor = &srcDescriptor.GetRef();
Expand Down
5 changes: 0 additions & 5 deletions tree/ntuple/src/RPageStorageDaos.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -596,11 +596,6 @@ ROOT::Experimental::Internal::RPageSourceDaos::LoadClusters(std::span<RCluster::
return clusters;
}

void ROOT::Experimental::Internal::RPageSourceDaos::LoadStreamerInfo()
{
R__LOG_WARNING(ROOT::Internal::NTupleLog()) << "DAOS-backed sources have no associated StreamerInfo to load.";
}

std::unique_ptr<ROOT::Internal::RPageSource>
ROOT::Experimental::Internal::RPageSourceDaos::OpenWithDifferentAnchor(const ROOT::Internal::RNTupleLink &,
const ROOT::RNTupleReadOptions &)
Expand Down
9 changes: 4 additions & 5 deletions tree/ntuple/src/RPageStorageFile.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,10 @@ void ROOT::Internal::RPageSourceFile::LoadStructureImpl()
// Otherwise, the page source was created by OpenFromAnchor()
if (!fAnchor) {
fAnchor = fReader.GetNTuple(fNTupleName).Unwrap();
// We couple finding the RNTuple anchor to loading the streamer infos.
// If we already have the anchor, we must have opened the file before (either through TFile or by the source of
// OpenWithDifferentAnchor(), in which case we already loaded the streamer info) .
fReader.LoadStreamerInfo();
}
fReader.SetMaxKeySize(fAnchor->GetMaxKeySize());

Expand Down Expand Up @@ -711,8 +715,3 @@ ROOT::Internal::RPageSourceFile::LoadClusters(std::span<RCluster::RKey> clusterK

return clusters;
}

void ROOT::Internal::RPageSourceFile::LoadStreamerInfo()
{
fReader.LoadStreamerInfo();
}
1 change: 0 additions & 1 deletion tree/ntuple/test/ntuple_cluster.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ class RPageSourceMock : public RPageSource {
std::unique_ptr<RPageSource> CloneImpl() const final { return nullptr; }
void LoadPageListImpl(const ROOT::RNTupleLocator &, unsigned char *) final {}
void LoadSealedPageImpl(const ROOT::RNTupleLocator &, RSealedPage &) final {}
void LoadStreamerInfo() final {}
std::unique_ptr<ROOT::Internal::RPageSource>
OpenWithDifferentAnchor(const ROOT::Internal::RNTupleLink &, const ROOT::RNTupleReadOptions &) final
{
Expand Down
60 changes: 16 additions & 44 deletions tree/ntuple/test/ntuple_emulated.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ TEST(RNTupleEmulated, EmulatedFields_Simple)

FileRaii fileGuard("test_ntuple_emulated_fields.root");

EXPECT_NO_STREAMER_OR_DICTIONARY();

ExecInFork([&] {
// The child process writes the file and exits, but the file must be preserved to be read by the parent.
fileGuard.PreserveFile();
Expand All @@ -32,12 +34,6 @@ TEST(RNTupleEmulated, EmulatedFields_Simple)
auto model = RNTupleModel::Create();
model->AddField(RFieldBase::Create("f", "Outer_Simple").Unwrap());

// TStreamerInfo::Build will report a warning for interpreted classes (but only for members).
// See also https://github.com/root-project/root/issues/9371
ROOT::TestSupport::CheckDiagsRAII diagRAII;
diagRAII.optionalDiag(kWarning, "TStreamerInfo::Build", "has no streamer or dictionary",
/*matchFullMessage=*/false);

auto writer = RNTupleWriter::Recreate(std::move(model), "ntpl", fileGuard.GetPath());
writer->Fill();

Expand Down Expand Up @@ -93,9 +89,6 @@ TEST(RNTupleEmulated, EmulatedFields_Simple)
RNTupleDescriptor::RCreateModelOptions cmOpts;
cmOpts.SetEmulateUnknownTypes(true);

ROOT::TestSupport::CheckDiagsRAII diagRAII;
diagRAII.optionalDiag(kWarning, "TClass::Init", "no dictionary for class",
/*matchFullMessage=*/false);
std::unique_ptr<TFile> file(TFile::Open(fileGuard.GetPath().c_str()));
std::unique_ptr<ROOT::RNTuple> ntpl(file->Get<ROOT::RNTuple>("ntpl"));
reader = RNTupleReader::Open(cmOpts, *ntpl);
Expand All @@ -121,6 +114,8 @@ TEST(RNTupleEmulated, EmulatedFields_Vecs)

FileRaii fileGuard("test_ntuple_emulated_fields_vecs.root");

EXPECT_NO_STREAMER_OR_DICTIONARY();

ExecInFork([&] {
// The child process writes the file and exits, but the file must be preserved to be read by the parent.
fileGuard.PreserveFile();
Expand All @@ -144,12 +139,6 @@ TEST(RNTupleEmulated, EmulatedFields_Vecs)
auto model = RNTupleModel::Create();
model->AddField(RFieldBase::Create("outers", "std::vector<Outer_Vecs>").Unwrap());

// TStreamerInfo::Build will report a warning for interpreted classes (but only for members).
// See also https://github.com/root-project/root/issues/9371
ROOT::TestSupport::CheckDiagsRAII diagRAII;
diagRAII.optionalDiag(kWarning, "TStreamerInfo::Build", "has no streamer or dictionary",
/*matchFullMessage=*/false);

auto writer = RNTupleWriter::Recreate(std::move(model), "ntpl", fileGuard.GetPath());
writer->Fill();

Expand Down Expand Up @@ -222,6 +211,8 @@ TEST(RNTupleEmulated, EmulatedFields_VecsTemplatedWrapper)
{
FileRaii fileGuard("test_ntuple_emulated_fields_vecs_templated_wrapper.root");

EXPECT_NO_STREAMER_OR_DICTIONARY();

ExecInFork([&] {
// The child process writes the file and exits, but the file must be preserved to be read by the parent.
fileGuard.PreserveFile();
Expand Down Expand Up @@ -298,6 +289,8 @@ TEST(RNTupleEmulated, EmulatedFields_EmptyStruct)

FileRaii fileGuard("test_ntuple_emulated_emptystruct.root");

EXPECT_NO_STREAMER_OR_DICTIONARY();

ExecInFork([&] {
// The child process writes the file and exits, but the file must be preserved to be read by the parent.
fileGuard.PreserveFile();
Expand All @@ -316,12 +309,6 @@ TEST(RNTupleEmulated, EmulatedFields_EmptyStruct)
auto model = RNTupleModel::Create();
model->AddField(RFieldBase::Create("f", "Outer_EmptyStruct").Unwrap());

// TStreamerInfo::Build will report a warning for interpreted classes (but only for members).
// See also https://github.com/root-project/root/issues/9371
ROOT::TestSupport::CheckDiagsRAII diagRAII;
diagRAII.optionalDiag(kWarning, "TStreamerInfo::Build", "has no streamer or dictionary",
/*matchFullMessage=*/false);

auto writer = RNTupleWriter::Recreate(std::move(model), "ntpl", fileGuard.GetPath());
writer->Fill();
});
Expand Down Expand Up @@ -373,6 +360,8 @@ TEST(RNTupleEmulated, EmulatedFields_EmptyVec)

FileRaii fileGuard("test_ntuple_emulated_emptyvec.root");

EXPECT_NO_STREAMER_OR_DICTIONARY();

ExecInFork([&] {
// The child process writes the file and exits, but the file must be preserved to be read by the parent.
fileGuard.PreserveFile();
Expand All @@ -396,11 +385,6 @@ TEST(RNTupleEmulated, EmulatedFields_EmptyVec)
ProcessLine("ptrInners->push_back(Inner_EmptyVec{});");
ProcessLine("ptrInners->push_back(Inner_EmptyVec{});");

// TStreamerInfo::Build will report a warning for interpreted classes (but only for members).
// See also https://github.com/root-project/root/issues/9371
ROOT::TestSupport::CheckDiagsRAII diagRAII;
diagRAII.optionalDiag(kWarning, "TStreamerInfo::Build", "has no streamer or dictionary",
/*matchFullMessage=*/false);
writer.reset();
});

Expand Down Expand Up @@ -453,6 +437,8 @@ TEST(RNTupleEmulated, EmulatedFields_Write)

FileRaii fileGuard("test_ntuple_emulated_write.root");

EXPECT_NO_STREAMER_OR_DICTIONARY();

ExecInFork([&] {
fileGuard.PreserveFile();

Expand All @@ -476,11 +462,6 @@ TEST(RNTupleEmulated, EmulatedFields_Write)
auto writer = RNTupleWriter::Recreate(std::move(model), "ntpl", fileGuard.GetPath());
writer->Fill();

// TStreamerInfo::Build will report a warning for interpreted classes (but only for members).
// See also https://github.com/root-project/root/issues/9371
ROOT::TestSupport::CheckDiagsRAII diagRAII;
diagRAII.optionalDiag(kWarning, "TStreamerInfo::Build", "has no streamer or dictionary",
/*matchFullMessage=*/false);
writer.reset();
});

Expand All @@ -504,6 +485,8 @@ TEST(RNTupleEmulated, CollectionProxy)
{
FileRaii fileGuard("test_ntuple_emulated_collproxy.root");

EXPECT_NO_STREAMER_OR_DICTIONARY();

// Declare a custom type in a separate process, then write it through a custom collection proxy.
// In the main process we load the generated RNTuple without having its dictionary available and we verify
// we can read it (only) via field emulation (as an untyped VectorField).
Expand Down Expand Up @@ -648,11 +631,6 @@ TEST(RNTupleEmulated, CollectionProxy)
ProcessLine("pProxyC->v.clear();");
writer->Fill();

// TStreamerInfo::Build will report a warning for interpreted classes (but only for members).
// See also https://github.com/root-project/root/issues/9371
ROOT::TestSupport::CheckDiagsRAII diagRAII;
diagRAII.optionalDiag(kWarning, "TStreamerInfo::Build", "has no streamer or dictionary",
/*matchFullMessage=*/false);
writer.reset();
});

Expand Down Expand Up @@ -692,6 +670,8 @@ TEST(RNTupleEmulated, MergeEmulated)
FileRaii fileGuard2("test_ntuple_merge_emulated2.root");
FileRaii fileGuardOut("test_ntuple_merge_emulated_out.root");

EXPECT_NO_STREAMER_OR_DICTIONARY();

ExecInFork([&] {
fileGuard1.PreserveFile();
fileGuard2.PreserveFile();
Expand Down Expand Up @@ -726,11 +706,6 @@ TEST(RNTupleEmulated, MergeEmulated)
ProcessLine("ptr2->fInt2 = 66;");
writer2->Fill();

// TStreamerInfo::Build will report a warning for interpreted classes (but only for members).
// See also https://github.com/root-project/root/issues/9371
ROOT::TestSupport::CheckDiagsRAII diagRAII;
diagRAII.optionalDiag(kWarning, "TStreamerInfo::Build", "has no streamer or dictionary",
/*matchFullMessage=*/false);
writer.reset();
writer2.reset();
});
Expand All @@ -745,9 +720,6 @@ TEST(RNTupleEmulated, MergeEmulated)
}

{
ROOT::TestSupport::CheckDiagsRAII diagRAII;
diagRAII.requiredDiag(kWarning, "TClass::Init", "no dictionary", /*matchFullMessage=*/false);

auto destination = std::make_unique<RPageSinkFile>("ntuple", fileGuardOut.GetPath(), RNTupleWriteOptions());
RNTupleMerger merger{std::move(destination)};
auto res = merger.Merge(sourcePtrs);
Expand Down
1 change: 0 additions & 1 deletion tree/ntuple/test/ntuple_endian.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ class RPageSourceMock : public RPageSource {
std::unique_ptr<RPageSource> CloneImpl() const final { return nullptr; }
void LoadPageListImpl(const ROOT::RNTupleLocator &, unsigned char *) final {}
void LoadSealedPageImpl(const ROOT::RNTupleLocator &, RSealedPage &) final {}
void LoadStreamerInfo() final {}

std::unique_ptr<ROOT::Internal::RPageSource>
OpenWithDifferentAnchor(const ROOT::Internal::RNTupleLink &, const ROOT::RNTupleReadOptions &) final
Expand Down
Loading
Loading