Improve db_stress with transactions

Summary:
db_stress was already capable running transactions by setting use_txn. Running it under stress showed a couple of problems fixed in this patch.
- The uncommitted transaction must be either rolled back or commit after recovery.
- Current implementation of WritePrepared transaction cannot handle cf drop before crash. Clarified that in the comments and added safety checks. When running with use_txn, clear_column_family_one_in must be set to 0.
Closes https://github.com/facebook/rocksdb/pull/3733

Differential Revision: D7654419

Pulled By: maysamyabandeh

fbshipit-source-id: a024bad80a9dc99677398c00d29ff17d4436b7f3
This commit is contained in:
Maysam Yabandeh 2018-04-18 16:25:33 -07:00 committed by Facebook Github Bot
parent 2ee1496c43
commit 6d06be22c0
2 changed files with 45 additions and 1 deletions

View File

@ -1930,6 +1930,9 @@ class StressTest {
i == thread->snapshot_queue.front().first) { i == thread->snapshot_queue.front().first) {
auto snap_state = thread->snapshot_queue.front().second; auto snap_state = thread->snapshot_queue.front().second;
assert(snap_state.snapshot); assert(snap_state.snapshot);
// Note: this is unsafe as the cf might be dropped concurrently. But it
// is ok since unclean cf drop is cunnrently not supported by write
// prepared transactions.
Status s = Status s =
AssertSame(db_, column_families_[snap_state.cf_at], snap_state); AssertSame(db_, column_families_[snap_state.cf_at], snap_state);
if (!s.ok()) { if (!s.ok()) {
@ -2589,6 +2592,23 @@ class StressTest {
s = TransactionDB::Open(options_, txn_db_options, FLAGS_db, s = TransactionDB::Open(options_, txn_db_options, FLAGS_db,
cf_descriptors, &column_families_, &txn_db_); cf_descriptors, &column_families_, &txn_db_);
db_ = txn_db_; db_ = txn_db_;
// after a crash, rollback to commit recovered transactions
std::vector<Transaction*> trans;
txn_db_->GetAllPreparedTransactions(&trans);
Random rand(FLAGS_seed);
for (auto txn : trans) {
if (rand.OneIn(2)) {
s = txn->Commit();
assert(s.ok());
} else {
s = txn->Rollback();
assert(s.ok());
}
delete txn;
}
trans.clear();
txn_db_->GetAllPreparedTransactions(&trans);
assert(trans.size() == 0);
#endif #endif
} }
assert(!s.ok() || column_families_.size() == assert(!s.ok() || column_families_.size() ==

View File

@ -5,6 +5,12 @@
#pragma once #pragma once
#ifndef __STDC_FORMAT_MACROS
#define __STDC_FORMAT_MACROS
#endif
#include <inttypes.h>
#include "util/set_comparator.h" #include "util/set_comparator.h"
namespace rocksdb { namespace rocksdb {
@ -41,7 +47,25 @@ class DuplicateDetector {
using CFKeys = std::set<Slice, SetComparator>; using CFKeys = std::set<Slice, SetComparator>;
std::map<uint32_t, CFKeys> keys_; std::map<uint32_t, CFKeys> keys_;
void InitWithComp(const uint32_t cf) { void InitWithComp(const uint32_t cf) {
auto cmp = db_->GetColumnFamilyHandle(cf)->GetComparator(); auto h = db_->GetColumnFamilyHandle(cf);
if (!h) {
// TODO(myabandeh): This is not a concern in MyRocks as drop cf is not
// implemented yet. When it does, we should return proper error instead
// of throwing exception.
ROCKS_LOG_FATAL(
db_->immutable_db_options().info_log,
"Recovering an entry from the dropped column family %" PRIu32
". WAL must must have been emptied before dropping the column "
"family");
#ifndef ROCKSDB_LITE
throw std::runtime_error(
"Recovering an entry from the dropped column family %" PRIu32
". WAL must must have been flushed before dropping the column "
"family");
#endif
return;
}
auto cmp = h->GetComparator();
keys_[cf] = CFKeys(SetComparator(cmp)); keys_[cf] = CFKeys(SetComparator(cmp));
} }
}; };