mirror of
https://github.com/apple/foundationdb.git
synced 2025-05-14 01:42:37 +08:00
Merge pull request #7620 from sfc-gh-ajbeamon/make-tuple
Add a Tuple::makeTuple function to easily construct a tuple
This commit is contained in:
commit
410f27412b
@ -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).appendVersionstamp(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(
|
||||
|
@ -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::makeTuple((double)1.5);
|
||||
|
||||
FDBTransaction* tr = ...;
|
||||
tr->setOption(FDBTransactionOptions::SPECIAL_KEY_SPACE_ENABLE_WRITES);
|
||||
|
@ -97,8 +97,8 @@ ACTOR Future<bool> profileCommandActor(Database db,
|
||||
}
|
||||
}
|
||||
|
||||
Tuple rate = Tuple().appendDouble(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());
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -200,13 +200,7 @@ public:
|
||||
Version endVersion{ ::invalidVersion }; // not meaningful for range files
|
||||
|
||||
Tuple pack() const {
|
||||
return Tuple()
|
||||
.append(version)
|
||||
.append(StringRef(fileName))
|
||||
.append(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;
|
||||
|
@ -183,13 +183,13 @@ ACTOR Future<Void> GlobalConfig::migrate(GlobalConfig* self) {
|
||||
if (sampleRate.present()) {
|
||||
const double sampleRateDbl =
|
||||
BinaryReader::fromStringRef<double>(sampleRate.get().contents(), Unversioned());
|
||||
Tuple rate = Tuple().appendDouble(sampleRateDbl);
|
||||
Tuple rate = Tuple::makeTuple(sampleRateDbl);
|
||||
tr->set(GlobalConfig::prefixedKey(fdbClientInfoTxnSampleRate), rate.pack());
|
||||
}
|
||||
if (sizeLimit.present()) {
|
||||
const int64_t sizeLimitInt =
|
||||
BinaryReader::fromStringRef<int64_t>(sizeLimit.get().contents(), Unversioned());
|
||||
Tuple size = Tuple().append(sizeLimitInt);
|
||||
Tuple size = Tuple::makeTuple(sizeLimitInt);
|
||||
tr->set(GlobalConfig::prefixedKey(fdbClientInfoTxnSizeLimit), size.pack());
|
||||
}
|
||||
|
||||
|
@ -1132,10 +1132,9 @@ ACTOR static Future<Void> handleTssMismatches(DatabaseContext* cx) {
|
||||
|
||||
for (const DetailedTSSMismatch& d : data.second) {
|
||||
// <tssid, time, mismatchid> -> 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());
|
||||
|
@ -2005,7 +2005,7 @@ Future<Optional<std::string>> ClientProfilingImpl::commit(ReadYourWritesTransact
|
||||
} else {
|
||||
try {
|
||||
double sampleRate = boost::lexical_cast<double>(sampleRateStr);
|
||||
Tuple rate = Tuple().appendDouble(sampleRate);
|
||||
Tuple rate = Tuple::makeTuple(sampleRate);
|
||||
insertions.push_back_deep(insertions.arena(), KeyValueRef(fdbClientInfoTxnSampleRate, rate.pack()));
|
||||
} catch (boost::bad_lexical_cast& e) {
|
||||
return Optional<std::string>(ManagementAPIError::toJsonString(
|
||||
@ -2024,7 +2024,7 @@ Future<Optional<std::string>> ClientProfilingImpl::commit(ReadYourWritesTransact
|
||||
} else {
|
||||
try {
|
||||
int64_t sizeLimit = boost::lexical_cast<int64_t>(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<std::string>(ManagementAPIError::toJsonString(
|
||||
|
@ -141,12 +141,7 @@ bool ThrottleApi::TagQuotaValue::isValid() const {
|
||||
}
|
||||
|
||||
Value ThrottleApi::TagQuotaValue::toValue() const {
|
||||
Tuple tuple;
|
||||
tuple.appendDouble(reservedReadQuota);
|
||||
tuple.appendDouble(totalReadQuota);
|
||||
tuple.appendDouble(reservedWriteQuota);
|
||||
tuple.appendDouble(totalWriteQuota);
|
||||
return tuple.pack();
|
||||
return Tuple::makeTuple(reservedReadQuota, totalReadQuota, reservedWriteQuota, totalWriteQuota).pack();
|
||||
}
|
||||
|
||||
ThrottleApi::TagQuotaValue ThrottleApi::TagQuotaValue::fromValue(ValueRef value) {
|
||||
|
@ -651,10 +651,7 @@ public:
|
||||
Reference<Task> 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<bool> TaskBucket::isEmpty(Reference<ReadYourWritesTransaction> tr) {
|
||||
Future<Void> TaskBucket::finish(Reference<ReadYourWritesTransaction> tr, Reference<Task> 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"),
|
||||
|
@ -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,30 @@ 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);
|
||||
ASSERT(t1.size() == 8);
|
||||
|
||||
return Void();
|
||||
}
|
||||
|
@ -361,7 +361,7 @@ public:
|
||||
template <>
|
||||
inline Standalone<StringRef> TupleCodec<FileBackupAgent::ERestoreState>::pack(
|
||||
FileBackupAgent::ERestoreState const& val) {
|
||||
return Tuple().append(val).pack();
|
||||
return Tuple::makeTuple(static_cast<int>(val)).pack();
|
||||
}
|
||||
template <>
|
||||
inline FileBackupAgent::ERestoreState TupleCodec<FileBackupAgent::ERestoreState>::unpack(
|
||||
@ -578,7 +578,7 @@ ACTOR Future<Void> cleanupBackup(Database cx, DeleteData deleteData);
|
||||
using EBackupState = BackupAgentBase::EnumState;
|
||||
template <>
|
||||
inline Standalone<StringRef> TupleCodec<EBackupState>::pack(EBackupState const& val) {
|
||||
return Tuple().append(static_cast<int>(val)).pack();
|
||||
return Tuple::makeTuple(static_cast<int>(val)).pack();
|
||||
}
|
||||
template <>
|
||||
inline EBackupState TupleCodec<EBackupState>::unpack(Standalone<StringRef> const& val) {
|
||||
@ -727,8 +727,7 @@ protected:
|
||||
|
||||
template <>
|
||||
inline Standalone<StringRef> TupleCodec<Reference<IBackupContainer>>::pack(Reference<IBackupContainer> 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;
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ inline Tuple TupleCodec<Tuple>::unpack(Standalone<StringRef> const& val) {
|
||||
|
||||
template <>
|
||||
inline Standalone<StringRef> TupleCodec<int64_t>::pack(int64_t const& val) {
|
||||
return Tuple().append(val).pack();
|
||||
return Tuple::makeTuple(val).pack();
|
||||
}
|
||||
template <>
|
||||
inline int64_t TupleCodec<int64_t>::unpack(Standalone<StringRef> const& val) {
|
||||
@ -68,7 +68,7 @@ inline int64_t TupleCodec<int64_t>::unpack(Standalone<StringRef> const& val) {
|
||||
|
||||
template <>
|
||||
inline Standalone<StringRef> TupleCodec<bool>::pack(bool const& val) {
|
||||
return Tuple().append(val ? 1 : 0).pack();
|
||||
return Tuple::makeTuple(val ? 1 : 0).pack();
|
||||
}
|
||||
template <>
|
||||
inline bool TupleCodec<bool>::unpack(Standalone<StringRef> const& val) {
|
||||
@ -77,7 +77,7 @@ inline bool TupleCodec<bool>::unpack(Standalone<StringRef> const& val) {
|
||||
|
||||
template <>
|
||||
inline Standalone<StringRef> TupleCodec<Standalone<StringRef>>::pack(Standalone<StringRef> const& val) {
|
||||
return Tuple().append(val).pack();
|
||||
return Tuple::makeTuple(val).pack();
|
||||
}
|
||||
template <>
|
||||
inline Standalone<StringRef> TupleCodec<Standalone<StringRef>>::unpack(Standalone<StringRef> const& val) {
|
||||
@ -96,7 +96,7 @@ inline UID TupleCodec<UID>::unpack(Standalone<StringRef> const& val) {
|
||||
// This is backward compatible with TupleCodec<Standalone<StringRef>>
|
||||
template <>
|
||||
inline Standalone<StringRef> TupleCodec<std::string>::pack(std::string const& val) {
|
||||
return Tuple().append(StringRef(val)).pack();
|
||||
return Tuple::makeTuple(val).pack();
|
||||
}
|
||||
template <>
|
||||
inline std::string TupleCodec<std::string>::unpack(Standalone<StringRef> const& val) {
|
||||
@ -143,7 +143,7 @@ struct TupleCodec<std::vector<T>> {
|
||||
|
||||
template <>
|
||||
inline Standalone<StringRef> TupleCodec<KeyRange>::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<KeyRange>::unpack(Standalone<StringRef> const& val) {
|
||||
|
@ -42,9 +42,7 @@ public:
|
||||
|
||||
template <class T>
|
||||
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 <class T>
|
||||
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 {
|
||||
|
@ -28,6 +28,11 @@
|
||||
#include "fdbclient/Versionstamp.h"
|
||||
|
||||
struct Tuple {
|
||||
struct UnicodeStr {
|
||||
StringRef str;
|
||||
explicit 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,18 @@ struct Tuple {
|
||||
Standalone<VectorRef<uint8_t>> getData() { return data; }
|
||||
Standalone<StringRef> getDataAsStandalone() { return Standalone<StringRef>(pack(), data.arena()); }
|
||||
|
||||
// Create a tuple from a parameter pack
|
||||
template <class... Types>
|
||||
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 << ... << std::forward<Types>(args));
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
private:
|
||||
Tuple(const StringRef& data, bool exclude_incomplete = false);
|
||||
Standalone<VectorRef<uint8_t>> data;
|
||||
|
@ -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) {
|
||||
|
@ -112,13 +112,7 @@ public:
|
||||
|
||||
Tuple pack() const {
|
||||
// fprintf(stderr, "Filename:%s\n", fileName.c_str());
|
||||
return Tuple()
|
||||
.append(version)
|
||||
.append(StringRef(fileName))
|
||||
.append(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(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;
|
||||
|
@ -3693,9 +3693,7 @@ void preprocessMappedKey(Tuple& mappedKeyFormatTuple, std::vector<Optional<Tuple
|
||||
bool escaped = unescapeLiterals(s, "{{", "{");
|
||||
escaped = unescapeLiterals(s, "}}", "}") || escaped;
|
||||
if (escaped) {
|
||||
Tuple escapedTuple;
|
||||
escapedTuple.append(s);
|
||||
vt.emplace_back(escapedTuple);
|
||||
vt.emplace_back(Tuple::makeTuple(s));
|
||||
} else if (singleKeyOrValue(s, sz)) {
|
||||
// when it is SingleKeyOrValue, insert an empty Tuple to vector as placeholder
|
||||
vt.emplace_back(Tuple());
|
||||
@ -3767,16 +3765,12 @@ Key constructMappedKey(KeyValueRef* keyValue,
|
||||
}
|
||||
|
||||
TEST_CASE("/fdbserver/storageserver/constructMappedKey") {
|
||||
Key key = Tuple().append("key-0"_sr).append("key-1"_sr).append("key-2"_sr).getDataAsStandalone();
|
||||
Value value = Tuple().append("value-0"_sr).append("value-1"_sr).append("value-2"_sr).getDataAsStandalone();
|
||||
Key key = Tuple::makeTuple("key-0"_sr, "key-1"_sr, "key-2"_sr).getDataAsStandalone();
|
||||
Value value = Tuple::makeTuple("value-0"_sr, "value-1"_sr, "value-2"_sr).getDataAsStandalone();
|
||||
state KeyValueRef kvr(key, value);
|
||||
{
|
||||
Tuple mappedKeyFormatTuple = Tuple()
|
||||
.append("normal"_sr)
|
||||
.append("{{escaped}}"_sr)
|
||||
.append("{K[2]}"_sr)
|
||||
.append("{V[0]}"_sr)
|
||||
.append("{...}"_sr);
|
||||
Tuple mappedKeyFormatTuple =
|
||||
Tuple::makeTuple("normal"_sr, "{{escaped}}"_sr, "{K[2]}"_sr, "{V[0]}"_sr, "{...}"_sr);
|
||||
|
||||
Tuple mappedKeyTuple;
|
||||
std::vector<Optional<Tuple>> vt;
|
||||
@ -3785,19 +3779,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<Optional<Tuple>> vt;
|
||||
@ -3805,13 +3795,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<Optional<Tuple>> vt;
|
||||
@ -3819,13 +3809,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;
|
||||
@ -3841,7 +3831,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;
|
||||
@ -3857,7 +3847,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;
|
||||
|
@ -294,8 +294,8 @@ struct ClientTransactionProfileCorrectnessWorkload : TestWorkload {
|
||||
wait(runRYWTransaction(cx, [=](Reference<ReadYourWritesTransaction> tr) -> Future<Void> {
|
||||
tr->setOption(FDBTransactionOptions::SPECIAL_KEY_SPACE_ENABLE_WRITES);
|
||||
tr->setOption(FDBTransactionOptions::LOCK_AWARE);
|
||||
Tuple rate = Tuple().appendDouble(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();
|
||||
|
@ -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<int> get(Reference<ISingleThreadTransaction> tr) {
|
||||
TraceEvent(SevDebug, "ConfigIncrementGet");
|
||||
|
@ -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<Void> 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<TransactionWrapper>& 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,
|
||||
|
@ -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"));
|
||||
|
Loading…
x
Reference in New Issue
Block a user