Coverage Report

Created: 2026-06-18 19:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/root/bitcoin/src/leveldb/table/format.cc
Line
Count
Source
1
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
2
// Use of this source code is governed by a BSD-style license that can be
3
// found in the LICENSE file. See the AUTHORS file for names of contributors.
4
5
#include "table/format.h"
6
7
#include "leveldb/env.h"
8
#include "port/port.h"
9
#include "table/block.h"
10
#include "util/coding.h"
11
#include "util/crc32c.h"
12
13
namespace leveldb {
14
15
23.1k
void BlockHandle::EncodeTo(std::string* dst) const {
16
  // Sanity check that all fields have been set
17
23.1k
  assert(offset_ != ~static_cast<uint64_t>(0));
  Branch (17:3): [True: 23.1k, False: 0]
18
23.1k
  assert(size_ != ~static_cast<uint64_t>(0));
  Branch (18:3): [True: 23.1k, False: 0]
19
23.1k
  PutVarint64(dst, offset_);
20
23.1k
  PutVarint64(dst, size_);
21
23.1k
}
22
23
3.33k
Status BlockHandle::DecodeFrom(Slice* input) {
24
3.33k
  if (GetVarint64(input, &offset_) && GetVarint64(input, &size_)) {
  Branch (24:7): [True: 3.33k, False: 0]
  Branch (24:39): [True: 3.33k, False: 0]
25
3.33k
    return Status::OK();
26
3.33k
  } else {
27
0
    return Status::Corruption("bad block handle");
28
0
  }
29
3.33k
}
30
31
1.11k
void Footer::EncodeTo(std::string* dst) const {
32
1.11k
  const size_t original_size = dst->size();
33
1.11k
  metaindex_handle_.EncodeTo(dst);
34
1.11k
  index_handle_.EncodeTo(dst);
35
1.11k
  dst->resize(2 * BlockHandle::kMaxEncodedLength);  // Padding
36
1.11k
  PutFixed32(dst, static_cast<uint32_t>(kTableMagicNumber & 0xffffffffu));
37
1.11k
  PutFixed32(dst, static_cast<uint32_t>(kTableMagicNumber >> 32));
38
1.11k
  assert(dst->size() == original_size + kEncodedLength);
  Branch (38:3): [True: 1.11k, False: 0]
39
1.11k
  (void)original_size;  // Disable unused variable warning.
40
1.11k
}
41
42
1.11k
Status Footer::DecodeFrom(Slice* input) {
43
1.11k
  const char* magic_ptr = input->data() + kEncodedLength - 8;
44
1.11k
  const uint32_t magic_lo = DecodeFixed32(magic_ptr);
45
1.11k
  const uint32_t magic_hi = DecodeFixed32(magic_ptr + 4);
46
1.11k
  const uint64_t magic = ((static_cast<uint64_t>(magic_hi) << 32) |
47
1.11k
                          (static_cast<uint64_t>(magic_lo)));
48
1.11k
  if (magic != kTableMagicNumber) {
  Branch (48:7): [True: 0, False: 1.11k]
49
0
    return Status::Corruption("not an sstable (bad magic number)");
50
0
  }
51
52
1.11k
  Status result = metaindex_handle_.DecodeFrom(input);
53
1.11k
  if (result.ok()) {
  Branch (53:7): [True: 1.11k, False: 0]
54
1.11k
    result = index_handle_.DecodeFrom(input);
55
1.11k
  }
56
1.11k
  if (result.ok()) {
  Branch (56:7): [True: 1.11k, False: 0]
57
    // We skip over any leftover data (just padding for now) in "input"
58
1.11k
    const char* end = magic_ptr + 8;
59
1.11k
    *input = Slice(end, input->data() + input->size() - end);
60
1.11k
  }
61
1.11k
  return result;
62
1.11k
}
63
64
Status ReadBlock(RandomAccessFile* file, const ReadOptions& options,
65
3.33k
                 const BlockHandle& handle, BlockContents* result) {
66
3.33k
  result->data = Slice();
67
3.33k
  result->cachable = false;
68
3.33k
  result->heap_allocated = false;
69
70
  // Read the block contents as well as the type/crc footer.
71
  // See table_builder.cc for the code that built this structure.
72
3.33k
  size_t n = static_cast<size_t>(handle.size());
73
3.33k
  char* buf = new char[n + kBlockTrailerSize];
74
3.33k
  Slice contents;
75
3.33k
  Status s = file->Read(handle.offset(), n + kBlockTrailerSize, &contents, buf);
76
3.33k
  if (!s.ok()) {
  Branch (76:7): [True: 0, False: 3.33k]
77
0
    delete[] buf;
78
0
    return s;
79
0
  }
80
3.33k
  if (contents.size() != n + kBlockTrailerSize) {
  Branch (80:7): [True: 0, False: 3.33k]
81
0
    delete[] buf;
82
0
    return Status::Corruption("truncated block read", file->GetName());
83
0
  }
84
85
  // Check the crc of the type and the block contents
86
3.33k
  const char* data = contents.data();  // Pointer to where Read put the data
87
3.33k
  if (options.verify_checksums) {
  Branch (87:7): [True: 3.33k, False: 0]
88
3.33k
    const uint32_t crc = crc32c::Unmask(DecodeFixed32(data + n + 1));
89
3.33k
    const uint32_t actual = crc32c::Value(data, n + 1);
90
3.33k
    if (actual != crc) {
  Branch (90:9): [True: 0, False: 3.33k]
91
0
      delete[] buf;
92
0
      s = Status::Corruption("block checksum mismatch", file->GetName());
93
0
      return s;
94
0
    }
95
3.33k
  }
96
97
3.33k
  switch (data[n]) {
98
3.33k
    case kNoCompression:
  Branch (98:5): [True: 3.33k, False: 0]
99
3.33k
      if (data != buf) {
  Branch (99:11): [True: 0, False: 3.33k]
100
        // File implementation gave us pointer to some other data.
101
        // Use it directly under the assumption that it will be live
102
        // while the file is open.
103
0
        delete[] buf;
104
0
        result->data = Slice(data, n);
105
0
        result->heap_allocated = false;
106
0
        result->cachable = false;  // Do not double-cache
107
3.33k
      } else {
108
3.33k
        result->data = Slice(buf, n);
109
3.33k
        result->heap_allocated = true;
110
3.33k
        result->cachable = true;
111
3.33k
      }
112
113
      // Ok
114
3.33k
      break;
115
0
    case kSnappyCompression: {
  Branch (115:5): [True: 0, False: 3.33k]
116
0
      size_t ulength = 0;
117
0
      if (!port::Snappy_GetUncompressedLength(data, n, &ulength)) {
  Branch (117:11): [True: 0, False: 0]
118
0
        delete[] buf;
119
0
        return Status::Corruption("corrupted compressed block contents", file->GetName());
120
0
      }
121
0
      char* ubuf = new char[ulength];
122
0
      if (!port::Snappy_Uncompress(data, n, ubuf)) {
  Branch (122:11): [True: 0, False: 0]
123
0
        delete[] buf;
124
0
        delete[] ubuf;
125
0
        return Status::Corruption("corrupted compressed block contents", file->GetName());
126
0
      }
127
0
      delete[] buf;
128
0
      result->data = Slice(ubuf, ulength);
129
0
      result->heap_allocated = true;
130
0
      result->cachable = true;
131
0
      break;
132
0
    }
133
0
    default:
  Branch (133:5): [True: 0, False: 3.33k]
134
0
      delete[] buf;
135
0
      return Status::Corruption("bad block type", file->GetName());
136
3.33k
  }
137
138
3.33k
  return Status::OK();
139
3.33k
}
140
141
}  // namespace leveldb