Skip to content

Commit 1f6a481

Browse files
committed
[ntuple] create streamer infos from TClass names
Get the streamer info records of class fields and streamer fields from their meta (TClass) normalized name. Previously, the names came from the descriptor, which has them already RNTuple normalized.
1 parent 2d27aed commit 1f6a481

15 files changed

+188
-279
lines changed

tree/ntuple/inc/ROOT/RField.hxx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,7 @@ public:
281281
size_t GetAlignment() const final;
282282
std::uint32_t GetTypeVersion() const final;
283283
std::uint32_t GetTypeChecksum() const final;
284+
TClass *GetClass() const { return fClass; }
284285
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final;
285286
};
286287

tree/ntuple/inc/ROOT/RNTupleDescriptor.hxx

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1762,9 +1762,6 @@ public:
17621762
/// - Logical columns of piece two
17631763
/// - ...
17641764
void ShiftAliasColumns(std::uint32_t offset);
1765-
1766-
/// Get the streamer info records for custom classes. Currently requires the corresponding dictionaries to be loaded.
1767-
ROOT::Internal::RNTupleSerializer::StreamerInfoMap_t BuildStreamerInfos() const;
17681765
};
17691766

17701767
inline RNTupleDescriptor CloneDescriptorSchema(const RNTupleDescriptor &desc)

tree/ntuple/inc/ROOT/RPageStorage.hxx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -521,7 +521,7 @@ public:
521521

522522
/// Updates the descriptor and calls InitImpl() that handles the backend-specific details (file, DAOS, etc.)
523523
void InitImpl(RNTupleModel &model) final;
524-
void UpdateSchema(const ROOT::Internal::RNTupleModelChangeset &changeset, ROOT::NTupleSize_t firstEntry) final;
524+
void UpdateSchema(const ROOT::Internal::RNTupleModelChangeset &changeset, ROOT::NTupleSize_t firstEntry) override;
525525
void UpdateExtraTypeInfo(const ROOT::RExtraTypeInfoDescriptor &extraTypeInfo) final;
526526

527527
/// Initialize sink based on an existing descriptor and fill into the descriptor builder, optionally copying over

tree/ntuple/inc/ROOT/RPageStorageFile.hxx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ private:
6565
std::unique_ptr<ROOT::Internal::RNTupleFileWriter> fWriter;
6666
/// Number of bytes committed to storage in the current cluster
6767
std::uint64_t fNBytesCurrentCluster = 0;
68+
/// On UpdateSchema(), the new class fields register the corresponding streamer info here so that the
69+
/// streamer info records in the file can be properly updated on dataset commit
70+
ROOT::Internal::RNTupleSerializer::StreamerInfoMap_t fInfosOfClassFields;
71+
6872
RPageSinkFile(std::string_view ntupleName, const ROOT::RNTupleWriteOptions &options);
6973

7074
/// We pass bytesPacked so that TFile::ls() reports a reasonable value for the compression ratio of the corresponding
@@ -98,6 +102,8 @@ public:
98102
RPageSinkFile(RPageSinkFile &&) = default;
99103
RPageSinkFile &operator=(RPageSinkFile &&) = default;
100104
~RPageSinkFile() override;
105+
106+
void UpdateSchema(const ROOT::Internal::RNTupleModelChangeset &changeset, ROOT::NTupleSize_t firstEntry) final;
101107
}; // class RPageSinkFile
102108

103109
// clang-format off

tree/ntuple/src/RNTupleDescriptor.cxx

Lines changed: 0 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424

2525
#include <RZip.h>
2626
#include <TError.h>
27-
#include <TVirtualStreamerInfo.h>
2827

2928
#include <algorithm>
3029
#include <cstdint>
@@ -1412,48 +1411,6 @@ ROOT::Internal::RNTupleDescriptorBuilder::AddAttributeSet(Experimental::RNTupleA
14121411
return RResult<void>::Success();
14131412
}
14141413

1415-
RNTupleSerializer::StreamerInfoMap_t ROOT::Internal::RNTupleDescriptorBuilder::BuildStreamerInfos() const
1416-
{
1417-
RNTupleSerializer::StreamerInfoMap_t streamerInfoMap;
1418-
const auto &desc = GetDescriptor();
1419-
1420-
std::function<void(const RFieldDescriptor &)> fnWalkFieldTree;
1421-
fnWalkFieldTree = [&desc, &streamerInfoMap, &fnWalkFieldTree](const RFieldDescriptor &fieldDesc) {
1422-
if (fieldDesc.IsCustomClass()) {
1423-
// Add streamer info for this class to streamerInfoMap
1424-
auto cl = TClass::GetClass(fieldDesc.GetTypeName().c_str());
1425-
if (!cl) {
1426-
throw RException(R__FAIL(std::string("cannot get TClass for ") + fieldDesc.GetTypeName()));
1427-
}
1428-
auto streamerInfo = cl->GetStreamerInfo(fieldDesc.GetTypeVersion());
1429-
if (!streamerInfo) {
1430-
throw RException(R__FAIL(std::string("cannot get streamerInfo for ") + fieldDesc.GetTypeName()));
1431-
}
1432-
streamerInfoMap[streamerInfo->GetNumber()] = streamerInfo;
1433-
}
1434-
1435-
// Recursively traverse sub fields
1436-
for (const auto &subFieldDesc : desc.GetFieldIterable(fieldDesc)) {
1437-
fnWalkFieldTree(subFieldDesc);
1438-
}
1439-
};
1440-
1441-
fnWalkFieldTree(desc.GetFieldZero());
1442-
1443-
// Add the streamer info records from streamer fields: because of runtime polymorphism we may need to add additional
1444-
// types not covered by the type names stored in the field headers
1445-
for (const auto &extraTypeInfo : desc.GetExtraTypeInfoIterable()) {
1446-
if (extraTypeInfo.GetContentId() != EExtraTypeInfoIds::kStreamerInfo)
1447-
continue;
1448-
// Ideally, we would avoid deserializing the streamer info records of the streamer fields that we just serialized.
1449-
// However, this happens only once at the end of writing and only when streamer fields are used, so the
1450-
// preference here is for code simplicity.
1451-
streamerInfoMap.merge(RNTupleSerializer::DeserializeStreamerInfos(extraTypeInfo.GetContent()).Unwrap());
1452-
}
1453-
1454-
return streamerInfoMap;
1455-
}
1456-
14571414
ROOT::RClusterDescriptor::RColumnRangeIterable ROOT::RClusterDescriptor::GetColumnRangeIterable() const
14581415
{
14591416
return RColumnRangeIterable(*this);

tree/ntuple/src/RPageStorageFile.cxx

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include <RVersion.h>
3131
#include <TDirectory.h>
3232
#include <TError.h>
33+
#include <TVirtualStreamerInfo.h>
3334

3435
#include <algorithm>
3536
#include <cstdio>
@@ -85,6 +86,37 @@ void ROOT::Internal::RPageSinkFile::InitImpl(unsigned char *serializedHeader, st
8586
fWriter->WriteNTupleHeader(zipBuffer.get(), szZipHeader, length);
8687
}
8788

89+
void ROOT::Internal::RPageSinkFile::UpdateSchema(const ROOT::Internal::RNTupleModelChangeset &changeset,
90+
ROOT::NTupleSize_t firstEntry)
91+
{
92+
RPagePersistentSink::UpdateSchema(changeset, firstEntry);
93+
94+
auto fnAddStreamerInfo = [this](const ROOT::RFieldBase *field) {
95+
const TClass *cl = nullptr;
96+
if (auto classField = dynamic_cast<const RClassField *>(field)) {
97+
cl = classField->GetClass();
98+
} else if (auto streamerField = dynamic_cast<const RStreamerField *>(field)) {
99+
cl = streamerField->GetClass();
100+
}
101+
if (!cl)
102+
return;
103+
104+
auto streamerInfo = cl->GetStreamerInfo(field->GetTypeVersion());
105+
if (!streamerInfo) {
106+
throw RException(R__FAIL(std::string("cannot get streamerInfo for ") + cl->GetName() + " [" +
107+
std::to_string(field->GetTypeVersion()) + "]"));
108+
}
109+
fInfosOfClassFields[streamerInfo->GetNumber()] = streamerInfo;
110+
};
111+
112+
for (const auto field : changeset.fAddedFields) {
113+
fnAddStreamerInfo(field);
114+
for (const auto &subField : *field) {
115+
fnAddStreamerInfo(&subField);
116+
}
117+
}
118+
}
119+
88120
inline ROOT::RNTupleLocator
89121
ROOT::Internal::RPageSinkFile::WriteSealedPage(const RPageStorage::RSealedPage &sealedPage, std::size_t bytesPacked)
90122
{
@@ -244,7 +276,18 @@ ROOT::Internal::RPageSinkFile::CommitClusterGroupImpl(unsigned char *serializedP
244276

245277
void ROOT::Internal::RPageSinkFile::CommitDatasetImpl(unsigned char *serializedFooter, std::uint32_t length)
246278
{
247-
fWriter->UpdateStreamerInfos(fDescriptorBuilder.BuildStreamerInfos());
279+
// Add the streamer info records from streamer fields: because of runtime polymorphism we may need to add additional
280+
// types not covered by the type names of the class fields
281+
for (const auto &extraTypeInfo : fDescriptorBuilder.GetDescriptor().GetExtraTypeInfoIterable()) {
282+
if (extraTypeInfo.GetContentId() != EExtraTypeInfoIds::kStreamerInfo)
283+
continue;
284+
// Ideally, we would avoid deserializing the streamer info records of the streamer fields that we just serialized.
285+
// However, this happens only once at the end of writing and only when streamer fields are used, so the
286+
// preference here is for code simplicity.
287+
fInfosOfClassFields.merge(RNTupleSerializer::DeserializeStreamerInfos(extraTypeInfo.GetContent()).Unwrap());
288+
}
289+
fWriter->UpdateStreamerInfos(fInfosOfClassFields);
290+
248291
auto bufFooterZip = MakeUninitArray<unsigned char>(length);
249292
auto szFooterZip =
250293
RNTupleCompressor::Zip(serializedFooter, length, GetWriteOptions().GetCompression(), bufFooterZip.get());

tree/ntuple/test/CMakeLists.txt

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,6 @@ ROOT_GENERATE_DICTIONARY(RXTupleDict ${CMAKE_CURRENT_SOURCE_DIR}/RXTuple.hxx
3030
LINKDEF RXTupleLinkDef.h
3131
DEPENDENCIES RIO)
3232
ROOT_ADD_GTEST(ntuple_descriptor ntuple_descriptor.cxx LIBRARIES ROOTNTuple)
33-
ROOT_GENERATE_DICTIONARY(RNTupleDescriptorDict ${CMAKE_CURRENT_SOURCE_DIR}/RNTupleDescriptorDict.hxx
34-
MODULE ntuple_descriptor
35-
LINKDEF RNTupleDescriptorLinkDef.h
36-
OPTIONS -inlineInputHeader
37-
DEPENDENCIES RIO)
3833

3934
ROOT_ADD_GTEST(ntuple_endian ntuple_endian.cxx LIBRARIES ROOTNTuple)
4035
ROOT_ADD_GTEST(ntuple_evolution_type ntuple_evolution_type.cxx LIBRARIES ROOTNTuple)

tree/ntuple/test/CustomStruct.hxx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <cstddef>
1212
#include <cstdint>
1313
#include <functional>
14+
#include <map>
1415
#include <random>
1516
#include <string>
1617
#include <variant>

tree/ntuple/test/CustomStructLinkDef.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@
2727
#pragma link C++ class IOConstructor+;
2828
#pragma link C++ class LowPrecisionFloats+;
2929

30+
#pragma link C++ class std::map<int, CustomStruct>+ ;
31+
#pragma link C++ class std::map<int, float>+ ;
32+
3033
#pragma link C++ class EdmWrapper<CustomStruct> +;
3134
#pragma link C++ class EdmHash < 1> + ;
3235
#pragma link C++ class EdmWrapper<long long>+;

tree/ntuple/test/RNTupleDescriptorDict.hxx

Lines changed: 0 additions & 9 deletions
This file was deleted.

0 commit comments

Comments
 (0)