YugabyteDB (2.13.1.0-b60, 21121d69985fbf76aa6958d8f04a9bfa936293b5)

Coverage Report

Created: 2022-03-22 16:43

/Users/deen/code/yugabyte-db/src/yb/util/physical_time.cc
Line
Count
Source (jump to first uncovered line)
1
// Copyright (c) YugaByte, Inc.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
4
// in compliance with the License.  You may obtain a copy of the License at
5
//
6
// http://www.apache.org/licenses/LICENSE-2.0
7
//
8
// Unless required by applicable law or agreed to in writing, software distributed under the License
9
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
10
// or implied.  See the License for the specific language governing permissions and limitations
11
// under the License.
12
//
13
14
#include "yb/util/physical_time.h"
15
16
#if !defined(__APPLE__)
17
#include <sys/timex.h>
18
#endif
19
20
#include "yb/gutil/walltime.h"
21
22
#include "yb/util/atomic.h"
23
#include "yb/util/errno.h"
24
#include "yb/util/flag_tags.h"
25
#include "yb/util/format.h"
26
#include "yb/util/logging.h"
27
#include "yb/util/result.h"
28
#include "yb/util/status_format.h"
29
30
DEFINE_uint64(max_clock_sync_error_usec, 10 * 1000 * 1000,
31
              "Maximum allowed clock synchronization error as reported by NTP "
32
              "before the server will abort.");
33
DEFINE_bool(disable_clock_sync_error, true,
34
            "Whether or not we should keep running if we detect a clock synchronization issue.");
35
TAG_FLAG(disable_clock_sync_error, advanced);
36
TAG_FLAG(max_clock_sync_error_usec, advanced);
37
TAG_FLAG(max_clock_sync_error_usec, runtime);
38
39
DEFINE_uint64(max_clock_skew_usec, 500 * 1000,
40
              "Transaction read clock skew in usec. "
41
              "This is the maximum allowed time delta between servers of a single cluster.");
42
43
namespace yb {
44
45
namespace {
46
47
212M
Result<PhysicalTime> CheckClockSyncError(PhysicalTime time) {
48
212M
  if (!FLAGS_disable_clock_sync_error && 
time.max_error > FLAGS_max_clock_sync_error_usec0
) {
49
0
    return STATUS_FORMAT(ServiceUnavailable, "Error: Clock error was too high ($0 us), max "
50
0
                                             "allowed ($1 us).", time.max_error,
51
0
                                             FLAGS_max_clock_sync_error_usec);
52
0
  }
53
212M
  return time;
54
212M
}
55
56
class WallClockImpl : public PhysicalClock {
57
212M
  Result<PhysicalTime> Now() override {
58
212M
    return CheckClockSyncError(
59
212M
        { static_cast<MicrosTime>(GetCurrentTimeMicros()),
60
212M
          GetAtomicFlag(&FLAGS_max_clock_skew_usec) });
61
212M
  }
62
63
207M
  MicrosTime MaxGlobalTime(PhysicalTime time) override {
64
207M
    return time.time_point + GetAtomicFlag(&FLAGS_max_clock_skew_usec);
65
207M
  }
66
};
67
68
#if !defined(__APPLE__)
69
70
CHECKED_STATUS CallAdjTime(timex* tx) {
71
  // Set mode to 0 to query the current time.
72
  tx->modes = 0;
73
  int rc = ntp_adjtime(tx);
74
  if (rc == TIME_OK) {
75
    return Status::OK();
76
  }
77
78
  switch (rc) {
79
    case -1: // generic error
80
      return STATUS(ServiceUnavailable,
81
                    "Error reading clock. ntp_adjtime() failed",
82
                    ErrnoToString(errno));
83
    case TIME_ERROR:
84
      if (FLAGS_disable_clock_sync_error) {
85
        YB_LOG_EVERY_N_SECS(ERROR, 15) << "Clock unsynchronized, status: " << tx->status;
86
        return Status::OK();
87
      }
88
      return STATUS_FORMAT(
89
          ServiceUnavailable, "Error reading clock. Clock considered unsynchronized, status: $0",
90
          tx->status);
91
    default:
92
      // TODO what to do about leap seconds? see KUDU-146
93
      YB_LOG_FIRST_N(ERROR, 1) << "Server undergoing leap second. This may cause consistency "
94
                               << "issues (rc=" << rc << ")";
95
      return Status::OK();
96
  }
97
}
98
99
class AdjTimeClockImpl : public PhysicalClock {
100
  Result<PhysicalTime> Now() override {
101
    const MicrosTime kMicrosPerSec = 1000000;
102
103
    timex tx;
104
    RETURN_NOT_OK(CallAdjTime(&tx));
105
106
    if (tx.status & STA_NANO) {
107
      tx.time.tv_usec /= 1000;
108
    }
109
    DCHECK_LT(tx.time.tv_usec, 1000000);
110
111
    return CheckClockSyncError(
112
        { tx.time.tv_sec * kMicrosPerSec + tx.time.tv_usec,
113
          static_cast<yb::MicrosTime>(tx.maxerror) });
114
  }
115
116
  MicrosTime MaxGlobalTime(PhysicalTime time) override {
117
    return time.time_point + GetAtomicFlag(&FLAGS_max_clock_skew_usec);
118
  }
119
};
120
121
#endif
122
123
} // namespace
124
125
0
std::string PhysicalTime::ToString() const {
126
0
  return YB_STRUCT_TO_STRING(time_point, max_error);
127
0
}
128
129
26.7k
const PhysicalClockPtr& WallClock() {
130
26.7k
  static PhysicalClockPtr instance = std::make_shared<WallClockImpl>();
131
26.7k
  return instance;
132
26.7k
}
133
134
#if !defined(__APPLE__)
135
const PhysicalClockPtr& AdjTimeClock() {
136
  static PhysicalClockPtr instance = std::make_shared<AdjTimeClockImpl>();
137
  return instance;
138
}
139
#endif
140
141
6
Result<PhysicalTime> MockClock::Now() {
142
6
  return CheckClockSyncError(value_.load(boost::memory_order_acquire));
143
6
}
144
145
1
void MockClock::Set(const PhysicalTime& value) {
146
1
  value_.store(value, boost::memory_order_release);
147
1
}
148
149
4
PhysicalClockPtr MockClock::AsClock() {
150
4
  return PhysicalClockPtr(this, [](PhysicalClock*)
{}1
);
151
4
}
152
153
1
PhysicalClockProvider MockClock::AsProvider() {
154
1
  return std::bind(&MockClock::AsClock, this);
155
1
}
156
157
} // namespace yb