1、创建一个DBImpl对象,DBImpl是DB的子类
2、加锁
3、调用Recover把数据库恢复成为上次退出时的状态
4、创建日志文件以及对应的内存table
5、把版本变更应用到当前的版本上,使当前版本的状态最新
6、删除过期文件
7、调度后台进程,后台进程的功能是进行table数据的合并压缩
2、加锁
3、调用Recover把数据库恢复成为上次退出时的状态
4、创建日志文件以及对应的内存table
5、把版本变更应用到当前的版本上,使当前版本的状态最新
6、删除过期文件
7、调度后台进程,后台进程的功能是进行table数据的合并压缩
8、返回
// 打开数据库
Status DB::Open(const Options& options, // 选项
const std::string& dbname, // 数据库名字
DB** dbptr) // DB指针的指针
{
*dbptr = NULL;
// DBImpl是数据库的实现
// 创建一个DB对象
DBImpl* impl = new DBImpl(options, dbname);
// 上锁
impl->mutex_.Lock();
// VersionEdit表示一个Version和另一个Version之间的变化
VersionEdit edit;
// Recover handles create_if_missing, error_if_exists
// 是否保存清单
bool save_manifest = false;
// 恢复成为上次崩溃前或者退出前的状态
Status s = impl->Recover(&edit, &save_manifest);
// 成功,但是在内存中不存在,那么需要创建内存表格
if (s.ok() && impl->mem_ == NULL)
{
// Create new log and a corresponding memtable.
// 创建一个日志文件以及相对应的内存表
// 注意这里的日志并不是我们所说的那种打印几行文字的信息
// 而是在把数据写入数据库之前,先数据记录到日志文件中,成功之后才会写入到数据库中
// 这样就会更加安全了
// 创建一个日志编号
uint64_t new_log_number = impl->versions_->NewFileNumber();
// 创建一个可写文件——日志
WritableFile* lfile;
s = options.env->NewWritableFile(LogFileName(dbname, new_log_number),
&lfile);
// 成功
if (s.ok())
{
// 设置日志编号
edit.SetLogNumber(new_log_number);
// 设置日志文件
impl->logfile_ = lfile;
impl->logfile_number_ = new_log_number;
// 日志写入器,是对lfile的包装
impl->log_ = new log::Writer(lfile);
// 创建内存表格
impl->mem_ = new MemTable(impl->internal_comparator_);
// 增加内存表的引用
impl->mem_->Ref();
}
}
if (s.ok() && save_manifest)
{
// 设置版本变更的一些信息
edit.SetPrevLogNumber(0); // No older logs needed after recovery.
edit.SetLogNumber(impl->logfile_number_);
// 记录并应用——对于当前的版本应用一次版本变更,市值成为最新的状态
s = impl->versions_->LogAndApply(&edit, &impl->mutex_);
}
if (s.ok())
{
// 删除过时的文件
impl->DeleteObsoleteFiles();
// 调度后台进行进行压缩等等
impl->MaybeScheduleCompaction();
}
// 解锁
impl->mutex_.Unlock();
if (s.ok())
{
assert(impl->mem_ != NULL);
*dbptr = impl;
}
else
{
delete impl;
}
return s;
}