14 DB的查询与遍历之2
14.4 DBIter
从前面函数NewIterator的代码还能看到,DBIter内部使用了MergingIterator,在调用MergingItertor的系列seek函数后,DBIter还要处理key的删除标记。否则,遍历时会把已删除的key列举出来。
DBIter还定义了两个移动方向,默认是kForward:
1) kForward,向前移动,代码保证此时DBIter的内部迭代器刚好定位在this->key(),this->value()这条记录上;
2) kReverse,向后移动,代码保证此时DBIter的内部迭代器刚好定位在所有key=this->key()的entry之前。
其成员变量savedkey和saved value保存的是KReverse方向移动时的k/v对,每次seek系调用之后,其值都会跟随iter_而改变。
DBIter的代码开始读来感觉有些绕,主要就是它要处理删除标记,而且其底层的MergingIterator,对于同一个key会有多个不同sequence的entry。导致其Next/Prev操作比较复杂,要考虑到上一次移动的影响,跳过删除标记和重复的key。
DBIter必须导出Iterator定义的几个接口,下面就拖出来挨个分析。
14.4.1 Get系接口
首先是几个简单接口,获取key、value和status的:
virtual Slice key() const { //kForward直接取iter_->key(),否则取saved key
assert(valid_);
return (direction_ ==kForward) ? ExtractUserKey(iter_->key()) : saved_key_;
}
virtual Slice value() const { //kForward直接取iter_->value(),否则取saved value
assert(valid_);
return (direction_ ==kForward) ? iter_->value() : saved_value_;
}
virtual Status status() const {
if (status_.ok()) returniter_->status();
return status_;
}
14.4.2 辅助函数
在分析seek系函数之前,先来理解两个重要的辅助函数:FindNextUserEntry和FindPrevUserEntry的功能和逻辑。其功能就是循环跳过下一个/前一个delete的记录,直到遇到kValueType的记录。先来看看,函数声明为:
void DBIter::FindNextUserEntry(bool skipping, std::string* skip)
参数@skipping表明是否要跳过sequence更小的entry;
参数@skip临时存储空间,保存seek时要跳过的key;
在进入FindNextUserEntry时,iter_刚好定位在this->key(), this->value()这条记录上。下面来看函数实现: