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).
10 #include <unordered_map>
12 #include "util/mutexlock.h"
13 #include "utilities/transactions/lock/lock_tracker.h"
14 #include "utilities/transactions/pessimistic_transaction.h"
17 #include "lib/locktree/lock_request.h"
18 #include "lib/locktree/locktree.h"
20 namespace ROCKSDB_NAMESPACE
{
22 class RangeTreeLockManager
;
24 // Storage for locks that are currently held by a transaction.
26 // Locks are kept in toku::range_buffer because toku::locktree::release_locks()
27 // accepts that as an argument.
29 // Note: the list of locks may differ slighly from the contents of the lock
30 // tree, due to concurrency between lock acquisition, lock release, and lock
31 // escalation. See MDEV-18227 and RangeTreeLockManager::UnLock for details.
32 // This property is currently harmless.
34 // Append() and ReleaseLocks() are not thread-safe, as they are expected to be
35 // called only by the owner transaction. ReplaceLocks() is safe to call from
39 ~RangeLockList() { Clear(); }
41 RangeLockList() : releasing_locks_(false) {}
43 void Append(ColumnFamilyId cf_id
, const DBT
* left_key
, const DBT
* right_key
);
44 void ReleaseLocks(RangeTreeLockManager
* mgr
, PessimisticTransaction
* txn
,
46 void ReplaceLocks(const toku::locktree
* lt
, const toku::range_buffer
& buffer
);
50 for (auto it
: buffers_
) {
56 std::unordered_map
<ColumnFamilyId
, std::shared_ptr
<toku::range_buffer
>>
59 std::atomic
<bool> releasing_locks_
;
62 // A LockTracker-based object that is used together with RangeTreeLockManager.
63 class RangeTreeLockTracker
: public LockTracker
{
65 RangeTreeLockTracker() : range_list_(nullptr) {}
67 RangeTreeLockTracker(const RangeTreeLockTracker
&) = delete;
68 RangeTreeLockTracker
& operator=(const RangeTreeLockTracker
&) = delete;
70 void Track(const PointLockRequest
&) override
;
71 void Track(const RangeLockRequest
&) override
;
73 bool IsPointLockSupported() const override
{
74 // This indicates that we don't implement GetPointLockStatus()
77 bool IsRangeLockSupported() const override
{ return true; }
79 // a Not-supported dummy implementation.
80 UntrackStatus
Untrack(const RangeLockRequest
& /*lock_request*/) override
{
81 return UntrackStatus::NOT_TRACKED
;
84 UntrackStatus
Untrack(const PointLockRequest
& /*lock_request*/) override
{
85 return UntrackStatus::NOT_TRACKED
;
88 // "If this method is not supported, leave it as a no-op."
89 void Merge(const LockTracker
&) override
{}
91 // "If this method is not supported, leave it as a no-op."
92 void Subtract(const LockTracker
&) override
{}
94 void Clear() override
;
96 // "If this method is not supported, returns nullptr."
97 virtual LockTracker
* GetTrackedLocksSinceSavePoint(
98 const LockTracker
&) const override
{
102 PointLockStatus
GetPointLockStatus(ColumnFamilyId column_family_id
,
103 const std::string
& key
) const override
;
105 // The return value is only used for tests
106 uint64_t GetNumPointLocks() const override
{ return 0; }
108 ColumnFamilyIterator
* GetColumnFamilyIterator() const override
{
112 KeyIterator
* GetKeyIterator(
113 ColumnFamilyId
/*column_family_id*/) const override
{
117 void ReleaseLocks(RangeTreeLockManager
* mgr
, PessimisticTransaction
* txn
,
118 bool all_trx_locks
) {
119 if (range_list_
) range_list_
->ReleaseLocks(mgr
, txn
, all_trx_locks
);
122 void ReplaceLocks(const toku::locktree
* lt
,
123 const toku::range_buffer
& buffer
) {
124 // range_list_ cannot be NULL here
125 range_list_
->ReplaceLocks(lt
, buffer
);
129 RangeLockList
* getOrCreateList();
130 std::unique_ptr
<RangeLockList
> range_list_
;
133 class RangeTreeLockTrackerFactory
: public LockTrackerFactory
{
135 static const RangeTreeLockTrackerFactory
& Get() {
136 static const RangeTreeLockTrackerFactory instance
;
140 LockTracker
* Create() const override
{ return new RangeTreeLockTracker(); }
143 RangeTreeLockTrackerFactory() {}
146 } // namespace ROCKSDB_NAMESPACE