Skip to content

Commit 5cfe091

Browse files
committed
[ntuple] fix up serialization of cluster summary
1 parent bec1bd6 commit 5cfe091

File tree

3 files changed

+39
-31
lines changed

3 files changed

+39
-31
lines changed

tree/ntuple/v7/inc/ROOT/RNTupleSerialize.hxx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ public:
8787
struct RClusterSummary {
8888
std::uint64_t fFirstEntry = 0;
8989
std::uint64_t fNEntries = 0;
90+
std::uint8_t fFlags = 0;
9091
/// -1 for "all columns"
9192
std::int32_t fColumnGroupID = -1;
9293
};

tree/ntuple/v7/src/RNTupleSerialize.cxx

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1096,19 +1096,21 @@ std::uint32_t
10961096
ROOT::Experimental::Internal::RNTupleSerializer::SerializeClusterSummary(const RClusterSummary &clusterSummary,
10971097
void *buffer)
10981098
{
1099+
if (clusterSummary.fNEntries >= (static_cast<std::uint64_t>(1) << 56)) {
1100+
throw RException(R__FAIL("number of entries in cluster exceeds maximum of 2^56"));
1101+
}
1102+
10991103
auto base = reinterpret_cast<unsigned char *>(buffer);
11001104
auto pos = base;
11011105
void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
11021106

11031107
auto frame = pos;
11041108
pos += SerializeRecordFramePreamble(*where);
11051109
pos += SerializeUInt64(clusterSummary.fFirstEntry, *where);
1106-
if (clusterSummary.fColumnGroupID >= 0) {
1107-
pos += SerializeInt64(-static_cast<int64_t>(clusterSummary.fNEntries), *where);
1108-
pos += SerializeUInt32(clusterSummary.fColumnGroupID, *where);
1109-
} else {
1110-
pos += SerializeInt64(static_cast<int64_t>(clusterSummary.fNEntries), *where);
1111-
}
1110+
const std::uint64_t nEntriesAndFlags =
1111+
(static_cast<std::uint64_t>(clusterSummary.fFlags) << 56) | clusterSummary.fNEntries;
1112+
pos += SerializeUInt64(nEntriesAndFlags, *where);
1113+
11121114
auto size = pos - frame;
11131115
pos += SerializeFramePostscript(frame, size);
11141116
return size;
@@ -1131,21 +1133,20 @@ ROOT::Experimental::Internal::RNTupleSerializer::DeserializeClusterSummary(const
11311133
return R__FAIL("too short cluster summary");
11321134

11331135
bytes += DeserializeUInt64(bytes, clusterSummary.fFirstEntry);
1134-
std::int64_t nEntries;
1135-
bytes += DeserializeInt64(bytes, nEntries);
1136+
std::uint64_t nEntriesAndFlags;
1137+
bytes += DeserializeUInt64(bytes, nEntriesAndFlags);
11361138

1137-
if (nEntries < 0) {
1138-
if (fnFrameSizeLeft() < sizeof(std::uint32_t))
1139-
return R__FAIL("too short cluster summary");
1140-
clusterSummary.fNEntries = -nEntries;
1141-
std::uint32_t columnGroupID;
1142-
bytes += DeserializeUInt32(bytes, columnGroupID);
1143-
clusterSummary.fColumnGroupID = columnGroupID;
1144-
} else {
1145-
clusterSummary.fNEntries = nEntries;
1146-
clusterSummary.fColumnGroupID = -1;
1139+
const std::uint64_t nEntries = (nEntriesAndFlags << 8) >> 8;
1140+
const std::uint8_t flags = nEntriesAndFlags >> 56;
1141+
1142+
if (flags & 0x01) {
1143+
return R__FAIL("sharded cluster flag set in cluster summary; sharded clusters are currently unsupported.");
11471144
}
11481145

1146+
clusterSummary.fNEntries = nEntries;
1147+
clusterSummary.fFlags = flags;
1148+
clusterSummary.fColumnGroupID = -1;
1149+
11491150
return frameSize;
11501151
}
11511152

@@ -1511,7 +1512,7 @@ ROOT::Experimental::Internal::RNTupleSerializer::SerializePageList(void *buffer,
15111512
pos += SerializeListFramePreamble(nClusters, *where);
15121513
for (auto clusterId : physClusterIDs) {
15131514
const auto &clusterDesc = desc.GetClusterDescriptor(context.GetMemClusterId(clusterId));
1514-
RClusterSummary summary{clusterDesc.GetFirstEntryIndex(), clusterDesc.GetNEntries(), -1};
1515+
RClusterSummary summary{clusterDesc.GetFirstEntryIndex(), clusterDesc.GetNEntries(), 0, -1};
15151516
pos += SerializeClusterSummary(summary, *where);
15161517
}
15171518
pos += SerializeFramePostscript(buffer ? clusterSummaryFrame : nullptr, pos - clusterSummaryFrame);

tree/ntuple/v7/test/ntuple_serialize.cxx

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -439,9 +439,10 @@ TEST(RNTuple, SerializeClusterSummary)
439439
{
440440
RNTupleSerializer::RClusterSummary summary;
441441
summary.fFirstEntry = 42;
442-
summary.fNEntries = 137;
442+
summary.fNEntries = (static_cast<std::uint64_t>(1) << 56) - 1;
443+
summary.fFlags = 0x02;
443444

444-
unsigned char buffer[28];
445+
unsigned char buffer[24];
445446
ASSERT_EQ(24u, RNTupleSerializer::SerializeClusterSummary(summary, nullptr));
446447
EXPECT_EQ(24u, RNTupleSerializer::SerializeClusterSummary(summary, buffer));
447448
RNTupleSerializer::RClusterSummary reco;
@@ -454,21 +455,26 @@ TEST(RNTuple, SerializeClusterSummary)
454455
EXPECT_EQ(24u, RNTupleSerializer::DeserializeClusterSummary(buffer, 24, reco).Unwrap());
455456
EXPECT_EQ(summary.fFirstEntry, reco.fFirstEntry);
456457
EXPECT_EQ(summary.fNEntries, reco.fNEntries);
458+
EXPECT_EQ(summary.fFlags, reco.fFlags);
457459
EXPECT_EQ(summary.fColumnGroupID, reco.fColumnGroupID);
458460

459-
summary.fColumnGroupID = 13;
460-
ASSERT_EQ(28u, RNTupleSerializer::SerializeClusterSummary(summary, nullptr));
461-
EXPECT_EQ(28u, RNTupleSerializer::SerializeClusterSummary(summary, buffer));
461+
summary.fFlags |= 0x01;
462+
EXPECT_EQ(24u, RNTupleSerializer::SerializeClusterSummary(summary, buffer));
462463
try {
463-
RNTupleSerializer::DeserializeClusterSummary(buffer, 27, reco).Unwrap();
464-
FAIL() << "too short cluster summary should fail";
464+
RNTupleSerializer::DeserializeClusterSummary(buffer, 24, reco).Unwrap();
465+
FAIL() << "sharded cluster flag should fail";
465466
} catch (const RException& err) {
466-
EXPECT_THAT(err.what(), testing::HasSubstr("too short"));
467+
EXPECT_THAT(err.what(), testing::HasSubstr("sharded"));
468+
}
469+
470+
summary.fFlags = 0;
471+
summary.fNEntries++;
472+
try {
473+
RNTupleSerializer::SerializeClusterSummary(summary, buffer);
474+
FAIL() << "overesized cluster should fail";
475+
} catch (const RException &err) {
476+
EXPECT_THAT(err.what(), testing::HasSubstr("exceed"));
467477
}
468-
EXPECT_EQ(28u, RNTupleSerializer::DeserializeClusterSummary(buffer, 28, reco).Unwrap());
469-
EXPECT_EQ(summary.fFirstEntry, reco.fFirstEntry);
470-
EXPECT_EQ(summary.fNEntries, reco.fNEntries);
471-
EXPECT_EQ(summary.fColumnGroupID, reco.fColumnGroupID);
472478
}
473479

474480
TEST(RNTuple, SerializeClusterGroup)

0 commit comments

Comments
 (0)