YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/util/uuid.h
Line
Count
Source
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
#ifndef YB_UTIL_UUID_H
15
#define YB_UTIL_UUID_H
16
17
#include <uuid/uuid.h>
18
19
#include <array>
20
#include <random>
21
22
#include <boost/uuid/uuid.hpp>
23
24
#include "yb/util/status_fwd.h"
25
26
namespace yb {
27
28
class Slice;
29
30
constexpr size_t kUuidSize = 16;
31
constexpr int kShaDigestSize = 5;
32
// Generic class that UUID type and uses the boost implementation underneath.
33
// Implements a custom comparator that follows the cassandra implementation.
34
class Uuid {
35
 public:
36
  static constexpr size_t kUuidMsbSize = 8;
37
  static constexpr size_t kUuidLsbSize = kUuidSize - kUuidMsbSize;
38
  static constexpr size_t kTimeUUIDMacOffset = 10;
39
  static constexpr size_t kTimeUUIDTotalMacBytes = 6;
40
41
  // The timestamp is a 60-bit value.  For UUID version 1, this is
42
  // represented by Coordinated Universal Time (UTC) as a count of 100-
43
  // nanosecond intervals since 00:00:00.00, 15 October 1582 (the date of
44
  // Gregorian reform to the Christian calendar).
45
  static constexpr int64_t kGregorianOffsetMillis = -12219292800000;
46
47
  static constexpr int64_t kMillisPerHundredNanos = 10000;
48
49
  Uuid();
50
51
217M
  explicit Uuid(const boost::uuids::uuid& boost_uuid) : boost_uuid_(boost_uuid) {}
52
53
  explicit Uuid(const uuid_t copy);
54
55
  Uuid(const Uuid& other);
56
57
  // Generate a new boost uuid
58
  static Uuid Generate();
59
  static Uuid Generate(std::mt19937_64* rng);
60
  static Uuid Nil();
61
62
  static Result<Uuid> FromString(const std::string& strval);
63
  // name is used in error message in case of failure.
64
  static Result<Uuid> FullyDecode(const Slice& slice, const char* name = nullptr);
65
  static Uuid TryFullyDecode(const Slice& slice);
66
  static Result<Uuid> Decode(Slice* slice, const char* name = nullptr);
67
68
  // Fills in strval with the string representation of the UUID.
69
  CHECKED_STATUS ToString(std::string* strval) const;
70
71
  // Returns string representation the UUID. This method doesn't return a
72
  // Status for usecases in the code where we don't support returning a status.
73
  std::string ToString() const;
74
75
  // Fills in the given string with the raw bytes for the appropriate address in network byte order.
76
  void ToBytes(std::string* bytes) const;
77
  void ToBytes(std::array<uint8_t, kUuidSize>* out) const;
78
  Slice AsSlice() const;
79
80
  // Encodes the UUID into the time comparable uuid to be stored in RocksDB.
81
  void EncodeToComparable(uint8_t* output) const;
82
  void EncodeToComparable(std::string* bytes) const;
83
84
  // Given a string holding the raw bytes in network byte order, it builds the appropriate
85
  // UUID object.
86
  CHECKED_STATUS FromBytes(const std::string& bytes);
87
88
  // Given a string representation of uuid in hex where the bytes are in host byte order, build
89
  // an appropriate UUID object.
90
  CHECKED_STATUS FromHexString(const std::string& hex_string);
91
92
  std::string ToHexString() const;
93
94
  // Decodes the Comparable UUID bytes into a lexical UUID.
95
  CHECKED_STATUS DecodeFromComparable(const std::string& bytes);
96
97
  // Give a slice holding raw bytes in network byte order, build the appropriate UUID
98
  // object. If size_hint is specified, it indicates the number of bytes to decode from the slice.
99
  CHECKED_STATUS FromSlice(const Slice& slice, size_t size_hint = 0);
100
101
  CHECKED_STATUS DecodeFromComparableSlice(const Slice& slice, size_t size_hint = 0);
102
103
  // For time UUIDs only.
104
  // This function takes a time UUID and generates a SHA hash for the MAC address bits.
105
  // This is done because it is not secure to generate UUIDs directly from the MAC address.
106
  CHECKED_STATUS HashMACAddress();
107
108
  // Builds the smallest TimeUUID that willl compare as larger than any TimeUUID with the given
109
  // timestamp.
110
  CHECKED_STATUS MaxFromUnixTimestamp(int64_t timestamp_ms);
111
112
  // Builds the largest TimeUUID that willl compare as smaller than any TimeUUID with the given
113
  // timestamp.
114
  CHECKED_STATUS MinFromUnixTimestamp(int64_t timestamp_ms);
115
116
  // This function takes a 64 bit integer that represents the timestamp, that is basically the
117
  // number of milliseconds since epoch.
118
  CHECKED_STATUS ToUnixTimestamp(int64_t *timestamp_ms) const;
119
120
  CHECKED_STATUS IsTimeUuid() const;
121
122
275M
  bool IsNil() const {
123
275M
    return boost_uuid_.is_nil();
124
275M
  }
125
126
652
  bool operator==(const Uuid& other) const {
127
652
    return (boost_uuid_ == other.boost_uuid_);
128
652
  }
129
130
1
  bool operator!=(const Uuid& other) const {
131
1
    return !(*this == other);
132
1
  }
133
134
  // A custom comparator that compares UUID v1 according to their timestamp.
135
  // If not, it will compare the version first and then lexicographically.
136
  bool operator<(const Uuid& other) const;
137
138
760
  bool operator>(const Uuid& other) const {
139
760
    return (other < *this);
140
760
  }
141
142
2
  bool operator<=(const Uuid& other) const {
143
2
    return !(other < *this);
144
2
  }
145
146
1
  bool operator>=(const Uuid& other) const {
147
1
    return !(*this < other);
148
1
  }
149
150
86.0M
  Uuid& operator=(const Uuid& other) {
151
86.0M
    boost_uuid_ = other.boost_uuid_;
152
86.0M
    return *this;
153
86.0M
  }
154
155
74.4M
  const boost::uuids::uuid& impl() const {
156
74.4M
    return boost_uuid_;
157
74.4M
  }
158
159
36.8M
  uint8_t* data() {
160
36.8M
    return boost_uuid_.data;
161
36.8M
  }
162
163
4.80M
  const uint8_t* data() const {
164
4.80M
    return boost_uuid_.data;
165
4.80M
  }
166
167
3.27M
  size_t size() const {
168
3.27M
    return boost_uuid_.size();
169
3.27M
  }
170
171
14
  auto version() const {
172
14
    return boost_uuid_.version();
173
14
  }
174
175
 private:
176
  boost::uuids::uuid boost_uuid_;
177
178
  // Encodes the MSB of the uuid into a timestamp based byte stream as follows.
179
  // [Timestamp Low (32 bits)][Timestamp Mid (16 bits)][Version (4 bits)][Timestamp High (12 bits)]
180
  // into
181
  // [Version (4 bits)][Timestamp High (12 bits)][Timestamp Mid (16 bits)][Timestamp Low (32 bits)]
182
  // So that their lexical comparison of the bytes will result in time based comparison.
183
1.08k
  void ToTimestampBytes(uint8_t* output) const {
184
1.08k
    output[0] = boost_uuid_.data[6];
185
1.08k
    output[1] = boost_uuid_.data[7];
186
1.08k
    output[2] = boost_uuid_.data[4];
187
1.08k
    output[3] = boost_uuid_.data[5];
188
1.08k
    output[4] = boost_uuid_.data[0];
189
1.08k
    output[5] = boost_uuid_.data[1];
190
1.08k
    output[6] = boost_uuid_.data[2];
191
1.08k
    output[7] = boost_uuid_.data[3];
192
1.08k
  }
193
194
  // Reverse the timestamp based byte stream into regular UUID style MSB.
195
  // See comments for toTimestampBytes function for more detail.
196
6.92k
  void FromTimestampBytes(const uint8_t* input) {
197
6.92k
    uint8_t tmp[kUuidMsbSize];
198
6.92k
    tmp[0] = input[4];
199
6.92k
    tmp[1] = input[5];
200
6.92k
    tmp[2] = input[6];
201
6.92k
    tmp[3] = input[7];
202
6.92k
    tmp[4] = input[2];
203
6.92k
    tmp[5] = input[3];
204
6.92k
    tmp[6] = input[0];
205
6.92k
    tmp[7] = input[1];
206
6.92k
    memcpy(boost_uuid_.data, tmp, kUuidMsbSize);
207
6.92k
  }
208
209
  // Utility method used by minTimeuuid and maxTimeuuid.
210
  // Set the timestamp bytes of a (time)uuid to the specified value (in hundred nanos).
211
  // Also ensure that the uuid is a version 1 uuid (i.e. timeuuid) by setting the version.
212
  void FromTimestamp(int64_t ts_hnanos);
213
214
  // Encodes the MSB of the uuid into a version based byte stream as follows.
215
  // Used for non-time-based UUIDs, i.e. not version 1.
216
  // [Timestamp Low (32 bits)][Timestamp Mid (16 bits)][Version (4 bits)][Timestamp High (12 bits)]
217
  // into
218
  // [Version (4 bits)][Timestamp Low (32 bits)][Timestamp Mid (16 bits)][Timestamp High (12 bits)]
219
  // So that their lexical comparison of the bytes will result in version based comparison.
220
16.3M
  void ToVersionFirstBytes(uint8_t* output) const {
221
16.3M
    output[0] = (uint8_t) ( ((boost_uuid_.data[6] & 0xF0))
222
16.3M
                          | ((boost_uuid_.data[0] & 0xF0) >> 4));
223
16.3M
    output[1] = (uint8_t) ( ((boost_uuid_.data[0] & 0x0F) << 4)
224
16.3M
                          | ((boost_uuid_.data[1] & 0xF0) >> 4));
225
16.3M
    output[2] = (uint8_t) ( ((boost_uuid_.data[1] & 0x0F) << 4)
226
16.3M
                          | ((boost_uuid_.data[2] & 0xF0) >> 4));
227
16.3M
    output[3] = (uint8_t) ( ((boost_uuid_.data[2] & 0x0F) << 4)
228
16.3M
                          | ((boost_uuid_.data[3] & 0xF0) >> 4));
229
16.3M
    output[4] = (uint8_t) ( ((boost_uuid_.data[3] & 0x0F) << 4)
230
16.3M
                          | ((boost_uuid_.data[4] & 0xF0) >> 4));
231
16.3M
    output[5] = (uint8_t) ( ((boost_uuid_.data[4] & 0x0F) << 4)
232
16.3M
                          | ((boost_uuid_.data[5] & 0xF0) >> 4));
233
16.3M
    output[6] = (uint8_t) ( ((boost_uuid_.data[5] & 0x0F) << 4)
234
16.3M
                          | ((boost_uuid_.data[6] & 0x0F)));
235
16.3M
    output[7] = boost_uuid_.data[7];
236
16.3M
  }
237
238
  // Reverse the version based byte stream into regular UUID style MSB.
239
  // See comments for toVersionFirstBytes function for more detail.
240
87.0M
  void FromVersionFirstBytes(const uint8_t* input) {
241
87.0M
    uint8_t tmp[kUuidMsbSize];
242
87.0M
    tmp[0] = (uint8_t)  ( ((input[0] & 0x0F) << 4)
243
87.0M
                        | ((input[1] & 0xF0) >> 4));
244
87.0M
    tmp[1] = (uint8_t)  ( ((input[1] & 0x0F) << 4)
245
87.0M
                        | ((input[2] & 0xF0) >> 4));
246
87.0M
    tmp[2] = (uint8_t)  ( ((input[2] & 0x0F) << 4)
247
87.0M
                        | ((input[3] & 0xF0) >> 4));
248
87.0M
    tmp[3] = (uint8_t)  ( ((input[3] & 0x0F) << 4)
249
87.0M
                        | ((input[4] & 0xF0) >> 4));
250
87.0M
    tmp[4] = (uint8_t)  ( ((input[4] & 0x0F) << 4)
251
87.0M
                        | ((input[5] & 0xF0) >> 4));
252
87.0M
    tmp[5] = (uint8_t)  ( ((input[5] & 0x0F) << 4)
253
87.0M
                        | ((input[6] & 0xF0) >> 4));
254
87.0M
    tmp[6] = (uint8_t)  ( ((input[0] & 0xF0))
255
87.0M
                        | ((input[6] & 0x0F)));
256
87.0M
    tmp[7] = input[7];
257
87.0M
    memcpy(boost_uuid_.data, tmp, kUuidMsbSize);
258
87.0M
  }
259
260
};
261
262
} // namespace yb
263
264
#endif // YB_UTIL_UUID_H