Coverage Report

Created: 2025-06-10 13:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/bitcoin/src/leveldb/db/memtable.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 "db/memtable.h"
6
#include "db/dbformat.h"
7
#include "leveldb/comparator.h"
8
#include "leveldb/env.h"
9
#include "leveldb/iterator.h"
10
#include "util/coding.h"
11
12
namespace leveldb {
13
14
149M
static Slice GetLengthPrefixedSlice(const char* data) {
15
149M
  uint32_t len;
16
149M
  const char* p = data;
17
149M
  p = GetVarint32Ptr(p, p + 5, &len);  // +5: we assume "p" is not corrupted
18
149M
  return Slice(p, len);
19
149M
}
20
21
MemTable::MemTable(const InternalKeyComparator& comparator)
22
33.3k
    : comparator_(comparator), refs_(0), table_(comparator_, &arena_) {}
23
24
33.3k
MemTable::~MemTable() { assert(refs_ == 0); }
  Branch (24:25): [True: 33.3k, False: 0]
25
26
2.32M
size_t MemTable::ApproximateMemoryUsage() { return arena_.MemoryUsage(); }
27
28
int MemTable::KeyComparator::operator()(const char* aptr,
29
74.6M
                                        const char* bptr) const {
30
  // Internal keys are encoded as length-prefixed strings.
31
74.6M
  Slice a = GetLengthPrefixedSlice(aptr);
32
74.6M
  Slice b = GetLengthPrefixedSlice(bptr);
33
74.6M
  return comparator.Compare(a, b);
34
74.6M
}
35
36
// Encode a suitable internal key target for "target" and return it.
37
// Uses *scratch as scratch space, and the returned pointer will point
38
// into this scratch space.
39
24.8k
static const char* EncodeKey(std::string* scratch, const Slice& target) {
40
24.8k
  scratch->clear();
41
24.8k
  PutVarint32(scratch, target.size());
42
24.8k
  scratch->append(target.data(), target.size());
43
24.8k
  return scratch->data();
44
24.8k
}
45
46
class MemTableIterator : public Iterator {
47
 public:
48
35.9k
  explicit MemTableIterator(MemTable::Table* table) : iter_(table) {}
49
50
  MemTableIterator(const MemTableIterator&) = delete;
51
  MemTableIterator& operator=(const MemTableIterator&) = delete;
52
53
35.9k
  ~MemTableIterator() override = default;
54
55
64.2k
  bool Valid() const override { return iter_.Valid(); }
56
24.8k
  void Seek(const Slice& k) override { iter_.Seek(EncodeKey(&tmp_, k)); }
57
11.1k
  void SeekToFirst() override { iter_.SeekToFirst(); }
58
0
  void SeekToLast() override { iter_.SeekToLast(); }
59
20.9k
  void Next() override { iter_.Next(); }
60
0
  void Prev() override { iter_.Prev(); }
61
34.0k
  Slice key() const override { return GetLengthPrefixedSlice(iter_.key()); }
62
27.4k
  Slice value() const override {
63
27.4k
    Slice key_slice = GetLengthPrefixedSlice(iter_.key());
64
27.4k
    return GetLengthPrefixedSlice(key_slice.data() + key_slice.size());
65
27.4k
  }
66
67
24
  Status status() const override { return Status::OK(); }
68
69
 private:
70
  MemTable::Table::Iterator iter_;
71
  std::string tmp_;  // For passing to EncodeKey
72
};
73
74
35.9k
Iterator* MemTable::NewIterator() { return new MemTableIterator(&table_); }
75
76
void MemTable::Add(SequenceNumber s, ValueType type, const Slice& key,
77
6.93M
                   const Slice& value) {
78
  // Format of an entry is concatenation of:
79
  //  key_size     : varint32 of internal_key.size()
80
  //  key bytes    : char[internal_key.size()]
81
  //  value_size   : varint32 of value.size()
82
  //  value bytes  : char[value.size()]
83
6.93M
  size_t key_size = key.size();
84
6.93M
  size_t val_size = value.size();
85
6.93M
  size_t internal_key_size = key_size + 8;
86
6.93M
  const size_t encoded_len = VarintLength(internal_key_size) +
87
6.93M
                             internal_key_size + VarintLength(val_size) +
88
6.93M
                             val_size;
89
6.93M
  char* buf = arena_.Allocate(encoded_len);
90
6.93M
  char* p = EncodeVarint32(buf, internal_key_size);
91
6.93M
  memcpy(p, key.data(), key_size);
92
6.93M
  p += key_size;
93
6.93M
  EncodeFixed64(p, (s << 8) | type);
94
6.93M
  p += 8;
95
6.93M
  p = EncodeVarint32(p, val_size);
96
6.93M
  memcpy(p, value.data(), val_size);
97
6.93M
  assert(p + val_size == buf + encoded_len);
  Branch (97:3): [True: 6.93M, False: 0]
98
6.93M
  table_.Insert(buf);
99
6.93M
}
100
101
5.07M
bool MemTable::Get(const LookupKey& key, std::string* value, Status* s) {
102
5.07M
  Slice memkey = key.memtable_key();
103
5.07M
  Table::Iterator iter(&table_);
104
5.07M
  iter.Seek(memkey.data());
105
5.07M
  if (iter.Valid()) {
  Branch (105:7): [True: 141k, False: 4.92M]
106
    // entry format is:
107
    //    klength  varint32
108
    //    userkey  char[klength]
109
    //    tag      uint64
110
    //    vlength  varint32
111
    //    value    char[vlength]
112
    // Check that it belongs to same user key.  We do not check the
113
    // sequence number since the Seek() call above should have skipped
114
    // all entries with overly large sequence numbers.
115
141k
    const char* entry = iter.key();
116
141k
    uint32_t key_length;
117
141k
    const char* key_ptr = GetVarint32Ptr(entry, entry + 5, &key_length);
118
141k
    if (comparator_.comparator.user_comparator()->Compare(
  Branch (118:9): [True: 21.2k, False: 120k]
119
141k
            Slice(key_ptr, key_length - 8), key.user_key()) == 0) {
120
      // Correct user key
121
21.2k
      const uint64_t tag = DecodeFixed64(key_ptr + key_length - 8);
122
21.2k
      switch (static_cast<ValueType>(tag & 0xff)) {
  Branch (122:15): [True: 0, False: 21.2k]
123
20.7k
        case kTypeValue: {
  Branch (123:9): [True: 20.7k, False: 526]
124
20.7k
          Slice v = GetLengthPrefixedSlice(key_ptr + key_length);
125
20.7k
          value->assign(v.data(), v.size());
126
20.7k
          return true;
127
0
        }
128
526
        case kTypeDeletion:
  Branch (128:9): [True: 526, False: 20.7k]
129
526
          *s = Status::NotFound(Slice());
130
526
          return true;
131
21.2k
      }
132
21.2k
    }
133
141k
  }
134
5.05M
  return false;
135
5.07M
}
136
137
}  // namespace leveldb