LevelDB源码分析8-db key
2016-11-30 10:45
316 查看
为了更好的阅读Memtable,先看一看Memtable的key.
SequnceNumber只占56bits,ValueType占用8bits.
因此定义了其最大值:
转换函数:
InternalKey是内部成员为一个rep_(string).这个string组成为ParseInternalKey的元素:
整体的结果如下
ValueType
levledb更新时不会操控db中的数据,每次操作都是直接插入一份kv数据,具体的数据合并和清除工作由后台的compact完成。所以,每次 put,db 中就会新加入一份 KV 数据,即使该 key 已经存在;而 delete 等同于 put 空的 value。为了区分真实 kv 数据和删除操作的 mock 数据,使用 ValueType 来标识:enum ValueType { kTypeDeletion = 0x0, //删除的key kTypeValue = 0x1 //插入的key };
SequenceNumber
SequenceNumber的定义为:typedef uint64_t SequenceNumber;.可见sequenceNumber是一个64位的数。每次更新时,由SequenceNumber来标识,整个 db 有一个全局值保存着当前使用到的 SequnceNumber。SequnceNumber 在 leveldb 有重要的地位,key 的排序,compact 以及 snapshot 都依赖于它。存储结构如下:
0 | 56 |
---|---|
SequenceNumber | ValueType |
因此定义了其最大值:
//SequenceNumber的最大值,56位 static const SequenceNumber kMaxSequenceNumber = ((0x1ull << 56) - 1);
ParsedInternalKey
ParsedInternalKey为db内部操作的key.db内部需要把user key(用户传入的key,为Slice格式)加入元信息一并处理。//db内部操作的key,对用户传入的key(Slice)加入一个信息 struct ParsedInternalKey { Slice user_key; SequenceNumber sequence; ValueType type; ParsedInternalKey() { } // Intentionally left uninitialized (for speed) ParsedInternalKey(const Slice& u, const SequenceNumber& seq, ValueType t) : user_key(u), sequence(seq), type(t) { } std::string DebugString() const; };
转换函数:
//把一个slice形式的internal_key转为一个ParsedInternalKey的struct inline bool ParseInternalKey(const Slice& internal_key, ParsedInternalKey* result) { const size_t n = internal_key.size(); if (n < 8) return false; uint64_t num = DecodeFixed64(internal_key.data() + n - 8);//seq+type unsigned char c = num & 0xff; result->sequence = num >> 8; result->type = static_cast<ValueType>(c); result->user_key = Slice(internal_key.data(), n - 8);//user_key return (c <= static_cast<unsigned char>(kTypeValue)); }
InternalKey
InternalKey为db内部使用,包装易用的结构,包含userkey于SequnceNumber/ValueTypeInternalKey是内部成员为一个rep_(string).这个string组成为ParseInternalKey的元素:
//增加一个key的操作 void AppendInternalKey(std::string* result, const ParsedInternalKey& key) { result->append(key.user_key.data(), key.user_key.size());//user key PutFixed64(result, PackSequenceAndType(key.sequence, key.type));// SequenceNumber 和 ValueType }
整体的结果如下
//InternalKey class InternalKey { private: std::string rep_;//a string represent all the information public: InternalKey() { } // Leave rep_ as empty to indicate it is invalid //InternalKey string consist of (user_key) InternalKey(const Slice& user_key, SequenceNumber s, ValueType t) { AppendInternalKey(&rep_, ParsedInternalKey(user_key, s, t)); } void DecodeFrom(const Slice& s) { rep_.assign(s.data(), s.size()); } Slice Encode() const { assert(!rep_.empty()); return rep_; } Slice user_key() const { return ExtractUserKey(rep_); } void SetFrom(const ParsedInternalKey& p) { rep_.clear(); AppendInternalKey(&rep_, p); } void Clear() { rep_.clear(); } std::string DebugString() const; };
LookupKey
db内部在memetable中查找数据使用//LookupKey:db内部在memtable中查找数据 class LookupKey { public: // Initialize *this for looking up user_key at a snapshot with // the specified sequence number. LookupKey(const Slice& user_key, SequenceNumber sequence); ~LookupKey(); // Return a key suitable for lookup in a MemTable. Slice memtable_key() const { return Slice(start_, end_ - start_); } // Return an internal key (suitable for passing to an internal iterator) Slice internal_key() const { return Slice(kstart_, end_ - kstart_); } // Return the user key Slice user_key() const { return Slice(kstart_, end_ - kstart_ - 8); } private: // We construct a char array of the form: // klength varint32 <-- start_ // userkey char[klength] <-- kstart_ // tag uint64 // <-- end_ // The array is a suitable MemTable key. // The suffix starting with "userkey" can be used as an InternalKey. const char* start_; const char* kstart_; const char* end_; char space_[200]; // Avoid allocation for short keys // No copying allowed LookupKey(const LookupKey&); void operator=(const LookupKey&); }; inline LookupKey::~LookupKey() { if (start_ != space_) delete[] start_; }
SkipList中的key
skiplist中的单个节点不仅存储了Key,也存储了value.格式如下图。内部的比较函数使用的是InternalKey。相关文章推荐
- levelDB源码分析-Status
- levelDB源码分析-Skiplist
- Leveldb源码分析--13
- Leveldb源码分析--19
- Leveldb源码分析--18
- levelDB源码分析-提纲
- Leveldb源码分析--15
- [Leveldb]源码分析之二 Cache模块的实现
- Leveldb源码分析--11
- Leveldb源码分析--20
- levelDB源码分析-Memtable
- Leveldb源码分析--2
- Leveldb源码分析--5
- leveldb源码分析 之 入门使用
- Leveldb源码分析--12
- levelDB源码分析-Arena
- levelDB源码分析-SSTable:.sst文件构建与读取
- leveldb源码分析 之 入门使用
- Leveldb源码分析--17
- [Leveldb] 源码分析之一接口文件介绍