1 // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
2 // This source code is licensed under the BSD-style license found in the
3 // LICENSE file in the root directory of this source tree. An additional grant
4 // of patent rights can be found in the PATENTS file in the same directory.
8 #include "utilities/transactions/optimistic_transaction_impl.h"
14 #include "db/column_family.h"
15 #include "db/db_impl.h"
16 #include "rocksdb/comparator.h"
17 #include "rocksdb/db.h"
18 #include "rocksdb/status.h"
19 #include "rocksdb/utilities/optimistic_transaction_db.h"
20 #include "util/string_util.h"
21 #include "utilities/transactions/transaction_util.h"
27 OptimisticTransactionImpl::OptimisticTransactionImpl(
28 OptimisticTransactionDB
* txn_db
, const WriteOptions
& write_options
,
29 const OptimisticTransactionOptions
& txn_options
)
30 : TransactionBaseImpl(txn_db
->GetBaseDB(), write_options
), txn_db_(txn_db
) {
31 Initialize(txn_options
);
34 void OptimisticTransactionImpl::Initialize(
35 const OptimisticTransactionOptions
& txn_options
) {
36 if (txn_options
.set_snapshot
) {
41 void OptimisticTransactionImpl::Reinitialize(
42 OptimisticTransactionDB
* txn_db
, const WriteOptions
& write_options
,
43 const OptimisticTransactionOptions
& txn_options
) {
44 TransactionBaseImpl::Reinitialize(txn_db
->GetBaseDB(), write_options
);
45 Initialize(txn_options
);
48 OptimisticTransactionImpl::~OptimisticTransactionImpl() {
51 void OptimisticTransactionImpl::Clear() {
52 TransactionBaseImpl::Clear();
55 Status
OptimisticTransactionImpl::Prepare() {
56 return Status::InvalidArgument(
57 "Two phase commit not supported for optimistic transactions.");
60 Status
OptimisticTransactionImpl::Commit() {
61 // Set up callback which will call CheckTransactionForConflicts() to
62 // check whether this transaction is safe to be committed.
63 OptimisticTransactionCallback
callback(this);
65 DBImpl
* db_impl
= dynamic_cast<DBImpl
*>(db_
->GetRootDB());
66 if (db_impl
== nullptr) {
67 // This should only happen if we support creating transactions from
68 // a StackableDB and someone overrides GetRootDB().
69 return Status::InvalidArgument(
70 "DB::GetRootDB() returned an unexpected DB class");
73 Status s
= db_impl
->WriteWithCallback(
74 write_options_
, GetWriteBatch()->GetWriteBatch(), &callback
);
83 Status
OptimisticTransactionImpl::Rollback() {
88 // Record this key so that we can check it for conflicts at commit time.
90 // 'exclusive' is unused for OptimisticTransaction.
91 Status
OptimisticTransactionImpl::TryLock(ColumnFamilyHandle
* column_family
,
92 const Slice
& key
, bool read_only
,
93 bool exclusive
, bool untracked
) {
97 uint32_t cfh_id
= GetColumnFamilyID(column_family
);
99 SetSnapshotIfNeeded();
103 seq
= snapshot_
->GetSequenceNumber();
105 seq
= db_
->GetLatestSequenceNumber();
108 std::string key_str
= key
.ToString();
110 TrackKey(cfh_id
, key_str
, seq
, read_only
, exclusive
);
112 // Always return OK. Confilct checking will happen at commit time.
116 // Returns OK if it is safe to commit this transaction. Returns Status::Busy
117 // if there are read or write conflicts that would prevent us from committing OR
118 // if we can not determine whether there would be any such conflicts.
120 // Should only be called on writer thread in order to avoid any race conditions
121 // in detecting write conflicts.
122 Status
OptimisticTransactionImpl::CheckTransactionForConflicts(DB
* db
) {
125 assert(dynamic_cast<DBImpl
*>(db
) != nullptr);
126 auto db_impl
= reinterpret_cast<DBImpl
*>(db
);
128 // Since we are on the write thread and do not want to block other writers,
129 // we will do a cache-only conflict check. This can result in TryAgain
130 // getting returned if there is not sufficient memtable history to check
132 return TransactionUtil::CheckKeysForConflicts(db_impl
, GetTrackedKeys(),
133 true /* cache_only */);
136 Status
OptimisticTransactionImpl::SetName(const TransactionName
& name
) {
137 return Status::InvalidArgument("Optimistic transactions cannot be named.");
140 } // namespace rocksdb
142 #endif // ROCKSDB_LITE