diff --git a/tree/ntuple/inc/ROOT/RNTupleTypes.hxx b/tree/ntuple/inc/ROOT/RNTupleTypes.hxx index 9692a542cb017..ef2cea983359a 100644 --- a/tree/ntuple/inc/ROOT/RNTupleTypes.hxx +++ b/tree/ntuple/inc/ROOT/RNTupleTypes.hxx @@ -236,6 +236,7 @@ public: // if the size of the referenced data block is >2GB kTypeFile = 0x00, kTypeDAOS = 0x02, + kTypeS3 = 0x03, kLastSerializableType = 0x7f, kTypePageZero = kLastSerializableType + 1, diff --git a/tree/ntuple/src/RNTupleSerialize.cxx b/tree/ntuple/src/RNTupleSerialize.cxx index 5da2fa6a4f6b9..985f503ff1007 100644 --- a/tree/ntuple/src/RNTupleSerialize.cxx +++ b/tree/ntuple/src/RNTupleSerialize.cxx @@ -506,7 +506,7 @@ ROOT::RResult DeserializeLocatorPayloadObject64(const unsigned char *buffe locator.SetNBytesOnStorage(nBytesOnStorage); RNTupleSerializer::DeserializeUInt64(buffer + sizeof(std::uint64_t), location); } else { - return R__FAIL("invalid DAOS locator payload size: " + std::to_string(sizeofLocatorPayload)); + return R__FAIL("invalid Object64 locator payload size: " + std::to_string(sizeofLocatorPayload)); } locator.SetPosition(ROOT::RNTupleLocatorObject64{location}); return ROOT::RResult::Success(); @@ -1091,6 +1091,10 @@ ROOT::Internal::RNTupleSerializer::SerializeLocator(const RNTupleLocator &locato size += SerializeLocatorPayloadObject64(locator, payloadp); locatorType = 0x02; break; + case RNTupleLocator::kTypeS3: + size += SerializeLocatorPayloadObject64(locator, payloadp); + locatorType = 0x03; + break; default: if (locator.GetType() == ROOT::Internal::kTestLocatorType) { // For the testing locator, use the same payload format as Object64. We won't read it back anyway. @@ -1139,6 +1143,10 @@ ROOT::RResult ROOT::Internal::RNTupleSerializer::DeserializeLocat locator.SetType(RNTupleLocator::kTypeDAOS); DeserializeLocatorPayloadObject64(bytes, payloadSize, locator); break; + case 0x03: + locator.SetType(RNTupleLocator::kTypeS3); + DeserializeLocatorPayloadObject64(bytes, payloadSize, locator); + break; default: locator.SetType(RNTupleLocator::kTypeUnknown); } bytes += payloadSize; diff --git a/tree/ntuple/src/RNTupleTypes.cxx b/tree/ntuple/src/RNTupleTypes.cxx index 1325e9ce702e6..cba10277dbeb3 100644 --- a/tree/ntuple/src/RNTupleTypes.cxx +++ b/tree/ntuple/src/RNTupleTypes.cxx @@ -45,7 +45,8 @@ ROOT::RNTupleLocator::ELocatorType ROOT::RNTupleLocator::GetType() const case 1: return kTypeDAOS; case 2: return kTypePageZero; case 3: return kTypeUnknown; - case 4: return Internal::kTestLocatorType; + case 4: return kTypeS3; + case 5: return Internal::kTestLocatorType; default: break; } R__ASSERT(false); @@ -60,9 +61,10 @@ void ROOT::RNTupleLocator::SetType(ELocatorType type) case kTypeDAOS: compactType = 1; break; case kTypePageZero: compactType = 2; break; case kTypeUnknown: compactType = 3; break; + case kTypeS3: compactType = 4; break; default: if (type == Internal::kTestLocatorType) - compactType = 4; + compactType = 5; else throw RException(R__FAIL("invalid locator type: " + std::to_string(type))); } @@ -79,7 +81,7 @@ void ROOT::RNTupleLocator::SetPosition(std::uint64_t position) void ROOT::RNTupleLocator::SetPosition(RNTupleLocatorObject64 position) { - if (GetType() != kTypeDAOS) + if (GetType() != kTypeDAOS && GetType() != kTypeS3) throw RException(R__FAIL("cannot set position as 64bit object for type " + std::to_string(GetType()))); fPosition = position.GetLocation(); } @@ -94,7 +96,7 @@ std::uint64_t ROOT::Internal::RNTupleLocatorHelper::Get(const RNT ROOT::RNTupleLocatorObject64 ROOT::Internal::RNTupleLocatorHelper::Get(const RNTupleLocator &loc) { - if (loc.GetType() != ROOT::RNTupleLocator::kTypeDAOS) + if (loc.GetType() != ROOT::RNTupleLocator::kTypeDAOS && loc.GetType() != ROOT::RNTupleLocator::kTypeS3) throw RException(R__FAIL("cannot retrieve position as 64bit object for type " + std::to_string(loc.GetType()))); return RNTupleLocatorObject64{loc.fPosition}; } diff --git a/tree/ntuple/test/ntuple_serialize.cxx b/tree/ntuple/test/ntuple_serialize.cxx index 4867a7353b9b8..4fe742daf4f3c 100644 --- a/tree/ntuple/test/ntuple_serialize.cxx +++ b/tree/ntuple/test/ntuple_serialize.cxx @@ -399,6 +399,31 @@ TEST(RNTuple, SerializeLocator) EXPECT_EQ(locator.GetReserved(), 1); EXPECT_EQ(1337U, locator.GetPosition().GetLocation()); + // S3 locator round-trip with 32-bit nBytesOnStorage + locator = RNTupleLocator{}; + locator.SetType(RNTupleLocator::kTypeS3); + locator.SetPosition(RNTupleLocatorObject64{42U}); + locator.SetNBytesOnStorage(1024U); + locator.SetReserved(0); + EXPECT_EQ(16u, RNTupleSerializer::SerializeLocator(locator, buffer).Unwrap()); + locator = RNTupleLocator{}; + EXPECT_EQ(16u, RNTupleSerializer::DeserializeLocator(buffer, 16, locator).Unwrap()); + EXPECT_EQ(locator.GetType(), RNTupleLocator::kTypeS3); + EXPECT_EQ(locator.GetNBytesOnStorage(), 1024U); + EXPECT_EQ(locator.GetReserved(), 0); + EXPECT_EQ(42U, locator.GetPosition().GetLocation()); + + // S3 locator round-trip with 64-bit nBytesOnStorage and reserved bit + locator.SetNBytesOnStorage(static_cast(std::numeric_limits::max()) + 1); + locator.SetReserved(1); + EXPECT_EQ(20u, RNTupleSerializer::SerializeLocator(locator, buffer).Unwrap()); + locator = RNTupleLocator{}; + EXPECT_EQ(20u, RNTupleSerializer::DeserializeLocator(buffer, 20, locator).Unwrap()); + EXPECT_EQ(locator.GetType(), RNTupleLocator::kTypeS3); + EXPECT_EQ(locator.GetNBytesOnStorage(), static_cast(std::numeric_limits::max()) + 1); + EXPECT_EQ(locator.GetReserved(), 1); + EXPECT_EQ(42U, locator.GetPosition().GetLocation()); + std::int32_t *head = reinterpret_cast(buffer); #ifndef R__BYTESWAP // on big endian system