leveldb 学习记录(四) skiplist补与变长数字

leveldb 学习记录(一) skiplist 已经将skiplist的插入 查找等操作流程用图示说明

这里在介绍 下skiplist的代码

里面有几个模块  

template<typename Key, class Comparator>
class SkipList {......}

class Arena;(内存池模块 暂时不介绍)

struct Node;(节点 存储key 和指向其他Node的指针)

 

//Node 构造函数  KEY赋值
// Implementation details follow
template<typename Key, class Comparator>
struct SkipList<Key,Comparator>::Node {
  explicit Node(const Key& k) : key(k) { }

  Key const key;

  // Accessors/mutators for links.  Wrapped in methods so we can
  // add the appropriate barriers as necessary.
  // 访问修改器使用 包装在方法中 可以使用内存屏障
  // Node指向的另一层?
  Node* Next(int n) {
    assert(n >= 0);
    // Use an 'acquire load' so that we observe a fully initialized
    // version of the returned Node.
    return reinterpret_cast<Node*>(next_[n].Acquire_Load());
  }
  //设置下层Node指向
  void SetNext(int n, Node* x) {
    assert(n >= 0);
    // Use a 'release store' so that anybody who reads through this
    // pointer observes a fully initialized version of the inserted node.
    next_[n].Release_Store(x);
  }

  // No-barrier variants that can be safely used in a few locations.
  // 读取本Node在N层的NODE指向  非内存屏蔽操作
  Node* NoBarrier_Next(int n) {
    assert(n >= 0);
    return reinterpret_cast<Node*>(next_[n].NoBarrier_Load());
  }
  
  //设置Node 在N层的Node指向  非内存屏蔽操作 
  void NoBarrier_SetNext(int n, Node* x) {
    assert(n >= 0);
    next_[n].NoBarrier_Store(x);
  }

 private:
  // Array of length equal to the node height.  next_[0] is lowest level link.
  // 原子指针数组  指向其他Node  创建时候动态确认数组长度
  port::AtomicPointer next_[1];
};

  

结构示意图如下

其他操作可参见系列文章一

最后附上我注释的代码

  1 #include <assert.h>
  2 #include <stdlib.h>
  3 #include "port/port.h"
  4 #include "util/arena.h"
  5 #include "util/random.h"
  6 
  7 namespace leveldb {
  8 
  9 class Arena;
 10 
 11 template<typename Key, class Comparator>
 12 class SkipList {
 13  private:
 14   struct Node;
 15 
 16  public:
 17   // Create a new SkipList object that will use "cmp" for comparing keys,
 18   // and will allocate memory using "*arena".  Objects allocated in the arena
 19   // must remain allocated for the lifetime of the skiplist object.
 20   explicit SkipList(Comparator cmp, Arena* arena);
 21 
 22   // Insert key into the list.
 23   // REQUIRES: nothing that compares equal to key is currently in the list.
 24   void Insert(const Key& key);
 25 
 26   // Returns true iff an entry that compares equal to key is in the list.
 27   bool Contains(const Key& key) const;
 28 
 29   // Iteration over the contents of a skip list
 30   class Iterator {
 31    public:
 32     // Initialize an iterator over the specified list.
 33     // The returned iterator is not valid.
 34     explicit Iterator(const SkipList* list);
 35 
 36     // Returns true iff the iterator is positioned at a valid node.
 37     bool Valid() const;
 38 
 39     // Returns the key at the current position.
 40     // REQUIRES: Valid()
 41     const Key& key() const;
 42 
 43     // Advances to the next position.
 44     // REQUIRES: Valid()
 45     void Next();
 46 
 47     // Advances to the previous position.
 48     // REQUIRES: Valid()
 49     void Prev();
 50 
 51     // Advance to the first entry with a key >= target
 52     void Seek(const Key& target);
 53 
 54     // Position at the first entry in list.
 55     // Final state of iterator is Valid() iff list is not empty.
 56     void SeekToFirst();
 57 
 58     // Position at the last entry in list.
 59     // Final state of iterator is Valid() iff list is not empty.
 60     void SeekToLast();
 61 
 62    private:
 63     const SkipList* list_;
 64     Node* node_;
 65     // Intentionally copyable
 66   };
 67 
 68  private:
 69   enum { kMaxHeight = 12 };
 70 
 71   // Immutable after construction
 72   Comparator const compare_;
 73   Arena* const arena_;    // Arena used for allocations of nodes
 74 
 75   Node* const head_;
 76 
 77   // Modified only by Insert().  Read racily by readers, but stale
 78   // values are ok.
 79   port::AtomicPointer max_height_;   // Height of the entire list
 80 
 81   inline int GetMaxHeight() const {
 82     return reinterpret_cast<intptr_t>(max_height_.NoBarrier_Load());
 83   }
 84 
 85   // Read/written only by Insert().
 86   Random rnd_;
 87 
 88   Node* NewNode(const Key& key, int height);
 89   int RandomHeight();
 90   bool Equal(const Key& a, const Key& b) const { return (compare_(a, b) == 0); }
 91 
 92   // Return true if key is greater than the data stored in "n"
 93   bool KeyIsAfterNode(const Key& key, Node* n) const;
 94 
 95   // Return the earliest node that comes at or after key.
 96   // Return NULL if there is no such node.
 97   //
 98   // If prev is non-NULL, fills prev[level] with pointer to previous
 99   // node at "level" for every level in [0..max_height_-1].
100   Node* FindGreaterOrEqual(const Key& key, Node** prev) const;
101 
102   // Return the latest node with a key < key.
103   // Return head_ if there is no such node.
104   Node* FindLessThan(const Key& key) const;
105 
106   // Return the last node in the list.
107   // Return head_ if list is empty.
108   Node* FindLast() const;
109 
110   // No copying allowed
111   SkipList(const SkipList&);
112   void operator=(const SkipList&);
113 };
114 
115 
116 //Node 构造函数  KEY赋值
117 // Implementation details follow
118 template<typename Key, class Comparator>
119 struct SkipList<Key,Comparator>::Node {
120   explicit Node(const Key& k) : key(k) { }
121 
122   Key const key;
123 
124   // Accessors/mutators for links.  Wrapped in methods so we can
125   // add the appropriate barriers as necessary.
126   // 访问修改器使用 包装在方法中 可以使用内存屏障
127   // Node指向的另一层?
128   Node* Next(int n) {
129     assert(n >= 0);
130     // Use an 'acquire load' so that we observe a fully initialized
131     // version of the returned Node.
132     return reinterpret_cast<Node*>(next_[n].Acquire_Load());
133   }
134   //设置下层Node指向
135   void SetNext(int n, Node* x) {
136     assert(n >= 0);
137     // Use a 'release store' so that anybody who reads through this
138     // pointer observes a fully initialized version of the inserted node.
139     next_[n].Release_Store(x);
140   }
141 
142   // No-barrier variants that can be safely used in a few locations.
143   // 读取本Node在N层的NODE指向  非内存屏蔽操作
144   Node* NoBarrier_Next(int n) {
145     assert(n >= 0);
146     return reinterpret_cast<Node*>(next_[n].NoBarrier_Load());
147   }
148   
149   //设置Node 在N层的Node指向  非内存屏蔽操作 
150   void NoBarrier_SetNext(int n, Node* x) {
151     assert(n >= 0);
152     next_[n].NoBarrier_Store(x);
153   }
154 
155  private:
156   // Array of length equal to the node height.  next_[0] is lowest level link.
157   // 原子指针数组  指向其他Node  创建时候动态确认数组长度
158   port::AtomicPointer next_[1];
159 };
160 
161 
162 //创建一个NODE 内存池arena_分配内存  height确认该NODE的Node指向数量
163 template<typename Key, class Comparator>
164 typename SkipList<Key,Comparator>::Node*
165 SkipList<Key,Comparator>::NewNode(const Key& key, int height) {
166   char* mem = arena_->AllocateAligned(
167       sizeof(Node) + sizeof(port::AtomicPointer) * (height - 1));
168   return new (mem) Node(key);
169 }
170 
171 //根据输入的SkipList指针构造一个  iterator
172 template<typename Key, class Comparator>
173 inline SkipList<Key,Comparator>::Iterator::Iterator(const SkipList* list) {
174   list_ = list;
175   node_ = NULL;
176 }
177 
178 //
179 template<typename Key, class Comparator>
180 inline bool SkipList<Key,Comparator>::Iterator::Valid() const {
181   return node_ != NULL;
182 }
183 
184 
185 //返回iterator指向的Node的key
186 template<typename Key, class Comparator>
187 inline const Key& SkipList<Key,Comparator>::Iterator::key() const {
188   assert(Valid());
189   return node_->key;
190 }
191 
192 
193 //获取iterator指向的下一个node  在第0层获取(Node第0层均有记录)
194 template<typename Key, class Comparator>
195 inline void SkipList<Key,Comparator>::Iterator::Next() {
196   assert(Valid());
197   node_ = node_->Next(0);
198 }
199 
200 //寻找该node上一个node
201 template<typename Key, class Comparator>
202 inline void SkipList<Key,Comparator>::Iterator::Prev() {
203   // Instead of using explicit "prev" links, we just search for the
204   // last node that falls before key.
205   assert(Valid());
206   node_ = list_->FindLessThan(node_->key);
207   if (node_ == list_->head_) {
208     node_ = NULL;
209   }
210 }
211 
212 
213 //调用 FindGreaterOrEqual 查找 
214 template<typename Key, class Comparator>
215 inline void SkipList<Key,Comparator>::Iterator::Seek(const Key& target) {
216   node_ = list_->FindGreaterOrEqual(target, NULL);
217 }
218 
219 //重置到head  Node 第0层 第一个Node
220 template<typename Key, class Comparator>
221 inline void SkipList<Key,Comparator>::Iterator::SeekToFirst() {
222   node_ = list_->head_->Next(0);
223 }
224 
225 //重置到last Node
226 template<typename Key, class Comparator>
227 inline void SkipList<Key,Comparator>::Iterator::SeekToLast() {
228   node_ = list_->FindLast();
229   if (node_ == list_->head_) {
230     node_ = NULL;
231   }
232 }
233 
234 
235 //返回height  随机增加1
236 template<typename Key, class Comparator>
237 int SkipList<Key,Comparator>::RandomHeight() {
238   // Increase height with probability 1 in kBranching
239   static const unsigned int kBranching = 4;
240   int height = 1;
241   while (height < kMaxHeight && ((rnd_.Next() % kBranching) == 0)) {
242     height++;
243   }
244   assert(height > 0);
245   assert(height <= kMaxHeight);
246   return height;
247 }
248 
249 //调用 cmp 比较是大小
250 template<typename Key, class Comparator>
251 bool SkipList<Key,Comparator>::KeyIsAfterNode(const Key& key, Node* n) const {
252   // NULL n is considered infinite
253   return (n != NULL) && (compare_(n->key, key) < 0);
254 }
255 
256 
257 //寻找比key大或者等于的Node
258 template<typename Key, class Comparator>
259 typename SkipList<Key,Comparator>::Node* SkipList<Key,Comparator>::FindGreaterOrEqual(const Key& key, Node** prev)
260     const {
261   Node* x = head_;
262   int level = GetMaxHeight() - 1;
263   //    k在Next后面 则在本level寻找 否则 在下一层level寻找
264   while (true) {
265     Node* next = x->(level);
266     if (KeyIsAfterNode(key, next)) {
267       // Keep searching in this list
268       x = next;
269     } else {
270       if (prev != NULL) prev[level] = x;
271       if (level == 0) {
272         return next;
273       } else {
274         // Switch to next list
275         level--;
276       }
277     }
278   }
279 }
280 
281 
282 //寻找小于等于KEY的第一个NODE
283 template<typename Key, class Comparator>
284 typename SkipList<Key,Comparator>::Node*
285 SkipList<Key,Comparator>::FindLessThan(const Key& key) const {
286   Node* x = head_;
287   int level = GetMaxHeight() - 1;
288   while (true) {
289     assert(x == head_ || compare_(x->key, key) < 0);
290     Node* next = x->Next(level);
291     if (next == NULL || compare_(next->key, key) >= 0) {
292       if (level == 0) {
293         return x;
294       } else {
295         // Switch to next list
296         level--;
297       }
298     } else {
299       x = next;
300     }
301   }
302 }
303 
304 //在最高层 寻找最后一个Node
305 template<typename Key, class Comparator>
306 typename SkipList<Key,Comparator>::Node* SkipList<Key,Comparator>::FindLast()
307     const {
308   Node* x = head_;
309   int level = GetMaxHeight() - 1;
310   while (true) {
311     Node* next = x->Next(level);
312     if (next == NULL) {
313       if (level == 0) {
314         return x;
315       } else {
316         // Switch to next list
317         level--;
318       }
319     } else {
320       x = next;
321     }
322   }
323 }
324 
325 
326 //构建函数 第一个head Node key是0 后继Node指针最大kMaxHeight
327 template<typename Key, class Comparator>
328 SkipList<Key,Comparator>::SkipList(Comparator cmp, Arena* arena)
329     : compare_(cmp),
330       arena_(arena),
331       head_(NewNode(0 /* any key will do */, kMaxHeight)),
332       max_height_(reinterpret_cast<void*>(1)),
333       rnd_(0xdeadbeef) {
334   for (int i = 0; i < kMaxHeight; i++) {
335     head_->SetNext(i, NULL);
336   }
337 }
338 
339 //insert算法
340 template<typename Key, class Comparator>
341 void SkipList<Key,Comparator>::Insert(const Key& key) {
342   // TODO(opt): We can use a barrier-free variant of FindGreaterOrEqual()
343   // here since Insert() is externally synchronized.
344   Node* prev[kMaxHeight];
345   Node* x = FindGreaterOrEqual(key, prev);
346 
347   // Our data structure does not allow duplicate insertion
348   assert(x == NULL || !Equal(key, x->key));
349 
350   int height = RandomHeight();
351   if (height > GetMaxHeight()) {
352     for (int i = GetMaxHeight(); i < height; i++) {
353       prev[i] = head_;
354     }
355     //fprintf(stderr, "Change height from %d to %d\n", max_height_, height);
356 
357     // It is ok to mutate max_height_ without any synchronization
358     // with concurrent readers.  A concurrent reader that observes
359     // the new value of max_height_ will see either the old value of
360     // new level pointers from head_ (NULL), or a new value set in
361     // the loop below.  In the former case the reader will
362     // immediately drop to the next level since NULL sorts after all
363     // keys.  In the latter case the reader will use the new node.
364     max_height_.NoBarrier_Store(reinterpret_cast<void*>(height));
365   }
366 
367   x = NewNode(key, height);
368   for (int i = 0; i < height; i++) {
369     // NoBarrier_SetNext() suffices since we will add a barrier when
370     // we publish a pointer to "x" in prev[i].
371     x->NoBarrier_SetNext(i, prev[i]->NoBarrier_Next(i));
372     prev[i]->SetNext(i, x);
373   }
374 }
375 
376 
377 //寻找等于KEY 即可确认是否包含与KEY相等的Node
378 template<typename Key, class Comparator>
379 bool SkipList<Key,Comparator>::Contains(const Key& key) const {
380   Node* x = FindGreaterOrEqual(key, NULL);
381   if (x != NULL && Equal(key, x->key)) {
382     return true;
383   } else {
384     return false;
385   }
386 }
387 
388 }
View Code

 

 varint变长数

 leveldb使用了Protocol Buffers的变长字节整形编码 每个字节中使用7位来表示数字 最高位用作他处

300的编码,编码后是两个字节:

1010 1100 0000 0010

  它这个例子是每个字节左边是高位,可以看到每个字节的最高位是一个标识位,从左到右第一个字节是10101100,最高位是1,说明后面还有字节需要解码,然后第二个字节是00000010,最高位是0,后面没字节了。所以这两个字节就需要解码成一个整数,再往下看。

代码
1010 1100 0000 0010
→ 010 1100 000 0010 //每个字节去掉最高位
→ 000 0010 010 1100 //字节序转换,两个字节互换位置
→ 000 0010 ++ 010 1100 //两个字节进行链接操作(不是相加)
→ 100101100 //合并后的结果,高位位0的部分截取掉
→ 256 + 32 + 8 + 4 = 300 //每个值为1的bit位乘以以2为底的幂,得出编码后的值

主要函数在 

coding.h

extern void PutFixed32(std::string* dst, uint32_t value);
extern void PutFixed64(std::string* dst, uint64_t value);
extern void PutVarint32(std::string* dst, uint32_t value);
extern void PutVarint64(std::string* dst, uint64_t value);
extern void PutLengthPrefixedSlice(std::string* dst, const Slice& value);

extern bool GetVarint32(Slice* input, uint32_t* value);
extern bool GetVarint64(Slice* input, uint64_t* value);
extern bool GetLengthPrefixedSlice(Slice* input, Slice* result);

extern const char* GetVarint32Ptr(const char* p,const char* limit, uint32_t* v);
extern const char* GetVarint64Ptr(const char* p,const char* limit, uint64_t* v);


extern int VarintLength(uint64_t v);

extern void EncodeFixed32(char* dst, uint32_t value);
extern void EncodeFixed64(char* dst, uint64_t value);

extern char* EncodeVarint32(char* dst, uint32_t value);
extern char* EncodeVarint64(char* dst, uint64_t value);

 

 

 

 

 

 

 

 

 

 

参考

https://www.cnblogs.com/onlytiancai/archive/2010/10/16/1853003.html

 

 

posted on 2018-04-14 19:13  itdef  阅读(588)  评论(0编辑  收藏  举报

导航