Fix operation_failed thrown incorrectly from transactions (#6993)
* Add a test demonstrating the issue If you write a versionstamped value after a set, then reading throws operation_failed. * Treat SetVersionstampedValue as independent in coalesce and mutate
This commit is contained in:
parent
cf6e39af79
commit
0a4b364379
|
@ -430,6 +430,27 @@ TEST_CASE("/fdbclient/WriteMap/emptiness") {
|
|||
return Void();
|
||||
}
|
||||
|
||||
TEST_CASE("/fdbclient/WriteMap/VersionstampedvalueAfterSet") {
|
||||
Arena arena = Arena();
|
||||
SnapshotCache cache(&arena);
|
||||
WriteMap writes = WriteMap(&arena);
|
||||
|
||||
ASSERT(writes.empty());
|
||||
writes.mutate("apple"_sr, MutationRef::SetValue, "red"_sr, true);
|
||||
writes.mutate("apple"_sr, MutationRef::SetVersionstampedValue, metadataVersionRequiredValue, true);
|
||||
|
||||
RYWIterator it(&cache, &writes);
|
||||
it.bypassUnreadableProtection();
|
||||
it.skip("apple"_sr);
|
||||
ASSERT(it.is_unreadable());
|
||||
ASSERT(it.is_kv());
|
||||
const KeyValueRef* kv = it.kv(arena);
|
||||
ASSERT(kv->key == "apple"_sr);
|
||||
ASSERT(kv->value == metadataVersionRequiredValue);
|
||||
|
||||
return Void();
|
||||
}
|
||||
|
||||
TEST_CASE("/fdbclient/WriteMap/clear") {
|
||||
Arena arena = Arena();
|
||||
WriteMap writes = WriteMap(&arena);
|
||||
|
|
|
@ -231,7 +231,8 @@ public:
|
|||
is_unreadable));
|
||||
}
|
||||
} else {
|
||||
if (!it.is_unreadable() && operation == MutationRef::SetValue) {
|
||||
if (!it.is_unreadable() &&
|
||||
(operation == MutationRef::SetValue || operation == MutationRef::SetVersionstampedValue)) {
|
||||
it.tree.clear();
|
||||
PTreeImpl::remove(writes, ver, key);
|
||||
PTreeImpl::insert(writes,
|
||||
|
@ -523,9 +524,10 @@ public:
|
|||
static RYWMutation coalesce(RYWMutation existingEntry, RYWMutation newEntry, Arena& arena) {
|
||||
ASSERT(newEntry.value.present());
|
||||
|
||||
if (newEntry.type == MutationRef::SetValue)
|
||||
if (newEntry.type == MutationRef::SetValue || newEntry.type == MutationRef::SetVersionstampedValue) {
|
||||
// independent mutations
|
||||
return newEntry;
|
||||
else if (newEntry.type == MutationRef::AddValue) {
|
||||
} else if (newEntry.type == MutationRef::AddValue) {
|
||||
switch (existingEntry.type) {
|
||||
case MutationRef::SetValue:
|
||||
return RYWMutation(doLittleEndianAdd(existingEntry.value, newEntry.value.get(), arena),
|
||||
|
|
Loading…
Reference in New Issue