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
, bool untracked
) {
87 uint32_t cfh_id
= GetColumnFamilyID(column_family
);
89 SetSnapshotIfNeeded();
93 seq
= snapshot_
->GetSequenceNumber();
95 seq
= db_
->GetLatestSequenceNumber();
98 std::string key_str
= key
.ToString();
100 TrackKey(cfh_id
, key_str
, seq
, read_only
, exclusive
);
102 // Always return OK. Confilct checking will happen at commit time.
106 // Returns OK if it is safe to commit this transaction. Returns Status::Busy
107 // if there are read or write conflicts that would prevent us from committing OR
108 // if we can not determine whether there would be any such conflicts.
110 // Should only be called on writer thread in order to avoid any race conditions
111 // in detecting write conflicts.
112 Status
OptimisticTransaction::CheckTransactionForConflicts(DB
* db
) {
115 auto db_impl
= static_cast_with_check
<DBImpl
, DB
>(db
);
117 // Since we are on the write thread and do not want to block other writers,
118 // we will do a cache-only conflict check. This can result in TryAgain
119 // getting returned if there is not sufficient memtable history to check
121 return TransactionUtil::CheckKeysForConflicts(db_impl
, GetTrackedKeys(),
122 true /* cache_only */);
125 Status
OptimisticTransaction::SetName(const TransactionName
& /* unused */) {
126 return Status::InvalidArgument("Optimistic transactions cannot be named.");
129 } // namespace rocksdb
131 #endif // ROCKSDB_LITE