leveldb的启动流程

一、 manifest文件的作用

manifest文件是保存每次压缩记录的。current文件里面只有一条记录,就是现在有些小的manifest文件。
只有数据库重新open的时候才会用到manifest文件来进行恢复。

二、 manifest文件的格式

manifest文件的格式是record,读取的时候会先读取数据类型,类似kLogNumber,读取到类型之后再读取内容。

三、第一个manifest文件时何时产生的?

见启动流程

四、leveldb启动流程

笔者采用gdb跟踪的方式(https://mp.****.net/mdeditor/85548269#),缕出leveldb启动的流程(后续代码详解还没完全写完):
leveldb的启动流程

3-1 创建db文件夹,初始化DBImpl全局变量

leveldb的启动流程
在gdb调试打印这个option可以看到leveldb的默认设置,包括默认的比较函数,默认块大小等:
leveldb的启动流程

DB::Open->DBImpl::DBImpl 在首次初始化DB参数option_的时候创建的db文件夹
具体创建就在SanitizeOptions中;另外,在初始化DBImpl时还初始化了versions_全局变量,在第一次recover中将使用versions_变量进行恢复操作,见
leveldb的启动流程
3-2创建第一个manifest文件和current文件
DB::Open->impl->Recover 首次创建进入Recover时没有current文件,无法恢复。
所以走NewDB分支
leveldb的启动流程
通过gdb跟踪,可以看到整个db的第一个manifest文件就是在NewDB中创建出来的,名字就是 MANIFEST-000001,这也是为何上面setNextFile为2的原因,因为第一个数字给了manifest文件了。
并且可以看到,record信息是
“\001\032leveldb.BytewiseComparator\002\000\003\002\004”
分别对应代码中的new_db.EncodeTo()函数中的各个字段
leveldb的启动流程
3-3 恢复数据库
DBImpl::Recover -> VersionSet::Recover
如果不是第一次创建数据库,则实际上为恢复数据库中current文件中的所有数据库到缓存中;如果时第一次创建数据库,则无需做什么

VersionSet::Recover函数中current文件读出来就是MANIFEST-000001\n
dscname则为全路径 ./testdb/MANIFEST-000001(前面将\n去掉了)
这些都是为了创建这个file文件,便于后续访问。
leveldb的启动流程
接下来的这个while循环,对于新建立的数据库,record读出来为:
{data_ = 0x5555557cf167 “\001\032leveldb.BytewiseComparator\002”, size_ = 34}
什么都没有,因此Apply函数也没有做什么,while循环也只是做了一次就退出。
如果是存在数据库为了恢复,就是为了从current文件中循环读出每次compaction的内容,一次循环调用一次builder.Apply函数,将version的每次变化累计到edit中。后续调用builder.SaveTo函数一起生效。
leveldb的启动流程
下面红框中即为上述SaveTo流程,
leveldb的启动流程
走到这个位置的时候 ReuseManifest函数时
manifest_file_number_ = 2
next_file_number_ = 3
leveldb的启动流程

leveldb的启动流程
接下来,在DB::Open中创建了第一个log文件000003.log
leveldb的启动流程

impl->versions_->LogAndApply中造出MANIFEST-000002