Skip to content

Commit 2b715cd

Browse files
committed
[ntuple] Add de/serialization of RNTupleAttributes
1 parent 956e1b9 commit 2b715cd

File tree

8 files changed

+498
-30
lines changed

8 files changed

+498
-30
lines changed

tree/ntuple/inc/ROOT/RNTuple.hxx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,8 @@ class RNTuple final {
7777
public:
7878
static constexpr std::uint16_t kVersionEpoch = 1;
7979
static constexpr std::uint16_t kVersionMajor = 0;
80-
static constexpr std::uint16_t kVersionMinor = 0;
81-
static constexpr std::uint16_t kVersionPatch = 2;
80+
static constexpr std::uint16_t kVersionMinor = 1;
81+
static constexpr std::uint16_t kVersionPatch = 0;
8282

8383
private:
8484
/// Version of the RNTuple binary format that the writer supports (see specification).

tree/ntuple/inc/ROOT/RNTupleDescriptor.hxx

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

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

705751
// We don't expose this publicly because when we add sharded clusters, this interface does not make sense anymore
706752
ROOT::DescriptorId_t FindClusterId(ROOT::NTupleSize_t entryIdx) const;
@@ -718,6 +764,7 @@ public:
718764
class RClusterGroupDescriptorIterable;
719765
class RClusterDescriptorIterable;
720766
class RExtraTypeInfoDescriptorIterable;
767+
friend class Experimental::RNTupleAttrSetDescriptorIterable;
721768

722769
/// Modifiers passed to CreateModel()
723770
struct RCreateModelOptions {
@@ -806,6 +853,8 @@ public:
806853

807854
RExtraTypeInfoDescriptorIterable GetExtraTypeInfoIterable() const;
808855

856+
ROOT::Experimental::RNTupleAttrSetDescriptorIterable GetAttrSetIterable() const;
857+
809858
const std::string &GetName() const { return fName; }
810859
const std::string &GetDescription() const { return fDescription; }
811860

@@ -816,6 +865,7 @@ public:
816865
std::size_t GetNClusters() const { return fNClusters; }
817866
std::size_t GetNActiveClusters() const { return fClusterDescriptors.size(); }
818867
std::size_t GetNExtraTypeInfos() const { return fExtraTypeInfoDescriptors.size(); }
868+
std::size_t GetNAttributeSets() const { return fAttributeSets.size(); }
819869

820870
/// We know the number of entries from adding the cluster summaries
821871
ROOT::NTupleSize_t GetNEntries() const { return fNEntries; }
@@ -1145,6 +1195,59 @@ public:
11451195
RIterator end() { return RIterator(fNTuple.fExtraTypeInfoDescriptors.cend()); }
11461196
};
11471197

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

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

12231359
// clang-format off
@@ -1601,6 +1737,8 @@ public:
16011737
RResult<void> AddExtraTypeInfo(RExtraTypeInfoDescriptor &&extraTypeInfoDesc);
16021738
void ReplaceExtraTypeInfo(RExtraTypeInfoDescriptor &&extraTypeInfoDesc);
16031739

1740+
RResult<void> AddAttributeSet(Experimental::RNTupleAttrSetDescriptor &&attrSetDesc);
1741+
16041742
/// Mark the beginning of the header extension; any fields and columns added after a call to this function are
16051743
/// annotated as begin part of the header extension.
16061744
void BeginHeaderExtension();
@@ -1634,6 +1772,7 @@ inline RNTupleDescriptor CloneDescriptorSchema(const RNTupleDescriptor &desc)
16341772
}
16351773

16361774
} // namespace Internal
1775+
16371776
} // namespace ROOT
16381777

16391778
#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)