提交 c3466eab 编写于 作者: A agiardullo

Have Transactions use WriteBatch::RollbackToSavePoint

Summary:
Clean up transactions to use the new RollbackToSavePoint api in WriteBatchWithIndex.

Note, this diff depends on Pessimistic Transactions diff and ManagedSnapshot diff (D40869 and D43293).

Test Plan: unit tests

Reviewers: rven, yhchiang, kradhakrishnan, spetrunia, sdong

Reviewed By: sdong

Subscribers: dhruba, leveldb

Differential Revision: https://reviews.facebook.net/D43371
上级 0db807ec
...@@ -93,12 +93,10 @@ class Transaction { ...@@ -93,12 +93,10 @@ class Transaction {
virtual void SetSavePoint() = 0; virtual void SetSavePoint() = 0;
// Undo all operations in this transaction (Put, Merge, Delete, PutLogData) // Undo all operations in this transaction (Put, Merge, Delete, PutLogData)
// since the // since the most recent call to SetSavePoint() and removes the most recent
// most recent call to SetSavePoint() and removes the most recent
// SetSavePoint(). // SetSavePoint().
// If there is no previous call to SetSavePoint(), behaves the same as // If there is no previous call to SetSavePoint(), returns Status::NotFound()
// Rollback() virtual Status RollbackToSavePoint() = 0;
virtual void RollbackToSavePoint() = 0;
// This function is similar to DB::Get() except it will also read pending // This function is similar to DB::Get() except it will also read pending
// changes in this transaction. // changes in this transaction.
......
...@@ -30,30 +30,24 @@ OptimisticTransactionImpl::OptimisticTransactionImpl( ...@@ -30,30 +30,24 @@ OptimisticTransactionImpl::OptimisticTransactionImpl(
: txn_db_(txn_db), : txn_db_(txn_db),
db_(txn_db->GetBaseDB()), db_(txn_db->GetBaseDB()),
write_options_(write_options), write_options_(write_options),
snapshot_(nullptr),
cmp_(txn_options.cmp), cmp_(txn_options.cmp),
write_batch_(new WriteBatchWithIndex(txn_options.cmp, 0, true)) { write_batch_(new WriteBatchWithIndex(txn_options.cmp, 0, true)) {
if (txn_options.set_snapshot) { if (txn_options.set_snapshot) {
SetSnapshot(); SetSnapshot();
} else {
start_sequence_number_ = db_->GetLatestSequenceNumber();
} }
} }
OptimisticTransactionImpl::~OptimisticTransactionImpl() { OptimisticTransactionImpl::~OptimisticTransactionImpl() {
}
void OptimisticTransactionImpl::Cleanup() {
tracked_keys_.clear(); tracked_keys_.clear();
if (snapshot_ != nullptr) { save_points_.reset(nullptr);
db_->ReleaseSnapshot(snapshot_); write_batch_->Clear();
}
} }
void OptimisticTransactionImpl::SetSnapshot() { void OptimisticTransactionImpl::SetSnapshot() {
if (snapshot_ != nullptr) { snapshot_.reset(new ManagedSnapshot(db_));
db_->ReleaseSnapshot(snapshot_);
}
snapshot_ = db_->GetSnapshot();
start_sequence_number_ = snapshot_->GetSequenceNumber();
} }
Status OptimisticTransactionImpl::Commit() { Status OptimisticTransactionImpl::Commit() {
...@@ -73,66 +67,38 @@ Status OptimisticTransactionImpl::Commit() { ...@@ -73,66 +67,38 @@ Status OptimisticTransactionImpl::Commit() {
write_options_, write_batch_->GetWriteBatch(), &callback); write_options_, write_batch_->GetWriteBatch(), &callback);
if (s.ok()) { if (s.ok()) {
tracked_keys_.clear(); Cleanup();
write_batch_->Clear();
num_entries_ = 0;
} }
return s; return s;
} }
void OptimisticTransactionImpl::Rollback() { void OptimisticTransactionImpl::Rollback() {
tracked_keys_.clear(); Cleanup();
write_batch_->Clear();
num_entries_ = 0;
} }
void OptimisticTransactionImpl::SetSavePoint() { void OptimisticTransactionImpl::SetSavePoint() {
if (num_entries_ > 0) { if (save_points_ == nullptr) {
// If transaction is empty, no need to record anything. save_points_.reset(new std::stack<std::shared_ptr<ManagedSnapshot>>());
if (save_points_ == nullptr) {
save_points_.reset(new std::stack<size_t>());
}
save_points_->push(num_entries_);
} }
save_points_->push(snapshot_);
write_batch_->SetSavePoint();
} }
void OptimisticTransactionImpl::RollbackToSavePoint() { Status OptimisticTransactionImpl::RollbackToSavePoint() {
size_t savepoint_entries = 0;
if (save_points_ != nullptr && save_points_->size() > 0) { if (save_points_ != nullptr && save_points_->size() > 0) {
savepoint_entries = save_points_->top(); // Restore saved snapshot
snapshot_ = save_points_->top();
save_points_->pop(); save_points_->pop();
}
assert(savepoint_entries <= num_entries_); // Rollback batch
Status s = write_batch_->RollbackToSavePoint();
assert(s.ok());
if (savepoint_entries == num_entries_) { return s;
// No changes to rollback
} else if (savepoint_entries == 0) {
// Rollback everything
Rollback();
} else { } else {
DBImpl* db_impl = dynamic_cast<DBImpl*>(db_->GetRootDB()); assert(write_batch_->RollbackToSavePoint().IsNotFound());
assert(db_impl); return Status::NotFound();
WriteBatchWithIndex* new_batch = new WriteBatchWithIndex(cmp_, 0, true);
Status s = TransactionUtil::CopyFirstN(
savepoint_entries, write_batch_.get(), new_batch, db_impl);
if (!s.ok()) {
// TODO: Should we change this function to return a Status or should we
// somehow make it
// so RollbackToSavePoint() can never fail??
// Consider moving this functionality into WriteBatchWithIndex
fprintf(stderr, "STATUS: %s \n", s.ToString().c_str());
delete new_batch;
} else {
write_batch_.reset(new_batch);
}
num_entries_ = savepoint_entries;
} }
} }
...@@ -143,7 +109,7 @@ void OptimisticTransactionImpl::RecordOperation( ...@@ -143,7 +109,7 @@ void OptimisticTransactionImpl::RecordOperation(
SequenceNumber seq; SequenceNumber seq;
if (snapshot_) { if (snapshot_) {
seq = start_sequence_number_; seq = snapshot_->snapshot()->GetSequenceNumber();
} else { } else {
seq = db_->GetLatestSequenceNumber(); seq = db_->GetLatestSequenceNumber();
} }
...@@ -261,7 +227,6 @@ Status OptimisticTransactionImpl::Put(ColumnFamilyHandle* column_family, ...@@ -261,7 +227,6 @@ Status OptimisticTransactionImpl::Put(ColumnFamilyHandle* column_family,
RecordOperation(column_family, key); RecordOperation(column_family, key);
write_batch_->Put(column_family, key, value); write_batch_->Put(column_family, key, value);
num_entries_++;
return Status::OK(); return Status::OK();
} }
...@@ -272,7 +237,6 @@ Status OptimisticTransactionImpl::Put(ColumnFamilyHandle* column_family, ...@@ -272,7 +237,6 @@ Status OptimisticTransactionImpl::Put(ColumnFamilyHandle* column_family,
RecordOperation(column_family, key); RecordOperation(column_family, key);
write_batch_->Put(column_family, key, value); write_batch_->Put(column_family, key, value);
num_entries_++;
return Status::OK(); return Status::OK();
} }
...@@ -307,7 +271,6 @@ Status OptimisticTransactionImpl::Delete(ColumnFamilyHandle* column_family, ...@@ -307,7 +271,6 @@ Status OptimisticTransactionImpl::Delete(ColumnFamilyHandle* column_family,
Status OptimisticTransactionImpl::PutUntracked( Status OptimisticTransactionImpl::PutUntracked(
ColumnFamilyHandle* column_family, const Slice& key, const Slice& value) { ColumnFamilyHandle* column_family, const Slice& key, const Slice& value) {
write_batch_->Put(column_family, key, value); write_batch_->Put(column_family, key, value);
num_entries_++;
return Status::OK(); return Status::OK();
} }
...@@ -316,7 +279,6 @@ Status OptimisticTransactionImpl::PutUntracked( ...@@ -316,7 +279,6 @@ Status OptimisticTransactionImpl::PutUntracked(
ColumnFamilyHandle* column_family, const SliceParts& key, ColumnFamilyHandle* column_family, const SliceParts& key,
const SliceParts& value) { const SliceParts& value) {
write_batch_->Put(column_family, key, value); write_batch_->Put(column_family, key, value);
num_entries_++;
return Status::OK(); return Status::OK();
} }
...@@ -324,7 +286,6 @@ Status OptimisticTransactionImpl::PutUntracked( ...@@ -324,7 +286,6 @@ Status OptimisticTransactionImpl::PutUntracked(
Status OptimisticTransactionImpl::MergeUntracked( Status OptimisticTransactionImpl::MergeUntracked(
ColumnFamilyHandle* column_family, const Slice& key, const Slice& value) { ColumnFamilyHandle* column_family, const Slice& key, const Slice& value) {
write_batch_->Merge(column_family, key, value); write_batch_->Merge(column_family, key, value);
num_entries_++;
return Status::OK(); return Status::OK();
} }
...@@ -332,7 +293,6 @@ Status OptimisticTransactionImpl::MergeUntracked( ...@@ -332,7 +293,6 @@ Status OptimisticTransactionImpl::MergeUntracked(
Status OptimisticTransactionImpl::DeleteUntracked( Status OptimisticTransactionImpl::DeleteUntracked(
ColumnFamilyHandle* column_family, const Slice& key) { ColumnFamilyHandle* column_family, const Slice& key) {
write_batch_->Delete(column_family, key); write_batch_->Delete(column_family, key);
num_entries_++;
return Status::OK(); return Status::OK();
} }
...@@ -340,14 +300,12 @@ Status OptimisticTransactionImpl::DeleteUntracked( ...@@ -340,14 +300,12 @@ Status OptimisticTransactionImpl::DeleteUntracked(
Status OptimisticTransactionImpl::DeleteUntracked( Status OptimisticTransactionImpl::DeleteUntracked(
ColumnFamilyHandle* column_family, const SliceParts& key) { ColumnFamilyHandle* column_family, const SliceParts& key) {
write_batch_->Delete(column_family, key); write_batch_->Delete(column_family, key);
num_entries_++;
return Status::OK(); return Status::OK();
} }
void OptimisticTransactionImpl::PutLogData(const Slice& blob) { void OptimisticTransactionImpl::PutLogData(const Slice& blob) {
write_batch_->PutLogData(blob); write_batch_->PutLogData(blob);
num_entries_++;
} }
WriteBatchWithIndex* OptimisticTransactionImpl::GetWriteBatch() { WriteBatchWithIndex* OptimisticTransactionImpl::GetWriteBatch() {
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "db/write_callback.h" #include "db/write_callback.h"
#include "rocksdb/db.h" #include "rocksdb/db.h"
#include "rocksdb/slice.h" #include "rocksdb/slice.h"
#include "rocksdb/snapshot.h"
#include "rocksdb/status.h" #include "rocksdb/status.h"
#include "rocksdb/types.h" #include "rocksdb/types.h"
#include "rocksdb/utilities/transaction.h" #include "rocksdb/utilities/transaction.h"
...@@ -38,7 +39,7 @@ class OptimisticTransactionImpl : public Transaction { ...@@ -38,7 +39,7 @@ class OptimisticTransactionImpl : public Transaction {
void SetSavePoint() override; void SetSavePoint() override;
void RollbackToSavePoint() override; Status RollbackToSavePoint() override;
Status Get(const ReadOptions& options, ColumnFamilyHandle* column_family, Status Get(const ReadOptions& options, ColumnFamilyHandle* column_family,
const Slice& key, std::string* value) override; const Slice& key, std::string* value) override;
...@@ -147,7 +148,9 @@ class OptimisticTransactionImpl : public Transaction { ...@@ -147,7 +148,9 @@ class OptimisticTransactionImpl : public Transaction {
const TransactionKeyMap* GetTrackedKeys() const { return &tracked_keys_; } const TransactionKeyMap* GetTrackedKeys() const { return &tracked_keys_; }
const Snapshot* GetSnapshot() const override { return snapshot_; } const Snapshot* GetSnapshot() const override {
return snapshot_ ? snapshot_->snapshot() : nullptr;
}
void SetSnapshot() override; void SetSnapshot() override;
...@@ -157,8 +160,7 @@ class OptimisticTransactionImpl : public Transaction { ...@@ -157,8 +160,7 @@ class OptimisticTransactionImpl : public Transaction {
OptimisticTransactionDB* const txn_db_; OptimisticTransactionDB* const txn_db_;
DB* db_; DB* db_;
const WriteOptions write_options_; const WriteOptions write_options_;
const Snapshot* snapshot_; std::shared_ptr<ManagedSnapshot> snapshot_;
SequenceNumber start_sequence_number_;
const Comparator* cmp_; const Comparator* cmp_;
std::unique_ptr<WriteBatchWithIndex> write_batch_; std::unique_ptr<WriteBatchWithIndex> write_batch_;
...@@ -169,13 +171,9 @@ class OptimisticTransactionImpl : public Transaction { ...@@ -169,13 +171,9 @@ class OptimisticTransactionImpl : public Transaction {
// not changed since this sequence number. // not changed since this sequence number.
TransactionKeyMap tracked_keys_; TransactionKeyMap tracked_keys_;
// Records the number of entries currently in the WriteBatch including calls // Stack of the Snapshot saved at each save point. Saved snapshots may be
// to // nullptr if there was no snapshot at the time SetSavePoint() was called.
// Put, Merge, Delete, and PutLogData() std::unique_ptr<std::stack<std::shared_ptr<ManagedSnapshot>>> save_points_;
size_t num_entries_ = 0;
// Stack of number of entries in write_batch at each save point
std::unique_ptr<std::stack<size_t>> save_points_;
friend class OptimisticTransactionCallback; friend class OptimisticTransactionCallback;
...@@ -190,6 +188,8 @@ class OptimisticTransactionImpl : public Transaction { ...@@ -190,6 +188,8 @@ class OptimisticTransactionImpl : public Transaction {
void RecordOperation(ColumnFamilyHandle* column_family, void RecordOperation(ColumnFamilyHandle* column_family,
const SliceParts& key); const SliceParts& key);
void Cleanup();
// No copying allowed // No copying allowed
OptimisticTransactionImpl(const OptimisticTransactionImpl&); OptimisticTransactionImpl(const OptimisticTransactionImpl&);
void operator=(const OptimisticTransactionImpl&); void operator=(const OptimisticTransactionImpl&);
......
...@@ -955,12 +955,14 @@ TEST_F(OptimisticTransactionTest, SavepointTest) { ...@@ -955,12 +955,14 @@ TEST_F(OptimisticTransactionTest, SavepointTest) {
Transaction* txn = txn_db->BeginTransaction(write_options); Transaction* txn = txn_db->BeginTransaction(write_options);
ASSERT_TRUE(txn); ASSERT_TRUE(txn);
txn->RollbackToSavePoint(); s = txn->RollbackToSavePoint();
ASSERT_TRUE(s.IsNotFound());
txn->SetSavePoint(); // 1 txn->SetSavePoint(); // 1
txn->RollbackToSavePoint(); // Rollback to beginning of txn ASSERT_OK(txn->RollbackToSavePoint()); // Rollback to beginning of txn
txn->RollbackToSavePoint(); s = txn->RollbackToSavePoint();
ASSERT_TRUE(s.IsNotFound());
s = txn->Put("B", "b"); s = txn->Put("B", "b");
ASSERT_OK(s); ASSERT_OK(s);
...@@ -996,7 +998,7 @@ TEST_F(OptimisticTransactionTest, SavepointTest) { ...@@ -996,7 +998,7 @@ TEST_F(OptimisticTransactionTest, SavepointTest) {
s = txn->Put("D", "d"); s = txn->Put("D", "d");
ASSERT_OK(s); ASSERT_OK(s);
txn->RollbackToSavePoint(); // Rollback to 2 ASSERT_OK(txn->RollbackToSavePoint()); // Rollback to 2
s = txn->Get(read_options, "A", &value); s = txn->Get(read_options, "A", &value);
ASSERT_OK(s); ASSERT_OK(s);
...@@ -1019,7 +1021,10 @@ TEST_F(OptimisticTransactionTest, SavepointTest) { ...@@ -1019,7 +1021,10 @@ TEST_F(OptimisticTransactionTest, SavepointTest) {
s = txn->Put("E", "e"); s = txn->Put("E", "e");
ASSERT_OK(s); ASSERT_OK(s);
txn->RollbackToSavePoint(); // Rollback to beginning of txn // Rollback to beginning of txn
s = txn->RollbackToSavePoint();
ASSERT_TRUE(s.IsNotFound());
txn->Rollback();
s = txn->Get(read_options, "A", &value); s = txn->Get(read_options, "A", &value);
ASSERT_TRUE(s.IsNotFound()); ASSERT_TRUE(s.IsNotFound());
...@@ -1065,7 +1070,7 @@ TEST_F(OptimisticTransactionTest, SavepointTest) { ...@@ -1065,7 +1070,7 @@ TEST_F(OptimisticTransactionTest, SavepointTest) {
s = txn->Get(read_options, "B", &value); s = txn->Get(read_options, "B", &value);
ASSERT_TRUE(s.IsNotFound()); ASSERT_TRUE(s.IsNotFound());
txn->RollbackToSavePoint(); // Rollback to 3 ASSERT_OK(txn->RollbackToSavePoint()); // Rollback to 3
s = txn->Get(read_options, "F", &value); s = txn->Get(read_options, "F", &value);
ASSERT_OK(s); ASSERT_OK(s);
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "db/db_impl.h" #include "db/db_impl.h"
#include "rocksdb/comparator.h" #include "rocksdb/comparator.h"
#include "rocksdb/db.h" #include "rocksdb/db.h"
#include "rocksdb/snapshot.h"
#include "rocksdb/status.h" #include "rocksdb/status.h"
#include "rocksdb/utilities/transaction_db.h" #include "rocksdb/utilities/transaction_db.h"
#include "util/string_util.h" #include "util/string_util.h"
...@@ -39,7 +40,6 @@ TransactionImpl::TransactionImpl(TransactionDB* txn_db, ...@@ -39,7 +40,6 @@ TransactionImpl::TransactionImpl(TransactionDB* txn_db,
txn_db_impl_(nullptr), txn_db_impl_(nullptr),
txn_id_(GenTxnID()), txn_id_(GenTxnID()),
write_options_(write_options), write_options_(write_options),
snapshot_(nullptr),
cmp_(GetColumnFamilyUserComparator(txn_db->DefaultColumnFamily())), cmp_(GetColumnFamilyUserComparator(txn_db->DefaultColumnFamily())),
write_batch_(new WriteBatchWithIndex(cmp_, 0, true)), write_batch_(new WriteBatchWithIndex(cmp_, 0, true)),
start_time_( start_time_(
...@@ -62,24 +62,15 @@ TransactionImpl::TransactionImpl(TransactionDB* txn_db, ...@@ -62,24 +62,15 @@ TransactionImpl::TransactionImpl(TransactionDB* txn_db,
} }
TransactionImpl::~TransactionImpl() { TransactionImpl::~TransactionImpl() {
Cleanup(); txn_db_impl_->UnLock(this, &tracked_keys_);
if (snapshot_ != nullptr) {
db_->ReleaseSnapshot(snapshot_);
}
} }
void TransactionImpl::SetSnapshot() { void TransactionImpl::SetSnapshot() {
if (snapshot_ != nullptr) { snapshot_.reset(new ManagedSnapshot(db_));
db_->ReleaseSnapshot(snapshot_);
}
snapshot_ = db_->GetSnapshot();
} }
void TransactionImpl::Cleanup() { void TransactionImpl::Cleanup() {
write_batch_->Clear(); write_batch_->Clear();
num_entries_ = 0;
txn_db_impl_->UnLock(this, &tracked_keys_); txn_db_impl_->UnLock(this, &tracked_keys_);
tracked_keys_.clear(); tracked_keys_.clear();
save_points_.reset(nullptr); save_points_.reset(nullptr);
...@@ -145,53 +136,27 @@ Status TransactionImpl::DoCommit(WriteBatch* batch) { ...@@ -145,53 +136,27 @@ Status TransactionImpl::DoCommit(WriteBatch* batch) {
void TransactionImpl::Rollback() { Cleanup(); } void TransactionImpl::Rollback() { Cleanup(); }
void TransactionImpl::SetSavePoint() { void TransactionImpl::SetSavePoint() {
if (num_entries_ > 0) { if (save_points_ == nullptr) {
// If transaction is empty, no need to record anything. save_points_.reset(new std::stack<std::shared_ptr<ManagedSnapshot>>());
if (save_points_ == nullptr) {
save_points_.reset(new std::stack<size_t>());
}
save_points_->push(num_entries_);
} }
save_points_->push(snapshot_);
write_batch_->SetSavePoint();
} }
void TransactionImpl::RollbackToSavePoint() { Status TransactionImpl::RollbackToSavePoint() {
size_t savepoint_entries = 0;
if (save_points_ != nullptr && save_points_->size() > 0) { if (save_points_ != nullptr && save_points_->size() > 0) {
savepoint_entries = save_points_->top(); // Restore saved snapshot
snapshot_ = save_points_->top();
save_points_->pop(); save_points_->pop();
}
assert(savepoint_entries <= num_entries_); // Rollback batch
Status s = write_batch_->RollbackToSavePoint();
assert(s.ok());
if (savepoint_entries == num_entries_) { return s;
// No changes to rollback
} else if (savepoint_entries == 0) {
// Rollback everything
Rollback();
} else { } else {
assert(dynamic_cast<DBImpl*>(db_->GetBaseDB()) != nullptr); assert(write_batch_->RollbackToSavePoint().IsNotFound());
auto db_impl = reinterpret_cast<DBImpl*>(db_->GetBaseDB()); return Status::NotFound();
WriteBatchWithIndex* new_batch = new WriteBatchWithIndex(cmp_, 0, true);
Status s = TransactionUtil::CopyFirstN(
savepoint_entries, write_batch_.get(), new_batch, db_impl);
if (!s.ok()) {
// TODO: Should we change this function to return a Status or should we
// somehow make it so RollbackToSavePoint() can never fail?? Not easy to
// handle the case where a client accesses a column family that's been
// dropped.
// After chatting with Siying, I'm going to send a diff that adds
// savepoint support in WriteBatchWithIndex and let reviewers decide which
// approach is cleaner.
fprintf(stderr, "STATUS: %s \n", s.ToString().c_str());
delete new_batch;
} else {
write_batch_.reset(new_batch);
}
num_entries_ = savepoint_entries;
} }
} }
...@@ -331,7 +296,8 @@ Status TransactionImpl::TryLock(ColumnFamilyHandle* column_family, ...@@ -331,7 +296,8 @@ Status TransactionImpl::TryLock(ColumnFamilyHandle* column_family,
// If the key has been previous validated at a sequence number earlier // If the key has been previous validated at a sequence number earlier
// than the curent snapshot's sequence number, we already know it has not // than the curent snapshot's sequence number, we already know it has not
// been modified. // been modified.
bool already_validated = iter->second <= snapshot_->GetSequenceNumber(); SequenceNumber seq = snapshot_->snapshot()->GetSequenceNumber();
bool already_validated = iter->second <= seq;
if (!already_validated) { if (!already_validated) {
s = CheckKeySequence(column_family, key); s = CheckKeySequence(column_family, key);
...@@ -339,7 +305,7 @@ Status TransactionImpl::TryLock(ColumnFamilyHandle* column_family, ...@@ -339,7 +305,7 @@ Status TransactionImpl::TryLock(ColumnFamilyHandle* column_family,
if (s.ok()) { if (s.ok()) {
// Record that there have been no writes to this key after this // Record that there have been no writes to this key after this
// sequence. // sequence.
iter->second = snapshot_->GetSequenceNumber(); iter->second = seq;
} else { } else {
// Failed to validate key // Failed to validate key
if (!previously_locked) { if (!previously_locked) {
...@@ -369,7 +335,7 @@ Status TransactionImpl::CheckKeySequence(ColumnFamilyHandle* column_family, ...@@ -369,7 +335,7 @@ Status TransactionImpl::CheckKeySequence(ColumnFamilyHandle* column_family,
result = TransactionUtil::CheckKeyForConflicts( result = TransactionUtil::CheckKeyForConflicts(
db_impl, cfh, key.ToString(), db_impl, cfh, key.ToString(),
snapshot_->GetSequenceNumber()); snapshot_->snapshot()->GetSequenceNumber());
} }
return result; return result;
...@@ -457,7 +423,6 @@ Status TransactionImpl::Put(ColumnFamilyHandle* column_family, const Slice& key, ...@@ -457,7 +423,6 @@ Status TransactionImpl::Put(ColumnFamilyHandle* column_family, const Slice& key,
if (s.ok()) { if (s.ok()) {
write_batch_->Put(column_family, key, value); write_batch_->Put(column_family, key, value);
num_entries_++;
} }
return s; return s;
...@@ -469,7 +434,6 @@ Status TransactionImpl::Put(ColumnFamilyHandle* column_family, ...@@ -469,7 +434,6 @@ Status TransactionImpl::Put(ColumnFamilyHandle* column_family,
if (s.ok()) { if (s.ok()) {
write_batch_->Put(column_family, key, value); write_batch_->Put(column_family, key, value);
num_entries_++;
} }
return s; return s;
...@@ -481,7 +445,6 @@ Status TransactionImpl::Merge(ColumnFamilyHandle* column_family, ...@@ -481,7 +445,6 @@ Status TransactionImpl::Merge(ColumnFamilyHandle* column_family,
if (s.ok()) { if (s.ok()) {
write_batch_->Merge(column_family, key, value); write_batch_->Merge(column_family, key, value);
num_entries_++;
} }
return s; return s;
...@@ -493,7 +456,6 @@ Status TransactionImpl::Delete(ColumnFamilyHandle* column_family, ...@@ -493,7 +456,6 @@ Status TransactionImpl::Delete(ColumnFamilyHandle* column_family,
if (s.ok()) { if (s.ok()) {
write_batch_->Delete(column_family, key); write_batch_->Delete(column_family, key);
num_entries_++;
} }
return s; return s;
...@@ -505,7 +467,6 @@ Status TransactionImpl::Delete(ColumnFamilyHandle* column_family, ...@@ -505,7 +467,6 @@ Status TransactionImpl::Delete(ColumnFamilyHandle* column_family,
if (s.ok()) { if (s.ok()) {
write_batch_->Delete(column_family, key); write_batch_->Delete(column_family, key);
num_entries_++;
} }
return s; return s;
...@@ -525,7 +486,6 @@ Status TransactionImpl::PutUntracked(ColumnFamilyHandle* column_family, ...@@ -525,7 +486,6 @@ Status TransactionImpl::PutUntracked(ColumnFamilyHandle* column_family,
if (s.ok()) { if (s.ok()) {
write_batch_->Put(column_family, key, value); write_batch_->Put(column_family, key, value);
num_entries_++;
} }
return s; return s;
...@@ -539,7 +499,6 @@ Status TransactionImpl::PutUntracked(ColumnFamilyHandle* column_family, ...@@ -539,7 +499,6 @@ Status TransactionImpl::PutUntracked(ColumnFamilyHandle* column_family,
if (s.ok()) { if (s.ok()) {
write_batch_->Put(column_family, key, value); write_batch_->Put(column_family, key, value);
num_entries_++;
} }
return s; return s;
...@@ -552,7 +511,6 @@ Status TransactionImpl::MergeUntracked(ColumnFamilyHandle* column_family, ...@@ -552,7 +511,6 @@ Status TransactionImpl::MergeUntracked(ColumnFamilyHandle* column_family,
if (s.ok()) { if (s.ok()) {
write_batch_->Merge(column_family, key, value); write_batch_->Merge(column_family, key, value);
num_entries_++;
} }
return s; return s;
...@@ -565,7 +523,6 @@ Status TransactionImpl::DeleteUntracked(ColumnFamilyHandle* column_family, ...@@ -565,7 +523,6 @@ Status TransactionImpl::DeleteUntracked(ColumnFamilyHandle* column_family,
if (s.ok()) { if (s.ok()) {
write_batch_->Delete(column_family, key); write_batch_->Delete(column_family, key);
num_entries_++;
} }
return s; return s;
...@@ -578,7 +535,6 @@ Status TransactionImpl::DeleteUntracked(ColumnFamilyHandle* column_family, ...@@ -578,7 +535,6 @@ Status TransactionImpl::DeleteUntracked(ColumnFamilyHandle* column_family,
if (s.ok()) { if (s.ok()) {
write_batch_->Delete(column_family, key); write_batch_->Delete(column_family, key);
num_entries_++;
} }
return s; return s;
...@@ -586,7 +542,6 @@ Status TransactionImpl::DeleteUntracked(ColumnFamilyHandle* column_family, ...@@ -586,7 +542,6 @@ Status TransactionImpl::DeleteUntracked(ColumnFamilyHandle* column_family,
void TransactionImpl::PutLogData(const Slice& blob) { void TransactionImpl::PutLogData(const Slice& blob) {
write_batch_->PutLogData(blob); write_batch_->PutLogData(blob);
num_entries_++;
} }
WriteBatchWithIndex* TransactionImpl::GetWriteBatch() { WriteBatchWithIndex* TransactionImpl::GetWriteBatch() {
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "db/write_callback.h" #include "db/write_callback.h"
#include "rocksdb/db.h" #include "rocksdb/db.h"
#include "rocksdb/slice.h" #include "rocksdb/slice.h"
#include "rocksdb/snapshot.h"
#include "rocksdb/status.h" #include "rocksdb/status.h"
#include "rocksdb/types.h" #include "rocksdb/types.h"
#include "rocksdb/utilities/transaction.h" #include "rocksdb/utilities/transaction.h"
...@@ -44,7 +45,7 @@ class TransactionImpl : public Transaction { ...@@ -44,7 +45,7 @@ class TransactionImpl : public Transaction {
void SetSavePoint() override; void SetSavePoint() override;
void RollbackToSavePoint() override; Status RollbackToSavePoint() override;
Status Get(const ReadOptions& options, ColumnFamilyHandle* column_family, Status Get(const ReadOptions& options, ColumnFamilyHandle* column_family,
const Slice& key, std::string* value) override; const Slice& key, std::string* value) override;
...@@ -151,7 +152,9 @@ class TransactionImpl : public Transaction { ...@@ -151,7 +152,9 @@ class TransactionImpl : public Transaction {
void PutLogData(const Slice& blob) override; void PutLogData(const Slice& blob) override;
const Snapshot* GetSnapshot() const override { return snapshot_; } const Snapshot* GetSnapshot() const override {
return snapshot_ ? snapshot_->snapshot() : nullptr;
}
void SetSnapshot() override; void SetSnapshot() override;
...@@ -190,7 +193,7 @@ class TransactionImpl : public Transaction { ...@@ -190,7 +193,7 @@ class TransactionImpl : public Transaction {
// If snapshot_ is set, all keys that locked must also have not been written // If snapshot_ is set, all keys that locked must also have not been written
// since this snapshot // since this snapshot
const Snapshot* snapshot_; std::shared_ptr<ManagedSnapshot> snapshot_;
const Comparator* cmp_; const Comparator* cmp_;
...@@ -214,12 +217,9 @@ class TransactionImpl : public Transaction { ...@@ -214,12 +217,9 @@ class TransactionImpl : public Transaction {
// stored. // stored.
TransactionKeyMap tracked_keys_; TransactionKeyMap tracked_keys_;
// Records the number of entries currently in the WriteBatch include calls to // Stack of the Snapshot saved at each save point. Saved snapshots may be
// PutLogData() // nullptr if there was no snapshot at the time SetSavePoint() was called.
size_t num_entries_ = 0; std::unique_ptr<std::stack<std::shared_ptr<ManagedSnapshot>>> save_points_;
// Stack of number of entries in write_batch at each save point
std::unique_ptr<std::stack<size_t>> save_points_;
Status TryLock(ColumnFamilyHandle* column_family, const Slice& key, Status TryLock(ColumnFamilyHandle* column_family, const Slice& key,
bool check_snapshot = true); bool check_snapshot = true);
......
...@@ -1299,12 +1299,14 @@ TEST_F(TransactionTest, SavepointTest) { ...@@ -1299,12 +1299,14 @@ TEST_F(TransactionTest, SavepointTest) {
Transaction* txn = db->BeginTransaction(write_options); Transaction* txn = db->BeginTransaction(write_options);
ASSERT_TRUE(txn); ASSERT_TRUE(txn);
txn->RollbackToSavePoint(); s = txn->RollbackToSavePoint();
ASSERT_TRUE(s.IsNotFound());
txn->SetSavePoint(); // 1 txn->SetSavePoint(); // 1
txn->RollbackToSavePoint(); // Rollback to beginning of txn ASSERT_OK(txn->RollbackToSavePoint()); // Rollback to beginning of txn
txn->RollbackToSavePoint(); s = txn->RollbackToSavePoint();
ASSERT_TRUE(s.IsNotFound());
s = txn->Put("B", "b"); s = txn->Put("B", "b");
ASSERT_OK(s); ASSERT_OK(s);
...@@ -1340,7 +1342,7 @@ TEST_F(TransactionTest, SavepointTest) { ...@@ -1340,7 +1342,7 @@ TEST_F(TransactionTest, SavepointTest) {
s = txn->Put("D", "d"); s = txn->Put("D", "d");
ASSERT_OK(s); ASSERT_OK(s);
txn->RollbackToSavePoint(); // Rollback to 2 ASSERT_OK(txn->RollbackToSavePoint()); // Rollback to 2
s = txn->Get(read_options, "A", &value); s = txn->Get(read_options, "A", &value);
ASSERT_OK(s); ASSERT_OK(s);
...@@ -1363,7 +1365,10 @@ TEST_F(TransactionTest, SavepointTest) { ...@@ -1363,7 +1365,10 @@ TEST_F(TransactionTest, SavepointTest) {
s = txn->Put("E", "e"); s = txn->Put("E", "e");
ASSERT_OK(s); ASSERT_OK(s);
txn->RollbackToSavePoint(); // Rollback to beginning of txn // Rollback to beginning of txn
s = txn->RollbackToSavePoint();
ASSERT_TRUE(s.IsNotFound());
txn->Rollback();
s = txn->Get(read_options, "A", &value); s = txn->Get(read_options, "A", &value);
ASSERT_TRUE(s.IsNotFound()); ASSERT_TRUE(s.IsNotFound());
...@@ -1409,7 +1414,7 @@ TEST_F(TransactionTest, SavepointTest) { ...@@ -1409,7 +1414,7 @@ TEST_F(TransactionTest, SavepointTest) {
s = txn->Get(read_options, "B", &value); s = txn->Get(read_options, "B", &value);
ASSERT_TRUE(s.IsNotFound()); ASSERT_TRUE(s.IsNotFound());
txn->RollbackToSavePoint(); // Rollback to 3 ASSERT_OK(txn->RollbackToSavePoint()); // Rollback to 3
s = txn->Get(read_options, "F", &value); s = txn->Get(read_options, "F", &value);
ASSERT_OK(s); ASSERT_OK(s);
......
...@@ -141,125 +141,6 @@ Status TransactionUtil::CheckKeysForConflicts(DBImpl* db_impl, ...@@ -141,125 +141,6 @@ Status TransactionUtil::CheckKeysForConflicts(DBImpl* db_impl,
return result; return result;
} }
Status TransactionUtil::CopyFirstN(size_t num, WriteBatchWithIndex* batch,
WriteBatchWithIndex* new_batch,
DBImpl* db_impl) {
// Handler for iterating through batch and copying entries to new_batch
class Handler : public WriteBatch::Handler {
public:
WriteBatchWithIndex* batch;
const size_t limit;
DBImpl* db_impl;
size_t seen = 0;
std::unordered_map<uint32_t, SuperVersion*> super_versions;
std::unordered_map<uint32_t, ColumnFamilyHandle*> handles;
Handler(WriteBatchWithIndex* dest, size_t new_limit, DBImpl* db)
: batch(dest), limit(new_limit), db_impl(db) {}
~Handler() {
for (auto& iter : super_versions) {
db_impl->ReturnAndCleanupSuperVersionUnlocked(iter.first, iter.second);
}
}
Status GetColumnFamily(uint32_t column_family_id,
ColumnFamilyHandle** cfh) {
// Need to look up ColumnFamilyHandle for this column family id. Since
// doing this requires grabbing a mutex, lets only do it once per column
// family and cache it.
// In order to ensure that the ColumnFamilyHandle is still valid, we need
// to hold the superversion.
const auto& iter = handles.find(column_family_id);
if (iter == handles.end()) {
// Don't have ColumnFamilyHandle cached, look it up from the db.
SuperVersion* sv =
db_impl->GetAndRefSuperVersionUnlocked(column_family_id);
if (sv == nullptr) {
return Status::InvalidArgument(
"Could not find column family for ID " +
ToString(column_family_id));
}
super_versions.insert({column_family_id, sv});
*cfh = db_impl->GetColumnFamilyHandleUnlocked(column_family_id);
if (*cfh == nullptr) {
return Status::InvalidArgument(
"Could not find column family handle for ID " +
ToString(column_family_id));
}
handles.insert({column_family_id, *cfh});
} else {
*cfh = iter->second;
}
return Status::OK();
}
virtual Status PutCF(uint32_t column_family_id, const Slice& key,
const Slice& value) override {
if (seen >= limit) {
// Found the first N entries, return Aborted to stop the Iteration.
return Status::Aborted();
}
ColumnFamilyHandle* cfh = nullptr;
Status s = GetColumnFamily(column_family_id, &cfh);
if (s.ok()) {
batch->Put(cfh, key, value);
}
seen++;
return s;
}
virtual Status MergeCF(uint32_t column_family_id, const Slice& key,
const Slice& value) override {
if (seen >= limit) {
// Found the first N entries, return Aborted to stop the Iteration.
return Status::Aborted();
}
ColumnFamilyHandle* cfh = nullptr;
Status s = GetColumnFamily(column_family_id, &cfh);
if (s.ok()) {
batch->Merge(cfh, key, value);
}
seen++;
return s;
}
virtual Status DeleteCF(uint32_t column_family_id,
const Slice& key) override {
if (seen >= limit) {
// Found the first N entries, return Aborted to stop the Iteration.
return Status::Aborted();
}
ColumnFamilyHandle* cfh = nullptr;
Status s = GetColumnFamily(column_family_id, &cfh);
if (s.ok()) {
batch->Delete(cfh, key);
}
seen++;
return s;
}
virtual void LogData(const Slice& blob) override {
if (seen < limit) {
batch->PutLogData(blob);
}
seen++;
}
};
// Iterating on this handler will add all keys in this batch into a new batch
// up to
// the limit.
Handler handler(new_batch, num, db_impl);
Status s = batch->GetWriteBatch()->Iterate(&handler);
if (s.IsAborted()) {
// Handler returns Aborted when it is done copying to stop the iteration.
s = Status::OK();
}
return s;
}
} // namespace rocksdb } // namespace rocksdb
......
...@@ -48,12 +48,6 @@ class TransactionUtil { ...@@ -48,12 +48,6 @@ class TransactionUtil {
// mutex is held. // mutex is held.
static Status CheckKeysForConflicts(DBImpl* db_impl, TransactionKeyMap* keys); static Status CheckKeysForConflicts(DBImpl* db_impl, TransactionKeyMap* keys);
// Copies the first num entries from batch into new_batch (including Put,
// Merge, Delete, and PutLogData).
// Returns non-OK on error.
static Status CopyFirstN(size_t num, WriteBatchWithIndex* batch,
WriteBatchWithIndex* new_batch, DBImpl* db_impl);
private: private:
static Status CheckKey(DBImpl* db_impl, SuperVersion* sv, static Status CheckKey(DBImpl* db_impl, SuperVersion* sv,
SequenceNumber earliest_seq, SequenceNumber key_seq, SequenceNumber earliest_seq, SequenceNumber key_seq,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册