我们先来参考来至使用Iterator简化代码2-TwoLevelIterator的例子,略微修改希望能帮助更加容易立即,如果有不理解请各位看客阅读原文。

下面我们再来看一个例子,我们为一个书店写程序,书店里有许多书Book,每个书架(BookShelf)上有多本书。

类结构如下所示

class Book {
private:
string book_name_;
};
class Shelf {
private:
vector<Book> books_;
};

如何遍历书架上所有的书呢?一种实现方法是:

vector<Book>& GetBooks() const {
return books_;
}
 

这样的实现暴漏了内部太多的细节,调用者根本就不需要知道Shelf存储Book的方式,仅仅需要遍历所有的数据即可。而且这样当我们换用另外一种数据结构存储Book时,客户端的代码就需要进行修改。但是如果使用Iterator模式则没有这个问题。具体的我们需要遍历书店中所有的书,现在应该如何实现呢?

一种实现方式是,由BookStore负责保存中间状态,包括当前遍历到了哪个书架,遍历到了书架上的那本书。

// 书店类
class BookStore {
Iterator* NewIterator() const;
private:
vector<Shelf> shelf_;
vector<Shelf>::iterator shelf_iter_;
vector<Book>::iterator book_iter_;
};

这种实现方法对外是干净的,但是对于BookStore的维护者来说却是不友好的,Iterator的中间状态不是BookStore的成员,逻辑上不应该由BookStore维护。而且当两个甚至多个用户同时遍历书店时BookStore得同时维护多个中间状态,极其容易出错。更好的一种实现方式是,把遍历Iterator相关的代码和状态封装成一个类,有两个层级Shelf 和 Book,这个类的名字我们叫做TwoLevelIteator.

class TwoLevelIterator: public Iterator {
vector<Shelf>::iterator shelf_iter_;
vector<Book>::iterator book_iter_;
void SeekToFirst() {
shelf_iter_.SeekToFirst();
if (shelf_iter_.iter() != NULL) book_iter_.SeekToFirst();
}
void TwoLevelIterator::Next() {
if (book_iter_ == shelf_iter_.end())
{
shelf_iter_.Next();
book_iter_.SeekToFirst();
}else{
book_iter_.Next();
}
}

这里只是作一个简单的示例过程,具体代码暂时不列出,如果以后有空进行整理的时候可以列一个完整的代码。

了解了这个基本原理以后,我们来看leveldb 中的

class TwoLevelIterator: public Iterator {
BlockFunction block_function_; block内部迭代器的生成函数
void* arg_; //通常为TableCahe,供block_function_调用的参数
const ReadOptions options_;
Status status_;
IteratorWrapper index_iter_; //大致相当于shelf_iter_
IteratorWrapper data_iter_; // 大致相当于book_iter_
std::string data_block_handle_;
}; void TwoLevelIterator::SeekToFirst() {
index_iter_.SeekToFirst(); //跳到第一个block
InitDataBlock(); //根据当前block设置data_iter_
if (data_iter_.iter() != NULL) data_iter_.SeekToFirst();
SkipEmptyDataBlocksForward(); //跳过空block
}

leveldb中TwoLevelIterator也类似BookStore有一个block的遍历指针存放至TwoLevelIterator中而已,当一个block遍历完的时候使用该迭代器跳到下一个block,然后在设置对应的data_iter_。只是在过程中遍历下一层data_iter时内部结构可能尚未初始化需要调用BlockReader从磁盘读取文件进行初始化设置。

这里只是说明了使用TwoLevelIterator遍历SSTable时,当遍历db的时候也同样可以类似的对应SSTable层级的一个迭代器即可,而block_function_需要设置为GetFileIterator就可以遍历整个数据库了。

LevelDB源码分析--使用Iterator简化代码设计的更多相关文章

  1. leveldb源码分析--WriteBatch

    从[leveldb源码分析--插入删除流程]和WriteBatch其名我们就很轻易的知道,这个是leveldb内部的一个批量写的结构,在leveldb为了提高插入和删除的效率,在其插入过程中都采用了批 ...

  2. leveldb源码分析--SSTable之block

    在SSTable中主要存储数据的地方是data block,block_builder就是这个专门进行block的组织的地方,我们来详细看看其中的内容,其主要有Add,Finish和CurrentSi ...

  3. leveldb源码分析--Key结构

    [注]本文参考了sparkliang的专栏的Leveldb源码分析--3并进行了一定的重组和排版 经过上一篇文章的分析我们队leveldb的插入流程有了一定的认识,而该文设计最多的又是Batch的概念 ...

  4. Leveldb源码分析--1

    coming from http://blog.csdn.net/sparkliang/article/details/8567602 [前言:看了一点oceanbase,没有意志力继续坚持下去了,暂 ...

  5. netty源码分析 - Recycler 对象池的设计

    目录 一.为什么需要对象池 二.使用姿势 2.1 同线程创建回收对象 2.2 异线程创建回收对象 三.数据结构 3.1 物理数据结构图 3.2 逻辑数据结构图(重要) 四.源码分析 4.2.同线程获取 ...

  6. leveldb源码分析--日志

    我们知道在一个数据库系统中为了保证数据的可靠性,我们都会记录对系统的操作日志.日志的功能就是用来在系统down掉的时候对数据进行恢复,所以日志系统对一个要求可靠性的存储系统是极其重要的.接下来我们分析 ...

  7. Java容器类源码分析之Iterator与ListIterator迭代器(基于JDK8)

    一.基本概念 迭代器是一个对象,也是一种设计模式,Java有两个用来实实现迭代器的接口,分别是Iterator接口和继承自Iterator的ListIterator接口.实现迭代器接口的类的对象有遍历 ...

  8. 【JDK】JDK源码分析-List, Iterator, ListIterator

    List 是最常用的容器之一.之前提到过,分析源码时,优先分析接口的源码,因此这里先从 List 接口分析.List 方法列表如下: 由于上文「JDK源码分析-Collection」已对 Collec ...

  9. leveldb源码分析之Slice

    转自:http://luodw.cc/2015/10/15/leveldb-02/ leveldb和redis这样的优秀开源框架都没有使用C++自带的字符串string,redis自己写了个sds,l ...

随机推荐

  1. UWP开发入门(十四)—— UserControl中Adaptive UI的小技巧

    本篇我们通过绘制一个非常简单的UserControl控件,来分享一下对Adaptive UI的理解及一些图形绘制的技巧. 现在流行的APP都少不了精致的用户头像,首先假设我们需要绘制如下的图形作为默认 ...

  2. Scrum 项目 6.0

    -------------------------6.0------------------------------------ sprint演示 1.坚持所有的sprint都结束于演示. 团队的成果 ...

  3. JS 数组去重的几个方法

    Array.prototype.unique1 = function () { var n = []; //一个新的临时数组 for (var i = 0; i < this.length; i ...

  4. 由node-webkit想到

    本人做为.NET的死忠也有些许年头.微软这几年被谷歌苹果之流打的有点招架不住..NET的前景也难免堪忧.虽然我认为就强类型语言方面,C#绝对是最强者.但是新技术的发展确实是可怕的,看看苹果几年就把no ...

  5. 【Win10】让 AppBarButton 支持更复杂的 Icon 内容

    最近有一个需求,需要制作这么一个 AppBarButton: 这个 AppBarButton 的 Icon 是一个评论框图标里面再显示评论数(大于 99 条则显示 99+).其中评论数是通过数据绑定得 ...

  6. Excel大数据量分段导入到Oracle

    客户需要将一个具有2W多条数据的Excel表格中的数据导入到Oracle数据库的A表中,开始采用的是利用Oledb直接将数据读入到DataTable中,然后通过拼接InserInto语句来插入到数据库 ...

  7. [CLR via C#]26. 计算限制的异步操作

    一.CLR线程池基础 前面说过,创建和销毁线程是一个比较昂贵的操作,太多的线程也会浪费内存资源.由于操作系统必须调度可运行的线程并执行上下文切换,所以太多的线程还有损于性能.为了改善这个情况,CLR使 ...

  8. jquery实现下拉框功能

    说不清楚,直接上图 <!DOCTYPE html> <html lang="en" xmlns="http://www.w3.org/1999/xhtm ...

  9. 【AngularJS学习笔记】00 序

    AngularJS通过新的属性与表达式来扩展HTML,有一种很形象的叫法,定义它为声明式语言. 为克服HTML在构建应用上的不足而设计! 这是它的目标. 它的官网进不去,应该是被墙了,这是goegle ...

  10. sql server2008中sql server身份能登录,window身份登录不了

    用sql server身份的sa登录成功进入,一切正常,用window身份登录不了,问题如下