From cfb36bd9c391d0ed82d3cd9d5d45084b8ff9195c Mon Sep 17 00:00:00 2001 From: "A.J. Beamon" Date: Wed, 5 Oct 2022 12:48:40 -0700 Subject: [PATCH 1/2] Support versionstamps in key backed object properties --- bindings/c/test/unit/unit_tests.cpp | 8 ++--- bindings/flow/Tuple.h | 4 ++- fdbclient/Tuple.cpp | 12 +++---- ...Versionstamp.cpp => TupleVersionstamp.cpp} | 16 +++++----- fdbclient/include/fdbclient/FDBTypes.h | 32 +++++++++++++++++++ fdbclient/include/fdbclient/KeyBackedTypes.h | 9 ++++++ fdbclient/include/fdbclient/Tuple.h | 6 ++-- .../{Versionstamp.h => TupleVersionstamp.h} | 8 ++--- 8 files changed, 69 insertions(+), 26 deletions(-) rename fdbclient/{Versionstamp.cpp => TupleVersionstamp.cpp} (64%) rename fdbclient/include/fdbclient/{Versionstamp.h => TupleVersionstamp.h} (88%) diff --git a/bindings/c/test/unit/unit_tests.cpp b/bindings/c/test/unit/unit_tests.cpp index 2d8dc2456f..a45221f606 100644 --- a/bindings/c/test/unit/unit_tests.cpp +++ b/bindings/c/test/unit/unit_tests.cpp @@ -1001,7 +1001,7 @@ GetMappedRangeResult getMappedIndexEntries(int beginId, TEST_CASE("versionstamp_unit_test") { // a random 12 bytes long StringRef as a versionstamp StringRef str = "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12"_sr; - Versionstamp vs(str), vs2(str); + TupleVersionstamp vs(str), vs2(str); ASSERT(vs == vs2); ASSERT(vs.begin() != vs2.begin()); @@ -1031,7 +1031,7 @@ TEST_CASE("versionstamp_unit_test") { TEST_CASE("tuple_support_versionstamp") { // a random 12 bytes long StringRef as a versionstamp StringRef str = "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12"_sr; - Versionstamp vs(str); + TupleVersionstamp vs(str); const Tuple t = Tuple::makeTuple(prefix, RECORD, vs, "{K[3]}"_sr, "{...}"_sr); ASSERT(t.getVersionstamp(2) == vs); @@ -1047,7 +1047,7 @@ TEST_CASE("tuple_fail_to_append_truncated_versionstamp") { // a truncated 11 bytes long StringRef as a versionstamp StringRef str = "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11"_sr; try { - Versionstamp truncatedVersionstamp(str); + TupleVersionstamp truncatedVersionstamp(str); } catch (Error& e) { return; } @@ -1058,7 +1058,7 @@ TEST_CASE("tuple_fail_to_append_longer_versionstamp") { // a longer than expected 13 bytes long StringRef as a versionstamp StringRef str = "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11"_sr; try { - Versionstamp longerVersionstamp(str); + TupleVersionstamp longerVersionstamp(str); } catch (Error& e) { return; } diff --git a/bindings/flow/Tuple.h b/bindings/flow/Tuple.h index a7feab9419..536d90bb41 100644 --- a/bindings/flow/Tuple.h +++ b/bindings/flow/Tuple.h @@ -24,7 +24,9 @@ #pragma once #include "bindings/flow/fdb_flow.h" -#include "fdbclient/Versionstamp.h" +#include "fdbclient/TupleVersionstamp.h" + +typedef TupleVersionstamp Versionstamp; namespace FDB { struct Uuid { diff --git a/fdbclient/Tuple.cpp b/fdbclient/Tuple.cpp index 212223abd2..042793a757 100644 --- a/fdbclient/Tuple.cpp +++ b/fdbclient/Tuple.cpp @@ -117,7 +117,7 @@ Tuple& Tuple::append(Tuple const& tuple) { return *this; } -Tuple& Tuple::append(Versionstamp const& vs) { +Tuple& Tuple::append(TupleVersionstamp const& vs) { offsets.push_back(data.size()); data.push_back(data.arena(), VERSIONSTAMP_96_CODE); @@ -413,7 +413,7 @@ double Tuple::getDouble(size_t index) const { return bigEndianDouble(swap); } -Versionstamp Tuple::getVersionstamp(size_t index) const { +TupleVersionstamp Tuple::getVersionstamp(size_t index) const { if (index >= offsets.size()) { throw invalid_tuple_index(); } @@ -422,7 +422,7 @@ Versionstamp Tuple::getVersionstamp(size_t index) const { if (code != VERSIONSTAMP_96_CODE) { throw invalid_tuple_data_type(); } - return Versionstamp(StringRef(data.begin() + offsets[index] + 1, VERSIONSTAMP_TUPLE_SIZE)); + return TupleVersionstamp(StringRef(data.begin() + offsets[index] + 1, VERSIONSTAMP_TUPLE_SIZE)); } Tuple::UserTypeStr Tuple::getUserType(size_t index) const { @@ -495,7 +495,7 @@ TEST_CASE("/fdbclient/Tuple/makeTuple") { "byteStr"_sr, Tuple::UnicodeStr("str"_sr), nullptr, - Versionstamp("000000000000"_sr), + TupleVersionstamp("000000000000"_sr), Tuple::UserTypeStr(0x41, "12345678"_sr)); Tuple t2 = Tuple() .append(1) @@ -505,7 +505,7 @@ TEST_CASE("/fdbclient/Tuple/makeTuple") { .append("byteStr"_sr) .append(Tuple::UnicodeStr("str"_sr)) .append(nullptr) - .append(Versionstamp("000000000000"_sr)) + .append(TupleVersionstamp("000000000000"_sr)) .append(Tuple::UserTypeStr(0x41, "12345678"_sr)); ASSERT(t1.pack() == t2.pack()); @@ -531,7 +531,7 @@ TEST_CASE("/fdbclient/Tuple/unpack") { "byteStr"_sr, Tuple::UnicodeStr("str"_sr), nullptr, - Versionstamp("000000000000"_sr), + TupleVersionstamp("000000000000"_sr), Tuple::UserTypeStr(0x41, "12345678"_sr)); Standalone packed = t1.pack(); diff --git a/fdbclient/Versionstamp.cpp b/fdbclient/TupleVersionstamp.cpp similarity index 64% rename from fdbclient/Versionstamp.cpp rename to fdbclient/TupleVersionstamp.cpp index 7a61936040..91e0182f4f 100644 --- a/fdbclient/Versionstamp.cpp +++ b/fdbclient/TupleVersionstamp.cpp @@ -1,13 +1,13 @@ -#include "fdbclient/Versionstamp.h" +#include "fdbclient/TupleVersionstamp.h" -Versionstamp::Versionstamp(StringRef str) { +TupleVersionstamp::TupleVersionstamp(StringRef str) { if (str.size() != VERSIONSTAMP_TUPLE_SIZE) { throw invalid_versionstamp_size(); } data = str; } -int16_t Versionstamp::getBatchNumber() const { +int16_t TupleVersionstamp::getBatchNumber() const { const uint8_t* begin = data.begin(); begin += 8; int16_t batchNumber = *(int16_t*)(begin); @@ -15,7 +15,7 @@ int16_t Versionstamp::getBatchNumber() const { return batchNumber; } -int16_t Versionstamp::getUserVersion() const { +int16_t TupleVersionstamp::getUserVersion() const { const uint8_t* begin = data.begin(); begin += 10; int16_t userVersion = *(int16_t*)(begin); @@ -23,22 +23,22 @@ int16_t Versionstamp::getUserVersion() const { return userVersion; } -const uint8_t* Versionstamp::begin() const { +const uint8_t* TupleVersionstamp::begin() const { return data.begin(); } -int64_t Versionstamp::getVersion() const { +int64_t TupleVersionstamp::getVersion() const { const uint8_t* begin = data.begin(); int64_t version = *(int64_t*)begin; version = bigEndian64(version); return version; } -size_t Versionstamp::size() const { +size_t TupleVersionstamp::size() const { return VERSIONSTAMP_TUPLE_SIZE; } -bool Versionstamp::operator==(const Versionstamp& other) const { +bool TupleVersionstamp::operator==(const TupleVersionstamp& other) const { return getVersion() == other.getVersion() && getBatchNumber() == other.getBatchNumber() && getUserVersion() == other.getUserVersion(); } \ No newline at end of file diff --git a/fdbclient/include/fdbclient/FDBTypes.h b/fdbclient/include/fdbclient/FDBTypes.h index 4da1d4f72b..e4c03b62bd 100644 --- a/fdbclient/include/fdbclient/FDBTypes.h +++ b/fdbclient/include/fdbclient/FDBTypes.h @@ -1654,4 +1654,36 @@ struct transaction_creator_traits> : st template constexpr bool is_transaction_creator = transaction_creator_traits::value; +struct Versionstamp { + Version version = invalidVersion; + uint16_t batchNumber = 0; + + bool operator==(const Versionstamp& r) const { return version == r.version && batchNumber == r.batchNumber; } + bool operator!=(const Versionstamp& r) const { return !(*this == r); } + bool operator<(const Versionstamp& r) const { + return version < r.version || (version == r.version && batchNumber < r.batchNumber); + } + bool operator>(const Versionstamp& r) const { return r < *this; } + bool operator<=(const Versionstamp& r) const { return !(*this > r); } + bool operator>=(const Versionstamp& r) const { return !(*this < r); } + + template + void serialize(Ar& ar) { + int64_t beVersion; + int16_t beBatch; + + if constexpr (!Ar::isDeserializing) { + beVersion = bigEndian64(version); + beBatch = bigEndian16(batchNumber); + } + + serializer(ar, beVersion, beBatch); + + if constexpr (Ar::isDeserializing) { + version = bigEndian64(version); + batchNumber = bigEndian16(beBatch); + } + } +}; + #endif diff --git a/fdbclient/include/fdbclient/KeyBackedTypes.h b/fdbclient/include/fdbclient/KeyBackedTypes.h index a3fee57644..2eaee39cb5 100644 --- a/fdbclient/include/fdbclient/KeyBackedTypes.h +++ b/fdbclient/include/fdbclient/KeyBackedTypes.h @@ -29,6 +29,7 @@ #include "fdbclient/GenericTransactionHelper.h" #include "fdbclient/Subspace.h" #include "flow/ObjectSerializer.h" +#include "flow/Platform.h" #include "flow/genericactors.actor.h" #include "flow/serialize.h" @@ -305,6 +306,14 @@ public: tr->atomicOp(key, BinaryWriter::toValue(val, Unversioned()), type); } + template + void setVersionstamp(Transaction tr, T const& val, int offset) { + tr->atomicOp( + key, + BinaryWriter::toValue(val, Unversioned()).withSuffix(StringRef(reinterpret_cast(offset), 4)), + MutationRef::SetVersionstampedValue); + } + template void clear(Transaction tr) { tr->clear(key); diff --git a/fdbclient/include/fdbclient/Tuple.h b/fdbclient/include/fdbclient/Tuple.h index bf997e4309..a1363b6d34 100644 --- a/fdbclient/include/fdbclient/Tuple.h +++ b/fdbclient/include/fdbclient/Tuple.h @@ -25,7 +25,7 @@ #include "flow/flow.h" #include "fdbclient/FDBTypes.h" -#include "fdbclient/Versionstamp.h" +#include "fdbclient/TupleVersionstamp.h" struct Tuple { struct UnicodeStr { @@ -63,7 +63,7 @@ struct Tuple { Tuple& append(double); Tuple& append(std::nullptr_t); Tuple& appendNull(); - Tuple& append(Versionstamp const&); + Tuple& append(TupleVersionstamp const&); Tuple& append(UserTypeStr const&); Standalone pack() const { @@ -92,7 +92,7 @@ struct Tuple { StringRef subTupleRawString(size_t index) const; ElementType getType(size_t index) const; Standalone getString(size_t index) const; - Versionstamp getVersionstamp(size_t index) const; + TupleVersionstamp getVersionstamp(size_t index) const; int64_t getInt(size_t index, bool allow_incomplete = false) const; bool getBool(size_t index) const; float getFloat(size_t index) const; diff --git a/fdbclient/include/fdbclient/Versionstamp.h b/fdbclient/include/fdbclient/TupleVersionstamp.h similarity index 88% rename from fdbclient/include/fdbclient/Versionstamp.h rename to fdbclient/include/fdbclient/TupleVersionstamp.h index b3fd6770c7..730e7647f6 100644 --- a/fdbclient/include/fdbclient/Versionstamp.h +++ b/fdbclient/include/fdbclient/TupleVersionstamp.h @@ -1,5 +1,5 @@ /* - * Versionstamp.h + * TupleVersionstamp.h * * This source file is part of the FoundationDB open source project * @@ -27,15 +27,15 @@ const size_t VERSIONSTAMP_TUPLE_SIZE = 12; -struct Versionstamp { - Versionstamp(StringRef); +struct TupleVersionstamp { + TupleVersionstamp(StringRef); int64_t getVersion() const; int16_t getBatchNumber() const; int16_t getUserVersion() const; size_t size() const; const uint8_t* begin() const; - bool operator==(const Versionstamp&) const; + bool operator==(const TupleVersionstamp&) const; private: Standalone data; From 44ab6046e3eee9496375a18aebfaf92a5115ea19 Mon Sep 17 00:00:00 2001 From: "A.J. Beamon" Date: Wed, 5 Oct 2022 12:55:33 -0700 Subject: [PATCH 2/2] Fix missing operator to get address of offset --- fdbclient/include/fdbclient/KeyBackedTypes.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fdbclient/include/fdbclient/KeyBackedTypes.h b/fdbclient/include/fdbclient/KeyBackedTypes.h index 2eaee39cb5..293a90ba07 100644 --- a/fdbclient/include/fdbclient/KeyBackedTypes.h +++ b/fdbclient/include/fdbclient/KeyBackedTypes.h @@ -310,7 +310,7 @@ public: void setVersionstamp(Transaction tr, T const& val, int offset) { tr->atomicOp( key, - BinaryWriter::toValue(val, Unversioned()).withSuffix(StringRef(reinterpret_cast(offset), 4)), + BinaryWriter::toValue(val, Unversioned()).withSuffix(StringRef(reinterpret_cast(&offset), 4)), MutationRef::SetVersionstampedValue); }