YugabyteDB (2.13.1.0-b60, 21121d69985fbf76aa6958d8f04a9bfa936293b5)

Coverage Report

Created: 2022-03-22 16:43

/Users/deen/code/yugabyte-db/src/yb/docdb/value.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/docdb/value.h"
15
16
#include <string>
17
18
#include "yb/common/table_properties_constants.h"
19
20
#include "yb/docdb/value_type.h"
21
22
#include "yb/gutil/strings/substitute.h"
23
24
#include "yb/util/fast_varint.h"
25
#include "yb/util/kv_util.h"
26
#include "yb/util/result.h"
27
28
namespace yb {
29
namespace docdb {
30
31
using std::string;
32
using strings::Substitute;
33
34
const MonoDelta ValueControlFields::kMaxTtl = common::kMaxTtl;
35
const MonoDelta ValueControlFields::kResetTtl = MonoDelta::FromNanoseconds(0);
36
const int64_t ValueControlFields::kInvalidUserTimestamp = common::kInvalidUserTimestamp;
37
38
template <typename T>
39
bool DecodeType(ValueType expected_value_type, const T& default_value, Slice* slice, T* val) {
40
  if (!slice->TryConsumeByte(static_cast<char>(expected_value_type))) {
41
    *val = default_value;
42
    return false;
43
  }
44
45
  return true;
46
}
47
48
namespace {
49
50
760M
Result<uint64_t> DecodeMergeFlags(Slice* slice) {
51
760M
  if (slice->TryConsumeByte(ValueTypeAsChar::kMergeFlags)) {
52
568
    return util::FastDecodeUnsignedVarInt(slice);
53
760M
  } else {
54
760M
    return 0;
55
760M
  }
56
760M
}
57
58
758M
Result<DocHybridTime> DecodeIntentDocHT(Slice* slice) {
59
758M
  if (slice->TryConsumeByte(ValueTypeAsChar::kHybridTime)) {
60
113M
    return DocHybridTime::DecodeFrom(slice);
61
644M
  } else {
62
644M
    return DocHybridTime::kInvalid;
63
644M
  }
64
758M
}
65
66
761M
Result<MonoDelta> DecodeTTL(Slice* slice) {
67
761M
  if (slice->TryConsumeByte(ValueTypeAsChar::kTtl)) {
68
101k
    return MonoDelta::FromMilliseconds(VERIFY_RESULT(util::FastDecodeSignedVarIntUnsafe(slice)));
69
761M
  } else {
70
761M
    return ValueControlFields::kMaxTtl;
71
761M
  }
72
761M
}
73
74
759M
Result<UserTimeMicros> DecodeUserTimestamp(Slice* slice) {
75
759M
  if (slice->TryConsumeByte(ValueTypeAsChar::kUserTimestamp)) {
76
359
    static constexpr int kBytesPerInt64 = sizeof(int64_t);
77
359
    if (slice->size() < kBytesPerInt64) {
78
0
      return STATUS(Corruption, Substitute(
79
0
          "Failed to decode TTL from value, size too small: $1, need $2",
80
0
          slice->size(), kBytesPerInt64));
81
0
    }
82
83
359
    slice->remove_prefix(kBytesPerInt64);
84
359
    return BigEndian::Load64(slice->data() - kBytesPerInt64);
85
759M
  } else {
86
759M
    return ValueControlFields::kInvalidUserTimestamp;
87
759M
  }
88
759M
}
89
90
/*Status Value::DecodeTTL(const rocksdb::Slice& rocksdb_value, MonoDelta* ttl) {
91
  rocksdb::Slice value_copy = rocksdb_value;
92
  uint64_t merge_flags;
93
  RETURN_NOT_OK(DecodeMergeFlags(&value_copy, &merge_flags));
94
  return DecodeTTL(&value_copy, ttl);
95
}
96
97
Result<UserTimeMicros> DecodeUserTimestamp(const Slice& rocksdb_value) {
98
  MonoDelta ttl;
99
  auto slice_copy = rocksdb_value;
100
  RETURN_NOT_OK(DecodeTTL(&slice_copy, &ttl));
101
  return DecodeUserTimestamp(&slice_copy, user_timestamp);
102
}*/
103
104
} // namespace
105
106
760M
Result<ValueControlFields> ValueControlFields::Decode(Slice* slice) {
107
760M
  Slice original = *slice;
108
760M
  ValueControlFields result = {
109
760M
    .merge_flags = VERIFY_RESULT_PREPEND(
110
0
        DecodeMergeFlags(slice),
111
0
        Format("Failed to decode merge flags in $0", original.ToDebugHexString())),
112
760M
    .intent_doc_ht = VERIFY_RESULT_PREPEND(
113
0
        DecodeIntentDocHT(slice),
114
0
        Format("Failed to decode intent ht in $0", original.ToDebugHexString())),
115
760M
    .ttl = VERIFY_RESULT_PREPEND(
116
0
        DecodeTTL(slice),
117
0
        Format("Failed to decode TTL in $0", original.ToDebugHexString())),
118
760M
    .user_timestamp = VERIFY_RESULT_PREPEND(
119
760M
        DecodeUserTimestamp(slice),
120
760M
        Format("Failed to decode user timestamp in $0", original.ToDebugHexString())),
121
760M
  };
122
0
  return result;
123
760M
}
124
125
71.6M
void ValueControlFields::AppendEncoded(std::string* out) const {
126
71.6M
  if (merge_flags) {
127
92
    out->push_back(ValueTypeAsChar::kMergeFlags);
128
92
    util::FastAppendUnsignedVarIntToStr(merge_flags, out);
129
92
  }
130
71.6M
  if (intent_doc_ht.is_valid()) {
131
0
    out->push_back(ValueTypeAsChar::kHybridTime);
132
0
    intent_doc_ht.AppendEncodedInDocDbFormat(out);
133
0
  }
134
71.6M
  if (!ttl.Equals(kMaxTtl)) {
135
482k
    out->push_back(ValueTypeAsChar::kTtl);
136
482k
    util::FastAppendSignedVarIntToBuffer(ttl.ToMilliseconds(), out);
137
482k
  }
138
71.6M
  if (user_timestamp != kInvalidUserTimestamp) {
139
152
    out->push_back(ValueTypeAsChar::kUserTimestamp);
140
152
    util::AppendBigEndianUInt64(user_timestamp, out);
141
152
  }
142
71.6M
}
143
144
184k
std::string ValueControlFields::ToString() const {
145
184k
  std::string result;
146
184k
  if (merge_flags) {
147
198
    result += Format("; merge flags: $0", merge_flags);
148
198
  }
149
184k
  if (intent_doc_ht.is_valid()) {
150
0
    result += Format("; intent doc ht: $0", intent_doc_ht);
151
0
  }
152
184k
  if (!ttl.Equals(kMaxTtl)) {
153
2.38k
    result += Format("; ttl: $0", ttl);
154
2.38k
  }
155
184k
  if (user_timestamp != kInvalidUserTimestamp) {
156
32
    result += Format("; user timestamp: $0", user_timestamp);
157
32
  }
158
184k
  return result;
159
184k
}
160
161
750M
Status Value::Decode(const Slice& rocksdb_value) {
162
750M
  Slice slice = rocksdb_value;
163
750M
  control_fields_ = VERIFY_RESULT(ValueControlFields::Decode(&slice));
164
750M
  RETURN_NOT_OK_PREPEND(
165
750M
      primitive_value_.DecodeFromValue(slice),
166
750M
      Format("Failed to decode value in $0", rocksdb_value.ToDebugHexString()));
167
750M
  return Status::OK();
168
750M
}
169
170
184k
std::string Value::ToString() const {
171
184k
  return primitive_value_.ToString() + control_fields_.ToString();
172
184k
}
173
174
0
std::string Value::DebugSliceToString(const Slice& encoded_value) {
175
0
  Value value;
176
0
  auto status = value.Decode(encoded_value);
177
0
  if (!status.ok()) {
178
0
    return status.ToString();
179
0
  }
180
181
0
  return value.ToString();
182
0
}
183
184
Result<ValueType> Value::DecodePrimitiveValueType(
185
7.51M
    const Slice& rocksdb_value) {
186
7.51M
  auto slice_copy = rocksdb_value;
187
7.51M
  RETURN_NOT_OK(ValueControlFields::Decode(&slice_copy));
188
7.51M
  return DecodeValueType(slice_copy);
189
7.51M
}
190
191
84
const Value& Value::Tombstone() {
192
84
  static const auto kTombstone = Value(PrimitiveValue::kTombstone);
193
84
  return kTombstone;
194
84
}
195
196
10
const string& Value::EncodedTombstone() {
197
10
  static const string kEncodedTombstone(1, ValueTypeAsChar::kTombstone);
198
10
  return kEncodedTombstone;
199
10
}
200
201
7.51M
Result<bool> Value::IsTombstoned(const Slice& slice) {
202
7.51M
  return VERIFY_RESULT(DecodePrimitiveValueType(slice)) == ValueType::kTombstone;
203
7.51M
}
204
205
}  // namespace docdb
206
}  // namespace yb