当我们不再使用leveldb时,会将 db 这个对象删除。 那在db的析构函数中会做哪些工作?
1 2 3 leveldb::DB *db; ... delete db;
1. db的析构函数·
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 DBImpl::~DBImpl () { mutex_.Lock (); shutting_down_.store (true , std::memory_order_release); while (background_compaction_scheduled_) { background_work_finished_signal_.Wait (); } mutex_.Unlock (); if (db_lock_ != nullptr ) { env_->UnlockFile (db_lock_); } delete versions_; if (mem_ != nullptr ) mem_->Unref (); if (imm_ != nullptr ) imm_->Unref (); delete tmp_batch_; delete log_; delete logfile_; delete table_cache_; if (owns_info_log_) { delete options_.info_log; } if (owns_cache_) { delete options_.block_cache; } }
基本上这个函数都是在做资源释放,包括:
等待compaction结束,强制开启shutting_down_
, 后序compaction会监测这个变量,一旦它为true,就不会compaction了。也就是说当前的memtable不一定能完全dump到下层中。 但是后序重启Open leveldb时,可以从log文件中恢复。
解文件锁,这个文件锁是用来保证同一时刻只有一个进程可以使用一个leveldb数据库。
释放version_资源
释放memtable
释放其它资源
2. versions_析构·
1 2 3 4 5 6 7 8 VersionSet::~VersionSet () { current_->Unref (); assert (dummy_versions_.next_ == &dummy_versions_); delete descriptor_log_; delete descriptor_file_; }
首先看 current_->Unref():
1 2 3 4 5 6 7 8 void Version::Unref () { assert (this != &vset_->dummy_versions_); assert (refs_ >= 1 ); --refs_; if (refs_ == 0 ) { delete this ; } }
1. version析构·
接着是当前版本的析够:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 Version::~Version () { assert (refs_ == 0 ); prev_->next_ = next_; next_->prev_ = prev_; for (int level = 0 ; level < config::kNumLevels; level++) { for (size_t i = 0 ; i < files_[level].size (); i++) { FileMetaData* f = files_[level][i]; assert (f->refs > 0 ); f->refs--; if (f->refs <= 0 ) { delete f; } } } }
第一步从versionset中移除本版本,第二步释放所有 FileMeta 。
3. mem析构·
mem的析够比较简单了,当引用计数降低到0时,自动delete:
1 2 3 4 5 6 7 8 void Unref () { --refs_; assert (refs_ >= 0 ); if (refs_ <= 0 ) { delete this ; } }
4. 总结·
db对象的删除,基本做的工作就是释放各个环节中设涉及到的资源,如version,memtable,cache。