前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【深入浅出leveldb】文件类型与文件名

【深入浅出leveldb】文件类型与文件名

作者头像
公众号guangcity
发布2021-07-30 10:44:58
1.2K0
发布2021-07-30 10:44:58
举报
文章被收录于专栏:光城(guangcity)

【深入浅出leveldb】文件类型与文件名

leveldb运行一段时间后,系统中会产生一些文件,这些文件有哪些,各个文件又有什么作用,文件名怎么命名的呢?

本节来剖析这一块东东,代码在【db/filename.h】【 db/filename.cc】文件夹下面。

1.文件类型

总共有如下几种文件类型。

代码语言:javascript
复制
enum FileType {
  kLogFile,
  kDBLockFile,
  kTableFile,
  kDescriptorFile,
  kCurrentFile,
  kTempFile,
  kInfoLogFile  // Either the current one, or an old one
};
  • Log

LOG文件,以.log结尾,存储文件名是db/000003.log。

  • DBLock

该文件作为文件锁存在,文件名为LOCK,不保存任何东西。

  • DESCRIPTOR

这就是常说的manifest文件,以MANIFEST-开头。例如:db/MANIFEST-000002。

  • CURRENT

文件名就是CURRENT,里面的内容就是当前MANIFEST的文件名。

  • Temp

在使用新Manifest文件时,会创建一个dbtmp文件,然后rename成为真的,例如:db/000005.dbtmp。

  • INFO_LOG

文件名为LOG,当下次启动时,会以后缀LOG.old保存之前的LOG数据,新数据还会在LOG中。

2.文件名

FileNumber,每个文件会对应一个数字,且独一无二,不会出现MANIFEST-000002、000002.log这种情况,是全局递增的,

我们来看看MakeFileName。

代码语言:javascript
复制
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的有效后缀。

代码语言:javascript
复制
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。

代码语言:javascript
复制
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函数中,有下面一行:

代码语言:javascript
复制
const std::string manifest = DescriptorFileName(dbname_, 1);

可以看到给了manifest。

但实际上,我们看到的大部分情况是MANIFEST-000002,因为在Open调用NewDB后,调用了VersionSet.Recover,其中有一行:

代码语言:javascript
复制
next_file = edit.next_file_number_;

所以又回到了2。

在Open函数中,后面移除了为1的manifest文件。

代码语言:javascript
复制
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,这个后面说。

本节完~

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-07-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 光城 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 【深入浅出leveldb】文件类型与文件名
    • 1.文件类型
      • 2.文件名
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档