您的位置:首页 > 其它

leveldb 源码阅读,细节记录memberTable

2015-12-06 20:18 465 查看
leveldb 是看着前辈们的大概分析,然后看着源码,将自己的疑惑和解决记录下来:

Leveldb源码分析

从memberTable插入一条记录和查找一条记录从上而下分析

插入:

插入的函数 void MemTable::Add(SequenceNumber s, ValueType type,const Slice& key,const Slice& value)

参数:

SequenceNumber 插入的序号,在skiplist里,这个序号是降序列的

ValueType type   类型添加值还是删除值,

Slice key      就是key

value        就是value

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);
memcpy(p, key.data(), key_size);
p += key_size;
EncodeFixed64(p, (s << 8) | type);
p += 8;
p = EncodeVarint32(p, val_size);
memcpy(p, value.data(), val_size);
assert((p + val_size) - buf == encoded_len);
table_.Insert(buf);
}


这段代码是让

buf=key.size()压缩存储+(key+(SequenceNumber | TypeValue))+value.size()压缩存储+value

再将buf添加到skiplist里

查找:MemTable::Get(const LookupKey& key, std::string* value, Status* s)

参数:

LookupKey& key   查找的key,

string* value     用于存放查找结果的value

Status* s       存储key的状态,是删除还是添加

bool MemTable::Get(const LookupKey& key, std::string* value, Status* s) {
Slice memkey = key.memtable_key();
Table::Iterator iter(&table_);
iter.Seek(memkey.data());
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();
uint32_t key_length;
const char* key_ptr = GetVarint32Ptr(entry, entry+5, &key_length);
if (comparator_.comparator.user_comparator()->Compare(
Slice(key_ptr, key_length - 8),
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);
value->assign(v.data(), v.size());
return true;
}
case kTypeDeletion:
*s = Status::NotFound(Slice());
return true;
}
}
}
return false;
}


首先需要从LookupKey里提取符合memberTable格式的key出来,因为前面存储时是按照一定格式来的,所以LookupKey.memberTable_key()返回的字符串格式是:key.size()压缩存储+(key+(SequenceNumber | TypeValue),但是为什么没有后面的那部分呢(value.size()压缩存储+value),这是因为有 InternalKeyComparator class 的存在,这个是继承Comparator class的,而且里面包含了一个comparator。InternalKeyComparator相当于一个适配器,将符合memberTable key格式的数据段将key提取出来,再用用户自定义的comparator或者预置的comparator来对真实的key进行比较。如果真实key比较结果是相同,则将(SequenceNumber| TypeValue)提取出来进行比较,真实情况下,Type不会进行比较,只是SequenceNumber进行比较,因为SequenceNumber是在SkipList 里是降序排序的,为了防止TypeValue对排序的影响,所以LookupKey里的TypeValue是0x1。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: