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