summaryrefslogtreecommitdiffstats
path: root/src/rocksdb/utilities/transactions/lock/lock_tracker.h
blob: 5fa228a82900fb919884da10e001b351b8d9a2dc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
// Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
// This source code is licensed under both the GPLv2 (found in the
// COPYING file in the root directory) and Apache 2.0 License
// (found in the LICENSE.Apache file in the root directory).

#pragma once
#ifndef ROCKSDB_LITE

#include <memory>

#include "rocksdb/rocksdb_namespace.h"
#include "rocksdb/status.h"
#include "rocksdb/types.h"
#include "rocksdb/utilities/transaction_db.h"

namespace ROCKSDB_NAMESPACE {

// Request for locking a single key.
struct PointLockRequest {
  // The id of the key's column family.
  ColumnFamilyId column_family_id = 0;
  // The key to lock.
  std::string key;
  // The sequence number from which there is no concurrent update to key.
  SequenceNumber seq = 0;
  // Whether the lock is acquired only for read.
  bool read_only = false;
  // Whether the lock is in exclusive mode.
  bool exclusive = true;
};

// Request for locking a range of keys.
struct RangeLockRequest {
  // The id of the key's column family.
  ColumnFamilyId column_family_id;

  // The range to be locked
  Endpoint start_endp;
  Endpoint end_endp;
};

struct PointLockStatus {
  // Whether the key is locked.
  bool locked = false;
  // Whether the key is locked in exclusive mode.
  bool exclusive = true;
  // The sequence number in the tracked PointLockRequest.
  SequenceNumber seq = 0;
};

// Return status when calling LockTracker::Untrack.
enum class UntrackStatus {
  // The lock is not tracked at all, so no lock to untrack.
  NOT_TRACKED,
  // The lock is untracked but not removed from the tracker.
  UNTRACKED,
  // The lock is removed from the tracker.
  REMOVED,
};

// Tracks the lock requests.
// In PessimisticTransaction, it tracks the locks acquired through LockMgr;
// In OptimisticTransaction, since there is no LockMgr, it tracks the lock
// intention. Not thread-safe.
class LockTracker {
 public:
  virtual ~LockTracker() {}

  // Whether supports locking a specific key.
  virtual bool IsPointLockSupported() const = 0;

  // Whether supports locking a range of keys.
  virtual bool IsRangeLockSupported() const = 0;

  // Tracks the acquirement of a lock on key.
  //
  // If this method is not supported, leave it as a no-op.
  virtual void Track(const PointLockRequest& /*lock_request*/) = 0;

  // Untracks the lock on a key.
  // seq and exclusive in lock_request are not used.
  //
  // If this method is not supported, leave it as a no-op and
  // returns NOT_TRACKED.
  virtual UntrackStatus Untrack(const PointLockRequest& /*lock_request*/) = 0;

  // Counterpart of Track(const PointLockRequest&) for RangeLockRequest.
  virtual void Track(const RangeLockRequest& /*lock_request*/) = 0;

  // Counterpart of Untrack(const PointLockRequest&) for RangeLockRequest.
  virtual UntrackStatus Untrack(const RangeLockRequest& /*lock_request*/) = 0;

  // Merges lock requests tracked in the specified tracker into the current
  // tracker.
  //
  // E.g. for point lock, if a key in tracker is not yet tracked,
  // track this new key; otherwise, merge the tracked information of the key
  // such as lock's exclusiveness, read/write statistics.
  //
  // If this method is not supported, leave it as a no-op.
  //
  // REQUIRED: the specified tracker must be of the same concrete class type as
  // the current tracker.
  virtual void Merge(const LockTracker& /*tracker*/) = 0;

  // This is a reverse operation of Merge.
  //
  // E.g. for point lock, if a key exists in both current and the sepcified
  // tracker, then subtract the information (such as read/write statistics) of
  // the key in the specified tracker from the current tracker.
  //
  // If this method is not supported, leave it as a no-op.
  //
  // REQUIRED:
  // The specified tracker must be of the same concrete class type as
  // the current tracker.
  // The tracked locks in the specified tracker must be a subset of those
  // tracked by the current tracker.
  virtual void Subtract(const LockTracker& /*tracker*/) = 0;

  // Clears all tracked locks.
  virtual void Clear() = 0;

  // Gets the new locks (excluding the locks that have been tracked before the
  // save point) tracked since the specified save point, the result is stored
  // in an internally constructed LockTracker and returned.
  //
  // save_point_tracker is the tracker used by a SavePoint to track locks
  // tracked after creating the SavePoint.
  //
  // The implementation should document whether point lock, or range lock, or
  // both are considered in this method.
  // If this method is not supported, returns nullptr.
  //
  // REQUIRED:
  // The save_point_tracker must be of the same concrete class type as the
  // current tracker.
  // The tracked locks in the specified tracker must be a subset of those
  // tracked by the current tracker.
  virtual LockTracker* GetTrackedLocksSinceSavePoint(
      const LockTracker& /*save_point_tracker*/) const = 0;

  // Gets lock related information of the key.
  //
  // If point lock is not supported, always returns LockStatus with
  // locked=false.
  virtual PointLockStatus GetPointLockStatus(
      ColumnFamilyId /*column_family_id*/,
      const std::string& /*key*/) const = 0;

  // Gets number of tracked point locks.
  //
  // If point lock is not supported, always returns 0.
  virtual uint64_t GetNumPointLocks() const = 0;

  class ColumnFamilyIterator {
   public:
    virtual ~ColumnFamilyIterator() {}

    // Whether there are remaining column families.
    virtual bool HasNext() const = 0;

    // Gets next column family id.
    //
    // If HasNext is false, calling this method has undefined behavior.
    virtual ColumnFamilyId Next() = 0;
  };

  // Gets an iterator for column families.
  //
  // Returned iterator must not be nullptr.
  // If there is no column family to iterate,
  // returns an empty non-null iterator.
  // Caller owns the returned pointer.
  virtual ColumnFamilyIterator* GetColumnFamilyIterator() const = 0;

  class KeyIterator {
   public:
    virtual ~KeyIterator() {}

    // Whether there are remaining keys.
    virtual bool HasNext() const = 0;

    // Gets the next key.
    //
    // If HasNext is false, calling this method has undefined behavior.
    virtual const std::string& Next() = 0;
  };

  // Gets an iterator for keys with tracked point locks in the column family.
  //
  // The column family must exist.
  // Returned iterator must not be nullptr.
  // Caller owns the returned pointer.
  virtual KeyIterator* GetKeyIterator(
      ColumnFamilyId /*column_family_id*/) const = 0;
};

// LockTracker should always be constructed through this factory.
// Each LockManager owns a LockTrackerFactory.
class LockTrackerFactory {
 public:
  // Caller owns the returned pointer.
  virtual LockTracker* Create() const = 0;
  virtual ~LockTrackerFactory() {}
};

}  // namespace ROCKSDB_NAMESPACE
#endif  // ROCKSDB_LITE