YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/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
33.3M
  bool empty() const {
67
33.3M
    return lease.GetPhysicalValueMicros() >= kMaxHybridTimePhysicalMicros;
68
33.3M
  }
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
13.3M
  HybridTime SafeTime(const FixedHybridTimeLease& ht_lease) const EXCLUDES(mutex_) {
140
13.3M
    return SafeTime(HybridTime::kMin /* min_allowed */, CoarseTimePoint::max() /* deadline */,
141
13.3M
                    ht_lease);
142
13.3M
  }
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
5
  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
7.50M
    friend bool operator==(const QueueItem& lhs, const QueueItem& rhs) {
183
7.50M
      return lhs.Eq(rhs);
184
7.50M
    }
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_