Skip to content

Commit 135bbfa

Browse files
committed
[ntuple] Add de/serialization of RNTupleAttributes
1 parent dbeae9e commit 135bbfa

File tree

6 files changed

+491
-20
lines changed

6 files changed

+491
-20
lines changed

tree/ntuple/inc/ROOT/RNTupleDescriptor.hxx

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,53 @@ struct RNTupleClusterBoundaries {
6767
std::vector<ROOT::Internal::RNTupleClusterBoundaries> GetClusterBoundaries(const RNTupleDescriptor &desc);
6868
} // namespace Internal
6969

70+
namespace Experimental {
71+
namespace Internal {
72+
class RNTupleAttrSetDescriptorBuilder;
73+
}
74+
75+
// clang-format off
76+
/**
77+
\class ROOT::Experimental::RNTupleAttrSetDescriptor
78+
\ingroup NTuple
79+
\brief Metadata stored for every Attribute Set linked to an RNTuple.
80+
*/
81+
// clang-format on
82+
class RNTupleAttrSetDescriptor final {
83+
friend class Experimental::Internal::RNTupleAttrSetDescriptorBuilder;
84+
85+
std::uint16_t fSchemaVersionMajor = 0;
86+
std::uint16_t fSchemaVersionMinor = 0;
87+
std::uint32_t fAnchorLength = 0; ///< uncompressed size of the linked anchor
88+
// The locator of the AttributeSet anchor.
89+
// In case of kTypeFile, it points to the beginning of the Anchor's payload.
90+
// NOTE: Only kTypeFile is supported at the moment.
91+
RNTupleLocator fAnchorLocator;
92+
std::string fName;
93+
94+
public:
95+
RNTupleAttrSetDescriptor() = default;
96+
RNTupleAttrSetDescriptor(const RNTupleAttrSetDescriptor &other) = delete;
97+
RNTupleAttrSetDescriptor &operator=(const RNTupleAttrSetDescriptor &other) = delete;
98+
RNTupleAttrSetDescriptor(RNTupleAttrSetDescriptor &&other) = default;
99+
RNTupleAttrSetDescriptor &operator=(RNTupleAttrSetDescriptor &&other) = default;
100+
101+
bool operator==(const RNTupleAttrSetDescriptor &other) const;
102+
bool operator!=(const RNTupleAttrSetDescriptor &other) const { return !(*this == other); }
103+
104+
const std::string &GetName() const { return fName; }
105+
std::uint16_t GetSchemaVersionMajor() const { return fSchemaVersionMajor; }
106+
std::uint16_t GetSchemaVersionMinor() const { return fSchemaVersionMinor; }
107+
std::uint32_t GetAnchorLength() const { return fAnchorLength; }
108+
const RNTupleLocator &GetAnchorLocator() const { return fAnchorLocator; }
109+
110+
RNTupleAttrSetDescriptor Clone() const;
111+
};
112+
113+
class RNTupleAttrSetDescriptorIterable;
114+
115+
} // namespace Experimental
116+
70117
// clang-format off
71118
/**
72119
\class ROOT::RFieldDescriptor
@@ -701,6 +748,8 @@ private:
701748
std::vector<ROOT::DescriptorId_t> fSortedClusterGroupIds;
702749
/// Potentially a subset of all the available clusters
703750
std::unordered_map<ROOT::DescriptorId_t, RClusterDescriptor> fClusterDescriptors;
751+
/// List of AttributeSets linked to this RNTuple
752+
std::vector<Experimental::RNTupleAttrSetDescriptor> fAttributeSets;
704753

705754
// We don't expose this publicly because when we add sharded clusters, this interface does not make sense anymore
706755
ROOT::DescriptorId_t FindClusterId(ROOT::NTupleSize_t entryIdx) const;
@@ -718,6 +767,7 @@ public:
718767
class RClusterGroupDescriptorIterable;
719768
class RClusterDescriptorIterable;
720769
class RExtraTypeInfoDescriptorIterable;
770+
friend class Experimental::RNTupleAttrSetDescriptorIterable;
721771

722772
/// Modifiers passed to CreateModel()
723773
struct RCreateModelOptions {
@@ -806,6 +856,8 @@ public:
806856

807857
RExtraTypeInfoDescriptorIterable GetExtraTypeInfoIterable() const;
808858

859+
ROOT::Experimental::RNTupleAttrSetDescriptorIterable GetAttrSetIterable() const;
860+
809861
const std::string &GetName() const { return fName; }
810862
const std::string &GetDescription() const { return fDescription; }
811863

@@ -816,6 +868,7 @@ public:
816868
std::size_t GetNClusters() const { return fNClusters; }
817869
std::size_t GetNActiveClusters() const { return fClusterDescriptors.size(); }
818870
std::size_t GetNExtraTypeInfos() const { return fExtraTypeInfoDescriptors.size(); }
871+
std::size_t GetNAttributeSets() const { return fAttributeSets.size(); }
819872

820873
/// We know the number of entries from adding the cluster summaries
821874
ROOT::NTupleSize_t GetNEntries() const { return fNEntries; }
@@ -1145,6 +1198,59 @@ public:
11451198
RIterator end() { return RIterator(fNTuple.fExtraTypeInfoDescriptors.cend()); }
11461199
};
11471200

1201+
namespace Experimental {
1202+
// clang-format off
1203+
/**
1204+
\class ROOT::Experimental::RNTupleAttrSetDescriptorIterable
1205+
\ingroup NTuple
1206+
\brief Used to loop over all the Attribute Sets linked to an RNTuple
1207+
*/
1208+
// clang-format on
1209+
// TODO: move this to RNTupleDescriptor::RNTupleAttrSetDescriptorIterable when it moves out of Experimental.
1210+
class RNTupleAttrSetDescriptorIterable final {
1211+
private:
1212+
/// The associated RNTuple for this range.
1213+
const RNTupleDescriptor &fNTuple;
1214+
1215+
public:
1216+
class RIterator final {
1217+
private:
1218+
using Iter_t = std::vector<RNTupleAttrSetDescriptor>::const_iterator;
1219+
/// The wrapped vector iterator
1220+
Iter_t fIter;
1221+
1222+
public:
1223+
using iterator_category = std::forward_iterator_tag;
1224+
using iterator = RIterator;
1225+
using value_type = RNTupleAttrSetDescriptor;
1226+
using difference_type = std::ptrdiff_t;
1227+
using pointer = const value_type *;
1228+
using reference = const value_type &;
1229+
1230+
RIterator(Iter_t iter) : fIter(iter) {}
1231+
iterator &operator++() /* prefix */
1232+
{
1233+
++fIter;
1234+
return *this;
1235+
}
1236+
iterator operator++(int) /* postfix */
1237+
{
1238+
auto old = *this;
1239+
operator++();
1240+
return old;
1241+
}
1242+
reference operator*() const { return *fIter; }
1243+
pointer operator->() const { return &*fIter; }
1244+
bool operator!=(const iterator &rh) const { return fIter != rh.fIter; }
1245+
bool operator==(const iterator &rh) const { return fIter == rh.fIter; }
1246+
};
1247+
1248+
RNTupleAttrSetDescriptorIterable(const RNTupleDescriptor &ntuple) : fNTuple(ntuple) {}
1249+
RIterator begin() { return RIterator(fNTuple.fAttributeSets.cbegin()); }
1250+
RIterator end() { return RIterator(fNTuple.fAttributeSets.cend()); }
1251+
};
1252+
} // namespace Experimental
1253+
11481254
// clang-format off
11491255
/**
11501256
\class ROOT::RNTupleDescriptor::RHeaderExtension
@@ -1218,6 +1324,39 @@ public:
12181324
}
12191325
};
12201326

1327+
namespace Experimental::Internal {
1328+
class RNTupleAttrSetDescriptorBuilder final {
1329+
ROOT::Experimental::RNTupleAttrSetDescriptor fDesc;
1330+
1331+
public:
1332+
RNTupleAttrSetDescriptorBuilder &Name(std::string_view name)
1333+
{
1334+
fDesc.fName = name;
1335+
return *this;
1336+
}
1337+
RNTupleAttrSetDescriptorBuilder &SchemaVersion(std::uint16_t major, std::uint16_t minor)
1338+
{
1339+
fDesc.fSchemaVersionMajor = major;
1340+
fDesc.fSchemaVersionMinor = minor;
1341+
return *this;
1342+
}
1343+
RNTupleAttrSetDescriptorBuilder &AnchorLocator(const RNTupleLocator &loc)
1344+
{
1345+
fDesc.fAnchorLocator = loc;
1346+
return *this;
1347+
}
1348+
RNTupleAttrSetDescriptorBuilder &AnchorLength(std::uint32_t length)
1349+
{
1350+
fDesc.fAnchorLength = length;
1351+
return *this;
1352+
}
1353+
1354+
/// Attempt to make an AttributeSet descriptor. This may fail if the builder
1355+
/// was not given enough information to make a proper descriptor.
1356+
RResult<ROOT::Experimental::RNTupleAttrSetDescriptor> MoveDescriptor();
1357+
};
1358+
} // namespace Experimental::Internal
1359+
12211360
namespace Internal {
12221361

12231362
// clang-format off
@@ -1601,6 +1740,8 @@ public:
16011740
RResult<void> AddExtraTypeInfo(RExtraTypeInfoDescriptor &&extraTypeInfoDesc);
16021741
void ReplaceExtraTypeInfo(RExtraTypeInfoDescriptor &&extraTypeInfoDesc);
16031742

1743+
RResult<void> AddAttributeSet(Experimental::RNTupleAttrSetDescriptor &&attrSetDesc);
1744+
16041745
/// Mark the beginning of the header extension; any fields and columns added after a call to this function are
16051746
/// annotated as begin part of the header extension.
16061747
void BeginHeaderExtension();
@@ -1634,6 +1775,7 @@ inline RNTupleDescriptor CloneDescriptorSchema(const RNTupleDescriptor &desc)
16341775
}
16351776

16361777
} // namespace Internal
1778+
16371779
} // namespace ROOT
16381780

16391781
#endif // ROOT_RNTupleDescriptor

tree/ntuple/inc/ROOT/RNTupleSerialize.hxx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,13 @@ class RNTupleDescriptor;
3636
class RClusterDescriptor;
3737
enum class EExtraTypeInfoIds;
3838

39+
namespace Experimental {
40+
class RNTupleAttrSetDescriptor;
41+
namespace Internal {
42+
class RNTupleAttrSetDescriptorBuilder;
43+
} // namespace Internal
44+
} // namespace Experimental
45+
3946
namespace Internal {
4047

4148
class RClusterDescriptorBuilder;
@@ -271,6 +278,12 @@ public:
271278
static RResult<std::uint32_t> DeserializeSchemaDescription(const void *buffer, std::uint64_t bufSize,
272279
ROOT::Internal::RNTupleDescriptorBuilder &descBuilder);
273280

281+
static RResult<std::uint32_t>
282+
SerializeAttributeSet(const Experimental::RNTupleAttrSetDescriptor &attrSetDesc, void *buffer);
283+
static RResult<std::uint32_t>
284+
DeserializeAttributeSet(const void *buffer, std::uint64_t bufSize,
285+
Experimental::Internal::RNTupleAttrSetDescriptorBuilder &attrSetDescBld);
286+
274287
static RResult<RContext> SerializeHeader(void *buffer, const RNTupleDescriptor &desc);
275288
static RResult<std::uint32_t> SerializePageList(void *buffer, const RNTupleDescriptor &desc,
276289
std::span<ROOT::DescriptorId_t> physClusterIDs,

tree/ntuple/src/RNTupleDescriptor.cxx

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -803,6 +803,8 @@ ROOT::RNTupleDescriptor ROOT::RNTupleDescriptor::Clone() const
803803
clone.fSortedClusterGroupIds = fSortedClusterGroupIds;
804804
for (const auto &d : fClusterDescriptors)
805805
clone.fClusterDescriptors.emplace(d.first, d.second.Clone());
806+
for (const auto &d : fAttributeSets)
807+
clone.fAttributeSets.emplace_back(d.Clone());
806808
return clone;
807809
}
808810

@@ -1123,6 +1125,19 @@ void ROOT::Internal::RNTupleDescriptorBuilder::SetFeature(unsigned int flag)
11231125
fDescriptor.fFeatureFlags.insert(flag);
11241126
}
11251127

1128+
ROOT::RResult<ROOT::Experimental::RNTupleAttrSetDescriptor>
1129+
ROOT::Experimental::Internal::RNTupleAttrSetDescriptorBuilder::MoveDescriptor()
1130+
{
1131+
if (fDesc.fName.empty())
1132+
return R__FAIL("attribute set name cannot be empty");
1133+
if (fDesc.fAnchorLength == 0)
1134+
return R__FAIL("invalid anchor length");
1135+
if (fDesc.fAnchorLocator.GetType() == RNTupleLocator::kTypeUnknown)
1136+
return R__FAIL("invalid locator type");
1137+
1138+
return std::move(fDesc);
1139+
}
1140+
11261141
ROOT::RResult<ROOT::RColumnDescriptor> ROOT::Internal::RColumnDescriptorBuilder::MakeDescriptor() const
11271142
{
11281143
if (fColumn.GetLogicalId() == ROOT::kInvalidDescriptorId)
@@ -1377,6 +1392,19 @@ void ROOT::Internal::RNTupleDescriptorBuilder::ReplaceExtraTypeInfo(RExtraTypeIn
13771392
fDescriptor.fExtraTypeInfoDescriptors.emplace_back(std::move(extraTypeInfoDesc));
13781393
}
13791394

1395+
ROOT::RResult<void>
1396+
ROOT::Internal::RNTupleDescriptorBuilder::AddAttributeSet(Experimental::RNTupleAttrSetDescriptor &&attrSetDesc)
1397+
{
1398+
auto &attrSets = fDescriptor.fAttributeSets;
1399+
if (std::find_if(attrSets.begin(), attrSets.end(), [&name = attrSetDesc.GetName()](const auto &desc) {
1400+
return desc.GetName() == name;
1401+
}) != attrSets.end()) {
1402+
return R__FAIL("attribute sets with duplicate names");
1403+
}
1404+
attrSets.push_back(std::move(attrSetDesc));
1405+
return RResult<void>::Success();
1406+
}
1407+
13801408
RNTupleSerializer::StreamerInfoMap_t ROOT::Internal::RNTupleDescriptorBuilder::BuildStreamerInfos() const
13811409
{
13821410
RNTupleSerializer::StreamerInfoMap_t streamerInfoMap;
@@ -1492,3 +1520,26 @@ ROOT::RNTupleDescriptor::RExtraTypeInfoDescriptorIterable ROOT::RNTupleDescripto
14921520
{
14931521
return RExtraTypeInfoDescriptorIterable(*this);
14941522
}
1523+
1524+
ROOT::Experimental::RNTupleAttrSetDescriptorIterable ROOT::RNTupleDescriptor::GetAttrSetIterable() const
1525+
{
1526+
return Experimental::RNTupleAttrSetDescriptorIterable(*this);
1527+
}
1528+
1529+
bool ROOT::Experimental::RNTupleAttrSetDescriptor::operator==(const RNTupleAttrSetDescriptor &other) const
1530+
{
1531+
return fAnchorLength == other.fAnchorLength && fSchemaVersionMajor == other.fSchemaVersionMajor &&
1532+
fSchemaVersionMinor == other.fSchemaVersionMinor && fAnchorLocator == other.fAnchorLocator &&
1533+
fName == other.fName;
1534+
};
1535+
1536+
ROOT::Experimental::RNTupleAttrSetDescriptor ROOT::Experimental::RNTupleAttrSetDescriptor::Clone() const
1537+
{
1538+
RNTupleAttrSetDescriptor desc;
1539+
desc.fAnchorLength = fAnchorLength;
1540+
desc.fSchemaVersionMajor = fSchemaVersionMajor;
1541+
desc.fSchemaVersionMinor = fSchemaVersionMinor;
1542+
desc.fAnchorLocator = fAnchorLocator;
1543+
desc.fName = fName;
1544+
return desc;
1545+
}

0 commit comments

Comments
 (0)