YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/docdb/kv_debug.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
#include "yb/docdb/kv_debug.h"
14
15
#include <string>
16
17
#include "yb/common/common.pb.h"
18
19
#include "yb/docdb/doc_key.h"
20
#include "yb/docdb/doc_kv_util.h"
21
#include "yb/docdb/docdb-internal.h"
22
#include "yb/docdb/docdb_types.h"
23
#include "yb/docdb/intent.h"
24
#include "yb/docdb/value.h"
25
#include "yb/docdb/value_type.h"
26
27
#include "yb/gutil/casts.h"
28
29
#include "yb/util/bytes_formatter.h"
30
#include "yb/util/fast_varint.h"
31
#include "yb/util/result.h"
32
#include "yb/util/status_format.h"
33
34
namespace yb {
35
namespace docdb {
36
37
180k
Result<std::string> DocDBKeyToDebugStr(Slice key_slice, StorageDbType db_type) {
38
180k
  auto key_type = GetKeyType(key_slice, db_type);
39
180k
  SubDocKey subdoc_key;
40
180k
  switch (key_type) {
41
0
    case KeyType::kIntentKey:
42
0
    {
43
0
      auto decoded_intent_key = VERIFY_RESULT(DecodeIntentKey(key_slice));
44
0
      RETURN_NOT_OK(subdoc_key.FullyDecodeFromKeyWithOptionalHybridTime(
45
0
          decoded_intent_key.intent_prefix));
46
0
      return subdoc_key.ToString(AutoDecodeKeys::kTrue) + " " +
47
0
             ToString(decoded_intent_key.intent_types) + " " +
48
0
             decoded_intent_key.doc_ht.ToString();
49
0
    }
50
0
    case KeyType::kReverseTxnKey:
51
0
    {
52
0
      RETURN_NOT_OK(key_slice.consume_byte(ValueTypeAsChar::kTransactionId));
53
0
      auto transaction_id = VERIFY_RESULT(DecodeTransactionId(&key_slice));
54
0
      auto doc_ht = VERIFY_RESULT_PREPEND(
55
0
          DecodeInvertedDocHt(key_slice), Format("Reverse txn record for: $0", transaction_id));
56
0
      return Format("TXN REV $0 $1", transaction_id, doc_ht);
57
0
    }
58
0
    case KeyType::kTransactionMetadata:
59
0
    {
60
0
      RETURN_NOT_OK(key_slice.consume_byte(ValueTypeAsChar::kTransactionId));
61
0
      auto transaction_id = DecodeTransactionId(&key_slice);
62
0
      RETURN_NOT_OK(transaction_id);
63
0
      return Format("TXN META $0", *transaction_id);
64
0
    }
65
0
    case KeyType::kEmpty: FALLTHROUGH_INTENDED;
66
180k
    case KeyType::kPlainSubDocKey:
67
180k
      RETURN_NOT_OK_PREPEND(
68
180k
          subdoc_key.FullyDecodeFrom(key_slice),
69
180k
          "Error: failed decoding SubDocKey " +
70
180k
          FormatSliceAsStr(key_slice));
71
180k
      return subdoc_key.ToString(AutoDecodeKeys::kTrue);
72
0
    case KeyType::kExternalIntents:
73
0
    {
74
0
      RETURN_NOT_OK(key_slice.consume_byte(ValueTypeAsChar::kExternalTransactionId));
75
0
      auto transaction_id = VERIFY_RESULT(DecodeTransactionId(&key_slice));
76
0
      auto doc_hybrid_time = VERIFY_RESULT_PREPEND(
77
0
          DecodeInvertedDocHt(key_slice), Format("External txn record for: $0", transaction_id));
78
0
      return Format("TXN EXT $0 $1", transaction_id, doc_hybrid_time);
79
0
    }
80
0
  }
81
0
  return STATUS_FORMAT(Corruption, "Invalid KeyType: $0", yb::ToString(key_type));
82
0
}
83
84
namespace {
85
86
180k
Result<std::string> DocDBValueToDebugStrInternal(Slice value_slice, KeyType key_type) {
87
180k
  std::string prefix;
88
180k
  if (key_type == KeyType::kIntentKey) {
89
0
    auto txn_id_res = VERIFY_RESULT(DecodeTransactionIdFromIntentValue(&value_slice));
90
0
    prefix = Format("TransactionId($0) ", txn_id_res);
91
0
    if (!value_slice.empty()) {
92
0
      RETURN_NOT_OK(value_slice.consume_byte(ValueTypeAsChar::kWriteId));
93
0
      if (value_slice.size() < sizeof(IntraTxnWriteId)) {
94
0
        return STATUS_FORMAT(Corruption, "Not enough bytes for write id: $0", value_slice.size());
95
0
      }
96
0
      auto write_id = BigEndian::Load32(value_slice.data());
97
0
      value_slice.remove_prefix(sizeof(write_id));
98
0
      prefix += Format("WriteId($0) ", write_id);
99
0
    }
100
0
  }
101
102
  // Empty values are allowed for weak intents.
103
180k
  if (!value_slice.empty() || key_type != KeyType::kIntentKey) {
104
180k
    Value v;
105
180k
    RETURN_NOT_OK_PREPEND(
106
180k
        v.Decode(value_slice),
107
180k
        Format("Error: failed to decode value $0", prefix));
108
180k
    return prefix + v.ToString();
109
0
  } else {
110
0
    return prefix + "none";
111
0
  }
112
180k
}
113
114
}  // namespace
115
116
180k
Result<std::string> DocDBValueToDebugStr(KeyType key_type, Slice key, Slice value) {
117
180k
  switch (key_type) {
118
0
    case KeyType::kTransactionMetadata: {
119
0
      TransactionMetadataPB metadata_pb;
120
0
      if (!metadata_pb.ParseFromArray(value.cdata(), narrow_cast<int>(value.size()))) {
121
0
        return STATUS_FORMAT(Corruption, "Bad metadata: $0", value.ToDebugHexString());
122
0
      }
123
0
      return ToString(VERIFY_RESULT(TransactionMetadata::FromPB(metadata_pb)));
124
0
    }
125
0
    case KeyType::kReverseTxnKey:
126
0
      return DocDBKeyToDebugStr(value, StorageDbType::kIntents);
127
128
0
    case KeyType::kEmpty: FALLTHROUGH_INTENDED;
129
0
    case KeyType::kIntentKey: FALLTHROUGH_INTENDED;
130
180k
    case KeyType::kPlainSubDocKey:
131
180k
      return DocDBValueToDebugStrInternal(value, key_type);
132
133
0
    case KeyType::kExternalIntents: {
134
0
      std::vector<std::string> intents;
135
0
      SubDocKey sub_doc_key;
136
0
      RETURN_NOT_OK(value.consume_byte(ValueTypeAsChar::kUuid));
137
0
      Uuid involved_tablet;
138
0
      RETURN_NOT_OK(involved_tablet.FromSlice(value.Prefix(kUuidSize)));
139
0
      value.remove_prefix(kUuidSize);
140
0
      RETURN_NOT_OK(value.consume_byte(ValueTypeAsChar::kExternalIntents));
141
0
      for (;;) {
142
0
        auto len = VERIFY_RESULT(util::FastDecodeUnsignedVarInt(&value));
143
0
        if (len == 0) {
144
0
          break;
145
0
        }
146
0
        RETURN_NOT_OK(sub_doc_key.FullyDecodeFrom(value.Prefix(len), HybridTimeRequired::kFalse));
147
0
        value.remove_prefix(len);
148
0
        len = VERIFY_RESULT(util::FastDecodeUnsignedVarInt(&value));
149
0
        intents.push_back(Format(
150
0
            "$0 -> $1",
151
0
            sub_doc_key,
152
0
            VERIFY_RESULT(DocDBValueToDebugStrInternal(
153
0
                value.Prefix(len), KeyType::kPlainSubDocKey))));
154
0
        value.remove_prefix(len);
155
0
      }
156
0
      DCHECK(value.empty());
157
0
      return Format("IT $0 $1", involved_tablet.ToHexString(), intents);
158
0
    }
159
0
  }
160
0
  FATAL_INVALID_ENUM_VALUE(KeyType, key_type);
161
0
}
162
163
}  // namespace docdb
164
}  // namespace yb