1 // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
2 // This source code is licensed under both the GPLv2 (found in the
3 // COPYING file in the root directory) and Apache 2.0 License
4 // (found in the LICENSE.Apache file in the root directory).
8 #include "utilities/transactions/optimistic_transaction.h"
12 #include "db/column_family.h"
13 #include "db/db_impl.h"
14 #include "rocksdb/comparator.h"
15 #include "rocksdb/db.h"
16 #include "rocksdb/status.h"
17 #include "rocksdb/utilities/optimistic_transaction_db.h"
18 #include "util/cast_util.h"
19 #include "util/string_util.h"
20 #include "utilities/transactions/transaction_util.h"
26 OptimisticTransaction::OptimisticTransaction(
27 OptimisticTransactionDB
* txn_db
, const WriteOptions
& write_options
,
28 const OptimisticTransactionOptions
& txn_options
)
29 : TransactionBaseImpl(txn_db
->GetBaseDB(), write_options
), txn_db_(txn_db
) {
30 Initialize(txn_options
);
33 void OptimisticTransaction::Initialize(
34 const OptimisticTransactionOptions
& txn_options
) {
35 if (txn_options
.set_snapshot
) {
40 void OptimisticTransaction::Reinitialize(
41 OptimisticTransactionDB
* txn_db
, const WriteOptions
& write_options
,
42 const OptimisticTransactionOptions
& txn_options
) {
43 TransactionBaseImpl::Reinitialize(txn_db
->GetBaseDB(), write_options
);
44 Initialize(txn_options
);
47 OptimisticTransaction::~OptimisticTransaction() {}
49 void OptimisticTransaction::Clear() { TransactionBaseImpl::Clear(); }
51 Status
OptimisticTransaction::Prepare() {
52 return Status::InvalidArgument(
53 "Two phase commit not supported for optimistic transactions.");
56 Status
OptimisticTransaction::Commit() {
57 // Set up callback which will call CheckTransactionForConflicts() to
58 // check whether this transaction is safe to be committed.
59 OptimisticTransactionCallback
callback(this);
61 DBImpl
* db_impl
= static_cast_with_check
<DBImpl
, DB
>(db_
->GetRootDB());
63 Status s
= db_impl
->WriteWithCallback(
64 write_options_
, GetWriteBatch()->GetWriteBatch(), &callback
);
73 Status
OptimisticTransaction::Rollback() {
78 // Record this key so that we can check it for conflicts at commit time.
80 // 'exclusive' is unused for OptimisticTransaction.
81 Status
OptimisticTransaction::TryLock(ColumnFamilyHandle
* column_family
,
82 const Slice
& key
, bool read_only
,
83 bool exclusive
, const bool do_validate
,
84 const bool assume_tracked
) {
85 assert(!assume_tracked
); // not supported
90 uint32_t cfh_id
= GetColumnFamilyID(column_family
);
92 SetSnapshotIfNeeded();
96 seq
= snapshot_
->GetSequenceNumber();
98 seq
= db_
->GetLatestSequenceNumber();
101 std::string key_str
= key
.ToString();
103 TrackKey(cfh_id
, key_str
, seq
, read_only
, exclusive
);
105 // Always return OK. Confilct checking will happen at commit time.
109 // Returns OK if it is safe to commit this transaction. Returns Status::Busy
110 // if there are read or write conflicts that would prevent us from committing OR
111 // if we can not determine whether there would be any such conflicts.
113 // Should only be called on writer thread in order to avoid any race conditions
114 // in detecting write conflicts.
115 Status
OptimisticTransaction::CheckTransactionForConflicts(DB
* db
) {
118 auto db_impl
= static_cast_with_check
<DBImpl
, DB
>(db
);
120 // Since we are on the write thread and do not want to block other writers,
121 // we will do a cache-only conflict check. This can result in TryAgain
122 // getting returned if there is not sufficient memtable history to check
124 return TransactionUtil::CheckKeysForConflicts(db_impl
, GetTrackedKeys(),
125 true /* cache_only */);
128 Status
OptimisticTransaction::SetName(const TransactionName
& /* unused */) {
129 return Status::InvalidArgument("Optimistic transactions cannot be named.");
132 } // namespace rocksdb
134 #endif // ROCKSDB_LITE