mirror of https://github.com/facebook/rocksdb.git
Save the key before calling PrepareValue() in the stress tests (#13129)
Summary: Pull Request resolved: https://github.com/facebook/rocksdb/pull/13129 The `PrepareValue()` call on an iterator can fail, for example due to our stress tests' read fault injection. Such a failure invalidates the iterator, which makes it illegal to call methods like `key()` on it and leads to assertion violations. The patch fixes this by saving the key before calling `PrepareValue()`, so we can still print it for debugging purposes in case the call fails. Reviewed By: jowlyzhang Differential Revision: D65689225 fbshipit-source-id: c2bf298366def0ba3b3c089ee58e28609ecdfab4
This commit is contained in:
parent
87b4043a67
commit
a6ee297ac9
|
@ -615,10 +615,15 @@ class BatchedOpsStressTest : public StressTest {
|
||||||
iters[i]->key().starts_with(prefix_slices[i]));
|
iters[i]->key().starts_with(prefix_slices[i]));
|
||||||
|
|
||||||
if (ro_copies[i].allow_unprepared_value) {
|
if (ro_copies[i].allow_unprepared_value) {
|
||||||
|
// Save key in case PrepareValue fails and invalidates the iterator
|
||||||
|
const std::string prepare_value_key =
|
||||||
|
iters[i]->key().ToString(/* hex */ true);
|
||||||
|
|
||||||
if (!iters[i]->PrepareValue()) {
|
if (!iters[i]->PrepareValue()) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"prefix scan error: PrepareValue failed for key %s\n",
|
"prefix scan error: PrepareValue failed for key %s\n",
|
||||||
iters[i]->key().ToString(/* hex */ true).c_str());
|
prepare_value_key.c_str());
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2001,13 +2001,17 @@ void StressTest::VerifyIterator(
|
||||||
|
|
||||||
if (!*diverged && iter->Valid()) {
|
if (!*diverged && iter->Valid()) {
|
||||||
if (ro.allow_unprepared_value) {
|
if (ro.allow_unprepared_value) {
|
||||||
|
// Save key in case PrepareValue fails and invalidates the iterator
|
||||||
|
const std::string prepare_value_key =
|
||||||
|
iter->key().ToString(/* hex */ true);
|
||||||
|
|
||||||
if (!iter->PrepareValue()) {
|
if (!iter->PrepareValue()) {
|
||||||
fprintf(
|
fprintf(
|
||||||
stderr,
|
stderr,
|
||||||
"Iterator failed to prepare value for key %s %s under specified "
|
"Iterator failed to prepare value for key %s %s under specified "
|
||||||
"iterator ReadOptions: %s (Empty string or missing field indicates "
|
"iterator ReadOptions: %s (Empty string or missing field indicates "
|
||||||
"default option or value is used)\n",
|
"default option or value is used)\n",
|
||||||
iter->key().ToString(true).c_str(), op_logs.c_str(),
|
prepare_value_key.c_str(), op_logs.c_str(),
|
||||||
read_opt_oss.str().c_str());
|
read_opt_oss.str().c_str());
|
||||||
*diverged = true;
|
*diverged = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2301,12 +2301,16 @@ class NonBatchedOpsStressTest : public StressTest {
|
||||||
assert(iter->Valid());
|
assert(iter->Valid());
|
||||||
|
|
||||||
if (ro.allow_unprepared_value) {
|
if (ro.allow_unprepared_value) {
|
||||||
|
// Save key in case PrepareValue fails and invalidates the iterator
|
||||||
|
const std::string prepare_value_key =
|
||||||
|
iter->key().ToString(/* hex */ true);
|
||||||
|
|
||||||
if (!iter->PrepareValue()) {
|
if (!iter->PrepareValue()) {
|
||||||
shared->SetVerificationFailure();
|
shared->SetVerificationFailure();
|
||||||
|
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Verification failed for key %s: failed to prepare value\n",
|
"Verification failed for key %s: failed to prepare value\n",
|
||||||
Slice(iter->key()).ToString(/* hex */ true).c_str());
|
prepare_value_key.c_str());
|
||||||
fprintf(stderr, "Column family: %s, op_logs: %s\n",
|
fprintf(stderr, "Column family: %s, op_logs: %s\n",
|
||||||
cfh->GetName().c_str(), op_logs.c_str());
|
cfh->GetName().c_str(), op_logs.c_str());
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue