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:
Meng Xu 2020-07-24 21:11:42 -07:00 committed by GitHub
commit 9d3b1cc4e4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 27 additions and 27 deletions

View File

@ -338,13 +338,10 @@ Future<Standalone<RangeResultRef>> ConflictingKeysImpl::getRange(ReadYourWritesT
if (beginIter->begin() != kr.begin) ++beginIter; if (beginIter->begin() != kr.begin) ++beginIter;
auto endIter = krMapPtr->rangeContaining(kr.end); auto endIter = krMapPtr->rangeContaining(kr.end);
for (auto it = beginIter; it != endIter; ++it) { for (auto it = beginIter; it != endIter; ++it) {
// it->begin() is stored in the CoalescedKeyRangeMap in TransactionInfo result.push_back_deep(result.arena(), KeyValueRef(it->begin(), it->value()));
// it->value() is always constants in SystemData.cpp
// Thus, push_back() can be used
result.push_back(result.arena(), KeyValueRef(it->begin(), it->value()));
} }
if (endIter->begin() != kr.end) 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; return result;
} }

View File

@ -123,7 +123,7 @@ struct ReportConflictingKeysWorkload : TestWorkload {
} while (deterministicRandom()->random01() < addWriteConflictRangeProb); } 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, // 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/, // which means you will get an empty result form getRange(\xff\xff/transaction/conflicting_keys/,
// \xff\xff/transaction/conflicting_keys0) // \xff\xff/transaction/conflicting_keys0)
@ -134,42 +134,42 @@ struct ReportConflictingKeysWorkload : TestWorkload {
ACTOR Future<Void> conflictingClient(Database cx, ReportConflictingKeysWorkload* self) { ACTOR Future<Void> conflictingClient(Database cx, ReportConflictingKeysWorkload* self) {
state ReadYourWritesTransaction tr1(cx); state Reference<ReadYourWritesTransaction> tr1(new ReadYourWritesTransaction(cx));
state ReadYourWritesTransaction tr2(cx); state Reference<ReadYourWritesTransaction> tr2(new ReadYourWritesTransaction(cx));
state std::vector<KeyRange> readConflictRanges; state std::vector<KeyRange> readConflictRanges;
state std::vector<KeyRange> writeConflictRanges; state std::vector<KeyRange> writeConflictRanges;
loop { loop {
try { try {
// set the flag for empty key range testing // 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 // 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 // If READ_YOUR_WRITES_DISABLE set, it behaves like native transaction object
// where overlapped conflict ranges are not merged. // where overlapped conflict ranges are not merged.
if (deterministicRandom()->coinflip()) tr1.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); if (deterministicRandom()->coinflip()) tr2->setOption(FDBTransactionOptions::READ_YOUR_WRITES_DISABLE);
// We have the two tx with same grv, then commit the first // 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 // 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 // Otherwise, there is no conflicts between tr1's writeConflictRange and tr2's readConflictRange
Version readVersion = wait(tr1.getReadVersion()); Version readVersion = wait(tr1->getReadVersion());
tr2.setVersion(readVersion); tr2->setVersion(readVersion);
self->addRandomReadConflictRange(&tr1, nullptr); self->addRandomReadConflictRange(tr1.getPtr(), nullptr);
self->addRandomWriteConflictRange(&tr1, &writeConflictRanges); self->addRandomWriteConflictRange(tr1.getPtr(), &writeConflictRanges);
++self->commits; ++self->commits;
wait(tr1.commit()); wait(tr1->commit());
++self->xacts; ++self->xacts;
// tr1 should never have conflicting keys, test again after the commit // tr1 should never have conflicting keys, test again after the commit
self->emptyConflictingKeysTest(Reference<ReadYourWritesTransaction>::addRef(&tr1)); self->emptyConflictingKeysTest(tr1);
state bool foundConflict = false; state bool foundConflict = false;
try { try {
self->addRandomReadConflictRange(&tr2, &readConflictRanges); self->addRandomReadConflictRange(tr2.getPtr(), &readConflictRanges);
self->addRandomWriteConflictRange(&tr2, nullptr); self->addRandomWriteConflictRange(tr2.getPtr(), nullptr);
++self->commits; ++self->commits;
wait(tr2.commit()); wait(tr2->commit());
++self->xacts; ++self->xacts;
} catch (Error& e) { } catch (Error& e) {
if (e.code() != error_code_not_committed) throw 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 // The getRange here using the special key prefix "\xff\xff/transaction/conflicting_keys/" happens
// locally Thus, the error handling is not needed here // locally Thus, the error handling is not needed here
Future<Standalone<RangeResultRef>> conflictingKeyRangesFuture = Future<Standalone<RangeResultRef>> conflictingKeyRangesFuture =
tr2.getRange(ckr, CLIENT_KNOBS->TOO_MANY); tr2->getRange(ckr, CLIENT_KNOBS->TOO_MANY);
ASSERT(conflictingKeyRangesFuture.isReady()); ASSERT(conflictingKeyRangesFuture.isReady());
tr2 = Reference<ReadYourWritesTransaction>(new ReadYourWritesTransaction(cx));
const Standalone<RangeResultRef> conflictingKeyRanges = conflictingKeyRangesFuture.get(); const Standalone<RangeResultRef> conflictingKeyRanges = conflictingKeyRangesFuture.get();
ASSERT(conflictingKeyRanges.size() && ASSERT(conflictingKeyRanges.size() &&
(conflictingKeyRanges.size() <= readConflictRanges.size() * 2)); (conflictingKeyRanges.size() <= readConflictRanges.size() * 2));
@ -275,13 +278,13 @@ struct ReportConflictingKeysWorkload : TestWorkload {
} }
} catch (Error& e) { } catch (Error& e) {
state Error e2 = e; state Error e2 = e;
wait(tr1.onError(e2)); wait(tr1->onError(e2));
wait(tr2.onError(e2)); wait(tr2->onError(e2));
} }
readConflictRanges.clear(); readConflictRanges.clear();
writeConflictRanges.clear(); writeConflictRanges.clear();
tr1.reset(); tr1->reset();
tr2.reset(); tr2->reset();
} }
} }
}; };