leveldb学习笔记之六——db/memtable.h

db数据在内存中的存储格式,写操作的数据都会先写到memtable中

class MemTable {
public:
    //构造函数,不允许隐式转换,参数为内部key比较器
  	explicit MemTable(const InternalKeyComparator& comparator);

  	//引用计数
  	void Ref() { ++refs_; }

  	//解引用
  	void Unref() {
    	--refs_;
    	assert(refs_ >= 0);
    	if (refs_ <= 0) {
      		delete this;
    	}
  	}

  	//评估当前的内存使用量
  	size_t ApproximateMemoryUsage();

  	//创建迭代器,用来遍历MemTable中的对象
  	Iterator* NewIterator();

  	//向MemTable中添加对象
  	void Add(SequenceNumber seq, ValueType type,
           const Slice& key,
           const Slice& value);

  	// 读取数据,提供查询键,输出对象值和状态
  	bool Get(const LookupKey& key, std::string* value, Status* s);

 private:
  	~MemTable();  //析构函数私有化,使用者只能通过unref释放对象

	//比较器
  	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;
	
    //定义skiplist
  	typedef SkipList<const char*, KeyComparator> Table;

	//成员变量包括键值比较器、引用计数、内存管理和跳表
  	KeyComparator comparator_;
  	int refs_;
  	Arena arena_;
  	Table table_;

  	//禁止拷贝构造和赋值操作符
  	MemTable(const MemTable&);
  	void operator=(const MemTable&);
};

相关函数

主要分析以下几个函数:

  • 写入数据的函数
    memtable写入数据的格式如下:
    在这里插入图片描述
    代码如下:
void MemTable::Add(SequenceNumber s, ValueType type,
                   const Slice& key,
                   const Slice& value) {
  	size_t key_size = key.size(); //key的长度
  	size_t val_size = value.size(); //value的长度
  	size_t internal_key_size = key_size + 8; //内部key的长度,因为内部key要加上序列号,序列号长度是8个字节
  	const size_t encoded_len =    //编码后的总长度,key和value的长度分别用varint进行编码,所以总长度是此种计算方式
      	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); //首先写入内部key的长度(varint编码)
  	memcpy(p, key.data(), key_size);	//再写key的数据
  	p += key_size;
  	EncodeFixed64(p, (s << 8) | type);   //然后写入类型数据
  	p += 8;
  	p = EncodeVarint32(p, val_size);    //继续写入value的长度(varint编码)
  	memcpy(p, value.data(), val_size);  //写入value的数据
  	assert(p + val_size == buf + encoded_len);
  	table_.Insert(buf);   //将写入的数据插入到跳表中
}
  • 读取数据
//读数据为写数据的逆向过程
bool MemTable::Get(const LookupKey& key, std::string* value, Status* s) {
  	Slice memkey = key.memtable_key();	//获取memkey
  	Table::Iterator iter(&table_);		//获取对应的跳表
  	iter.Seek(memkey.data());			//查找到memkey对应的数据
  	if (iter.Valid()) {
    	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://已经删除的数据,返回NotFound
          			*s = Status::NotFound(Slice());
          			return true;
      		}
    	}
  	}
  	return false;
}

学习是一种慰藉,编程是一种情怀,技术提升永不可辜负!

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值