Coverage Report

Created: 2026-06-01 18:35

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
27.7k
static Slice GetLengthPrefixedSlice(const char* data) {
15
27.7k
  uint32_t len;
16
27.7k
  const char* p = data;
17
27.7k
  p = GetVarint32Ptr(p, p + 5, &len);  // +5: we assume "p" is not corrupted
18
27.7k
  return Slice(p, len);
19
27.7k
}
20
21
MemTable::MemTable(const InternalKeyComparator& comparator)
22
0
    : comparator_(comparator), refs_(0), table_(comparator_, &arena_) {}
23
24
915
MemTable::~MemTable() { assert(refs_ == 0); }
  Branch (24:25): [True: 915, False: 0]
25
26
1.52k
size_t MemTable::ApproximateMemoryUsage() { return arena_.MemoryUsage(); }
27
28
int MemTable::KeyComparator::operator()(const char* aptr,
29
13.7k
                                        const char* bptr) const {
30
  // Internal keys are encoded as length-prefixed strings.
31
13.7k
  Slice a = GetLengthPrefixedSlice(aptr);
32
13.7k
  Slice b = GetLengthPrefixedSlice(bptr);
33
13.7k
  return comparator.Compare(a, b);
34
13.7k
}
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
0
static const char* EncodeKey(std::string* scratch, const Slice& target) {
40
0
  scratch->clear();
41
0
  PutVarint32(scratch, target.size());
42
0
  scratch->append(target.data(), target.size());
43
0
  return scratch->data();
44
0
}
45
46
class MemTableIterator : public Iterator {
47
 public:
48
0
  explicit MemTableIterator(MemTable::Table* table) : iter_(table) {}
49
50
  MemTableIterator(const MemTableIterator&) = delete;
51
  MemTableIterator& operator=(const MemTableIterator&) = delete;
52
53
0
  ~MemTableIterator() override = default;
54
55
0
  bool Valid() const override { return iter_.Valid(); }
56
0
  void Seek(const Slice& k) override { iter_.Seek(EncodeKey(&tmp_, k)); }
57
0
  void SeekToFirst() override { iter_.SeekToFirst(); }
58
0
  void SeekToLast() override { iter_.SeekToLast(); }
59
0
  void Next() override { iter_.Next(); }
60
0
  void Prev() override { iter_.Prev(); }
61
0
  Slice key() const override { return GetLengthPrefixedSlice(iter_.key()); }
62
0
  Slice value() const override {
63
0
    Slice key_slice = GetLengthPrefixedSlice(iter_.key());
64
0
    return GetLengthPrefixedSlice(key_slice.data() + key_slice.size());
65
0
  }
66
67
0
  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
0
Iterator* MemTable::NewIterator() { return new MemTableIterator(&table_); }
75
76
void MemTable::Add(SequenceNumber s, ValueType type, const Slice& key,
77
4.27k
                   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
4.27k
  size_t key_size = key.size();
84
4.27k
  size_t val_size = value.size();
85
4.27k
  size_t internal_key_size = key_size + 8;
86
4.27k
  const size_t encoded_len = VarintLength(internal_key_size) +
87
4.27k
                             internal_key_size + VarintLength(val_size) +
88
4.27k
                             val_size;
89
4.27k
  char* buf = arena_.Allocate(encoded_len);
90
4.27k
  char* p = EncodeVarint32(buf, internal_key_size);
91
4.27k
  memcpy(p, key.data(), key_size);
92
4.27k
  p += key_size;
93
4.27k
  EncodeFixed64(p, (s << 8) | type);
94
4.27k
  p += 8;
95
4.27k
  p = EncodeVarint32(p, val_size);
96
4.27k
  memcpy(p, value.data(), val_size);
97
4.27k
  assert(p + val_size == buf + encoded_len);
  Branch (97:3): [True: 4.27k, False: 0]
98
4.27k
  table_.Insert(buf);
99
4.27k
}
100
101
915
bool MemTable::Get(const LookupKey& key, std::string* value, Status* s) {
102
915
  Slice memkey = key.memtable_key();
103
915
  Table::Iterator iter(&table_);
104
915
  iter.Seek(memkey.data());
105
915
  if (iter.Valid()) {
  Branch (105:7): [True: 305, False: 610]
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
305
    const char* entry = iter.key();
116
305
    uint32_t key_length;
117
305
    const char* key_ptr = GetVarint32Ptr(entry, entry + 5, &key_length);
118
305
    if (comparator_.comparator.user_comparator()->Compare(
  Branch (118:9): [True: 305, False: 0]
119
305
            Slice(key_ptr, key_length - 8), key.user_key()) == 0) {
120
      // Correct user key
121
305
      const uint64_t tag = DecodeFixed64(key_ptr + key_length - 8);
122
305
      switch (static_cast<ValueType>(tag & 0xff)) {
  Branch (122:15): [True: 0, False: 305]
123
305
        case kTypeValue: {
  Branch (123:9): [True: 305, False: 0]
124
305
          Slice v = GetLengthPrefixedSlice(key_ptr + key_length);
125
305
          value->assign(v.data(), v.size());
126
305
          return true;
127
0
        }
128
0
        case kTypeDeletion:
  Branch (128:9): [True: 0, False: 305]
129
0
          *s = Status::NotFound(Slice());
130
0
          return true;
131
305
      }
132
305
    }
133
305
  }
134
610
  return false;
135
915
}
136
137
}  // namespace leveldb