ldb中log的读写分析

 

log的读涉及到的关键变量如图所示。
ldb中log的读写分析_第1张图片
log文件在物理上是分块存储的,而在逻辑上一个个record存储的。

一个record可能跨越了几个block,所以每个record可能会被分为几个record,分别存储。

 

record的结构是[uint32_t crc32c校验][uint16_t 数据长度][uint8_t 类型]

log文件涉及到的record类型有

FULL      == 1

FIRST     == 2

MIDDLE  == 3

LAST      == 4

从字面意思我们可以很容易看出他们的作用。

这个类型可以有其他类型的,只是被log模块忽略。

 

log_read的对象不给复制,经典的写法

// No copying allowed
  Reader(const Reader&);
  void operator=(const Reader&);

 

log模块对数据的可靠性下了很多功夫,就是说,通过log_read读到的数据一定是正确的,

对于错误的数据它能自动抛弃掉,并且用户能自定义发现错误时的行为(例如将一些信息记录下来什么的)

  class Reporter {
   public:
    virtual ~Reporter();

    // Some corruption was detected.  "size" is the approximate number
    // of bytes dropped due to the corruption.
    virtual void Corruption(size_t bytes, const Status& status) = 0;
  };

 Corruption这个虚函数可以用户自己定义,当然也可以使用缺省的,ldb自带的。

一个record的crc32c是根据type和数据的body进行计算,tpye的crc32c作为初始值。

crc32c有标准的算法,所以ldb在代码逻辑上将算crc32c的算法模块独立出来的,

而代码中对于crc32c的计算是通过一个extern函数引进来的,ldb中有很多这样的理念,

就是把一个独立方法模块,通过extern引进来。至于怎么样才算独立,后续的分析再说说吧。

extern uint32_t Extend(uint32_t init_crc, const char* data, size_t n);

 

而且对算出来的crc32c的值做了一个变换(自定义mask操作)

这样做有什么好处是:在别人不知你代码中mask的情况下,无法篡改你的数据。

前面说log模块是极度保证数据的可靠性的。这也算是一个佐证吧。

 

虚函数和extern是ldb中使用广泛的手段,下来将持续关注分析。

好吧,其他的产品也是广泛使用,只是使用的方法不同,但是各有各的理由。

 

你可能感兴趣的:(log)