leveldb运行一段时间后,系统中会产生一些文件,这些文件有哪些,各个文件又有什么作用,文件名怎么命名的呢?
本节来剖析这一块东东,代码在【db/filename.h】【 db/filename.cc】文件夹下面。
总共有如下几种文件类型。
enum FileType {
kLogFile,
kDBLockFile,
kTableFile,
kDescriptorFile,
kCurrentFile,
kTempFile,
kInfoLogFile // Either the current one, or an old one
};
LOG文件,以.log结尾,存储文件名是db/000003.log。
该文件作为文件锁存在,文件名为LOCK,不保存任何东西。
这就是常说的manifest文件,以MANIFEST-开头。例如:db/MANIFEST-000002。
文件名就是CURRENT,里面的内容就是当前MANIFEST的文件名。
在使用新Manifest文件时,会创建一个dbtmp文件,然后rename成为真的,例如:db/000005.dbtmp。
文件名为LOG,当下次启动时,会以后缀LOG.old保存之前的LOG数据,新数据还会在LOG中。
FileNumber,每个文件会对应一个数字,且独一无二,不会出现MANIFEST-000002、000002.log这种情况,是全局递增的,
我们来看看MakeFileName。
static std::string MakeFileName(const std::string& dbname, uint64_t number,
const char* suffix) {
char buf[100];
std::snprintf(buf, sizeof(buf), "/%06llu.%s",
static_cast<unsigned long long>(number), suffix);
return dbname + buf;
}
在该函数中,会创建dbname+6位number+后缀组成的文件名。例如:testname=testdb,文件名可以是:testdb/000005.ldb。
ldb与sst都是sstable的有效后缀。
std::string TableFileName(const std::string& dbname, uint64_t number) {
assert(number > 0);
return MakeFileName(dbname, number, "ldb");
}
std::string SSTTableFileName(const std::string& dbname, uint64_t number) {
assert(number > 0);
return MakeFileName(dbname, number, "sst");
}
而manifest是单独实现,没有调用MakeFileName。
std::string DescriptorFileName(const std::string& dbname, uint64_t number) {
assert(number > 0);
char buf[100];
std::snprintf(buf, sizeof(buf), "/MANIFEST-%06llu",
static_cast<unsigned long long>(number));
return dbname + buf;
}
在sstable、log、manifest的文件numer,均是来自versionset,version相关代码,我们后面分析,这一块是最复杂一块,特别晕。
只需记得,这几个来自versionset的next_file_number_
,构造函数中初始化next_file_number_
位2。
那1给谁了呢?
在NewDB函数中,有下面一行:
const std::string manifest = DescriptorFileName(dbname_, 1);
可以看到给了manifest。
但实际上,我们看到的大部分情况是MANIFEST-000002,因为在Open调用NewDB后,调用了VersionSet.Recover,其中有一行:
next_file = edit.next_file_number_;
所以又回到了2。
在Open函数中,后面移除了为1的manifest文件。
impl->RemoveObsoleteFiles();
此外,还有一个ParseFileName函数,当传递一个文件时,可以解析出number与type,例如:db/MANIFEST-000002,我们知道文件类型是kDescriptorFile,编号是2。
SetCurrentFile则是将更新一个新的CURRENT文件,它会将MANIFEST变为dbtmp文件,例如:db/MANIFEST-000002会变为db/000002.dbtmp,随后将MANIFEST-000002写入dbtmp文件中,如果写入成功,重命名为CURRENT文件,否则,删除掉即可。
最后,少讲了一个WriteStringToFileSync,这个后面说。
本节完~