精通LevelDB
上QQ阅读APP看书,第一时间看更新

2.3 key比较函数接口Comparator

LevelDB是按key排序后进行存储,因此必然少不了对key的比较。在源码中,key的比较主要是基于Comparator这个接口实现的,Comparator是一个纯虚类,具体定义如下:

class Comparator{
public:
    virtual ~Comparator();
    virtual int Compare(const Slice &a, const Slice& b) const = 0;
    virtual const char* Name() const = 0;
    virtual void FindShortestSeparator(std::string *start, const Slice 
      &limit) const = 0;
    virtual void FindShortSuccessor(std::string *key) const = 0;
}

Comparator类的接口的具体作用,参见表2-1。其中,Compare方法是其主要的逻辑功能(即相应的字符串比较功能)的实现。Name用于获取这个比较器的名称,可以用这个函数检查比较器是否匹配。

表2-1 Comparator类的主要接口

000

一般而言,用户可以针对自身的要求,以Comparator为接口,定义新的比较算法模块。在LevelDB中,有两个实现Comparator的类:一个是BytewiseComparatorImpl,另一个是InternalKeyComparator。

BytewiseComparatorImpl是LevelDB中内置的默认比较器,主要采用字典序对两个字符串进行比较。Comparator接口理解的难点在于FindShortestSeparator和FindShortSuccessor这两个函数。下面分别对这两个函数在BytewiseComparatorImpl中的具体定义进行详细描述。

FindShortestSeparator(std::string* start, const Slice& limit)传入的参数是*start和limit这两个字符串。参数*start对应原字符串,而经过一系列逻辑处理后,相应的短字符串也将保存在*start中以返回。该函数在BytewiseComparatorImpl中的具体算法逻辑如下。

1)找出两个字符串*start和limit之间的共同前缀,如果没有共同前缀,则直接退出。

2)如果有共同前缀,判断start中共同前缀的后一个字符是否小于0xff,且后一个字符加1后要小于limit中共同前缀的后一个字符,如果条件不满足,则直接退出。

3)将*start中共同前缀的后一个字符串加1,然后去掉后续所有的字符,并返回退出。

为了更好地说明这个函数的具体实现,这里假如有*start = "abcd",limit="abzf ",则很明显它们之间有共同前缀ab,那么经过函数处理后c+1=d,*start最终为abd。

FindShortSuccessor(std::string* key)只传入一个参数,与FindShortestSeparator不同的是,该类没有limit参数,在实际的代码中,首先找出key字符串中第一个不为0xff的字符,并将该字符加1,然后丢弃后面的所有字符。例如,对于字符串"abcd",由于第一个字符a不等于0xff,那么最短的后继字符串为"a"+1,即"b"。