Coverage Report

Created: 2026-02-14 06:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/rocksdb/utilities/transactions/lock/lock_tracker.h
Line
Count
Source
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
10
#include "rocksdb/rocksdb_namespace.h"
11
#include "rocksdb/status.h"
12
#include "rocksdb/types.h"
13
#include "rocksdb/utilities/transaction_db.h"
14
15
namespace ROCKSDB_NAMESPACE {
16
17
// Request for locking a single key.
18
struct PointLockRequest {
19
  // The id of the key's column family.
20
  ColumnFamilyId column_family_id = 0;
21
  // The key to lock.
22
  std::string key;
23
  // The sequence number from which there is no concurrent update to key.
24
  SequenceNumber seq = 0;
25
  // Whether the lock is acquired only for read.
26
  bool read_only = false;
27
  // Whether the lock is in exclusive mode.
28
  bool exclusive = true;
29
};
30
31
// Request for locking a range of keys.
32
struct RangeLockRequest {
33
  // The id of the key's column family.
34
  ColumnFamilyId column_family_id;
35
36
  // The range to be locked
37
  Endpoint start_endp;
38
  Endpoint end_endp;
39
};
40
41
struct PointLockStatus {
42
  // Whether the key is locked.
43
  bool locked = false;
44
  // Whether the key is locked in exclusive mode.
45
  bool exclusive = true;
46
  // The sequence number in the tracked PointLockRequest.
47
  SequenceNumber seq = 0;
48
};
49
50
// Return status when calling LockTracker::Untrack.
51
enum class UntrackStatus {
52
  // The lock is not tracked at all, so no lock to untrack.
53
  NOT_TRACKED,
54
  // The lock is untracked but not removed from the tracker.
55
  UNTRACKED,
56
  // The lock is removed from the tracker.
57
  REMOVED,
58
};
59
60
// Tracks the lock requests.
61
// In PessimisticTransaction, it tracks the locks acquired through LockMgr;
62
// In OptimisticTransaction, since there is no LockMgr, it tracks the lock
63
// intention. Not thread-safe.
64
class LockTracker {
65
 public:
66
0
  virtual ~LockTracker() {}
67
68
  // Whether supports locking a specific key.
69
  virtual bool IsPointLockSupported() const = 0;
70
71
  // Whether supports locking a range of keys.
72
  virtual bool IsRangeLockSupported() const = 0;
73
74
  // Tracks the acquirement of a lock on key.
75
  //
76
  // If this method is not supported, leave it as a no-op.
77
  virtual void Track(const PointLockRequest& /*lock_request*/) = 0;
78
79
  // Untracks the lock on a key.
80
  // seq and exclusive in lock_request are not used.
81
  //
82
  // If this method is not supported, leave it as a no-op and
83
  // returns NOT_TRACKED.
84
  virtual UntrackStatus Untrack(const PointLockRequest& /*lock_request*/) = 0;
85
86
  // Counterpart of Track(const PointLockRequest&) for RangeLockRequest.
87
  virtual void Track(const RangeLockRequest& /*lock_request*/) = 0;
88
89
  // Counterpart of Untrack(const PointLockRequest&) for RangeLockRequest.
90
  virtual UntrackStatus Untrack(const RangeLockRequest& /*lock_request*/) = 0;
91
92
  // Merges lock requests tracked in the specified tracker into the current
93
  // tracker.
94
  //
95
  // E.g. for point lock, if a key in tracker is not yet tracked,
96
  // track this new key; otherwise, merge the tracked information of the key
97
  // such as lock's exclusiveness, read/write statistics.
98
  //
99
  // If this method is not supported, leave it as a no-op.
100
  //
101
  // REQUIRED: the specified tracker must be of the same concrete class type as
102
  // the current tracker.
103
  virtual void Merge(const LockTracker& /*tracker*/) = 0;
104
105
  // This is a reverse operation of Merge.
106
  //
107
  // E.g. for point lock, if a key exists in both current and the sepcified
108
  // tracker, then subtract the information (such as read/write statistics) of
109
  // the key in the specified tracker from the current tracker.
110
  //
111
  // If this method is not supported, leave it as a no-op.
112
  //
113
  // REQUIRED:
114
  // The specified tracker must be of the same concrete class type as
115
  // the current tracker.
116
  // The tracked locks in the specified tracker must be a subset of those
117
  // tracked by the current tracker.
118
  virtual void Subtract(const LockTracker& /*tracker*/) = 0;
119
120
  // Clears all tracked locks.
121
  virtual void Clear() = 0;
122
123
  // Gets the new locks (excluding the locks that have been tracked before the
124
  // save point) tracked since the specified save point, the result is stored
125
  // in an internally constructed LockTracker and returned.
126
  //
127
  // save_point_tracker is the tracker used by a SavePoint to track locks
128
  // tracked after creating the SavePoint.
129
  //
130
  // The implementation should document whether point lock, or range lock, or
131
  // both are considered in this method.
132
  // If this method is not supported, returns nullptr.
133
  //
134
  // REQUIRED:
135
  // The save_point_tracker must be of the same concrete class type as the
136
  // current tracker.
137
  // The tracked locks in the specified tracker must be a subset of those
138
  // tracked by the current tracker.
139
  virtual LockTracker* GetTrackedLocksSinceSavePoint(
140
      const LockTracker& /*save_point_tracker*/) const = 0;
141
142
  // Gets lock related information of the key.
143
  //
144
  // If point lock is not supported, always returns LockStatus with
145
  // locked=false.
146
  virtual PointLockStatus GetPointLockStatus(
147
      ColumnFamilyId /*column_family_id*/,
148
      const std::string& /*key*/) const = 0;
149
150
  // Gets number of tracked point locks.
151
  //
152
  // If point lock is not supported, always returns 0.
153
  virtual uint64_t GetNumPointLocks() const = 0;
154
155
  class ColumnFamilyIterator {
156
   public:
157
0
    virtual ~ColumnFamilyIterator() {}
158
159
    // Whether there are remaining column families.
160
    virtual bool HasNext() const = 0;
161
162
    // Gets next column family id.
163
    //
164
    // If HasNext is false, calling this method has undefined behavior.
165
    virtual ColumnFamilyId Next() = 0;
166
  };
167
168
  // Gets an iterator for column families.
169
  //
170
  // Returned iterator must not be nullptr.
171
  // If there is no column family to iterate,
172
  // returns an empty non-null iterator.
173
  // Caller owns the returned pointer.
174
  virtual ColumnFamilyIterator* GetColumnFamilyIterator() const = 0;
175
176
  class KeyIterator {
177
   public:
178
0
    virtual ~KeyIterator() {}
179
180
    // Whether there are remaining keys.
181
    virtual bool HasNext() const = 0;
182
183
    // Gets the next key.
184
    //
185
    // If HasNext is false, calling this method has undefined behavior.
186
    virtual const std::string& Next() = 0;
187
  };
188
189
  // Gets an iterator for keys with tracked point locks in the column family.
190
  //
191
  // The column family must exist.
192
  // Returned iterator must not be nullptr.
193
  // Caller owns the returned pointer.
194
  virtual KeyIterator* GetKeyIterator(
195
      ColumnFamilyId /*column_family_id*/) const = 0;
196
};
197
198
// LockTracker should always be constructed through this factory.
199
// Each LockManager owns a LockTrackerFactory.
200
class LockTrackerFactory {
201
 public:
202
  // Caller owns the returned pointer.
203
  virtual LockTracker* Create() const = 0;
204
0
  virtual ~LockTrackerFactory() {}
205
};
206
207
}  // namespace ROCKSDB_NAMESPACE