/Users/deen/code/yugabyte-db/src/yb/tablet/mvcc.h
Line | Count | Source (jump to first uncovered line) |
1 | | // Licensed to the Apache Software Foundation (ASF) under one |
2 | | // or more contributor license agreements. See the NOTICE file |
3 | | // distributed with this work for additional information |
4 | | // regarding copyright ownership. The ASF licenses this file |
5 | | // to you under the Apache License, Version 2.0 (the |
6 | | // "License"); you may not use this file except in compliance |
7 | | // with the License. You may obtain a copy of the License at |
8 | | // |
9 | | // http://www.apache.org/licenses/LICENSE-2.0 |
10 | | // |
11 | | // Unless required by applicable law or agreed to in writing, |
12 | | // software distributed under the License is distributed on an |
13 | | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
14 | | // KIND, either express or implied. See the License for the |
15 | | // specific language governing permissions and limitations |
16 | | // under the License. |
17 | | // |
18 | | // The following only applies to changes made to this file as part of YugaByte development. |
19 | | // |
20 | | // Portions Copyright (c) YugaByte, Inc. |
21 | | // |
22 | | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
23 | | // in compliance with the License. You may obtain a copy of the License at |
24 | | // |
25 | | // http://www.apache.org/licenses/LICENSE-2.0 |
26 | | // |
27 | | // Unless required by applicable law or agreed to in writing, software distributed under the License |
28 | | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
29 | | // or implied. See the License for the specific language governing permissions and limitations |
30 | | // under the License. |
31 | | // |
32 | | #ifndef YB_TABLET_MVCC_H_ |
33 | | #define YB_TABLET_MVCC_H_ |
34 | | |
35 | | #include <condition_variable> |
36 | | #include <deque> |
37 | | #include <vector> |
38 | | |
39 | | #include "yb/gutil/thread_annotations.h" |
40 | | |
41 | | #include "yb/server/clock.h" |
42 | | |
43 | | #include "yb/util/enums.h" |
44 | | #include "yb/util/math_util.h" |
45 | | #include "yb/util/opid.h" |
46 | | |
47 | | namespace yb { |
48 | | namespace tablet { |
49 | | |
50 | | // Allows us to keep track of how a particular value of safe time was obtained, for sanity |
51 | | // checking purposes. |
52 | | YB_DEFINE_ENUM(SafeTimeSource, |
53 | | (kUnknown)(kNow)(kNextInQueue)(kHybridTimeLease)(kPropagated)(kLastReplicated)); |
54 | | |
55 | | struct SafeTimeWithSource { |
56 | | HybridTime safe_time = HybridTime::kMin; |
57 | | SafeTimeSource source = SafeTimeSource::kUnknown; |
58 | | |
59 | | std::string ToString() const; |
60 | | }; |
61 | | |
62 | | struct FixedHybridTimeLease { |
63 | | HybridTime time; |
64 | | HybridTime lease = HybridTime::kMax; |
65 | | |
66 | 73.5M | bool empty() const { |
67 | 73.5M | return lease.GetPhysicalValueMicros() >= kMaxHybridTimePhysicalMicros; |
68 | 73.5M | } |
69 | | |
70 | | std::string ToString() const; |
71 | | }; |
72 | | |
73 | 0 | inline std::ostream& operator<<(std::ostream& out, const FixedHybridTimeLease& ht_lease) { |
74 | 0 | return out << ht_lease.ToString(); |
75 | 0 | } |
76 | | |
77 | | // MvccManager is used to track operations. |
78 | | // When new operation is initiated its time should be added using AddPending. |
79 | | // When operation is replicated or aborted, MvccManager is notified using Replicated or Aborted |
80 | | // methods. |
81 | | // Operations could be replicated only in the same order as they were added. |
82 | | // Time of newly added operation should be after time of all previously added operations. |
83 | | class MvccManager { |
84 | | public: |
85 | | // `prefix` is used for logging. |
86 | | explicit MvccManager(std::string prefix, server::ClockPtr clock); |
87 | | ~MvccManager(); |
88 | | |
89 | | // Set special RF==1 mode flag to handle safe time requests correctly in case |
90 | | // there are no heartbeats to update internal propagated_safe_time_ correctly. |
91 | | void SetLeaderOnlyMode(bool leader_only) EXCLUDES(mutex_); |
92 | | |
93 | | // Sets time of last replicated operation, used after bootstrap. |
94 | | void SetLastReplicated(HybridTime ht) EXCLUDES(mutex_); |
95 | | |
96 | | // Sets safe time that was sent to us by the leader. Should be called on followers. |
97 | | void SetPropagatedSafeTimeOnFollower(HybridTime ht) EXCLUDES(mutex_); |
98 | | |
99 | | // Updates the propagated_safe_time field to the current safe time. This should be called in the |
100 | | // majority-replicated watermark callback from Raft. If we have some read requests that were |
101 | | // initiated when this server was a follower and are waiting for the safe time to advance past |
102 | | // a certain point, they can also get unblocked by this update of propagated_safe_time. |
103 | | void UpdatePropagatedSafeTimeOnLeader(const FixedHybridTimeLease& ht_lease) EXCLUDES(mutex_); |
104 | | |
105 | | // Adds time of new tracked follower operation. |
106 | | // OpId is being passed for the ease of debugging. |
107 | | void AddFollowerPending(HybridTime ht, const OpId& op_id) EXCLUDES(mutex_); |
108 | | |
109 | | // Adds leader operation and returns its time. |
110 | | // OpId is being passed for the ease of debugging. |
111 | | HybridTime AddLeaderPending(const OpId& op_id) EXCLUDES(mutex_); |
112 | | |
113 | | // Notifies that operation with appropriate time was replicated. |
114 | | // It should be first operation in queue. |
115 | | void Replicated(HybridTime ht, const OpId& op_id) EXCLUDES(mutex_); |
116 | | |
117 | | // Notifies that operation with appropriate time was aborted. |
118 | | void Aborted(HybridTime ht, const OpId& op_id) EXCLUDES(mutex_); |
119 | | |
120 | | // Returns maximum allowed timestamp to read at. No operations that are initiated after this call |
121 | | // will receive hybrid time less than what's returned, provided that `ht_lease` is set to the |
122 | | // hybrid time leader lease expiration. |
123 | | // |
124 | | // `min_allowed` - result should be greater than or equal to `min_allowed`, otherwise it tries to |
125 | | // wait until safe hybrid time to read at reaches this value or `deadline` happens. Should be |
126 | | // less than the current hybrid time. |
127 | | // |
128 | | // `ht_lease` - result should be less than or equal to `ht_lease`, unless we have replicated |
129 | | // records past it. Should be past `min_allowed`. This is normally used to pass in the hybrid time |
130 | | // leader lease expiration, which limits the range of hybrid times that the current leader has |
131 | | // authority over, and thus imposes an upper bound on the safe time. |
132 | | // |
133 | | // Returns invalid hybrid time in case it cannot satisfy provided requirements, for instance |
134 | | // because of timeout. |
135 | | HybridTime SafeTime( |
136 | | HybridTime min_allowed, CoarseTimePoint deadline, const FixedHybridTimeLease& ht_lease) const |
137 | | EXCLUDES(mutex_); |
138 | | |
139 | 28.7M | HybridTime SafeTime(const FixedHybridTimeLease& ht_lease) const EXCLUDES(mutex_) { |
140 | 28.7M | return SafeTime(HybridTime::kMin /* min_allowed */, CoarseTimePoint::max() /* deadline */, |
141 | 28.7M | ht_lease); |
142 | 28.7M | } |
143 | | |
144 | | HybridTime SafeTimeForFollower(HybridTime min_allowed, CoarseTimePoint deadline) const |
145 | | EXCLUDES(mutex_); |
146 | | |
147 | | // Returns time of last replicated operation. |
148 | | HybridTime LastReplicatedHybridTime() const EXCLUDES(mutex_); |
149 | | |
150 | | class MvccOpTrace; |
151 | | |
152 | | void TEST_DumpTrace(std::ostream* out); |
153 | | |
154 | | private: |
155 | | HybridTime DoGetSafeTime(HybridTime min_allowed, |
156 | | CoarseTimePoint deadline, |
157 | | const FixedHybridTimeLease& ht_lease, |
158 | | std::unique_lock<std::mutex>* lock) const REQUIRES(mutex_); |
159 | | |
160 | 95 | const std::string& LogPrefix() const { return prefix_; } |
161 | | |
162 | | struct InvariantViolationLoggingHelper; |
163 | | InvariantViolationLoggingHelper InvariantViolationLogPrefix() const REQUIRES(mutex_); |
164 | | |
165 | | friend std::ostream& operator<<( |
166 | | std::ostream& out, const InvariantViolationLoggingHelper& helper); |
167 | | |
168 | | void AddPending(HybridTime ht, const OpId& op_id, bool is_follower_side) REQUIRES(mutex_); |
169 | | |
170 | | std::string prefix_; |
171 | | server::ClockPtr clock_; |
172 | | mutable std::mutex mutex_; |
173 | | mutable std::condition_variable cond_; |
174 | | |
175 | | struct QueueItem { |
176 | | HybridTime hybrid_time; |
177 | | OpId op_id; |
178 | | |
179 | | std::string ToString() const; |
180 | | bool Eq(const QueueItem& rhs) const; |
181 | | |
182 | 13.4M | friend bool operator==(const QueueItem& lhs, const QueueItem& rhs) { |
183 | 13.4M | return lhs.Eq(rhs); |
184 | 13.4M | } |
185 | | |
186 | 0 | friend bool operator<(const QueueItem& lhs, const QueueItem& rhs) { |
187 | 0 | return lhs.hybrid_time < rhs.hybrid_time || |
188 | 0 | (lhs.hybrid_time == rhs.hybrid_time && lhs.op_id < rhs.op_id); |
189 | 0 | } |
190 | | |
191 | 0 | friend bool operator>(const QueueItem& lhs, const QueueItem& rhs) { |
192 | 0 | return rhs < lhs; |
193 | 0 | } |
194 | | |
195 | 0 | friend std::ostream& operator<<(std::ostream& out, const QueueItem& item) { |
196 | 0 | return out << item.ToString(); |
197 | 0 | } |
198 | | }; |
199 | | // An ordered queue of times of tracked operations. |
200 | | std::deque<QueueItem> queue_; |
201 | | |
202 | | HybridTime last_replicated_ = HybridTime::kMin; |
203 | | |
204 | | // If we are a follower, this is the latest safe time sent by the leader to us. If we are the |
205 | | // leader, this is a safe time that gets updated every time the majority-replicated watermarks |
206 | | // change. |
207 | | HybridTime propagated_safe_time_ = HybridTime::kMin; |
208 | | // Special flag for RF==1 mode when propagated_safe_time_ can be not up-to-date. |
209 | | bool leader_only_mode_ = false; |
210 | | |
211 | | mutable SafeTimeWithSource max_safe_time_returned_with_lease_; |
212 | | mutable SafeTimeWithSource max_safe_time_returned_without_lease_; |
213 | | mutable SafeTimeWithSource max_safe_time_returned_for_follower_ { HybridTime::kMin }; |
214 | | |
215 | | std::unique_ptr<MvccOpTrace> op_trace_ GUARDED_BY(mutex_); |
216 | | }; |
217 | | |
218 | | } // namespace tablet |
219 | | } // namespace yb |
220 | | |
221 | | #endif // YB_TABLET_MVCC_H_ |