YugabyteDB (2.13.1.0-b60, 21121d69985fbf76aa6958d8f04a9bfa936293b5)

Coverage Report

Created: 2022-03-22 16:43

/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
188k
Result<std::string> DocDBKeyToDebugStr(Slice key_slice, StorageDbType db_type) {
38
188k
  auto key_type = GetKeyType(key_slice, db_type);
39
188k
  SubDocKey subdoc_key;
40
188k
  switch (key_type) {
41
2.47k
    case KeyType::kIntentKey:
42
2.47k
    {
43
2.47k
      auto decoded_intent_key = VERIFY_RESULT(DecodeIntentKey(key_slice));
44
2.47k
      RETURN_NOT_OK(subdoc_key.FullyDecodeFromKeyWithOptionalHybridTime(
45
2.47k
          decoded_intent_key.intent_prefix));
46
2.47k
      return subdoc_key.ToString(AutoDecodeKeys::kTrue) + " " +
47
2.47k
             ToString(decoded_intent_key.intent_types) + " " +
48
2.47k
             decoded_intent_key.doc_ht.ToString();
49
2.47k
    }
50
1.22k
    case KeyType::kReverseTxnKey:
51
1.22k
    {
52
1.22k
      RETURN_NOT_OK(key_slice.consume_byte(ValueTypeAsChar::kTransactionId));
53
1.22k
      auto transaction_id = VERIFY_RESULT(DecodeTransactionId(&key_slice));
54
1.22k
      auto doc_ht = VERIFY_RESULT_PREPEND(
55
1.22k
          DecodeInvertedDocHt(key_slice), Format("Reverse txn record for: $0", transaction_id));
56
0
      return Format("TXN REV $0 $1", transaction_id, doc_ht);
57
1.22k
    }
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
184k
    case KeyType::kPlainSubDocKey:
67
184k
      RETURN_NOT_OK_PREPEND(
68
184k
          subdoc_key.FullyDecodeFrom(key_slice),
69
184k
          "Error: failed decoding SubDocKey " +
70
184k
          FormatSliceAsStr(key_slice));
71
184k
      return subdoc_key.ToString(AutoDecodeKeys::kTrue);
72
4
    case KeyType::kExternalIntents:
73
4
    {
74
4
      RETURN_NOT_OK(key_slice.consume_byte(ValueTypeAsChar::kExternalTransactionId));
75
4
      auto transaction_id = VERIFY_RESULT(DecodeTransactionId(&key_slice));
76
4
      auto doc_hybrid_time = VERIFY_RESULT_PREPEND(
77
4
          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
4
    }
80
188k
  }
81
0
  return STATUS_FORMAT(Corruption, "Invalid KeyType: $0", yb::ToString(key_type));
82
188k
}
83
84
namespace {
85
86
185k
Result<std::string> DocDBValueToDebugStrInternal(Slice value_slice, KeyType key_type) {
87
185k
  std::string prefix;
88
185k
  if (key_type == KeyType::kIntentKey) {
89
1.24k
    auto txn_id_res = VERIFY_RESULT(DecodeTransactionIdFromIntentValue(&value_slice));
90
0
    prefix = Format("TransactionId($0) ", txn_id_res);
91
1.24k
    if (!value_slice.empty()) {
92
496
      RETURN_NOT_OK(value_slice.consume_byte(ValueTypeAsChar::kWriteId));
93
496
      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
496
      auto write_id = BigEndian::Load32(value_slice.data());
97
496
      value_slice.remove_prefix(sizeof(write_id));
98
496
      prefix += Format("WriteId($0) ", write_id);
99
496
    }
100
1.24k
  }
101
102
  // Empty values are allowed for weak intents.
103
185k
  if (!value_slice.empty() || 
key_type != KeyType::kIntentKey749
) {
104
184k
    Value v;
105
184k
    RETURN_NOT_OK_PREPEND(
106
184k
        v.Decode(value_slice),
107
184k
        Format("Error: failed to decode value $0", prefix));
108
184k
    return prefix + v.ToString();
109
184k
  } else {
110
749
    return prefix + "none";
111
749
  }
112
185k
}
113
114
}  // namespace
115
116
186k
Result<std::string> DocDBValueToDebugStr(KeyType key_type, Slice key, Slice value) {
117
186k
  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
1.22k
    case KeyType::kReverseTxnKey:
126
1.22k
      return DocDBKeyToDebugStr(value, StorageDbType::kIntents);
127
128
0
    case KeyType::kEmpty: FALLTHROUGH_INTENDED;
129
1.24k
    case KeyType::kIntentKey: FALLTHROUGH_INTENDED;
130
185k
    case KeyType::kPlainSubDocKey:
131
185k
      return DocDBValueToDebugStrInternal(value, key_type);
132
133
4
    case KeyType::kExternalIntents: {
134
4
      std::vector<std::string> intents;
135
4
      SubDocKey sub_doc_key;
136
4
      RETURN_NOT_OK(value.consume_byte(ValueTypeAsChar::kUuid));
137
4
      Uuid involved_tablet;
138
4
      RETURN_NOT_OK(involved_tablet.FromSlice(value.Prefix(kUuidSize)));
139
4
      value.remove_prefix(kUuidSize);
140
4
      RETURN_NOT_OK(value.consume_byte(ValueTypeAsChar::kExternalIntents));
141
12
      
for (;;)4
{
142
12
        auto len = VERIFY_RESULT(util::FastDecodeUnsignedVarInt(&value));
143
12
        if (len == 0) {
144
4
          break;
145
4
        }
146
8
        RETURN_NOT_OK(sub_doc_key.FullyDecodeFrom(value.Prefix(len), HybridTimeRequired::kFalse));
147
8
        value.remove_prefix(len);
148
8
        len = VERIFY_RESULT(util::FastDecodeUnsignedVarInt(&value));
149
0
        intents.push_back(Format(
150
8
            "$0 -> $1",
151
8
            sub_doc_key,
152
8
            VERIFY_RESULT(DocDBValueToDebugStrInternal(
153
8
                value.Prefix(len), KeyType::kPlainSubDocKey))));
154
0
        value.remove_prefix(len);
155
8
      }
156
4
      DCHECK(value.empty());
157
4
      return Format("IT $0 $1", involved_tablet.ToHexString(), intents);
158
4
    }
159
186k
  }
160
0
  FATAL_INVALID_ENUM_VALUE(KeyType, key_type);
161
0
}
162
163
}  // namespace docdb
164
}  // namespace yb