了解LevelDB block实现源码,并读取footer

LevelDB

Block类

构造函数

其中,对于block的构造函数,使用了explicit关键字,主要用于避免类型转换,参考这里

构造函数用于插入数据并判断大小:

sstable1

Iterator

block类中,还存在一个iter类,是nested classes,参考官网

主要看ParseNextKey函数,迭代器重要任务就是解析出记录:

  1. 当为第一条记录时,共享部分为0, key_.append(p, non_shared);这行代码就是将第一条完整记录加在key_后面。
  2. 当不是第一条记录时,此时key_.resize(shared);这行代码获取当前记录和上一条记录共享部分, key_.append(p, non_shared);这行代码就获得非共享部分,凑成完整的记录。
  3. 最后,如果下一个key是在另一个group中,就将restart_index往下指。

此时这个迭代器的key_指向第一条记录的key,value_指向第一条记录的value。

sstable2

Two Level Iterator类

如果要读取一个SStable文件的某个键值对,首先要读取data block,然后才是从这个data block中读取键值对。所以有两次迭代,即两个迭代器。

构造函数

sstable3

读取第一个样本

经过SeekToFirstInitDataBlock 这两个函数之后,index_iter_指向index_block第一条记录,data_iter_指向第一个块的首位置

sstable4

获取数据

先构造一个sst文件的Table类,然后构造出Table的迭代器,从迭代器就可以获取这个文件的任何键值(seek函数)

sstable5

读取footer

结构

sstable6

可以发现,footer一共有4个结构+magic number,每个结构最多10个字节,需要使用GetVarint64得到。

代码

首先需要创建一个SStable,然后通过指针指到footer,再依次读出里面的结构。


#include <cstdio>
#include <iostream>

using namespace std;

int getFileSize(const string &filename) {
    int size = 0;
    FILE* fp = nullptr;

    fp = fopen(filename.c_str(), "r");
    if (nullptr == fp) {
        return size;
    }
    fseek(fp, 0L, SEEK_END);
    size = ftell(fp);
    fclose(fp);

    return size;

}

char* GetVarint64Ptr(char* p, const char* limit, uint64_t* value) {
    uint64_t result = 0;
    for (uint32_t shift = 0; shift <= 63 && p < limit; shift += 7) {
        uint64_t byte = *(reinterpret_cast<const unsigned char*>(p));
        p++;
        if (byte & 128) {
            // More bytes are present
            result |= ((byte & 127) << shift);
        } else {
            result |= (byte << shift);
            *value = result;
            return p;
        }
    }
    return nullptr;
}

char* GetVarint64(char* input, int size, uint64_t* value) {
    char* limit = input + size;
    char* q = GetVarint64Ptr(input, limit, value);
    return q;
}

int main() {
    string fileName = "testdb.ldb";
    int fileSize = getFileSize(fileName);
    //文件总大小
    cout<<"File Size:"<<getFileSize(fileName)<<endl;

    FILE* fp = fopen(fileName.c_str(), "r");
    fseek(fp, -48L, SEEK_END);
    char* footer = (char *)malloc(48 * sizeof(char));
    fgets(footer, 48, fp);
    uint64_t metaOffset, metaSize, indexOffset, indexSize;
    footer = GetVarint64(footer, 10, &metaOffset);
    footer = GetVarint64(footer, 10, &metaSize);
    footer = GetVarint64(footer, 10, &indexOffset);
    footer = GetVarint64(footer, 10, &indexSize);
    cout<<"Meta offset:"<<metaOffset<<endl
        <<"Meta size:"<<metaSize<<endl
        <<"Index offset:"<<indexOffset<<endl
        <<"Index size:"<<indexSize<<endl;

    char* index = (char *) malloc((indexSize + 1) * sizeof(char));
    fseek(fp, 0L, static_cast<int>(indexOffset));
    fgets(index, static_cast<int>(indexSize + 1), fp);
//    cout<<index[indexSize]<<endl;
    return 0;
}

results matching ""

    No results matching ""