revision-id: 51606993a6e04edfa32ba9ed445e47330a2b2647 (v5.8-1021-g51606993a) parent(s): 7f29e9512f6bd7a12d8a8d3a493eaff586c5f28b author: Sergei Petrunia committer: Sergei Petrunia timestamp: 2018-12-10 15:20:20 +0300 message: Make Range Locking use its own storage for acquired locks (Because it needs to store locked ranges, not just locked points. and it doesn't need the key tracking provided by TrackKey() so that one will be disabled) --- utilities/transactions/pessimistic_transaction.h | 12 ++++++ utilities/transactions/transaction_lock_mgr.cc | 52 +++++++++++++++++++++++- 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/utilities/transactions/pessimistic_transaction.h b/utilities/transactions/pessimistic_transaction.h index 340ea929e..50030700d 100644 --- a/utilities/transactions/pessimistic_transaction.h +++ b/utilities/transactions/pessimistic_transaction.h @@ -150,6 +150,18 @@ class PessimisticTransaction : public TransactionBaseImpl { // microseconds according to Env->NowMicros()) uint64_t expiration_time_; + /* + psergey: Range Locking: A list of locks the transaction is holding. + + (for point locking, the locks are kept in TransactionBaseImpl::tracked_keys_) + */ + public: + class LockStorage { + public: + virtual ~LockStorage(){} + }; + std::unique_ptr<LockStorage> owned_locks; + private: friend class TransactionTest_ValidateSnapshotTest_Test; // Used to create unique ids for transactions. diff --git a/utilities/transactions/transaction_lock_mgr.cc b/utilities/transactions/transaction_lock_mgr.cc index a7eb7e30b..561531f7e 100644 --- a/utilities/transactions/transaction_lock_mgr.cc +++ b/utilities/transactions/transaction_lock_mgr.cc @@ -321,6 +321,33 @@ void RangeLockMgr::KillLockWait(void *cdata) } +/* + Storage for locks that are held by this transaction. + + We store them in toku::range_buffer because toku::locktree::release_locks() + accepts that as an argument. + + TODO: lock escalation in the lock table should affect this structure, too? +*/ +class RangeLockList: public PessimisticTransaction::LockStorage +{ +public: + virtual ~RangeLockList() + { + buffer.destroy(); + } + + RangeLockList() + { + buffer.create(); + } + + void append(const DBT *left_key, const DBT *right_key) { + buffer.append(left_key, right_key); + } + + toku::range_buffer buffer; +}; // Get a range lock on [start_key; end_key] range // (TODO: check if we do what is inteded at the endpoints) @@ -391,7 +418,7 @@ Status RangeLockMgr::TryRangeLock(PessimisticTransaction* txn, request.destroy(); switch (r) { case 0: - return Status::OK(); + break; /* fall through */ case DB_LOCK_NOTGRANTED: return Status::TimedOut(Status::SubCode::kLockTimeout); case TOKUDB_OUT_OF_LOCKS: @@ -402,6 +429,17 @@ Status RangeLockMgr::TryRangeLock(PessimisticTransaction* txn, assert(0); return Status::Busy(Status::SubCode::kLockLimit); } + + /* Save the acquired lock in txn->owned_locks */ + if (!txn->owned_locks) + { + //create the object + txn->owned_locks= std::unique_ptr<RangeLockList>(new RangeLockList); + } + RangeLockList* range_list= (RangeLockList*)txn->owned_locks.get(); + range_list->append(&start_key_dbt, &end_key_dbt); + + return Status::OK(); } @@ -795,6 +833,7 @@ void RangeLockMgr::UnLock(const PessimisticTransaction* txn, void RangeLockMgr::UnLockAll(const PessimisticTransaction* txn, const TransactionKeyMap* key_map, Env* env) { +#if 0 //TODO: collecting multiple locks into a buffer and then making one call // to lock_tree::release_locks() will be faster. for (auto& key_map_iter : *key_map) { @@ -808,6 +847,17 @@ void RangeLockMgr::UnLockAll(const PessimisticTransaction* txn, } toku::lock_request::retry_all_lock_requests(lt, nullptr /* lock_wait_needed_callback */); +#endif + + // owned_locks may hold nullptr if the transaction has never acquired any + // locks. + if (txn->owned_locks) + { + RangeLockList* range_list= (RangeLockList*)txn->owned_locks.get(); + lt->release_locks(txn->GetID(), &range_list->buffer); + range_list->buffer.destroy(); + toku::lock_request::retry_all_lock_requests(lt, nullptr /* lock_wait_needed_callback */); + } #if 0 Original usage: