参考 1,http://mingxinglai.com/cn/2013/01/leveldb-memtable
参考 2,http://www.aikaiyuan.com/4591.html
具体结构如下图所示:
其主要的结构就是一个SkipList,list中没有将key和value区分开而是全部当成一个key,在从其中解析出相应的key与value。上图中有这么三个key:Lookupkey,internal_key, user_key. user_key指示的是用户真实的key。
class MemTable {
public:
// MemTables are reference counted. The initial reference count
// is zero and the caller must call Ref() at least once.
explicit MemTable(const InternalKeyComparator& comparator);
// Increase reference count.
void Ref() { ++refs_; }
// Drop reference count. Delete if no more references exist.
void Unref() {
--refs_;
assert(refs_ >= 0);
if (refs_ <= 0) {
delete this;
}
}
// Returns an estimate of the number of bytes of data in use by this
// data structure.
//
// REQUIRES: external synchronization to prevent simultaneous
// operations on the same MemTable.
size_t ApproximateMemoryUsage();
// Return an iterator that yields the contents of the memtable.
//
// The caller must ensure that the underlying MemTable remains live
// while the returned iterator is live. The keys returned by this
// iterator are internal keys encoded by AppendInternalKey in the
// db/format.{h,cc} module.
Iterator* NewIterator();
// Add an entry into memtable that maps key to value at the
// specified sequence number and with the specified type.
// Typically value will be empty if type==kTypeDeletion.
void Add(SequenceNumber seq, ValueType type,
const Slice& key,
const Slice& value);
// If memtable contains a value for key, store it in *value and return true.
// If memtable contains a deletion for key, store a NotFound() error
// in *status and return true.
// Else, return false.
bool Get(const LookupKey& key, std::string* value, Status* s);
private:
~MemTable(); // Private since only Unref() should be used to delete it 私有析构函数表示该结构不能再栈上定义只能在堆上。且不能调用delete删除。最终的删除在<span style="font-family: Arial, Helvetica, sans-serif;">Unref中delete this。 </span>
struct KeyComparator {
const InternalKeyComparator comparator;
explicit KeyComparator(const InternalKeyComparator& c) : comparator(c) { }
int operator()(const char* a, const char* b) const;
};
friend class MemTableIterator;
friend class MemTableBackwardIterator;
typedef SkipList<const char*, KeyComparator> Table; //主要的结构跳跃表
KeyComparator comparator_; //比较函数
int refs_;
Arena arena_; //内存池
Table table_;
// No copying allowed
MemTable(const MemTable&);
void operator=(const MemTable&);
};
Add函数:
void MemTable::Add(SequenceNumber s, ValueType type,
const Slice& key,
const Slice& value) {
// Format of an entry is concatenation of:
// key_size : varint32 of internal_key.size()
// key bytes : char[internal_key.size()]
// value_size : varint32 of value.size()
// value bytes : char[value.size()]
size_t key_size = key.size();
size_t val_size = value.size();
size_t internal_key_size = key_size + 8;
const size_t encoded_len =
VarintLength(internal_key_size) + internal_key_size +
VarintLength(val_size) + val_size; //总共需要分配的内存大小
char* buf = arena_.Allocate(encoded_len);
char* p = EncodeVarint32(buf, internal_key_size); //写入<span style="font-family: Arial, Helvetica, sans-serif;">internal_key_size,后面给据这个来获得internal_key 最终获得user_key</span>
memcpy(p, key.data(), key_size); //写入user_key
p += key_size;
EncodeFixed64(p, (s << 8) | type); // 写入sequence nu 和type
p += 8; // <span style="font-family: Arial, Helvetica, sans-serif;">sequence nu 和type 总共8个字节</span>
p = EncodeVarint32(p, val_size); //写入value_size
memcpy(p, value.data(), val_size); //写入value
assert((p + val_size) - buf == encoded_len); //断言写入数据的正确性
table_.Insert(buf); //插入SkipList
}
bool MemTable::Get(const LookupKey& key, std::string* value, Status* s) {
Slice memkey = key.memtable_key(); //生成lookupkey
Table::Iterator iter(&table_); // 产生SkipList
iter.Seek(memkey.data()); //找出该小于等于该key的值
if (iter.Valid()) {
// entry format is:
// klength varint32
// userkey char[klength]
// tag uint64
// vlength varint32
// value char[vlength]
// Check that it belongs to same user key. We do not check the
// sequence number since the Seek() call above should have skipped
// all entries with overly large sequence numbers.
const char* entry = iter.key(); //拿到存储内容(包含value)
uint32_t key_length;
const char* key_ptr = GetVarint32Ptr(entry, entry+5, &key_length); //32位变长存储,limit是5个字节所以加了一个 5
if (comparator_.comparator.user_comparator()->Compare(
Slice(key_ptr, key_length - 8), //获取用户的真实user_key
key.user_key()) == 0) {
// Correct user key
const uint64_t tag = DecodeFixed64(key_ptr + key_length - 8); //查看该值得类型,取最后一个字节
switch (static_cast<ValueType>(tag & 0xff)) {
case kTypeValue: {
Slice v = GetLengthPrefixedSlice(key_ptr + key_length); //获取该key的值,该函数和上面一样都是先获取value的size在进行取值
value->assign(v.data(), v.size());
return true;
}
case kTypeDeletion:
*s = Status::NotFound(Slice());
return true;
}
}
}
return false;
}