Coverage Report

Created: 2025-07-11 07:01

/src/leveldb/db/memtable.cc
Line
Count
Source (jump to first uncovered line)
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
69.2M
static Slice GetLengthPrefixedSlice(const char* data) {
15
69.2M
  uint32_t len;
16
69.2M
  const char* p = data;
17
69.2M
  p = GetVarint32Ptr(p, p + 5, &len);  // +5: we assume "p" is not corrupted
18
69.2M
  return Slice(p, len);
19
69.2M
}
20
21
MemTable::MemTable(const InternalKeyComparator& comparator)
22
186k
    : comparator_(comparator), refs_(0), table_(comparator_, &arena_) {}
23
24
186k
MemTable::~MemTable() { assert(refs_ == 0); }
25
26
3.65M
size_t MemTable::ApproximateMemoryUsage() { return arena_.MemoryUsage(); }
27
28
int MemTable::KeyComparator::operator()(const char* aptr,
29
30.7M
                                        const char* bptr) const {
30
  // Internal keys are encoded as length-prefixed strings.
31
30.7M
  Slice a = GetLengthPrefixedSlice(aptr);
32
30.7M
  Slice b = GetLengthPrefixedSlice(bptr);
33
30.7M
  return comparator.Compare(a, b);
34
30.7M
}
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
215k
  explicit MemTableIterator(MemTable::Table* table) : iter_(table) {}
49
50
  MemTableIterator(const MemTableIterator&) = delete;
51
  MemTableIterator& operator=(const MemTableIterator&) = delete;
52
53
215k
  ~MemTableIterator() override = default;
54
55
2.87M
  bool Valid() const override { return iter_.Valid(); }
56
0
  void Seek(const Slice& k) override { iter_.Seek(EncodeKey(&tmp_, k)); }
57
134k
  void SeekToFirst() override { iter_.SeekToFirst(); }
58
0
  void SeekToLast() override { iter_.SeekToLast(); }
59
2.55M
  void Next() override { iter_.Next(); }
60
0
  void Prev() override { iter_.Prev(); }
61
2.61M
  Slice key() const override { return GetLengthPrefixedSlice(iter_.key()); }
62
2.55M
  Slice value() const override {
63
2.55M
    Slice key_slice = GetLengthPrefixedSlice(iter_.key());
64
2.55M
    return GetLengthPrefixedSlice(key_slice.data() + key_slice.size());
65
2.55M
  }
66
67
71.3k
  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
215k
Iterator* MemTable::NewIterator() { return new MemTableIterator(&table_); }
75
76
void MemTable::Add(SequenceNumber s, ValueType type, const Slice& key,
77
3.62M
                   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
  //  tag          : uint64((sequence << 8) | type)
82
  //  value_size   : varint32 of value.size()
83
  //  value bytes  : char[value.size()]
84
3.62M
  size_t key_size = key.size();
85
3.62M
  size_t val_size = value.size();
86
3.62M
  size_t internal_key_size = key_size + 8;
87
3.62M
  const size_t encoded_len = VarintLength(internal_key_size) +
88
3.62M
                             internal_key_size + VarintLength(val_size) +
89
3.62M
                             val_size;
90
3.62M
  char* buf = arena_.Allocate(encoded_len);
91
3.62M
  char* p = EncodeVarint32(buf, internal_key_size);
92
3.62M
  std::memcpy(p, key.data(), key_size);
93
3.62M
  p += key_size;
94
3.62M
  EncodeFixed64(p, (s << 8) | type);
95
3.62M
  p += 8;
96
3.62M
  p = EncodeVarint32(p, val_size);
97
3.62M
  std::memcpy(p, value.data(), val_size);
98
3.62M
  assert(p + val_size == buf + encoded_len);
99
3.62M
  table_.Insert(buf);
100
3.62M
}
101
102
46.1k
bool MemTable::Get(const LookupKey& key, std::string* value, Status* s) {
103
46.1k
  Slice memkey = key.memtable_key();
104
46.1k
  Table::Iterator iter(&table_);
105
46.1k
  iter.Seek(memkey.data());
106
46.1k
  if (iter.Valid()) {
107
    // entry format is:
108
    //    klength  varint32
109
    //    userkey  char[klength]
110
    //    tag      uint64
111
    //    vlength  varint32
112
    //    value    char[vlength]
113
    // Check that it belongs to same user key.  We do not check the
114
    // sequence number since the Seek() call above should have skipped
115
    // all entries with overly large sequence numbers.
116
13.5k
    const char* entry = iter.key();
117
13.5k
    uint32_t key_length;
118
13.5k
    const char* key_ptr = GetVarint32Ptr(entry, entry + 5, &key_length);
119
13.5k
    if (comparator_.comparator.user_comparator()->Compare(
120
13.5k
            Slice(key_ptr, key_length - 8), key.user_key()) == 0) {
121
      // Correct user key
122
6.89k
      const uint64_t tag = DecodeFixed64(key_ptr + key_length - 8);
123
6.89k
      switch (static_cast<ValueType>(tag & 0xff)) {
124
4.46k
        case kTypeValue: {
125
4.46k
          Slice v = GetLengthPrefixedSlice(key_ptr + key_length);
126
4.46k
          value->assign(v.data(), v.size());
127
4.46k
          return true;
128
0
        }
129
2.42k
        case kTypeDeletion:
130
2.42k
          *s = Status::NotFound(Slice());
131
2.42k
          return true;
132
6.89k
      }
133
6.89k
    }
134
13.5k
  }
135
39.2k
  return false;
136
46.1k
}
137
138
}  // namespace leveldb