LevelDB源码分析--使用Iterator简化代码设计
2014-07-03 20:01
429 查看
我们先来参考来至使用Iterator简化代码2-TwoLevelIterator的例子,略微修改希望能帮助更加容易立即,如果有不理解请各位看客阅读原文。
下面我们再来看一个例子,我们为一个书店写程序,书店里有许多书Book,每个书架(BookShelf)上有多本书。
类结构如下所示
如何遍历书架上所有的书呢?一种实现方法是:
这样的实现暴漏了内部太多的细节,调用者根本就不需要知道Shelf存储Book的方式,仅仅需要遍历所有的数据即可。而且这样当我们换用另外一种数据结构存储Book时,客户端的代码就需要进行修改。但是如果使用Iterator模式则没有这个问题。具体的我们需要遍历书店中所有的书,现在应该如何实现呢?
一种实现方式是,由BookStore负责保存中间状态,包括当前遍历到了哪个书架,遍历到了书架上的那本书。
这种实现方法对外是干净的,但是对于BookStore的维护者来说却是不友好的,Iterator的中间状态不是BookStore的成员,逻辑上不应该由BookStore维护。而且当两个甚至多个用户同时遍历书店时BookStore得同时维护多个中间状态,极其容易出错。更好的一种实现方式是,把遍历Iterator相关的代码和状态封装成一个类,有两个层级Shelf和Book,这个类的名字我们叫做TwoLevelIteator.
这里只是作一个简单的示例过程,具体代码暂时不列出,如果以后有空进行整理的时候可以列一个完整的代码。
了解了这个基本原理以后,我们来看leveldb中的
leveldb中TwoLevelIterator也类似BookStore有一个block的遍历指针存放至TwoLevelIterator中而已,当一个block遍历完的时候使用该迭代器跳到下一个block,然后在设置对应的data_iter_。只是在过程中遍历下一层data_iter时内部结构可能尚未初始化需要调用BlockReader从磁盘读取文件进行初始化设置。
这里只是说明了使用TwoLevelIterator遍历SSTable时,当遍历db的时候也同样可以类似的对应SSTable层级的一个迭代器即可,而block_function_需要设置为GetFileIterator就可以遍历整个数据库了。
下面我们再来看一个例子,我们为一个书店写程序,书店里有许多书Book,每个书架(BookShelf)上有多本书。
类结构如下所示
classBook{ private: stringbook_name_; }; classShelf{ private: vector<Book>books_; };
如何遍历书架上所有的书呢?一种实现方法是:
vector<Book>&GetBooks()const{ returnbooks_; }
这样的实现暴漏了内部太多的细节,调用者根本就不需要知道Shelf存储Book的方式,仅仅需要遍历所有的数据即可。而且这样当我们换用另外一种数据结构存储Book时,客户端的代码就需要进行修改。但是如果使用Iterator模式则没有这个问题。具体的我们需要遍历书店中所有的书,现在应该如何实现呢?
一种实现方式是,由BookStore负责保存中间状态,包括当前遍历到了哪个书架,遍历到了书架上的那本书。
//书店类
classBookStore{
Iterator*NewIterator()const;
private:
vector<Shelf>shelf_;
vector<Shelf>::iteratorshelf_iter_;
vector<Book>::iteratorbook_iter_;
};
这种实现方法对外是干净的,但是对于BookStore的维护者来说却是不友好的,Iterator的中间状态不是BookStore的成员,逻辑上不应该由BookStore维护。而且当两个甚至多个用户同时遍历书店时BookStore得同时维护多个中间状态,极其容易出错。更好的一种实现方式是,把遍历Iterator相关的代码和状态封装成一个类,有两个层级Shelf和Book,这个类的名字我们叫做TwoLevelIteator.
classTwoLevelIterator:publicIterator{
vector<Shelf>::iteratorshelf_iter_;
vector<Book>::iteratorbook_iter_;
voidSeekToFirst(){
shelf_iter_.SeekToFirst();
if(shelf_iter_.iter()!=NULL)book_iter_.SeekToFirst();
}
voidTwoLevelIterator::Next(){
if(book_iter_==shelf_iter_.end())
{
shelf_iter_.Next();
book_iter_.SeekToFirst();
}else{
book_iter_.Next();
}
}
这里只是作一个简单的示例过程,具体代码暂时不列出,如果以后有空进行整理的时候可以列一个完整的代码。
了解了这个基本原理以后,我们来看leveldb中的
classTwoLevelIterator:publicIterator{
BlockFunctionblock_function_;block内部迭代器的生成函数
void*arg_;//通常为TableCahe,供block_function_调用的参数
constReadOptionsoptions_;
Statusstatus_;
IteratorWrapperindex_iter_;//大致相当于shelf_iter_
IteratorWrapperdata_iter_;//大致相当于book_iter_
std::stringdata_block_handle_;
};
voidTwoLevelIterator::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源码分析 之 入门使用
- Mybatis3源码分析(08)-加载Configuration-使用到的设计模式
- leveldb源码分析 之 入门使用
- 使用泛型程序简化代码设计
- leveldb源码分析--Iterator遍历数据库
- C#分析数据库结构,使用XSL模板自动生成代码 - 清清月儿 .NET万花筒 Asp.net技术 Asp.net教程 Asp.net源码 Asp.net基础 Asp.net控件 Asp.net入门 - CSDNBlog
- Google Test(GTest)使用方法和源码解析——私有属性代码测试技术分析
- Android项目-智慧北京:02(三种技术设计主页面及源码分析点击事件传递的机制及Json数据传递的使用)
- leveldb源码分析 之 入门使用
- 再议IIC协议与设计【2】--使用GPIO实现IIC从机通讯源码分析与测试
- [置顶] 代码覆盖工具Jacoco使用示例及源码分析
- android使用代码生成LayerDrawable的方法、源码分析和注意事项
- JUnit设计模式分析及简化的JUnit代码
- 从std::string、leveldb、openbsc源码,研究为什么他们要这么设计代码
- leveldb源码分析 之 入门使用
- struts2 paramsPrepareParamsStack拦截器简化代码(源码分析)
- 应用框架的设计与实现——.NET平台(4.3 SAF代码分析)
- Java源码分析:深入探讨Iterator模式
- EasyJWeb作为一个快速Java Web MVC框架,其设计目标不尽是要简化软件开发人员的代码书写工作,更是要能方便界面设计人员的工作。
- Java源码分析:深入探讨Iterator模式及Java 5.0中改进的for循环