接口 # 一个ABC,后面会继承这个类做各种实现
clean up function # 代码比较好懂,唯一让我感到疑惑的是 clean up function 这部分
1 2 // FIXME: 不太理解为什么需要很多个clean up function 3 // Cleanup functions are stored in a single-linked list. 4 // The list's head node is inlined in the iterator. 5 struct CleanupNode { 6 // True if the node is not used. Only head nodes might be unused. 7 bool IsEmpty() const { return function == nullptr; } 8 // Invokes the cleanup function. 9 void Run() { 10 assert(function != nullptr); 11 (*function)(arg1, arg2); 12 } 13 14 // The head node is used if the function pointer is not null. 15 CleanupFunction function; 16 void* arg1; 17 void* arg2; 18 CleanupNode* next; 19 }; 20 CleanupNode cleanup_head_; 21}; 从 table/iterator.cc 的析构函数中,可以看到在iterator析构的时候会依次调用多个clean up function
FilterPolicy接口 # 1 2class LEVELDB_EXPORT FilterPolicy { 3 public: 4 virtual ~FilterPolicy(); 5 6 // Return the name of this policy. Note that if the filter encoding 7 // changes in an incompatible way, the name returned by this method 8 // must be changed. Otherwise, old incompatible filters may be 9 // passed to methods of this type. 10 virtual const char* Name() const = 0; 11 12 // keys[0,n-1] contains a list of keys (potentially with duplicates) 13 // that are ordered according to the user supplied comparator. 14 // Append a filter that summarizes keys[0,n-1] to *dst. 15 // 16 // Warning: do not change the initial contents of *dst. Instead, 17 // append the newly constructed filter to *dst. 18 virtual void CreateFilter(const Slice* keys, int n, 19 std::string* dst) const = 0; 20 21 // "filter" contains the data appended by a preceding call to 22 // CreateFilter() on this class. This method must return true if 23 // the key was in the list of keys passed to CreateFilter(). 24 // This method may return true or false if the key was not on the 25 // list, but it should aim to return false with a high probability. 26 virtual bool KeyMayMatch(const Slice& key, const Slice& filter) const = 0; 27}; 其中CreateFilter的含义是从n个key生成一个 std::string. 生成的std::string可以包含n个key的信息(类似于生成了一个全集) 从而后续判断某个key是否在其中。
levelDB是一个有序的KV存储,因此key的顺序是十分关键的 levelDB提供用户自己定义key顺序的能力
先看下comparator的接口
接口 include/leveldb/comparator.h # 1 2// A Comparator object provides a total order across slices that are 3// used as keys in an sstable or a database. A Comparator implementation 4// must be thread-safe since leveldb may invoke its methods concurrently 5// from multiple threads. 6class LEVELDB_EXPORT Comparator { 7 public: 8 virtual ~Comparator(); 9 10 // Three-way comparison. Returns value: 11 // < 0 iff "a" < "b", 12 // == 0 iff "a" == "b", 13 // > 0 iff "a" > "b" 14 virtual int Compare(const Slice& a, const Slice& b) const = 0; 15 16 // The name of the comparator. Used to check for comparator 17 // mismatches (i.e., a DB created with one comparator is 18 // accessed using a different comparator. 19 // 20 // The client of this package should switch to a new name whenever 21 // the comparator implementation changes in a way that will cause 22 // the relative ordering of any two keys to change. 23 // 24 // Names starting with "leveldb." are reserved and should not be used 25 // by any clients of this package. 26 virtual const char* Name() const = 0; 27 28 // Advanced functions: these are used to reduce the space requirements 29 // for internal data structures like index blocks. 30 31 // If *start < limit, changes *start to a short string in [start,limit). 32 // Simple comparator implementations may return with *start unchanged, 33 // i.e., an implementation of this method that does nothing is correct. 34 virtual void FindShortestSeparator(std::string* start, 35 const Slice& limit) const = 0; 36 37 // Changes *key to a short string >= *key. 38 // Simple comparator implementations may return with *key unchanged, 39 // i.e., an implementation of this method that does nothing is correct. 40 virtual void FindShortSuccessor(std::string* key) const = 0; 41}; 比较让人迷惑的应该是 FindShortestSeparator 和 FindShortSuccessor 函数。 其实可以简单理解成为了节省存储,而对key做了一定修改。 这个实现是不确定的,甚至完全什么都不做也是合法的。
参考资料
看 leveldb 源码中遇到的,关于 lock-free 和 wait-free..感觉这个讲得不错,我试着翻译一下?
There are two types of non-blocking thread synchronization algorithms - lock-free, and wait-free. Their meaning is often confused. In lock-free systems, while any particular computation may be blocked for some period of time, all CPUs are able to continue performing other computations. To put it differently, while a given thread might be blocked by other threads in a lock-free system, all CPUs can continue doing other useful work without stalls. Lock-free algorithms increase the overall throughput of a system by occassionally increasing the latency of a particular transaction. Most high- end database systems are based on lock-free algorithms, to varying degrees.