本片文章我们说一说leveldb中的文件命名规则。
这篇文章虽然放在前置知识,但是内部原理牵涉到leveldb中的Version相关类,所以看不懂没关系,只用知道一个结论:leveldb的所有带编号的文件共用一套编号系统,也就是说任何带编号的文件不可能有重复的编号。如不会出现 000001.ldb和000001.log文件这种情况。
运行leveldb程序一段时间后,我们会发现在系统给中,存在很多由数字编号的文件:
这篇文章从整体上谈一谈leveldb的文件命令和文件编号的来源。
1. 文件命名·
在leveldb中和文件命名相关的代码在:
- leveldb/db/filename.cc
- leveldb/db/filename.h
其核心为MakeFileName函数:
1 | static std::string MakeFileName(const std::string& dbname, uint64_t number, |
可以看到文件名时由 dbname + 6位number + 后缀组成的。 比如dbname = testdb, 则一个sstable的文件名可以为: testdb/000132.ldb. (ldb和sst都是sstable的有效后缀)
1 | std::string TableFileName(const std::string& dbname, uint64_t number) { |
另外,manifest文件没有调用MakeFileName,而是自己单独的函数:
1 | std::string DescriptorFileName(const std::string& dbname, uint64_t number) { |
2. 文件编号·
1. sstable, log和manifest的number·
dbname和后缀容易理解。那number是在哪儿来的?
实际上在leveldb中所有和编号有关的文件名的编码都有versonset来维护:
如log file的number:
1 | uint64_t new_log_number = impl->versions_->NewFileNumber(); |
又如sstable的number:
1 | file_number = versions_->NewFileNumber(); |
看看NewFileNumber:
1 | uint64_t NewFileNumber() { return next_file_number_++; } |
所以log和sst文件的编号都是由versionset中的next_file_number_来维护的。注意在versionset的构造函数中,next_file_number被初始化为2:
1 | VersionSet::VersionSet(const std::string& dbname, const Options* options, |
文件编号1在哪儿?·
那谁在用1呢?manifest_file_number_
在用。注意到在versionset
的构造函数中manifest_file_number_
初始化为0. 如果系统是首次使用,则会在NewDB中重新对manifest_file_number_
赋值:
1 | Status DBImpl::NewDB() { |
不过一般来说,除非你修改了options,否则你在运行leveldb时,看到的最小的manifest文件应该是,MANIFEST-000002. 这是为什么?这是因为在DBImpl::Open函数中调用NewDB函数后,紧接着调用了Recover.
1 | Status VersionSet::Recover(bool* save_manifest) { |
从这里就解释了 manifest_file_number_ = 2是如何来的, 那manifest_file_number_ = 1是如何消失的?在DBImpl::Open的下半部分:
1 | if (s.ok()) { |
不过要意识到,这只是系统第一次使用启动时manifest_file_number的指定过程。 在后序的使用过程中,manifest_file_number的初始化是从VersionSet::Recover
中开始,这其中 manifest_file_number仍然由next_file_number_指定,另外还要考虑是否Reuse旧manifest文件,如果复用,manifest_file_number将等于旧manifest的number。
总结·
总结起来一句话,sstable, log, manifest的编号都是由versoinset的next_file_number_来指定。
2. VersoinSet中的LogNumber和PrevLogNumber·
PrevLogNumber已不再使用。
LogNumber存放的是当前系统有效的log file 的number。用于写log、recover系统时判定是否有newer log没有转化为sstable等。