Merge pull request #3562 from sfc-gh-anoyes/anoyes/memory-error
Fix memory error in report conflicting keys special keys
This commit is contained in:
commit
9d3b1cc4e4
|
@ -338,13 +338,10 @@ Future<Standalone<RangeResultRef>> ConflictingKeysImpl::getRange(ReadYourWritesT
|
|||
if (beginIter->begin() != kr.begin) ++beginIter;
|
||||
auto endIter = krMapPtr->rangeContaining(kr.end);
|
||||
for (auto it = beginIter; it != endIter; ++it) {
|
||||
// it->begin() is stored in the CoalescedKeyRangeMap in TransactionInfo
|
||||
// it->value() is always constants in SystemData.cpp
|
||||
// Thus, push_back() can be used
|
||||
result.push_back(result.arena(), KeyValueRef(it->begin(), it->value()));
|
||||
result.push_back_deep(result.arena(), KeyValueRef(it->begin(), it->value()));
|
||||
}
|
||||
if (endIter->begin() != kr.end)
|
||||
result.push_back(result.arena(), KeyValueRef(endIter->begin(), endIter->value()));
|
||||
result.push_back_deep(result.arena(), KeyValueRef(endIter->begin(), endIter->value()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -123,7 +123,7 @@ struct ReportConflictingKeysWorkload : TestWorkload {
|
|||
} while (deterministicRandom()->random01() < addWriteConflictRangeProb);
|
||||
}
|
||||
|
||||
void emptyConflictingKeysTest(Reference<ReadYourWritesTransaction> ryw) {
|
||||
void emptyConflictingKeysTest(const Reference<ReadYourWritesTransaction>& ryw) {
|
||||
// This test is called when you want to make sure there is no conflictingKeys,
|
||||
// which means you will get an empty result form getRange(\xff\xff/transaction/conflicting_keys/,
|
||||
// \xff\xff/transaction/conflicting_keys0)
|
||||
|
@ -134,42 +134,42 @@ struct ReportConflictingKeysWorkload : TestWorkload {
|
|||
|
||||
ACTOR Future<Void> conflictingClient(Database cx, ReportConflictingKeysWorkload* self) {
|
||||
|
||||
state ReadYourWritesTransaction tr1(cx);
|
||||
state ReadYourWritesTransaction tr2(cx);
|
||||
state Reference<ReadYourWritesTransaction> tr1(new ReadYourWritesTransaction(cx));
|
||||
state Reference<ReadYourWritesTransaction> tr2(new ReadYourWritesTransaction(cx));
|
||||
state std::vector<KeyRange> readConflictRanges;
|
||||
state std::vector<KeyRange> writeConflictRanges;
|
||||
|
||||
loop {
|
||||
try {
|
||||
// set the flag for empty key range testing
|
||||
tr1.setOption(FDBTransactionOptions::REPORT_CONFLICTING_KEYS);
|
||||
tr1->setOption(FDBTransactionOptions::REPORT_CONFLICTING_KEYS);
|
||||
// tr1 should never have conflicting keys, the result should always be empty
|
||||
self->emptyConflictingKeysTest(Reference<ReadYourWritesTransaction>::addRef(&tr1));
|
||||
self->emptyConflictingKeysTest(tr1);
|
||||
|
||||
tr2.setOption(FDBTransactionOptions::REPORT_CONFLICTING_KEYS);
|
||||
tr2->setOption(FDBTransactionOptions::REPORT_CONFLICTING_KEYS);
|
||||
// If READ_YOUR_WRITES_DISABLE set, it behaves like native transaction object
|
||||
// where overlapped conflict ranges are not merged.
|
||||
if (deterministicRandom()->coinflip()) tr1.setOption(FDBTransactionOptions::READ_YOUR_WRITES_DISABLE);
|
||||
if (deterministicRandom()->coinflip()) tr2.setOption(FDBTransactionOptions::READ_YOUR_WRITES_DISABLE);
|
||||
if (deterministicRandom()->coinflip()) tr1->setOption(FDBTransactionOptions::READ_YOUR_WRITES_DISABLE);
|
||||
if (deterministicRandom()->coinflip()) tr2->setOption(FDBTransactionOptions::READ_YOUR_WRITES_DISABLE);
|
||||
// We have the two tx with same grv, then commit the first
|
||||
// If the second one is not able to commit due to conflicts, verify the returned conflicting keys
|
||||
// Otherwise, there is no conflicts between tr1's writeConflictRange and tr2's readConflictRange
|
||||
Version readVersion = wait(tr1.getReadVersion());
|
||||
tr2.setVersion(readVersion);
|
||||
self->addRandomReadConflictRange(&tr1, nullptr);
|
||||
self->addRandomWriteConflictRange(&tr1, &writeConflictRanges);
|
||||
Version readVersion = wait(tr1->getReadVersion());
|
||||
tr2->setVersion(readVersion);
|
||||
self->addRandomReadConflictRange(tr1.getPtr(), nullptr);
|
||||
self->addRandomWriteConflictRange(tr1.getPtr(), &writeConflictRanges);
|
||||
++self->commits;
|
||||
wait(tr1.commit());
|
||||
wait(tr1->commit());
|
||||
++self->xacts;
|
||||
// tr1 should never have conflicting keys, test again after the commit
|
||||
self->emptyConflictingKeysTest(Reference<ReadYourWritesTransaction>::addRef(&tr1));
|
||||
self->emptyConflictingKeysTest(tr1);
|
||||
|
||||
state bool foundConflict = false;
|
||||
try {
|
||||
self->addRandomReadConflictRange(&tr2, &readConflictRanges);
|
||||
self->addRandomWriteConflictRange(&tr2, nullptr);
|
||||
self->addRandomReadConflictRange(tr2.getPtr(), &readConflictRanges);
|
||||
self->addRandomWriteConflictRange(tr2.getPtr(), nullptr);
|
||||
++self->commits;
|
||||
wait(tr2.commit());
|
||||
wait(tr2->commit());
|
||||
++self->xacts;
|
||||
} catch (Error& e) {
|
||||
if (e.code() != error_code_not_committed) throw e;
|
||||
|
@ -188,8 +188,11 @@ struct ReportConflictingKeysWorkload : TestWorkload {
|
|||
// The getRange here using the special key prefix "\xff\xff/transaction/conflicting_keys/" happens
|
||||
// locally Thus, the error handling is not needed here
|
||||
Future<Standalone<RangeResultRef>> conflictingKeyRangesFuture =
|
||||
tr2.getRange(ckr, CLIENT_KNOBS->TOO_MANY);
|
||||
tr2->getRange(ckr, CLIENT_KNOBS->TOO_MANY);
|
||||
ASSERT(conflictingKeyRangesFuture.isReady());
|
||||
|
||||
tr2 = Reference<ReadYourWritesTransaction>(new ReadYourWritesTransaction(cx));
|
||||
|
||||
const Standalone<RangeResultRef> conflictingKeyRanges = conflictingKeyRangesFuture.get();
|
||||
ASSERT(conflictingKeyRanges.size() &&
|
||||
(conflictingKeyRanges.size() <= readConflictRanges.size() * 2));
|
||||
|
@ -275,13 +278,13 @@ struct ReportConflictingKeysWorkload : TestWorkload {
|
|||
}
|
||||
} catch (Error& e) {
|
||||
state Error e2 = e;
|
||||
wait(tr1.onError(e2));
|
||||
wait(tr2.onError(e2));
|
||||
wait(tr1->onError(e2));
|
||||
wait(tr2->onError(e2));
|
||||
}
|
||||
readConflictRanges.clear();
|
||||
writeConflictRanges.clear();
|
||||
tr1.reset();
|
||||
tr2.reset();
|
||||
tr1->reset();
|
||||
tr2->reset();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue