From 1b81e7260415b8140bffa828236a1dacc39584ba Mon Sep 17 00:00:00 2001 From: "A.J. Beamon" Date: Tue, 19 Jul 2022 11:50:58 -0700 Subject: [PATCH 1/4] Add a Tuple::makeTuple function to easily construct a tuple. Update Tuple to allow all types to be passed via .append() so they can be used with makeTuple. --- bindings/c/test/unit/unit_tests.cpp | 2 +- .../sphinx/source/global-configuration.rst | 2 +- fdbcli/ProfileCommand.actor.cpp | 2 +- fdbclient/FileBackupAgent.actor.cpp | 2 +- fdbclient/GlobalConfig.actor.cpp | 2 +- fdbclient/SpecialKeySpace.actor.cpp | 2 +- fdbclient/TagThrottle.actor.cpp | 8 +-- fdbclient/Tuple.cpp | 49 +++++++++++++++++-- .../include/fdbclient/BackupAgent.actor.h | 2 +- fdbclient/include/fdbclient/Tuple.h | 25 +++++++--- .../include/fdbserver/RestoreCommon.actor.h | 4 +- ...entTransactionProfileCorrectness.actor.cpp | 2 +- 12 files changed, 77 insertions(+), 25 deletions(-) diff --git a/bindings/c/test/unit/unit_tests.cpp b/bindings/c/test/unit/unit_tests.cpp index 60af78c885..49e20be70a 100644 --- a/bindings/c/test/unit/unit_tests.cpp +++ b/bindings/c/test/unit/unit_tests.cpp @@ -1037,7 +1037,7 @@ 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); - const Tuple t = Tuple().append(prefix).append(RECORD).appendVersionstamp(vs).append("{K[3]}"_sr).append("{...}"_sr); + const Tuple t = Tuple().append(prefix).append(RECORD).append(vs).append("{K[3]}"_sr).append("{...}"_sr); ASSERT(t.getVersionstamp(2) == vs); // verify the round-way pack-unpack path for a Tuple containing a versionstamp diff --git a/documentation/sphinx/source/global-configuration.rst b/documentation/sphinx/source/global-configuration.rst index aad4c31d93..f163cc51bb 100644 --- a/documentation/sphinx/source/global-configuration.rst +++ b/documentation/sphinx/source/global-configuration.rst @@ -85,7 +85,7 @@ Values must always be encoded according to the :ref:`api-python-tuple-layer`. const KeyRef myGlobalConfigKey = LiteralStringRef("config/key"); // When you want to set the value.. - Tuple value = Tuple().appendDouble(1.5); + Tuple value = Tuple().append((double)1.5); FDBTransaction* tr = ...; tr->setOption(FDBTransactionOptions::SPECIAL_KEY_SPACE_ENABLE_WRITES); diff --git a/fdbcli/ProfileCommand.actor.cpp b/fdbcli/ProfileCommand.actor.cpp index d7f66ce080..adfe70b933 100644 --- a/fdbcli/ProfileCommand.actor.cpp +++ b/fdbcli/ProfileCommand.actor.cpp @@ -97,7 +97,7 @@ ACTOR Future profileCommandActor(Database db, } } - Tuple rate = Tuple().appendDouble(sampleRate); + Tuple rate = Tuple().append(sampleRate); Tuple size = Tuple().append(sizeLimit); tr->setOption(FDBTransactionOptions::SPECIAL_KEY_SPACE_ENABLE_WRITES); tr->set(GlobalConfig::prefixedKey(fdbClientInfoTxnSampleRate), rate.pack()); diff --git a/fdbclient/FileBackupAgent.actor.cpp b/fdbclient/FileBackupAgent.actor.cpp index 333cff9a81..6beb4d31f3 100644 --- a/fdbclient/FileBackupAgent.actor.cpp +++ b/fdbclient/FileBackupAgent.actor.cpp @@ -203,7 +203,7 @@ public: return Tuple() .append(version) .append(StringRef(fileName)) - .append(isRange) + .append((int)isRange) .append(fileSize) .append(blockSize) .append(endVersion); diff --git a/fdbclient/GlobalConfig.actor.cpp b/fdbclient/GlobalConfig.actor.cpp index c345e3669e..908574979f 100644 --- a/fdbclient/GlobalConfig.actor.cpp +++ b/fdbclient/GlobalConfig.actor.cpp @@ -183,7 +183,7 @@ ACTOR Future GlobalConfig::migrate(GlobalConfig* self) { if (sampleRate.present()) { const double sampleRateDbl = BinaryReader::fromStringRef(sampleRate.get().contents(), Unversioned()); - Tuple rate = Tuple().appendDouble(sampleRateDbl); + Tuple rate = Tuple().append(sampleRateDbl); tr->set(GlobalConfig::prefixedKey(fdbClientInfoTxnSampleRate), rate.pack()); } if (sizeLimit.present()) { diff --git a/fdbclient/SpecialKeySpace.actor.cpp b/fdbclient/SpecialKeySpace.actor.cpp index 85f237cb6d..64486085a2 100644 --- a/fdbclient/SpecialKeySpace.actor.cpp +++ b/fdbclient/SpecialKeySpace.actor.cpp @@ -2005,7 +2005,7 @@ Future> ClientProfilingImpl::commit(ReadYourWritesTransact } else { try { double sampleRate = boost::lexical_cast(sampleRateStr); - Tuple rate = Tuple().appendDouble(sampleRate); + Tuple rate = Tuple().append(sampleRate); insertions.push_back_deep(insertions.arena(), KeyValueRef(fdbClientInfoTxnSampleRate, rate.pack())); } catch (boost::bad_lexical_cast& e) { return Optional(ManagementAPIError::toJsonString( diff --git a/fdbclient/TagThrottle.actor.cpp b/fdbclient/TagThrottle.actor.cpp index b5205fd153..aa32f3da31 100644 --- a/fdbclient/TagThrottle.actor.cpp +++ b/fdbclient/TagThrottle.actor.cpp @@ -142,10 +142,10 @@ bool ThrottleApi::TagQuotaValue::isValid() const { Value ThrottleApi::TagQuotaValue::toValue() const { Tuple tuple; - tuple.appendDouble(reservedReadQuota); - tuple.appendDouble(totalReadQuota); - tuple.appendDouble(reservedWriteQuota); - tuple.appendDouble(totalWriteQuota); + tuple.append(reservedReadQuota); + tuple.append(totalReadQuota); + tuple.append(reservedWriteQuota); + tuple.append(totalWriteQuota); return tuple.pack(); } diff --git a/fdbclient/Tuple.cpp b/fdbclient/Tuple.cpp index 729c910252..8b8a0aebd0 100644 --- a/fdbclient/Tuple.cpp +++ b/fdbclient/Tuple.cpp @@ -19,6 +19,7 @@ */ #include "fdbclient/Tuple.h" +#include "flow/UnitTest.h" const uint8_t VERSIONSTAMP_96_CODE = 0x33; @@ -103,7 +104,7 @@ Tuple& Tuple::append(Tuple const& tuple) { return *this; } -Tuple& Tuple::appendVersionstamp(Versionstamp const& vs) { +Tuple& Tuple::append(Versionstamp const& vs) { offsets.push_back(data.size()); data.push_back(data.arena(), VERSIONSTAMP_96_CODE); @@ -134,6 +135,10 @@ Tuple& Tuple::append(StringRef const& str, bool utf8) { return *this; } +Tuple& Tuple::append(UnicodeStr const& str) { + return append(str.str, true); +} + Tuple& Tuple::appendRaw(StringRef const& str) { offsets.push_back(data.size()); @@ -166,7 +171,11 @@ Tuple& Tuple::append(int64_t value) { return *this; } -Tuple& Tuple::appendBool(bool value) { +Tuple& Tuple::append(int32_t value) { + return append((int64_t)value); +} + +Tuple& Tuple::append(bool value) { offsets.push_back(data.size()); if (value) { data.push_back(data.arena(), 0x27); @@ -176,7 +185,7 @@ Tuple& Tuple::appendBool(bool value) { return *this; } -Tuple& Tuple::appendFloat(float value) { +Tuple& Tuple::append(float value) { offsets.push_back(data.size()); float swap = bigEndianFloat(value); uint8_t* bytes = (uint8_t*)&swap; @@ -187,7 +196,7 @@ Tuple& Tuple::appendFloat(float value) { return *this; } -Tuple& Tuple::appendDouble(double value) { +Tuple& Tuple::append(double value) { offsets.push_back(data.size()); double swap = value; swap = bigEndianDouble(swap); @@ -199,12 +208,16 @@ Tuple& Tuple::appendDouble(double value) { return *this; } -Tuple& Tuple::appendNull() { +Tuple& Tuple::append(nullptr_t) { offsets.push_back(data.size()); data.push_back(data.arena(), (uint8_t)'\x00'); return *this; } +Tuple& Tuple::appendNull() { + return append(nullptr); +} + Tuple::ElementType Tuple::getType(size_t index) const { if (index >= offsets.size()) { throw invalid_tuple_index(); @@ -426,3 +439,29 @@ StringRef Tuple::subTupleRawString(size_t index) const { size_t endPos = end < offsets.size() ? offsets[end] : data.size(); return StringRef(data.begin() + offsets[index], endPos - offsets[index]); } + +TEST_CASE("fdbclient/Tuple/makeTuple") { + Tuple t1 = Tuple::makeTuple( + 1, 1.0f, 1.0, false, "byteStr"_sr, Tuple::UnicodeStr("str"_sr), nullptr, Versionstamp("000000000000"_sr)); + Tuple t2 = Tuple() + .append(1) + .append(1.0f) + .append(1.0) + .append(false) + .append("byteStr"_sr) + .append(Tuple::UnicodeStr("str"_sr)) + .append(nullptr) + .append(Versionstamp("000000000000"_sr)); + + ASSERT(t1.pack() == t2.pack()); + ASSERT(t1.getType(0) == Tuple::INT); + ASSERT(t1.getType(1) == Tuple::FLOAT); + ASSERT(t1.getType(2) == Tuple::DOUBLE); + ASSERT(t1.getType(3) == Tuple::BOOL); + ASSERT(t1.getType(4) == Tuple::BYTES); + ASSERT(t1.getType(5) == Tuple::UTF8); + ASSERT(t1.getType(6) == Tuple::NULL_TYPE); + ASSERT(t1.getType(7) == Tuple::VERSIONSTAMP); + + return Void(); +} \ No newline at end of file diff --git a/fdbclient/include/fdbclient/BackupAgent.actor.h b/fdbclient/include/fdbclient/BackupAgent.actor.h index 573c9c2c19..0f78afb837 100644 --- a/fdbclient/include/fdbclient/BackupAgent.actor.h +++ b/fdbclient/include/fdbclient/BackupAgent.actor.h @@ -361,7 +361,7 @@ public: template <> inline Standalone TupleCodec::pack( FileBackupAgent::ERestoreState const& val) { - return Tuple().append(val).pack(); + return Tuple().append(static_cast(val)).pack(); } template <> inline FileBackupAgent::ERestoreState TupleCodec::unpack( diff --git a/fdbclient/include/fdbclient/Tuple.h b/fdbclient/include/fdbclient/Tuple.h index 4c52c1ebc6..6093dc6779 100644 --- a/fdbclient/include/fdbclient/Tuple.h +++ b/fdbclient/include/fdbclient/Tuple.h @@ -28,6 +28,11 @@ #include "fdbclient/Versionstamp.h" struct Tuple { + struct UnicodeStr { + StringRef str; + UnicodeStr(StringRef str) : str(str) {} + }; + Tuple() {} // Tuple parsing normally does not care of the final value is a numeric type and is incomplete. @@ -41,14 +46,15 @@ struct Tuple { // the str needs to be a Tuple encoded string. Tuple& appendRaw(StringRef const& str); Tuple& append(StringRef const& str, bool utf8 = false); + Tuple& append(UnicodeStr const& str); + Tuple& append(int32_t); Tuple& append(int64_t); - // There are some ambiguous append calls in fdbclient, so to make it easier - // to add append for floats and doubles, name them differently for now. - Tuple& appendBool(bool); - Tuple& appendFloat(float); - Tuple& appendDouble(double); + Tuple& append(bool); + Tuple& append(float); + Tuple& append(double); + Tuple& append(std::nullptr_t); Tuple& appendNull(); - Tuple& appendVersionstamp(Versionstamp const&); + Tuple& append(Versionstamp const&); StringRef pack() const { return StringRef(data.begin(), data.size()); } @@ -84,6 +90,13 @@ struct Tuple { Standalone> getData() { return data; } Standalone getDataAsStandalone() { return Standalone(pack(), data.arena()); } + template + static Tuple makeTuple(Types&&... args) { + Tuple t; + (t << ... << args); + return t; + } + private: Tuple(const StringRef& data, bool exclude_incomplete = false); Standalone> data; diff --git a/fdbserver/include/fdbserver/RestoreCommon.actor.h b/fdbserver/include/fdbserver/RestoreCommon.actor.h index b647bb5326..692d760810 100644 --- a/fdbserver/include/fdbserver/RestoreCommon.actor.h +++ b/fdbserver/include/fdbserver/RestoreCommon.actor.h @@ -115,7 +115,7 @@ public: return Tuple() .append(version) .append(StringRef(fileName)) - .append(isRange) + .append((int)isRange) .append(fileSize) .append(blockSize) .append(endVersion); @@ -193,7 +193,7 @@ struct RestoreFileFR { return Tuple() .append(version) .append(StringRef(fileName)) - .append(isRange) + .append((int)isRange) .append(fileSize) .append(blockSize) .append(endVersion) diff --git a/fdbserver/workloads/ClientTransactionProfileCorrectness.actor.cpp b/fdbserver/workloads/ClientTransactionProfileCorrectness.actor.cpp index 64da60cf7a..d9b2e6b5fd 100644 --- a/fdbserver/workloads/ClientTransactionProfileCorrectness.actor.cpp +++ b/fdbserver/workloads/ClientTransactionProfileCorrectness.actor.cpp @@ -294,7 +294,7 @@ struct ClientTransactionProfileCorrectnessWorkload : TestWorkload { wait(runRYWTransaction(cx, [=](Reference tr) -> Future { tr->setOption(FDBTransactionOptions::SPECIAL_KEY_SPACE_ENABLE_WRITES); tr->setOption(FDBTransactionOptions::LOCK_AWARE); - Tuple rate = Tuple().appendDouble(sampleProbability); + Tuple rate = Tuple().append(sampleProbability); Tuple size = Tuple().append(sizeLimit); tr->set(GlobalConfig::prefixedKey(fdbClientInfoTxnSampleRate), rate.pack()); tr->set(GlobalConfig::prefixedKey(fdbClientInfoTxnSizeLimit), size.pack()); From 190ad8c7e9223bd0c682ead21fe3d6e10918de31 Mon Sep 17 00:00:00 2001 From: "A.J. Beamon" Date: Tue, 19 Jul 2022 13:45:59 -0700 Subject: [PATCH 2/4] Convert existing tuple usages to use Tuple::makeTuple() --- bindings/c/test/unit/unit_tests.cpp | 21 ++++------ .../sphinx/source/global-configuration.rst | 2 +- fdbcli/ProfileCommand.actor.cpp | 4 +- fdbclient/ConfigKnobs.cpp | 19 ++-------- fdbclient/FileBackupAgent.actor.cpp | 8 +--- fdbclient/GlobalConfig.actor.cpp | 4 +- fdbclient/NativeAPI.actor.cpp | 7 ++-- fdbclient/SpecialKeySpace.actor.cpp | 4 +- fdbclient/TagThrottle.actor.cpp | 7 +--- fdbclient/TaskBucket.actor.cpp | 9 +---- .../include/fdbclient/BackupAgent.actor.h | 11 ++---- .../HighContentionPrefixAllocator.actor.h | 2 +- fdbclient/include/fdbclient/KeyBackedTypes.h | 10 ++--- fdbclient/include/fdbclient/Subspace.h | 8 +--- fdbserver/MetricLogger.actor.cpp | 8 +--- .../include/fdbserver/RestoreCommon.actor.h | 29 ++++++-------- fdbserver/storageserver.actor.cpp | 38 +++++++------------ ...entTransactionProfileCorrectness.actor.cpp | 4 +- fdbserver/workloads/ConfigIncrement.actor.cpp | 7 +--- fdbserver/workloads/GetMappedRange.actor.cpp | 22 +++++------ .../workloads/TaskBucketCorrectness.actor.cpp | 9 ++--- 21 files changed, 78 insertions(+), 155 deletions(-) diff --git a/bindings/c/test/unit/unit_tests.cpp b/bindings/c/test/unit/unit_tests.cpp index 49e20be70a..9f5c015bfb 100644 --- a/bindings/c/test/unit/unit_tests.cpp +++ b/bindings/c/test/unit/unit_tests.cpp @@ -941,13 +941,13 @@ static Value dataOfRecord(const int i) { return Value(format("data-of-record-%08d", i)); } static std::string indexEntryKey(const int i) { - return Tuple().append(StringRef(prefix)).append(INDEX).append(indexKey(i)).append(primaryKey(i)).pack().toString(); + return Tuple::makeTuple(prefix, INDEX, indexKey(i), primaryKey(i)).pack().toString(); } static std::string recordKey(const int i, const int split) { - return Tuple().append(prefix).append(RECORD).append(primaryKey(i)).append(split).pack().toString(); + return Tuple::makeTuple(prefix, RECORD, primaryKey(i), split).pack().toString(); } static std::string recordValue(const int i, const int split) { - return Tuple().append(dataOfRecord(i)).append(split).pack().toString(); + return Tuple::makeTuple(dataOfRecord(i), split).pack().toString(); } const static int SPLIT_SIZE = 3; @@ -993,13 +993,8 @@ GetMappedRangeResult getMappedIndexEntries(int beginId, fdb::Transaction& tr, int matchIndex, bool allMissing) { - std::string mapper = Tuple() - .append(prefix) - .append(RECORD) - .append(allMissing ? "{K[2]}"_sr : "{K[3]}"_sr) - .append("{...}"_sr) - .pack() - .toString(); + std::string mapper = + Tuple::makeTuple(prefix, RECORD, (allMissing ? "{K[2]}"_sr : "{K[3]}"_sr), "{...}"_sr).pack().toString(); return getMappedIndexEntries(beginId, endId, tr, mapper, matchIndex); } @@ -1037,7 +1032,7 @@ 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); - const Tuple t = Tuple().append(prefix).append(RECORD).append(vs).append("{K[3]}"_sr).append("{...}"_sr); + const Tuple t = Tuple::makeTuple(prefix, RECORD, vs, "{K[3]}"_sr, "{...}"_sr); ASSERT(t.getVersionstamp(2) == vs); // verify the round-way pack-unpack path for a Tuple containing a versionstamp @@ -1181,7 +1176,7 @@ TEST_CASE("fdb_transaction_get_mapped_range_missing_all_secondary") { } TEST_CASE("fdb_transaction_get_mapped_range_restricted_to_serializable") { - std::string mapper = Tuple().append(prefix).append(RECORD).append("{K[3]}"_sr).pack().toString(); + std::string mapper = Tuple::makeTuple(prefix, RECORD, "{K[3]}"_sr).pack().toString(); fdb::Transaction tr(db); auto result = get_mapped_range( tr, @@ -1200,7 +1195,7 @@ TEST_CASE("fdb_transaction_get_mapped_range_restricted_to_serializable") { } TEST_CASE("fdb_transaction_get_mapped_range_restricted_to_ryw_enable") { - std::string mapper = Tuple().append(prefix).append(RECORD).append("{K[3]}"_sr).pack().toString(); + std::string mapper = Tuple::makeTuple(prefix, RECORD, "{K[3]}"_sr).pack().toString(); fdb::Transaction tr(db); fdb_check(tr.set_option(FDB_TR_OPTION_READ_YOUR_WRITES_DISABLE, nullptr, 0)); // Not disable RYW auto result = get_mapped_range( diff --git a/documentation/sphinx/source/global-configuration.rst b/documentation/sphinx/source/global-configuration.rst index f163cc51bb..1c5f94dc7d 100644 --- a/documentation/sphinx/source/global-configuration.rst +++ b/documentation/sphinx/source/global-configuration.rst @@ -85,7 +85,7 @@ Values must always be encoded according to the :ref:`api-python-tuple-layer`. const KeyRef myGlobalConfigKey = LiteralStringRef("config/key"); // When you want to set the value.. - Tuple value = Tuple().append((double)1.5); + Tuple value = Tuple::makeTuple((double)1.5); FDBTransaction* tr = ...; tr->setOption(FDBTransactionOptions::SPECIAL_KEY_SPACE_ENABLE_WRITES); diff --git a/fdbcli/ProfileCommand.actor.cpp b/fdbcli/ProfileCommand.actor.cpp index adfe70b933..c47a558258 100644 --- a/fdbcli/ProfileCommand.actor.cpp +++ b/fdbcli/ProfileCommand.actor.cpp @@ -97,8 +97,8 @@ ACTOR Future profileCommandActor(Database db, } } - Tuple rate = Tuple().append(sampleRate); - Tuple size = Tuple().append(sizeLimit); + Tuple rate = Tuple::makeTuple(sampleRate); + Tuple size = Tuple::makeTuple(sizeLimit); tr->setOption(FDBTransactionOptions::SPECIAL_KEY_SPACE_ENABLE_WRITES); tr->set(GlobalConfig::prefixedKey(fdbClientInfoTxnSampleRate), rate.pack()); tr->set(GlobalConfig::prefixedKey(fdbClientInfoTxnSizeLimit), size.pack()); diff --git a/fdbclient/ConfigKnobs.cpp b/fdbclient/ConfigKnobs.cpp index 03b4b09fbd..283e8208c2 100644 --- a/fdbclient/ConfigKnobs.cpp +++ b/fdbclient/ConfigKnobs.cpp @@ -144,10 +144,7 @@ std::string configDBTypeToString(ConfigDBType configDBType) { } TEST_CASE("/fdbclient/ConfigDB/ConfigKey/EncodeDecode") { - Tuple tuple; - tuple << "class-A"_sr - << "test_long"_sr; - auto packed = tuple.pack(); + auto packed = Tuple::makeTuple("class-A"_sr, "test_long"_sr).pack(); auto unpacked = ConfigKeyRef::decodeKey(packed); ASSERT(unpacked.configClass.get() == "class-A"_sr); ASSERT(unpacked.knobName == "test_long"_sr); @@ -169,18 +166,8 @@ void decodeFailureTest(KeyRef key) { } // namespace TEST_CASE("/fdbclient/ConfigDB/ConfigKey/DecodeFailure") { - { - Tuple tuple; - tuple << "s1"_sr - << "s2"_sr - << "s3"_sr; - decodeFailureTest(tuple.pack()); - } - { - Tuple tuple; - tuple << "s1"_sr << 5; - decodeFailureTest(tuple.pack()); - } + decodeFailureTest(Tuple::makeTuple("s1"_sr, "s2"_sr, "s3"_sr).pack()); + decodeFailureTest(Tuple::makeTuple("s1"_sr, 5).pack()); decodeFailureTest("non-tuple-key"_sr); return Void(); } diff --git a/fdbclient/FileBackupAgent.actor.cpp b/fdbclient/FileBackupAgent.actor.cpp index 6beb4d31f3..ed98e57c69 100644 --- a/fdbclient/FileBackupAgent.actor.cpp +++ b/fdbclient/FileBackupAgent.actor.cpp @@ -200,13 +200,7 @@ public: Version endVersion{ ::invalidVersion }; // not meaningful for range files Tuple pack() const { - return Tuple() - .append(version) - .append(StringRef(fileName)) - .append((int)isRange) - .append(fileSize) - .append(blockSize) - .append(endVersion); + return Tuple::makeTuple(version, fileName, (int)isRange, fileSize, blockSize, endVersion); } static RestoreFile unpack(Tuple const& t) { RestoreFile r; diff --git a/fdbclient/GlobalConfig.actor.cpp b/fdbclient/GlobalConfig.actor.cpp index 908574979f..856519e565 100644 --- a/fdbclient/GlobalConfig.actor.cpp +++ b/fdbclient/GlobalConfig.actor.cpp @@ -183,13 +183,13 @@ ACTOR Future GlobalConfig::migrate(GlobalConfig* self) { if (sampleRate.present()) { const double sampleRateDbl = BinaryReader::fromStringRef(sampleRate.get().contents(), Unversioned()); - Tuple rate = Tuple().append(sampleRateDbl); + Tuple rate = Tuple::makeTuple(sampleRateDbl); tr->set(GlobalConfig::prefixedKey(fdbClientInfoTxnSampleRate), rate.pack()); } if (sizeLimit.present()) { const int64_t sizeLimitInt = BinaryReader::fromStringRef(sizeLimit.get().contents(), Unversioned()); - Tuple size = Tuple().append(sizeLimitInt); + Tuple size = Tuple::makeTuple(sizeLimitInt); tr->set(GlobalConfig::prefixedKey(fdbClientInfoTxnSizeLimit), size.pack()); } diff --git a/fdbclient/NativeAPI.actor.cpp b/fdbclient/NativeAPI.actor.cpp index 89b0452489..aa3b06950d 100644 --- a/fdbclient/NativeAPI.actor.cpp +++ b/fdbclient/NativeAPI.actor.cpp @@ -1132,10 +1132,9 @@ ACTOR static Future handleTssMismatches(DatabaseContext* cx) { for (const DetailedTSSMismatch& d : data.second) { // -> mismatch data - tssMismatchDB.set( - tr, - Tuple().append(data.first.toString()).append(d.timestamp).append(d.mismatchId.toString()), - d.traceString); + tssMismatchDB.set(tr, + Tuple::makeTuple(data.first.toString(), d.timestamp, d.mismatchId.toString()), + d.traceString); } wait(tr->commit()); diff --git a/fdbclient/SpecialKeySpace.actor.cpp b/fdbclient/SpecialKeySpace.actor.cpp index 64486085a2..2d04f9c6cb 100644 --- a/fdbclient/SpecialKeySpace.actor.cpp +++ b/fdbclient/SpecialKeySpace.actor.cpp @@ -2005,7 +2005,7 @@ Future> ClientProfilingImpl::commit(ReadYourWritesTransact } else { try { double sampleRate = boost::lexical_cast(sampleRateStr); - Tuple rate = Tuple().append(sampleRate); + Tuple rate = Tuple::makeTuple(sampleRate); insertions.push_back_deep(insertions.arena(), KeyValueRef(fdbClientInfoTxnSampleRate, rate.pack())); } catch (boost::bad_lexical_cast& e) { return Optional(ManagementAPIError::toJsonString( @@ -2024,7 +2024,7 @@ Future> ClientProfilingImpl::commit(ReadYourWritesTransact } else { try { int64_t sizeLimit = boost::lexical_cast(sizeLimitStr); - Tuple size = Tuple().append(sizeLimit); + Tuple size = Tuple::makeTuple(sizeLimit); insertions.push_back_deep(insertions.arena(), KeyValueRef(fdbClientInfoTxnSizeLimit, size.pack())); } catch (boost::bad_lexical_cast& e) { return Optional(ManagementAPIError::toJsonString( diff --git a/fdbclient/TagThrottle.actor.cpp b/fdbclient/TagThrottle.actor.cpp index aa32f3da31..856c111dea 100644 --- a/fdbclient/TagThrottle.actor.cpp +++ b/fdbclient/TagThrottle.actor.cpp @@ -141,12 +141,7 @@ bool ThrottleApi::TagQuotaValue::isValid() const { } Value ThrottleApi::TagQuotaValue::toValue() const { - Tuple tuple; - tuple.append(reservedReadQuota); - tuple.append(totalReadQuota); - tuple.append(reservedWriteQuota); - tuple.append(totalWriteQuota); - return tuple.pack(); + return Tuple::makeTuple(reservedReadQuota, totalReadQuota, reservedWriteQuota, totalWriteQuota).pack(); } ThrottleApi::TagQuotaValue ThrottleApi::TagQuotaValue::fromValue(ValueRef value) { diff --git a/fdbclient/TaskBucket.actor.cpp b/fdbclient/TaskBucket.actor.cpp index dc3d75259a..be1f703e58 100644 --- a/fdbclient/TaskBucket.actor.cpp +++ b/fdbclient/TaskBucket.actor.cpp @@ -651,10 +651,7 @@ public: Reference task) { taskBucket->setOptions(tr); - Tuple t; - t.append(task->timeoutVersion); - t.append(task->key); - + Tuple t = Tuple::makeTuple(task->timeoutVersion, task->key); RangeResult values = wait(tr->getRange(taskBucket->timeouts.range(t), 1)); if (values.size() > 0) return false; @@ -996,9 +993,7 @@ Future TaskBucket::isEmpty(Reference tr) { Future TaskBucket::finish(Reference tr, Reference task) { setOptions(tr); - Tuple t; - t.append(task->timeoutVersion); - t.append(task->key); + Tuple t = Tuple::makeTuple(task->timeoutVersion, task->key); tr->atomicOp(prefix.pack(LiteralStringRef("task_count")), LiteralStringRef("\xff\xff\xff\xff\xff\xff\xff\xff"), diff --git a/fdbclient/include/fdbclient/BackupAgent.actor.h b/fdbclient/include/fdbclient/BackupAgent.actor.h index 0f78afb837..e0eb69ede6 100644 --- a/fdbclient/include/fdbclient/BackupAgent.actor.h +++ b/fdbclient/include/fdbclient/BackupAgent.actor.h @@ -361,7 +361,7 @@ public: template <> inline Standalone TupleCodec::pack( FileBackupAgent::ERestoreState const& val) { - return Tuple().append(static_cast(val)).pack(); + return Tuple::makeTuple(static_cast(val)).pack(); } template <> inline FileBackupAgent::ERestoreState TupleCodec::unpack( @@ -578,7 +578,7 @@ ACTOR Future cleanupBackup(Database cx, DeleteData deleteData); using EBackupState = BackupAgentBase::EnumState; template <> inline Standalone TupleCodec::pack(EBackupState const& val) { - return Tuple().append(static_cast(val)).pack(); + return Tuple::makeTuple(static_cast(val)).pack(); } template <> inline EBackupState TupleCodec::unpack(Standalone const& val) { @@ -727,8 +727,7 @@ protected: template <> inline Standalone TupleCodec>::pack(Reference const& bc) { - Tuple tuple; - tuple.append(StringRef(bc->getURL())); + Tuple tuple = Tuple::makeTuple(bc->getURL()); if (bc->getEncryptionKeyFileName().present()) { tuple.append(bc->getEncryptionKeyFileName().get()); @@ -775,9 +774,7 @@ public: Version version; std::string fileName; int64_t fileSize; - Tuple pack() const { - return Tuple().append(begin).append(version).append(StringRef(fileName)).append(fileSize); - } + Tuple pack() const { return Tuple::makeTuple(begin, version, fileName, fileSize); } static RangeSlice unpack(Tuple const& t) { RangeSlice r; int i = 0; diff --git a/fdbclient/include/fdbclient/HighContentionPrefixAllocator.actor.h b/fdbclient/include/fdbclient/HighContentionPrefixAllocator.actor.h index 57e185cd78..20ec964436 100644 --- a/fdbclient/include/fdbclient/HighContentionPrefixAllocator.actor.h +++ b/fdbclient/include/fdbclient/HighContentionPrefixAllocator.actor.h @@ -134,7 +134,7 @@ private: if (!candidateValueFuture.get().present()) { tr->addWriteConflictRange(singleKeyRange(self->recent.get(candidate).key())); - return Tuple().append(candidate).pack(); + return Tuple::makeTuple(candidate).pack(); } } } diff --git a/fdbclient/include/fdbclient/KeyBackedTypes.h b/fdbclient/include/fdbclient/KeyBackedTypes.h index 98171671ee..893cc1c5b4 100644 --- a/fdbclient/include/fdbclient/KeyBackedTypes.h +++ b/fdbclient/include/fdbclient/KeyBackedTypes.h @@ -59,7 +59,7 @@ inline Tuple TupleCodec::unpack(Standalone const& val) { template <> inline Standalone TupleCodec::pack(int64_t const& val) { - return Tuple().append(val).pack(); + return Tuple::makeTuple(val).pack(); } template <> inline int64_t TupleCodec::unpack(Standalone const& val) { @@ -68,7 +68,7 @@ inline int64_t TupleCodec::unpack(Standalone const& val) { template <> inline Standalone TupleCodec::pack(bool const& val) { - return Tuple().append(val ? 1 : 0).pack(); + return Tuple::makeTuple(val ? 1 : 0).pack(); } template <> inline bool TupleCodec::unpack(Standalone const& val) { @@ -77,7 +77,7 @@ inline bool TupleCodec::unpack(Standalone const& val) { template <> inline Standalone TupleCodec>::pack(Standalone const& val) { - return Tuple().append(val).pack(); + return Tuple::makeTuple(val).pack(); } template <> inline Standalone TupleCodec>::unpack(Standalone const& val) { @@ -96,7 +96,7 @@ inline UID TupleCodec::unpack(Standalone const& val) { // This is backward compatible with TupleCodec> template <> inline Standalone TupleCodec::pack(std::string const& val) { - return Tuple().append(StringRef(val)).pack(); + return Tuple::makeTuple(val).pack(); } template <> inline std::string TupleCodec::unpack(Standalone const& val) { @@ -143,7 +143,7 @@ struct TupleCodec> { template <> inline Standalone TupleCodec::pack(KeyRange const& val) { - return Tuple().append(val.begin).append(val.end).pack(); + return Tuple::makeTuple(val.begin, val.end).pack(); } template <> inline KeyRange TupleCodec::unpack(Standalone const& val) { diff --git a/fdbclient/include/fdbclient/Subspace.h b/fdbclient/include/fdbclient/Subspace.h index ef88fc3855..0cc85089d1 100644 --- a/fdbclient/include/fdbclient/Subspace.h +++ b/fdbclient/include/fdbclient/Subspace.h @@ -42,9 +42,7 @@ public: template Key pack(T const& item) const { - Tuple t; - t.append(item); - return pack(t); + return pack(Tuple::makeTuple(item)); } Key pack(StringRef const& item, bool utf8 = false) const { @@ -58,9 +56,7 @@ public: template Subspace get(T const& item) const { - Tuple t; - t.append(item); - return get(t); + return get(Tuple::makeTuple(item)); } Subspace get(StringRef const& item, bool utf8 = false) const { diff --git a/fdbserver/MetricLogger.actor.cpp b/fdbserver/MetricLogger.actor.cpp index 933c1f5d85..1d3e7fc26b 100644 --- a/fdbserver/MetricLogger.actor.cpp +++ b/fdbserver/MetricLogger.actor.cpp @@ -40,13 +40,7 @@ struct MetricsRule { int minLevel; Tuple pack() const { - return Tuple() - .append(namePattern) - .append(typePattern) - .append(addressPattern) - .append(idPattern) - .append(enabled ? 1 : 0) - .append(minLevel); + return Tuple::makeTuple(namePattern, typePattern, addressPattern, idPattern, enabled ? 1 : 0, minLevel); } static inline MetricsRule unpack(Tuple const& t) { diff --git a/fdbserver/include/fdbserver/RestoreCommon.actor.h b/fdbserver/include/fdbserver/RestoreCommon.actor.h index 692d760810..4b4dc6f0f9 100644 --- a/fdbserver/include/fdbserver/RestoreCommon.actor.h +++ b/fdbserver/include/fdbserver/RestoreCommon.actor.h @@ -112,13 +112,7 @@ public: Tuple pack() const { // fprintf(stderr, "Filename:%s\n", fileName.c_str()); - return Tuple() - .append(version) - .append(StringRef(fileName)) - .append((int)isRange) - .append(fileSize) - .append(blockSize) - .append(endVersion); + return Tuple::makeTuple(version, fileName, (int)isRange, fileSize, blockSize, endVersion); } static RestoreFile unpack(Tuple const& t) { RestoreFile r; @@ -190,17 +184,16 @@ struct RestoreFileFR { int partitionId = -1; // Partition ID (Log Router Tag ID) for mutation files. Tuple pack() const { - return Tuple() - .append(version) - .append(StringRef(fileName)) - .append((int)isRange) - .append(fileSize) - .append(blockSize) - .append(endVersion) - .append(beginVersion) - .append(cursor) - .append(fileIndex) - .append(partitionId); + return Tuple::makeTuple(version, + fileName, + (int)isRange, + fileSize, + blockSize, + endVersion, + beginVersion, + cursor, + fileIndex, + partitionId); } static RestoreFileFR unpack(Tuple const& t) { RestoreFileFR r; diff --git a/fdbserver/storageserver.actor.cpp b/fdbserver/storageserver.actor.cpp index 9a5ff1975a..12c208c9b2 100644 --- a/fdbserver/storageserver.actor.cpp +++ b/fdbserver/storageserver.actor.cpp @@ -3675,9 +3675,7 @@ void preprocessMappedKey(Tuple& mappedKeyFormatTuple, std::vector> vt; @@ -3767,19 +3761,15 @@ TEST_CASE("/fdbserver/storageserver/constructMappedKey") { Key mappedKey = constructMappedKey(&kvr, vt, mappedKeyTuple, mappedKeyFormatTuple); - Key expectedMappedKey = Tuple() - .append("normal"_sr) - .append("{escaped}"_sr) - .append("key-2"_sr) - .append("value-0"_sr) - .getDataAsStandalone(); + Key expectedMappedKey = + Tuple::makeTuple("normal"_sr, "{escaped}"_sr, "key-2"_sr, "value-0"_sr).getDataAsStandalone(); // std::cout << printable(mappedKey) << " == " << printable(expectedMappedKey) << std::endl; ASSERT(mappedKey.compare(expectedMappedKey) == 0); ASSERT(isRangeQuery == true); } { - Tuple mappedKeyFormatTuple = Tuple().append("{{{{}}"_sr).append("}}"_sr); + Tuple mappedKeyFormatTuple = Tuple::makeTuple("{{{{}}"_sr, "}}"_sr); Tuple mappedKeyTuple; std::vector> vt; @@ -3787,13 +3777,13 @@ TEST_CASE("/fdbserver/storageserver/constructMappedKey") { preprocessMappedKey(mappedKeyFormatTuple, vt, isRangeQuery); Key mappedKey = constructMappedKey(&kvr, vt, mappedKeyTuple, mappedKeyFormatTuple); - Key expectedMappedKey = Tuple().append("{{}"_sr).append("}"_sr).getDataAsStandalone(); + Key expectedMappedKey = Tuple::makeTuple("{{}"_sr, "}"_sr).getDataAsStandalone(); // std::cout << printable(mappedKey) << " == " << printable(expectedMappedKey) << std::endl; ASSERT(mappedKey.compare(expectedMappedKey) == 0); ASSERT(isRangeQuery == false); } { - Tuple mappedKeyFormatTuple = Tuple().append("{{{{}}"_sr).append("}}"_sr); + Tuple mappedKeyFormatTuple = Tuple::makeTuple("{{{{}}"_sr, "}}"_sr); Tuple mappedKeyTuple; std::vector> vt; @@ -3801,13 +3791,13 @@ TEST_CASE("/fdbserver/storageserver/constructMappedKey") { preprocessMappedKey(mappedKeyFormatTuple, vt, isRangeQuery); Key mappedKey = constructMappedKey(&kvr, vt, mappedKeyTuple, mappedKeyFormatTuple); - Key expectedMappedKey = Tuple().append("{{}"_sr).append("}"_sr).getDataAsStandalone(); + Key expectedMappedKey = Tuple::makeTuple("{{}"_sr, "}"_sr).getDataAsStandalone(); // std::cout << printable(mappedKey) << " == " << printable(expectedMappedKey) << std::endl; ASSERT(mappedKey.compare(expectedMappedKey) == 0); ASSERT(isRangeQuery == false); } { - Tuple mappedKeyFormatTuple = Tuple().append("{K[100]}"_sr); + Tuple mappedKeyFormatTuple = Tuple::makeTuple("{K[100]}"_sr); state bool throwException = false; try { Tuple mappedKeyTuple; @@ -3823,7 +3813,7 @@ TEST_CASE("/fdbserver/storageserver/constructMappedKey") { ASSERT(throwException); } { - Tuple mappedKeyFormatTuple = Tuple().append("{...}"_sr).append("last-element"_sr); + Tuple mappedKeyFormatTuple = Tuple::makeTuple("{...}"_sr, "last-element"_sr); state bool throwException2 = false; try { Tuple mappedKeyTuple; @@ -3839,7 +3829,7 @@ TEST_CASE("/fdbserver/storageserver/constructMappedKey") { ASSERT(throwException2); } { - Tuple mappedKeyFormatTuple = Tuple().append("{K[not-a-number]}"_sr); + Tuple mappedKeyFormatTuple = Tuple::makeTuple("{K[not-a-number]}"_sr); state bool throwException3 = false; try { Tuple mappedKeyTuple; diff --git a/fdbserver/workloads/ClientTransactionProfileCorrectness.actor.cpp b/fdbserver/workloads/ClientTransactionProfileCorrectness.actor.cpp index d9b2e6b5fd..de9ef2a60a 100644 --- a/fdbserver/workloads/ClientTransactionProfileCorrectness.actor.cpp +++ b/fdbserver/workloads/ClientTransactionProfileCorrectness.actor.cpp @@ -294,8 +294,8 @@ struct ClientTransactionProfileCorrectnessWorkload : TestWorkload { wait(runRYWTransaction(cx, [=](Reference tr) -> Future { tr->setOption(FDBTransactionOptions::SPECIAL_KEY_SPACE_ENABLE_WRITES); tr->setOption(FDBTransactionOptions::LOCK_AWARE); - Tuple rate = Tuple().append(sampleProbability); - Tuple size = Tuple().append(sizeLimit); + Tuple rate = Tuple::makeTuple(sampleProbability); + Tuple size = Tuple::makeTuple(sizeLimit); tr->set(GlobalConfig::prefixedKey(fdbClientInfoTxnSampleRate), rate.pack()); tr->set(GlobalConfig::prefixedKey(fdbClientInfoTxnSizeLimit), size.pack()); return Void(); diff --git a/fdbserver/workloads/ConfigIncrement.actor.cpp b/fdbserver/workloads/ConfigIncrement.actor.cpp index 6f1d1babb2..e1961b598f 100644 --- a/fdbserver/workloads/ConfigIncrement.actor.cpp +++ b/fdbserver/workloads/ConfigIncrement.actor.cpp @@ -36,12 +36,7 @@ class ConfigIncrementWorkload : public TestWorkload { PerfIntCounter transactions, retries, commitUnknownResult; - static Key getConfigKey() { - Tuple tuple; - tuple.appendNull(); // config class - tuple << testKnobName; - return tuple.pack(); - } + static Key getConfigKey() { return Tuple::makeTuple(/* config class */ nullptr, testKnobName).pack(); } ACTOR static Future get(Reference tr) { TraceEvent(SevDebug, "ConfigIncrementGet"); diff --git a/fdbserver/workloads/GetMappedRange.actor.cpp b/fdbserver/workloads/GetMappedRange.actor.cpp index 9a7eae6a7a..363193613f 100644 --- a/fdbserver/workloads/GetMappedRange.actor.cpp +++ b/fdbserver/workloads/GetMappedRange.actor.cpp @@ -83,15 +83,11 @@ struct GetMappedRangeWorkload : ApiWorkload { static Value dataOfRecord(int i) { return Key(format("data-of-record-%08d", i)); } static Value dataOfRecord(int i, int split) { return Key(format("data-of-record-%08d-split-%08d", i, split)); } - static Key indexEntryKey(int i) { - return Tuple().append(prefix).append(INDEX).append(indexKey(i)).append(primaryKey(i)).pack(); - } - static Key recordKey(int i) { return Tuple().append(prefix).append(RECORD).append(primaryKey(i)).pack(); } - static Key recordKey(int i, int split) { - return Tuple().append(prefix).append(RECORD).append(primaryKey(i)).append(split).pack(); - } - static Value recordValue(int i) { return Tuple().append(dataOfRecord(i)).pack(); } - static Value recordValue(int i, int split) { return Tuple().append(dataOfRecord(i, split)).pack(); } + static Key indexEntryKey(int i) { return Tuple::makeTuple(prefix, INDEX, indexKey(i), primaryKey(i)).pack(); } + static Key recordKey(int i) { return Tuple::makeTuple(prefix, RECORD, primaryKey(i)).pack(); } + static Key recordKey(int i, int split) { return Tuple::makeTuple(prefix, RECORD, primaryKey(i), split).pack(); } + static Value recordValue(int i) { return Tuple::makeTuple(dataOfRecord(i)).pack(); } + static Value recordValue(int i, int split) { return Tuple::makeTuple(dataOfRecord(i, split)).pack(); } ACTOR Future fillInRecords(Database cx, int n, GetMappedRangeWorkload* self) { state Transaction tr(cx); @@ -270,9 +266,9 @@ struct GetMappedRangeWorkload : ApiWorkload { GetMappedRangeWorkload* self, int matchIndex, bool allMissing = false) { - Key beginTuple = Tuple().append(prefix).append(INDEX).append(indexKey(beginId)).getDataAsStandalone(); + Key beginTuple = Tuple::makeTuple(prefix, INDEX, indexKey(beginId)).getDataAsStandalone(); state KeySelector beginSelector = KeySelector(firstGreaterOrEqual(beginTuple)); - Key endTuple = Tuple().append(prefix).append(INDEX).append(indexKey(endId)).getDataAsStandalone(); + Key endTuple = Tuple::makeTuple(prefix, INDEX, indexKey(endId)).getDataAsStandalone(); state KeySelector endSelector = KeySelector(firstGreaterOrEqual(endTuple)); state int limit = 100; state int expectedBeginId = beginId; @@ -322,9 +318,9 @@ struct GetMappedRangeWorkload : ApiWorkload { Reference& tr, GetMappedRangeWorkload* self) { Key mapper = getMapper(self, false); - Key beginTuple = Tuple().append(prefix).append(INDEX).append(indexKey(beginId)).getDataAsStandalone(); + Key beginTuple = Tuple::makeTuple(prefix, INDEX, indexKey(beginId)).getDataAsStandalone(); KeySelector beginSelector = KeySelector(firstGreaterOrEqual(beginTuple)); - Key endTuple = Tuple().append(prefix).append(INDEX).append(indexKey(endId)).getDataAsStandalone(); + Key endTuple = Tuple::makeTuple(prefix, INDEX, indexKey(endId)).getDataAsStandalone(); KeySelector endSelector = KeySelector(firstGreaterOrEqual(endTuple)); return tr->getMappedRange(beginSelector, endSelector, diff --git a/fdbserver/workloads/TaskBucketCorrectness.actor.cpp b/fdbserver/workloads/TaskBucketCorrectness.actor.cpp index 7a14a29652..2e2f265b19 100644 --- a/fdbserver/workloads/TaskBucketCorrectness.actor.cpp +++ b/fdbserver/workloads/TaskBucketCorrectness.actor.cpp @@ -359,8 +359,7 @@ TEST_CASE("/fdbclient/TaskBucket/Subspace") { print_subspace_key(subspace_test1, 1); ASSERT(subspace_test1.key() == LiteralStringRef("abc")); - Tuple t; - t.append(LiteralStringRef("user")); + Tuple t = Tuple::makeTuple("user"_sr); Subspace subspace_test2(t); print_subspace_key(subspace_test2, 2); ASSERT(subspace_test2.key() == LiteralStringRef("\x01user\x00")); @@ -369,8 +368,7 @@ TEST_CASE("/fdbclient/TaskBucket/Subspace") { print_subspace_key(subspace_test3, 3); ASSERT(subspace_test3.key() == LiteralStringRef("abc\x01user\x00")); - Tuple t1; - t1.append(1); + Tuple t1 = Tuple::makeTuple(1); Subspace subspace_test4(t1); print_subspace_key(subspace_test4, 4); ASSERT(subspace_test4.key() == LiteralStringRef("\x15\x01")); @@ -400,8 +398,7 @@ TEST_CASE("/fdbclient/TaskBucket/Subspace") { ASSERT(subspace_test8.key() == LiteralStringRef("\x01subitem\x00")); // pack - Tuple t3; - t3.append(StringRef()); + Tuple t3 = Tuple::makeTuple(""_sr); printf("%d==========%s===%d\n", 10, printable(subspace_test5.pack(t3)).c_str(), subspace_test5.pack(t3).size()); ASSERT(subspace_test5.pack(t3) == subspace_test5.pack(StringRef())); ASSERT(subspace_test5.pack(t3) == LiteralStringRef("abc\x01user\x00\x15\x7b\x01\x00")); From 37b76662627c98ffad9480abdfa9b9c7f95dd931 Mon Sep 17 00:00:00 2001 From: "A.J. Beamon" Date: Wed, 20 Jul 2022 13:57:55 -0700 Subject: [PATCH 3/4] Add a comment to name the fold expression syntax in makeTuple. This should make it easier to look up for those unfamiliar with the syntax. --- fdbclient/include/fdbclient/Tuple.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/fdbclient/include/fdbclient/Tuple.h b/fdbclient/include/fdbclient/Tuple.h index 6093dc6779..f517f97341 100644 --- a/fdbclient/include/fdbclient/Tuple.h +++ b/fdbclient/include/fdbclient/Tuple.h @@ -90,10 +90,15 @@ struct Tuple { Standalone> getData() { return data; } Standalone getDataAsStandalone() { return Standalone(pack(), data.arena()); } + // Create a tuple from a parameter pack template static Tuple makeTuple(Types&&... args) { Tuple t; + + // Use a fold expression to append each argument using the << operator. + // https://en.cppreference.com/w/cpp/language/fold (t << ... << args); + return t; } From 51204163dfaf7c5e26377d7523599c7de249412c Mon Sep 17 00:00:00 2001 From: "A.J. Beamon" Date: Wed, 20 Jul 2022 15:29:34 -0700 Subject: [PATCH 4/4] Some minor changes from code review --- fdbclient/Tuple.cpp | 3 ++- fdbclient/include/fdbclient/Tuple.h | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/fdbclient/Tuple.cpp b/fdbclient/Tuple.cpp index 8b8a0aebd0..d3c3416b88 100644 --- a/fdbclient/Tuple.cpp +++ b/fdbclient/Tuple.cpp @@ -462,6 +462,7 @@ TEST_CASE("fdbclient/Tuple/makeTuple") { ASSERT(t1.getType(5) == Tuple::UTF8); ASSERT(t1.getType(6) == Tuple::NULL_TYPE); ASSERT(t1.getType(7) == Tuple::VERSIONSTAMP); + ASSERT(t1.size() == 8); return Void(); -} \ No newline at end of file +} diff --git a/fdbclient/include/fdbclient/Tuple.h b/fdbclient/include/fdbclient/Tuple.h index f517f97341..4d933172af 100644 --- a/fdbclient/include/fdbclient/Tuple.h +++ b/fdbclient/include/fdbclient/Tuple.h @@ -30,7 +30,7 @@ struct Tuple { struct UnicodeStr { StringRef str; - UnicodeStr(StringRef str) : str(str) {} + explicit UnicodeStr(StringRef str) : str(str) {} }; Tuple() {} @@ -97,7 +97,7 @@ struct Tuple { // Use a fold expression to append each argument using the << operator. // https://en.cppreference.com/w/cpp/language/fold - (t << ... << args); + (t << ... << std::forward(args)); return t; }