YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/docdb/key_bytes.h
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
#ifndef YB_DOCDB_KEY_BYTES_H_
15
#define YB_DOCDB_KEY_BYTES_H_
16
17
#include <string>
18
19
#include "yb/common/common_fwd.h"
20
21
#include "yb/util/kv_util.h"
22
#include "yb/util/slice.h"
23
24
namespace yb {
25
namespace docdb {
26
27
enum class ValueType;
28
29
// Represents part (usually a prefix) of a RocksDB key. Has convenience methods for composing keys
30
// used in our DocDB layer -> RocksDB mapping.
31
class KeyBytes {
32
 public:
33
229M
  KeyBytes() = default;
34
24.8k
  explicit KeyBytes(const std::string& data) : data_(data) {}
35
271M
  explicit KeyBytes(const Slice& slice) : data_(slice) {}
36
37
311M
  KeyBytes(const KeyBytes& rhs) = default;
38
25.3M
  KeyBytes& operator=(const KeyBytes& rhs) = default;
39
16.1M
  KeyBytes(KeyBytes&& rhs) = default;
40
9.04M
  KeyBytes& operator=(KeyBytes&& rhs) = default;
41
42
0
  KeyBytes(const Slice& slice, char suffix) {
43
0
    data_.reserve(slice.size() + 1);
44
0
    data_.append(slice.cdata(), slice.size());
45
0
    data_.push_back(suffix);
46
0
  }
47
48
23.0M
  KeyBytes(const Slice& slice1, const Slice& slice2) {
49
23.0M
    data_.reserve(slice1.size() + slice2.size());
50
23.0M
    data_.append(slice1.cdata(), slice1.size());
51
23.0M
    data_.append(slice2.cdata(), slice2.size());
52
23.0M
  }
53
54
399M
  void Reserve(size_t len) {
55
399M
    data_.reserve(len);
56
399M
  }
57
58
  std::string ToString() const;
59
60
3.72G
  bool empty() const {
61
3.72G
    return data_.empty();
62
3.72G
  }
63
64
25.7M
  std::string ToStringBuffer() const {
65
25.7M
    return data().ToStringBuffer();
66
25.7M
  }
67
68
160M
  const KeyBuffer& data() const {
69
160M
    return data_;
70
160M
  }
71
72
0
  void Append(const KeyBytes& other) {
73
0
    data_.append(other.data_);
74
0
  }
75
76
64.5M
  void AppendRawBytes(const char* raw_bytes, size_t n) {
77
64.5M
    data_.append(raw_bytes, n);
78
64.5M
  }
79
80
591M
  void AppendRawBytes(const Slice& slice) {
81
591M
    data_.append(slice);
82
591M
  }
83
84
2.53M
  void AppendRawBytes(const std::string& data) {
85
2.53M
    data_.append(data);
86
2.53M
  }
87
88
  void AppendValueType(ValueType value_type);
89
90
  void AppendValueTypeBeforeGroupEnd(ValueType value_type);
91
92
  void AppendString(const std::string& raw_string);
93
94
  void AppendDescendingString(const std::string &raw_string);
95
96
24.0k
  void AppendDecimal(const std::string& encoded_decimal_str) {
97
24.0k
    data_.append(encoded_decimal_str);
98
24.0k
  }
99
100
124
  void AppendDecimalDescending(const std::string& encoded_decimal_str) {
101
    // Flipping all the bits negates the decimal number this string represents.
102
103
    // 0 is a special case because the first two bits are always 10.
104
124
    if ((unsigned char)encoded_decimal_str[0] == 128) {
105
1
      data_.push_back(encoded_decimal_str[0]);
106
1
      return;
107
1
    }
108
109
123
    data_.reserve(data_.size() + encoded_decimal_str.size());
110
7.32k
    for (auto c : encoded_decimal_str) {
111
7.32k
      data_.push_back(~c);
112
7.32k
    }
113
123
  }
114
115
23.0k
  void AppendVarInt(const std::string& encoded_varint_str) {
116
23.0k
    data_.append(encoded_varint_str);
117
23.0k
  }
118
119
  void AppendUInt64AsVarInt(uint64_t value);
120
121
122
  void AppendVarIntDescending(const std::string& encoded_varint_str) {
122
    // Flipping all the bits negates the varint number this string represents.
123
124
    // 0 is a special case because the first two bits are always 10.
125
122
    if (static_cast<uint8_t>(encoded_varint_str[0]) == 128) {
126
1
      data_.push_back(encoded_varint_str[0]);
127
1
      return;
128
1
    }
129
130
3.65k
    for (auto c : encoded_varint_str) {
131
3.65k
      data_.push_back(~c);
132
3.65k
    }
133
121
  }
134
135
1.50M
  void AppendInt64(int64_t x) {
136
1.50M
    util::AppendInt64ToKey(x, &data_);
137
1.50M
  }
138
139
  void AppendUInt64(uint64_t x);
140
141
  void AppendDescendingUInt64(uint64_t x);
142
143
41.0M
  void AppendInt32(int32_t x) {
144
41.0M
    util::AppendInt32ToKey(x, &data_);
145
41.0M
  }
146
147
  void AppendUInt32(uint32_t x);
148
149
  void AppendDescendingUInt32(uint32_t x);
150
151
  template <class EnumBitSet>
152
0
  void AppendIntentTypeSet(EnumBitSet intent_type_set) {
153
0
    data_.push_back(static_cast<char>(intent_type_set.ToUIntPtr()));
154
0
  }
155
156
698k
  void AppendDescendingInt64(int64_t x) {
157
    // AppendInt64ToKey flips the highest bit. We flip all the x's bits before calling
158
    // AppendInt64ToKey, but the order of the operations (FLIP_HIGHEST_BIT and FLIP_ALL_BITS)
159
    // doesn't matter because they are commutative operations.
160
    // Example for an 8-bit integer (works the same for 64-bit integers):
161
    //    normal encoding (flip first bit)
162
    //    -128 = 0x80 -> 0x00
163
    //    -1   = 0xFF -> 0x7F
164
    //    0    = 0x00 -> 0x80
165
    //    127  = 0x7F -> 0xFF
166
    //    (everything compares correctly)
167
    //
168
    //    descending encoding (flip all bits, then first, or flip first bit, then all, doesn't
169
    //    matter which)
170
    //    -128 = 0x80 -> 0x7F -> 0xFF
171
    //    -1   = 0xFF -> 0x00 -> 0x80
172
    //    0    = 0x00 -> 0xFF -> 0x7F
173
    //    127  = 0x7F -> 0x80 -> 0x00
174
698k
    util::AppendInt64ToKey(~x, &data_);
175
698k
  }
176
177
5.38k
  void AppendDescendingInt32(int32_t x) {
178
5.38k
    util::AppendInt32ToKey(~x, &data_);
179
5.38k
  }
180
181
351
  void AppendUint8(uint8_t x) {
182
351
    data_.push_back(static_cast<char>(x));
183
351
  }
184
185
  void AppendUInt16(uint16_t x);
186
187
  void AppendHybridTime(const DocHybridTime& hybrid_time);
188
189
  void AppendColumnId(ColumnId column_id);
190
191
420
  void AppendDescendingFloat(float x) {
192
420
    util::AppendFloatToKey(x, &data_, /* descending */ true);
193
420
  }
194
195
253
  void AppendFloat(float x) {
196
253
    util::AppendFloatToKey(x, &data_);
197
253
  }
198
199
420
  void AppendDescendingDouble(double x) {
200
420
    util::AppendDoubleToKey(x, &data_, /* descending */ true);
201
420
  }
202
203
524k
  void AppendDouble(double x) {
204
524k
    util::AppendDoubleToKey(x, &data_);
205
524k
  }
206
207
  void AppendGroupEnd();
208
209
  void RemoveValueTypeSuffix(ValueType value_type);
210
211
669M
  size_t size() const { return data_.size(); }
212
213
31.8k
  bool IsPrefixOf(const rocksdb::Slice& slice) const {
214
31.8k
    return slice.starts_with(data_.AsSlice());
215
31.8k
  }
216
217
909M
  rocksdb::Slice AsSlice() const { return data_.AsSlice(); }
218
219
1.07G
  operator Slice() const { return data_.AsSlice(); }
220
221
105M
  void Reset(const Slice& slice) {
222
105M
    data_.assign(slice.cdata(), slice.size());
223
105M
  }
224
225
0
  void ResetRawBytes(const char* raw_bytes, size_t n) {
226
0
    data_.assign(raw_bytes, n);
227
0
  }
228
229
151M
  void Clear() {
230
151M
    data_.clear();
231
151M
  }
232
233
120k
  int CompareTo(const KeyBytes& other) const {
234
120k
    return data_.AsSlice().compare(other.data_.AsSlice());
235
120k
  }
236
237
39.9M
  int CompareTo(const Slice& other) const {
238
39.9M
    return data_.AsSlice().compare(other);
239
39.9M
  }
240
241
  // This can be used to e.g. move the internal state of KeyBytes somewhere else, including a
242
  // string field in a protobuf, without copying the bytes.
243
25.2k
  KeyBuffer* mutable_data() {
244
25.2k
    return &data_;
245
25.2k
  }
246
247
  void Truncate(size_t new_size);
248
249
  void RemoveLastByte();
250
251
 private:
252
  KeyBuffer data_;
253
};
254
255
94.9k
inline bool operator<(const KeyBytes& lhs, const KeyBytes& rhs) {
256
94.9k
  return lhs.data() < rhs.data();
257
94.9k
}
258
259
166
inline bool operator>=(const KeyBytes& lhs, const KeyBytes& rhs) {
260
166
  return !(lhs < rhs);
261
166
}
262
263
47.2k
inline bool operator>(const KeyBytes& lhs, const KeyBytes& rhs) {
264
47.2k
  return rhs < lhs;
265
47.2k
}
266
267
190
inline bool operator<=(const KeyBytes& lhs, const KeyBytes& rhs) {
268
190
  return !(rhs < lhs);
269
190
}
270
271
242M
inline bool operator==(const KeyBytes& lhs, const KeyBytes& rhs) {
272
242M
  return lhs.AsSlice() == rhs.AsSlice();
273
242M
}
274
275
0
inline bool operator!=(const KeyBytes& lhs, const KeyBytes& rhs) {
276
0
  return lhs.AsSlice() != rhs.AsSlice();
277
0
}
278
279
void AppendDocHybridTime(const DocHybridTime& time, KeyBytes* key);
280
void AppendHash(uint16_t hash, KeyBytes* key);
281
282
}  // namespace docdb
283
}  // namespace yb
284
285
#endif  // YB_DOCDB_KEY_BYTES_H_