/Users/deen/code/yugabyte-db/src/yb/common/hybrid_time.cc
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 | | #include "yb/common/hybrid_time.h" |
34 | | |
35 | | #include <atomic> |
36 | | |
37 | | #include <boost/algorithm/string/trim.hpp> |
38 | | #include <boost/date_time/c_local_time_adjustor.hpp> |
39 | | #include <boost/date_time/posix_time/time_formatters.hpp> |
40 | | |
41 | | #include "yb/util/date_time.h" |
42 | | #include "yb/util/memcmpable_varint.h" |
43 | | #include "yb/util/result.h" |
44 | | |
45 | | using std::string; |
46 | | |
47 | | namespace yb { |
48 | | |
49 | | namespace { |
50 | | |
51 | | std::atomic<bool> pretty_to_string_mode_{false}; |
52 | | |
53 | | } |
54 | | |
55 | | const HybridTime HybridTime::kMin(kMinHybridTimeValue); |
56 | | const HybridTime HybridTime::kMax(kMaxHybridTimeValue); |
57 | | const HybridTime HybridTime::kInitial(kInitialHybridTimeValue); |
58 | | const HybridTime HybridTime::kInvalid(kInvalidHybridTimeValue); |
59 | | |
60 | 0 | bool HybridTime::DecodeFrom(Slice *input) { |
61 | 0 | return GetMemcmpableVarint64(input, &v).ok(); |
62 | 0 | } |
63 | | |
64 | 0 | void HybridTime::AppendAsUint64To(faststring *dst) const { |
65 | 0 | PutMemcmpableVarint64(dst, v); |
66 | 0 | } |
67 | | |
68 | 0 | void HybridTime::AppendAsUint64To(std::string* dst) const { |
69 | 0 | PutMemcmpableVarint64(dst, v); |
70 | 0 | } |
71 | | |
72 | 1.84M | string HybridTime::ToString() const { |
73 | 1.84M | switch (v) { |
74 | 38.9k | case kInvalidHybridTimeValue: |
75 | 38.9k | return "<invalid>"; |
76 | 47.4k | case kMaxHybridTimeValue: |
77 | 47.4k | return "<max>"; |
78 | 2.16k | case kMinHybridTimeValue: |
79 | 2.16k | return "<min>"; |
80 | 7.74k | case kInitialHybridTimeValue: |
81 | 7.74k | return "<initial>"; |
82 | 1.75M | default: |
83 | 1.75M | auto logical = GetLogicalValue(); |
84 | 1.75M | if (!pretty_to_string_mode_.load(std::memory_order_acquire)) { |
85 | 326k | if (logical) { |
86 | 229k | return Format("{ physical: $0 logical: $1 }", GetPhysicalValueMicros(), logical); |
87 | 229k | } else { |
88 | 96.9k | return Format("{ physical: $0 }", GetPhysicalValueMicros()); |
89 | 96.9k | } |
90 | 326k | } |
91 | | // When time is rendered with separate minutes and seconds it is easier to understand that |
92 | | // one value is 2 seconds later that another one. |
93 | | // With default rendering difference appears in the middle of 10+ digits number. |
94 | 1.42M | boost::posix_time::ptime start(boost::gregorian::date(1970, 1, 1)); |
95 | 1.42M | auto usec = GetPhysicalValueMicros(); |
96 | 1.42M | auto utc_time = start + boost::posix_time::microseconds(usec); |
97 | 1.42M | auto local_time = |
98 | 1.42M | boost::date_time::c_local_adjustor<boost::posix_time::ptime>::utc_to_local(utc_time); |
99 | 1.42M | auto date = local_time.date(); |
100 | 1.42M | auto time_of_day = local_time.time_of_day(); |
101 | 1.42M | auto days = (boost::posix_time::ptime(date) - start).hours() / 24; |
102 | 1.42M | auto time_of_day_str = boost::posix_time::to_simple_string(time_of_day); |
103 | 1.42M | if (logical) { |
104 | 68.8k | return Format("{ days: $0 time: $1 logical: $2 }", days, time_of_day_str, logical); |
105 | 1.35M | } else { |
106 | 1.35M | return Format("{ days: $0 time: $1 }", days, time_of_day_str); |
107 | 1.35M | } |
108 | 1.84M | } |
109 | 1.84M | } |
110 | | |
111 | 14.8k | void HybridTime::TEST_SetPrettyToString(bool flag) { |
112 | 14.8k | pretty_to_string_mode_ = flag; |
113 | 14.8k | } |
114 | | |
115 | 233k | string HybridTime::ToDebugString() const { |
116 | 233k | return kHybridTimeDebugStrPrefix + ToString(); |
117 | 233k | } |
118 | | |
119 | 189M | uint64_t HybridTime::ToUint64() const { |
120 | 189M | return v; |
121 | 189M | } |
122 | | |
123 | 371k | Status HybridTime::FromUint64(uint64_t value) { |
124 | 371k | v = value; |
125 | 371k | return Status::OK(); |
126 | 371k | } |
127 | | |
128 | 73.4M | MicrosTime HybridTime::CeilPhysicalValueMicros() const { |
129 | 73.4M | if (*this == kMin) { |
130 | 71.7M | return 0; |
131 | 71.7M | } |
132 | 1.66M | auto result = GetPhysicalValueMicros(); |
133 | 1.66M | if (GetLogicalValue()) { |
134 | 32.5k | ++result; |
135 | 32.5k | } |
136 | 1.66M | return result; |
137 | 73.4M | } |
138 | | |
139 | 10 | Result<HybridTime> HybridTime::ParseHybridTime(std::string input) { |
140 | 10 | boost::trim(input); |
141 | | |
142 | 10 | HybridTime ht; |
143 | | // The HybridTime is given in microseconds and will contain 16 chars. |
144 | 10 | static const std::regex int_regex("[0-9]{16}"); |
145 | 10 | if (std::regex_match(input, int_regex)) { |
146 | 0 | return HybridTime::FromMicros(std::stoul(input)); |
147 | 0 | } |
148 | 10 | if (!input.empty() && input[0] == '-') { |
149 | 0 | return HybridTime::FromMicros( |
150 | 0 | VERIFY_RESULT(WallClock()->Now()).time_point - |
151 | 0 | VERIFY_RESULT(DateTime::IntervalFromString(input.substr(1))).ToMicroseconds()); |
152 | 0 | } |
153 | 10 | auto ts = |
154 | 10 | VERIFY_RESULT(DateTime::TimestampFromString(input, DateTime::HumanReadableInputFormat)); |
155 | 0 | return HybridTime::FromMicros(ts.ToInt64()); |
156 | 10 | } |
157 | | |
158 | | const char* const HybridTime::kHybridTimeDebugStrPrefix = "HT"; |
159 | | |
160 | | } // namespace yb |