YugabyteDB (2.13.1.0-b60, 21121d69985fbf76aa6958d8f04a9bfa936293b5)

Coverage Report

Created: 2022-03-22 16:43

/Users/deen/code/yugabyte-db/src/yb/server/hybrid_clock.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
#ifndef YB_SERVER_HYBRID_CLOCK_H_
34
#define YB_SERVER_HYBRID_CLOCK_H_
35
36
#include <atomic>
37
#include <string>
38
#if !defined(__APPLE__)
39
#include <sys/timex.h>
40
#endif // !defined(__APPLE__)
41
42
#include <boost/atomic.hpp>
43
44
#include "yb/gutil/ref_counted.h"
45
#include "yb/server/clock.h"
46
#include "yb/util/locks.h"
47
#include "yb/util/physical_time.h"
48
49
namespace yb {
50
namespace server {
51
52
struct HybridClockComponents {
53
  // The last clock read/update, in microseconds.
54
  MicrosTime last_usec = 0;
55
56
  // The next logical value to be assigned to a hybrid time.
57
  uint64_t logical = 0;
58
59
0
  HybridClockComponents() noexcept {}
60
61
  HybridClockComponents(MicrosTime last_usec_, LogicalTimeComponent logical_)
62
      : last_usec(last_usec_),
63
312M
        logical(logical_) {
64
312M
  }
65
66
  HybridClockComponents(HybridClockComponents&& other) = default;
67
  HybridClockComponents(const HybridClockComponents& other) = default;
68
  HybridClockComponents& operator=(const HybridClockComponents& other) = default;
69
  HybridClockComponents& operator=(HybridClockComponents&& other) = default;
70
71
107M
  bool operator< (const HybridClockComponents& o) const {
72
107M
    return last_usec < o.last_usec || 
(59.4M
last_usec == o.last_usec59.4M
&&
logical < o.logical14.1M
);
73
107M
  }
74
75
0
  bool operator<= (const HybridClockComponents& o) const {
76
0
    return last_usec < o.last_usec || (last_usec == o.last_usec && logical <= o.logical);
77
0
  }
78
79
  void HandleLogicalComponentOverflow();
80
81
  std::string ToString() const;
82
};
83
84
std::ostream& operator<<(std::ostream& out, const HybridClockComponents& components);
85
86
// The HybridTime clock.
87
//
88
// HybridTime should not be used on a distributed cluster running on OS X hosts,
89
// since NTP clock error is not available.
90
class HybridClock : public Clock {
91
 public:
92
  HybridClock();
93
  explicit HybridClock(PhysicalClockPtr clock);
94
  explicit HybridClock(const std::string& time_source);
95
96
  CHECKED_STATUS Init() override;
97
98
  HybridTimeRange NowRange() override;
99
100
  // Updates the clock with a hybrid_time originating on another machine.
101
  void Update(const HybridTime& to_update) override;
102
103
  void RegisterMetrics(const scoped_refptr<MetricEntity>& metric_entity) override;
104
105
  // Obtains the hybrid_time corresponding to the current time and the associated
106
  // error in micros. This may fail if the clock is unsynchronized or synchronized
107
  // but the error is too high and, since we can't do anything about it,
108
  // LOG(FATAL)'s in that case.
109
  void NowWithError(HybridTime* hybrid_time, uint64_t* max_error_usec);
110
111
  // Static encoding/decoding methods for hybrid_times. Public mostly
112
  // for testing/debugging purposes.
113
114
  // Returns the logical value embedded in 'hybrid_time'
115
  static LogicalTimeComponent GetLogicalValue(const HybridTime& hybrid_time);
116
117
  // Returns the physical value embedded in 'hybrid_time', in microseconds.
118
  static MicrosTime GetPhysicalValueMicros(const HybridTime& hybrid_time);
119
120
  // Returns the physical value embedded in 'hybrid_time', in nanoseconds.
121
  static uint64_t GetPhysicalValueNanos(const HybridTime& hybrid_time);
122
123
  // Obtains a new HybridTime with the logical value zeroed out.
124
  static HybridTime HybridTimeFromMicroseconds(uint64_t micros);
125
126
  // Obtains a new HybridTime that embeds both the physical and logical values.
127
  static HybridTime HybridTimeFromMicrosecondsAndLogicalValue(
128
      MicrosTime micros, LogicalTimeComponent logical_value);
129
130
  // Creates a new hybrid_time whose physical time is GetPhysicalValue(original) +
131
  // 'micros_to_add' and which retains the same logical value.
132
  static HybridTime AddPhysicalTimeToHybridTime(const HybridTime& original,
133
                                                const MonoDelta& to_add);
134
135
  // Given two hybrid times, determines whether the delta between end and begin them is higher,
136
  // lower or equal to the given delta and returns 1, -1 and 0 respectively. Note that if end <
137
  // begin we return -1.
138
  static int CompareHybridClocksToDelta(const HybridTime& begin, const HybridTime& end,
139
                                        const MonoDelta& delta);
140
141
  static void RegisterProvider(std::string name, PhysicalClockProvider provider);
142
143
  // Enables check whether clock skew within configured bounds.
144
  static void EnableClockSkewControl();
145
146
5.25M
  const PhysicalClockPtr& physical_clock() { return clock_; }
147
148
 private:
149
  enum State {
150
    kNotInitialized,
151
    kInitialized
152
  };
153
154
  // Used to get the hybrid_time for metrics.
155
  uint64_t NowForMetrics();
156
157
  // Used to get the current error, for metrics.
158
  uint64_t ErrorForMetrics();
159
160
  // Used to get the current error, for metrics.
161
  int64_t SkewForMetrics();
162
163
  PhysicalClockPtr clock_;
164
  boost::atomic<HybridClockComponents> components_{HybridClockComponents(0, 0)};
165
  State state_ = kNotInitialized;
166
167
  // Clock metrics are set to detach to their last value. This means
168
  // that, during our destructor, we'll need to access other class members
169
  // declared above this. Hence, this member must be declared last.
170
  std::shared_ptr<void> metric_detacher_;
171
};
172
173
}  // namespace server
174
}  // namespace yb
175
176
#endif /* YB_SERVER_HYBRID_CLOCK_H_ */