版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/simonyucsdy/article/details/81587790
Open函数(db/db_impl.cc,1500-1504)
//定义在db/db_impl.cc中
Status DB::Open(const Options& options, const std::string& dbname,
DB** dbptr) {
*dbptr = nullptr;
DBImpl* impl = new DBImpl(options, dbname);
//
1504行用到了桥接模式,DB的桥接类DBImpl构造函数():
DBImpl::DBImpl(const Options& raw_options, const std::string& dbname)
: env_(raw_options.env),
internal_comparator_(raw_options.comparator),
internal_filter_policy_(raw_options.filter_policy),
options_(SanitizeOptions(dbname, &internal_comparator_,
&internal_filter_policy_, raw_options)),
owns_info_log_(options_.info_log != raw_options.info_log),
owns_cache_(options_.block_cache != raw_options.block_cache),
dbname_(dbname),
table_cache_(new TableCache(dbname_, options_, TableCacheSize(options_))),
db_lock_(nullptr),
shutting_down_(nullptr),
background_work_finished_signal_(&mutex_),
mem_(nullptr),
imm_(nullptr),
logfile_(nullptr),
logfile_number_(0),
log_(nullptr),
seed_(0),
tmp_batch_(new WriteBatch),
background_compaction_scheduled_(false),
manual_compaction_(nullptr),
versions_(new VersionSet(dbname_, &options_, table_cache_, &internal_comparator_))
{
has_imm_.Release_Store(nullptr);
}
- env_, 负责所有IO操作
- internal_comparator_, 比较器,比较不同key的大小
- internal_filter_policy_, 自定义文件过滤
- options_, 动作选择
- db_lock_, 文件锁
- shutting_down_, 基于memory barrier的原子指针
- mem_ , memtable
- imm_, immemtable
- tmp_batch_, 所有Put都是以batch写入, 这里建立个临时的
- manual_compaction_,
- has_imm_,是否有正在等待的immemtable
- table_cache_,SSTable查询缓存
- versions_,MVCC
Status DB::Open(const Options& options, const std::string& dbname,
DB** dbptr) {
*dbptr = nullptr;
DBImpl* impl = new DBImpl(options, dbname);
impl->mutex_.Lock(); //上锁
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_ == nullptr) {
// 恢复成功且没有memtable,则创建log和相应的memtable
// Create new log and a corresponding memtable.
uint64_t new_log_number = impl->versions_->NewFileNumber();
WritableFile* lfile;
// 新建可写文件lfile
s = options.env->NewWritableFile(LogFileName(dbname, new_log_number), &lfile);
if (s.ok()) {
edit.SetLogNumber(new_log_number); //
impl->logfile_ = lfile; //DB的log文件
impl->logfile_number_ = new_log_number; //log文件数目
impl->log_ = new log::Writer(lfile); //写文件
impl->mem_ = new MemTable(impl->internal_comparator_); //新建memtable
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(); //检查是否需要compaction
}
impl->mutex_.Unlock(); //解锁
if (s.ok()) {
assert(impl->mem_ != nullptr);
*dbptr = impl;
} else {
delete impl;
}
return s;
}
这就是整个的Open操作流程,需要着重说一下VersionEdit的概念,由于LSM Tree机制没有任何主索引体系(不使用哈希表), 只要保证Log+SSTable正确, 就一定能得到正确的结果,所以不同version之间的差别就是SSTable的差别, A版本到B版本, A版本对SSTable执行了删除e, d, f的操作, B版本对其执行了增加o, p, q的操作,两者合并就是最终的SSTable,这就使SSTable具有了性能稳定性。
VersionEdit_t0 + VersionEdit_t1 = Data_t1