Use versionstamped keys instead of atomic add in test

This makes it easier to debug if something goes wrong
This commit is contained in:
Andrew Noyes 2022-10-05 14:08:41 -07:00
parent 045452aec8
commit 43a72ad406
1 changed files with 29 additions and 18 deletions

View File

@ -24,13 +24,17 @@
#include "fdbserver/workloads/workloads.actor.h" #include "fdbserver/workloads/workloads.actor.h"
#include "flow/actorcompiler.h" // This must be the last #include. #include "flow/actorcompiler.h" // This must be the last #include.
// This tests launches a bunch of transactions with idempotency ids (so they should be idempotent automatically). Each
// transaction sets a version stamped key, and then we check that the right number of transactions were committed.
// If a transaction commits multiple times or doesn't commit, that probably indicates a problem with
// `determineCommitStatus` in NativeAPI.
struct AutomaticIdempotencyWorkload : TestWorkload { struct AutomaticIdempotencyWorkload : TestWorkload {
int64_t countTo; int64_t numTransactions;
Key key; Key keyPrefix;
AutomaticIdempotencyWorkload(WorkloadContext const& wcx) : TestWorkload(wcx) { AutomaticIdempotencyWorkload(WorkloadContext const& wcx) : TestWorkload(wcx) {
countTo = getOption(options, "countTo"_sr, 1000); numTransactions = getOption(options, "numTransactions"_sr, 1000);
key = KeyRef(getOption(options, "key"_sr, "automaticIdempotencyKey"_sr)); keyPrefix = KeyRef(getOption(options, "keyPrefix"_sr, "automaticIdempotencyKeyPrefix"_sr));
} }
std::string description() const override { return "AutomaticIdempotency"; } std::string description() const override { return "AutomaticIdempotency"; }
@ -41,14 +45,19 @@ struct AutomaticIdempotencyWorkload : TestWorkload {
ACTOR static Future<Void> _start(AutomaticIdempotencyWorkload* self, Database cx) { ACTOR static Future<Void> _start(AutomaticIdempotencyWorkload* self, Database cx) {
state int i = 0; state int i = 0;
for (; i < self->countTo; ++i) { for (; i < self->numTransactions; ++i) {
wait(runRYWTransaction(cx, [self = self](Reference<ReadYourWritesTransaction> tr) { state Value idempotencyId = BinaryWriter::toValue(deterministicRandom()->randomUniqueID(), Unversioned());
tr->setOption(FDBTransactionOptions::AUTOMATIC_IDEMPOTENCY); TraceEvent("IdempotencyIdWorkloadTransaction").detail("Id", idempotencyId);
uint64_t oneInt = 1; wait(runRYWTransaction(
Value oneVal = StringRef(reinterpret_cast<const uint8_t*>(&oneInt), sizeof(oneInt)); cx, [self = self, idempotencyId = idempotencyId](Reference<ReadYourWritesTransaction> tr) {
tr->atomicOp(self->key, oneVal, MutationRef::AddValue); tr->setOption(FDBTransactionOptions::IDEMPOTENCY_ID, idempotencyId);
return Future<Void>(Void()); uint32_t index = self->keyPrefix.size();
})); Value suffix = makeString(14);
memset(mutateString(suffix), 0, 10);
memcpy(mutateString(suffix) + 10, &index, 4);
tr->atomicOp(self->keyPrefix.withSuffix(suffix), idempotencyId, MutationRef::SetVersionstampedKey);
return Future<Void>(Void());
}));
} }
return Void(); return Void();
} }
@ -61,12 +70,14 @@ struct AutomaticIdempotencyWorkload : TestWorkload {
} }
ACTOR static Future<bool> _check(AutomaticIdempotencyWorkload* self, Reference<ReadYourWritesTransaction> tr) { ACTOR static Future<bool> _check(AutomaticIdempotencyWorkload* self, Reference<ReadYourWritesTransaction> tr) {
Optional<Value> val = wait(tr->get(self->key)); RangeResult result = wait(tr->getRange(prefixRange(self->keyPrefix), CLIENT_KNOBS->TOO_MANY));
ASSERT(val.present()); ASSERT(!result.more);
uint64_t result; if (result.size() != self->clientCount * self->numTransactions) {
ASSERT(val.get().size() == sizeof(result)); for (const auto& [k, v] : result) {
memcpy(&result, val.get().begin(), val.get().size()); TraceEvent("IdempotencyIdWorkloadTransactionCommitted").detail("Id", v);
ASSERT_EQ(result, self->clientCount * self->countTo); }
}
ASSERT_EQ(result.size(), self->clientCount * self->numTransactions);
return true; return true;
} }