YugabyteDB (2.13.1.0-b60, 21121d69985fbf76aa6958d8f04a9bfa936293b5)

Coverage Report

Created: 2022-03-22 16:43

/Users/deen/code/yugabyte-db/src/yb/common/hybrid_time.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
33
// Portions Copyright (c) YugaByte, Inc.
34
35
#ifndef YB_COMMON_HYBRID_TIME_H_
36
#define YB_COMMON_HYBRID_TIME_H_
37
38
#include <inttypes.h>
39
40
#include <limits>
41
#include <string>
42
43
#include "yb/util/status_fwd.h"
44
#include "yb/util/faststring.h"
45
#include "yb/util/monotime.h"
46
#include "yb/util/physical_time.h"
47
48
namespace yb {
49
50
class Slice;
51
52
// An alias for the raw in-memory representation of a HybridTime.
53
using HybridTimeRepr = uint64_t;
54
55
// An alias for the in-memory representation of the logical component of a HybridTime.
56
using LogicalTimeComponent = uint32_t;
57
58
constexpr HybridTimeRepr kMinHybridTimeValue = std::numeric_limits<HybridTimeRepr>::min();
59
constexpr HybridTimeRepr kMaxHybridTimeValue = std::numeric_limits<HybridTimeRepr>::max();
60
constexpr HybridTimeRepr kInitialHybridTimeValue = kMinHybridTimeValue + 1;
61
constexpr HybridTimeRepr kInvalidHybridTimeValue = kMaxHybridTimeValue - 1;
62
63
// A transaction hybrid time generated by a Clock.
64
class HybridTime {
65
 public:
66
  // TODO: replace all mentions of this with HybridTimeRepr itself and deprecate val_type.
67
  using val_type = HybridTimeRepr;
68
69
  // Left-shifting the microseconds timestamp 12 bits gives us 12 bits for the logical value and
70
  // should still keep accurate microseconds time until 2100+.
71
  static constexpr int kBitsForLogicalComponent = 12;
72
73
  // This mask gives us back the logical bits.
74
  static constexpr HybridTimeRepr kLogicalBitMask = (1 << kBitsForLogicalComponent) - 1;
75
76
  // An initial transaction hybrid time, higher than min so that we can have
77
  // a hybrid time guaranteed to be lower than all generated hybrid times.
78
  static const HybridTime kInitial;
79
80
  // An invalid transaction hybrid time -- HybridTime types initialize to this variable.
81
  static const HybridTime kInvalid;
82
83
  // The maximum hybrid time.
84
  static const HybridTime kMax;
85
86
  // The minimum hybrid time.
87
  static const HybridTime kMin;
88
89
  // Hybrid times are converted to debug strings as <this_string_constant>(<hybrid_time_value>).
90
  static const char* const kHybridTimeDebugStrPrefix;
91
92
  // ----------------------------------------------------------------------------------------------
93
  // Constructors / static factories
94
95
4.94G
  HybridTime() noexcept : v(kInvalidHybridTimeValue) {}
96
97
1.85G
  HybridTime(MicrosTime micros, LogicalTimeComponent logical_value) {
98
1.85G
    v = (micros << kBitsForLogicalComponent) + logical_value;
99
1.85G
  }
100
101
  static inline HybridTime FromMicrosecondsAndLogicalValue(
102
1.38G
      MicrosTime micros, LogicalTimeComponent logical_value) {
103
1.38G
    return HybridTime(micros, logical_value);
104
1.38G
  }
105
106
403M
  static inline HybridTime FromMicros(MicrosTime micros) {
107
403M
    return HybridTime(micros, 0);
108
403M
  }
109
110
258M
  explicit HybridTime(uint64_t val) : v(val) {}
111
112
1.23G
  bool operator ==(const HybridTime &other) const {
113
1.23G
    return v == other.v;
114
1.23G
  }
115
47.4M
  bool operator !=(const HybridTime &other) const {
116
47.4M
    return v != other.v;
117
47.4M
  }
118
119
  // Decode a hybrid time from the given input slice.
120
  // Mutates the slice to point after the decoded hybrid time.
121
  // Returns true upon success.
122
  bool DecodeFrom(Slice *input);
123
124
  // Append the hybrid time to the given buffer.
125
  void AppendAsUint64To(faststring *dst) const;
126
  void AppendAsUint64To(std::string* dst) const;
127
128
  int CompareTo(const HybridTime &other) const;
129
130
  std::string ToString() const;
131
132
  std::string ToDebugString() const;
133
134
  // Returns this hybrid time as an uint64_t
135
  uint64_t ToUint64() const;
136
137
  // Return the highest value of a HybridTime that is lower than this. If called on kMin, returns
138
  // kMin itself, because it cannot be decremented.
139
29.1M
  HybridTime Decremented() const {
140
29.1M
    if (v == 0) 
return *this0
;
141
29.1M
    return HybridTime(v - 1);
142
29.1M
  }
143
144
  // Returns the hybrid time value by the smallest possible amount. For invalid / max hybrid time,
145
  // returns the unmodified value.
146
0
  HybridTime Incremented() const {
147
0
    if (v >= kInvalidHybridTimeValue) return *this;
148
0
    return HybridTime(v + 1);
149
0
  }
150
151
1.72M
  HybridTime AddMicroseconds(MicrosTime micros) const {
152
1.72M
    if (is_special()) 
return *this1
;
153
1.72M
    return HybridTime(v + (micros << kBitsForLogicalComponent));
154
1.72M
  }
155
156
529
  HybridTime AddMilliseconds(int64_t millis) const {
157
529
    return AddMicroseconds(millis * MonoTime::kMicrosecondsPerMillisecond);
158
529
  }
159
160
353
  HybridTime AddSeconds(int64_t seconds) const {
161
353
    return AddMicroseconds(seconds * MonoTime::kMicrosecondsPerSecond);
162
353
  }
163
164
1.67M
  HybridTime AddDelta(MonoDelta delta) const {
165
1.67M
    return AddMicroseconds(delta.ToMicroseconds());
166
1.67M
  }
167
168
  // Sets this hybrid time from 'value'
169
  CHECKED_STATUS FromUint64(uint64_t value);
170
171
48.8M
  static HybridTime FromPB(uint64_t value) {
172
48.8M
    return value ? 
HybridTime(value)46.2M
:
HybridTime()2.58M
;
173
48.8M
  }
174
175
48.8M
  HybridTimeRepr value() const { return v; }
176
177
  // Returns this HybridTime if valid, otherwise returns the one provided.
178
74
  HybridTime GetValueOr(const HybridTime& other) const {
179
74
    return is_valid() ? 
*this59
:
other15
;
180
74
  }
181
182
1.72M
  bool is_special() const {
183
1.72M
    switch (v) {
184
1
      case kMinHybridTimeValue: FALLTHROUGH_INTENDED;
185
2
      case kMaxHybridTimeValue: FALLTHROUGH_INTENDED;
186
3
      case kInvalidHybridTimeValue:
187
3
        return true;
188
1.72M
      default:
189
1.72M
        return false;
190
1.72M
    }
191
1.72M
  }
192
193
435M
  bool operator <(const HybridTime& other) const {
194
435M
    return CompareTo(other) < 0;
195
435M
  }
196
197
170M
  bool operator >(const HybridTime& other) const {
198
170M
    return CompareTo(other) > 0;
199
170M
  }
200
201
97.0M
  bool operator <=(const HybridTime& other) const {
202
97.0M
    return CompareTo(other) <= 0;
203
97.0M
  }
204
205
1.03G
  bool operator >=(const HybridTime& other) const {
206
1.03G
    return CompareTo(other) >= 0;
207
1.03G
  }
208
209
  // Returns the physical value embedded in this HybridTime, in microseconds.
210
1.55G
  inline MicrosTime GetPhysicalValueMicros() const {
211
1.55G
    return v >> kBitsForLogicalComponent;
212
1.55G
  }
213
214
  MicrosTime CeilPhysicalValueMicros() const;
215
216
32
  inline int64_t PhysicalDiff(const HybridTime& other) const {
217
32
    return static_cast<int64_t>(GetPhysicalValueMicros() - other.GetPhysicalValueMicros());
218
32
  }
219
220
550M
  inline LogicalTimeComponent GetLogicalValue() const {
221
550M
    return v & kLogicalBitMask;
222
550M
  }
223
224
2.75G
  inline bool is_valid() const { return v != kInvalidHybridTimeValue; }
225
226
140M
  explicit operator bool() const { return is_valid(); }
227
228
893M
  void MakeAtLeast(HybridTime rhs) {
229
893M
    if (rhs.is_valid()) {
230
872M
      v = is_valid() ? 
std::max(v, rhs.v)871M
:
rhs.v599k
;
231
872M
    }
232
893M
  }
233
234
34.6M
  void MakeAtMost(HybridTime rhs) {
235
34.6M
    if (rhs.is_valid()) {
236
18.4E
      v = 
is_valid()11.5M
?
std::min(v, rhs.v)11.5M
: rhs.v;
237
11.5M
    }
238
34.6M
  }
239
240
  // Set mode for HybridTime::ToString, in case of true hybrid time is rendered as human readable.
241
  // It is slower than default one.
242
  static void TEST_SetPrettyToString(bool flag);
243
244
  // Acceptable system time formats:
245
  //  1. HybridTime Timestamp (in Microseconds)
246
  //  2. Interval
247
  //  3. Human readable string
248
  static Result<HybridTime> ParseHybridTime(std::string input);
249
250
 private:
251
252
  HybridTimeRepr v;
253
};
254
255
// The maximum microsecond value possible so that the corresponding HybridTime can still fit into a
256
// uint64_t.
257
constexpr MicrosTime kMaxHybridTimePhysicalMicros{
258
    kMaxHybridTimeValue >> HybridTime::kBitsForLogicalComponent};
259
260
class faststring;
261
262
class Slice;
263
264
3.26G
inline int HybridTime::CompareTo(const HybridTime &other) const {
265
3.26G
  if (v < other.v) {
266
388M
    return -1;
267
2.87G
  } else if (v > other.v) {
268
2.08G
    return 1;
269
2.08G
  }
270
792M
  return 0;
271
3.26G
}
272
273
121k
inline std::ostream &operator <<(std::ostream &o, const HybridTime &hybridTime) {
274
121k
  return o << hybridTime.ToString();
275
121k
}
276
277
namespace hybrid_time_literals {
278
279
inline HybridTime operator "" _usec_ht(unsigned long long microseconds) { // NOLINT
280
  return HybridTime::FromMicros(microseconds);
281
}
282
283
} // namespace hybrid_time_literals
284
285
using hybrid_time_literals::operator"" _usec_ht;
286
287
}  // namespace yb
288
289
#endif  // YB_COMMON_HYBRID_TIME_H_