]> git.proxmox.com Git - ceph.git/blob - ceph/src/rocksdb/utilities/transactions/lock/range/range_tree/range_tree_lock_tracker.h
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / rocksdb / utilities / transactions / lock / range / range_tree / range_tree_lock_tracker.h
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).
5
6 #pragma once
7
8 #include <memory>
9 #include <string>
10 #include <unordered_map>
11
12 #include "util/mutexlock.h"
13 #include "utilities/transactions/lock/lock_tracker.h"
14 #include "utilities/transactions/pessimistic_transaction.h"
15
16 // Range Locking:
17 #include "lib/locktree/lock_request.h"
18 #include "lib/locktree/locktree.h"
19
20 namespace ROCKSDB_NAMESPACE {
21
22 class RangeTreeLockManager;
23
24 // Storage for locks that are currently held by a transaction.
25 //
26 // Locks are kept in toku::range_buffer because toku::locktree::release_locks()
27 // accepts that as an argument.
28 //
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.
33 //
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
36 // other threads.
37 class RangeLockList {
38 public:
39 ~RangeLockList() { Clear(); }
40
41 RangeLockList() : releasing_locks_(false) {}
42
43 void Append(ColumnFamilyId cf_id, const DBT* left_key, const DBT* right_key);
44 void ReleaseLocks(RangeTreeLockManager* mgr, PessimisticTransaction* txn,
45 bool all_trx_locks);
46 void ReplaceLocks(const toku::locktree* lt, const toku::range_buffer& buffer);
47
48 private:
49 void Clear() {
50 for (auto it : buffers_) {
51 it.second->destroy();
52 }
53 buffers_.clear();
54 }
55
56 std::unordered_map<ColumnFamilyId, std::shared_ptr<toku::range_buffer>>
57 buffers_;
58 port::Mutex mutex_;
59 std::atomic<bool> releasing_locks_;
60 };
61
62 // A LockTracker-based object that is used together with RangeTreeLockManager.
63 class RangeTreeLockTracker : public LockTracker {
64 public:
65 RangeTreeLockTracker() : range_list_(nullptr) {}
66
67 RangeTreeLockTracker(const RangeTreeLockTracker&) = delete;
68 RangeTreeLockTracker& operator=(const RangeTreeLockTracker&) = delete;
69
70 void Track(const PointLockRequest&) override;
71 void Track(const RangeLockRequest&) override;
72
73 bool IsPointLockSupported() const override {
74 // This indicates that we don't implement GetPointLockStatus()
75 return false;
76 }
77 bool IsRangeLockSupported() const override { return true; }
78
79 // a Not-supported dummy implementation.
80 UntrackStatus Untrack(const RangeLockRequest& /*lock_request*/) override {
81 return UntrackStatus::NOT_TRACKED;
82 }
83
84 UntrackStatus Untrack(const PointLockRequest& /*lock_request*/) override {
85 return UntrackStatus::NOT_TRACKED;
86 }
87
88 // "If this method is not supported, leave it as a no-op."
89 void Merge(const LockTracker&) override {}
90
91 // "If this method is not supported, leave it as a no-op."
92 void Subtract(const LockTracker&) override {}
93
94 void Clear() override;
95
96 // "If this method is not supported, returns nullptr."
97 virtual LockTracker* GetTrackedLocksSinceSavePoint(
98 const LockTracker&) const override {
99 return nullptr;
100 }
101
102 PointLockStatus GetPointLockStatus(ColumnFamilyId column_family_id,
103 const std::string& key) const override;
104
105 // The return value is only used for tests
106 uint64_t GetNumPointLocks() const override { return 0; }
107
108 ColumnFamilyIterator* GetColumnFamilyIterator() const override {
109 return nullptr;
110 }
111
112 KeyIterator* GetKeyIterator(
113 ColumnFamilyId /*column_family_id*/) const override {
114 return nullptr;
115 }
116
117 void ReleaseLocks(RangeTreeLockManager* mgr, PessimisticTransaction* txn,
118 bool all_trx_locks) {
119 if (range_list_) range_list_->ReleaseLocks(mgr, txn, all_trx_locks);
120 }
121
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);
126 }
127
128 private:
129 RangeLockList* getOrCreateList();
130 std::unique_ptr<RangeLockList> range_list_;
131 };
132
133 class RangeTreeLockTrackerFactory : public LockTrackerFactory {
134 public:
135 static const RangeTreeLockTrackerFactory& Get() {
136 static const RangeTreeLockTrackerFactory instance;
137 return instance;
138 }
139
140 LockTracker* Create() const override { return new RangeTreeLockTracker(); }
141
142 private:
143 RangeTreeLockTrackerFactory() {}
144 };
145
146 } // namespace ROCKSDB_NAMESPACE