YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/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
1.76G
  HybridTime() noexcept : v(kInvalidHybridTimeValue) {}
96
97
698M
  HybridTime(MicrosTime micros, LogicalTimeComponent logical_value) {
98
698M
    v = (micros << kBitsForLogicalComponent) + logical_value;
99
698M
  }
100
101
  static inline HybridTime FromMicrosecondsAndLogicalValue(
102
474M
      MicrosTime micros, LogicalTimeComponent logical_value) {
103
474M
    return HybridTime(micros, logical_value);
104
474M
  }
105
106
192M
  static inline HybridTime FromMicros(MicrosTime micros) {
107
192M
    return HybridTime(micros, 0);
108
192M
  }
109
110
121M
  explicit HybridTime(uint64_t val) : v(val) {}
111
112
427M
  bool operator ==(const HybridTime &other) const {
113
427M
    return v == other.v;
114
427M
  }
115
16.1M
  bool operator !=(const HybridTime &other) const {
116
16.1M
    return v != other.v;
117
16.1M
  }
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
18.8M
  HybridTime Decremented() const {
140
18.8M
    if (v == 0) return *this;
141
18.8M
    return HybridTime(v - 1);
142
18.8M
  }
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.00M
  HybridTime AddMicroseconds(MicrosTime micros) const {
152
1.00M
    if (is_special()) return *this;
153
1.00M
    return HybridTime(v + (micros << kBitsForLogicalComponent));
154
1.00M
  }
155
156
506
  HybridTime AddMilliseconds(int64_t millis) const {
157
506
    return AddMicroseconds(millis * MonoTime::kMicrosecondsPerMillisecond);
158
506
  }
159
160
0
  HybridTime AddSeconds(int64_t seconds) const {
161
0
    return AddMicroseconds(seconds * MonoTime::kMicrosecondsPerSecond);
162
0
  }
163
164
968k
  HybridTime AddDelta(MonoDelta delta) const {
165
968k
    return AddMicroseconds(delta.ToMicroseconds());
166
968k
  }
167
168
  // Sets this hybrid time from 'value'
169
  CHECKED_STATUS FromUint64(uint64_t value);
170
171
19.8M
  static HybridTime FromPB(uint64_t value) {
172
18.9M
    return value ? HybridTime(value) : HybridTime();
173
19.8M
  }
174
175
26.7M
  HybridTimeRepr value() const { return v; }
176
177
  // Returns this HybridTime if valid, otherwise returns the one provided.
178
0
  HybridTime GetValueOr(const HybridTime& other) const {
179
0
    return is_valid() ? *this : other;
180
0
  }
181
182
1.00M
  bool is_special() const {
183
1.00M
    switch (v) {
184
1
      case kMinHybridTimeValue: FALLTHROUGH_INTENDED;
185
1
      case kMaxHybridTimeValue: FALLTHROUGH_INTENDED;
186
1
      case kInvalidHybridTimeValue:
187
1
        return true;
188
1.00M
      default:
189
1.00M
        return false;
190
1.00M
    }
191
1.00M
  }
192
193
209M
  bool operator <(const HybridTime& other) const {
194
209M
    return CompareTo(other) < 0;
195
209M
  }
196
197
84.2M
  bool operator >(const HybridTime& other) const {
198
84.2M
    return CompareTo(other) > 0;
199
84.2M
  }
200
201
46.3M
  bool operator <=(const HybridTime& other) const {
202
46.3M
    return CompareTo(other) <= 0;
203
46.3M
  }
204
205
371M
  bool operator >=(const HybridTime& other) const {
206
371M
    return CompareTo(other) >= 0;
207
371M
  }
208
209
  // Returns the physical value embedded in this HybridTime, in microseconds.
210
596M
  inline MicrosTime GetPhysicalValueMicros() const {
211
596M
    return v >> kBitsForLogicalComponent;
212
596M
  }
213
214
  MicrosTime CeilPhysicalValueMicros() const;
215
216
0
  inline int64_t PhysicalDiff(const HybridTime& other) const {
217
0
    return static_cast<int64_t>(GetPhysicalValueMicros() - other.GetPhysicalValueMicros());
218
0
  }
219
220
192M
  inline LogicalTimeComponent GetLogicalValue() const {
221
192M
    return v & kLogicalBitMask;
222
192M
  }
223
224
1.05G
  inline bool is_valid() const { return v != kInvalidHybridTimeValue; }
225
226
60.5M
  explicit operator bool() const { return is_valid(); }
227
228
317M
  void MakeAtLeast(HybridTime rhs) {
229
317M
    if (rhs.is_valid()) {
230
306M
      v = is_valid() ? std::max(v, rhs.v) : rhs.v;
231
306M
    }
232
317M
  }
233
234
19.0M
  void MakeAtMost(HybridTime rhs) {
235
19.0M
    if (rhs.is_valid()) {
236
18.4E
      v = is_valid() ? std::min(v, rhs.v) : rhs.v;
237
6.34M
    }
238
19.0M
  }
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
1.23G
inline int HybridTime::CompareTo(const HybridTime &other) const {
265
1.23G
  if (v < other.v) {
266
140M
    return -1;
267
1.09G
  } else if (v > other.v) {
268
793M
    return 1;
269
793M
  }
270
297M
  return 0;
271
297M
}
272
273
23.2k
inline std::ostream &operator <<(std::ostream &o, const HybridTime &hybridTime) {
274
23.2k
  return o << hybridTime.ToString();
275
23.2k
}
276
277
namespace hybrid_time_literals {
278
279
0
inline HybridTime operator "" _usec_ht(unsigned long long microseconds) { // NOLINT
280
0
  return HybridTime::FromMicros(microseconds);
281
0
}
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_