<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    小明思考

    Just a software engineer
    posts - 124, comments - 36, trackbacks - 0, articles - 0
      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理
    我們知道,leveldb在寫數據的時候,除了log文件,都要在內存中寫一份。

    先看看SkipList【跳表】這個數據結構:


    SkipList有如下特點:
    1. 本質上一個排序好的鏈表
    2. 分層,上層節點比下層的少,更具有跳躍性
    3. 查詢的復雜度是O(logn)

    SkipList跟紅黑樹等還是比較容易實現和理解的,主要長處是比較容易實現Lock free和遍歷。
    我們來看看leveldb的實現
    插入:
    //插入一個新的key
    template<typename Key, class Comparator>
    void SkipList<Key,Comparator>::Insert(const Key& key) {
      
    //查找插入節點,prev為各層的前置節點
      Node* prev[kMaxHeight];
      Node
    * x = FindGreaterOrEqual(key, prev);

      
    // Our data structure does not allow duplicate insertion
      assert(x == NULL || !Equal(key, x->key));

      
    //生成隨機高度
      int height = RandomHeight();
      
    if (height > GetMaxHeight()) {
        
    for (int i = GetMaxHeight(); i < height; i++) {
          prev[i] 
    = head_;
        }
        
    //設置當前最大高度
        max_height_.NoBarrier_Store(reinterpret_cast<void*>(height));
      }

      
    //生成新節點
      x = NewNode(key, height);
      
    for (int i = 0; i < height; i++) {
        
    //設置新節點的各層的下一跳
        x->NoBarrier_SetNext(i, prev[i]->NoBarrier_Next(i));
        
    //設置前節點的next為當前節點,完成插入
        prev[i]->SetNext(i, x);
      }
    }

    查詢:
    template<typename Key, class Comparator>
    typename SkipList
    <Key,Comparator>::Node* SkipList<Key,Comparator>::FindGreaterOrEqual(const Key& key, Node** prev)
        
    const {
      Node
    * x = head_;
      
    int level = GetMaxHeight() - 1//從高層開始查找,依次到0 level
      while (true) {
        Node
    * next = x->Next(level); 
        
    if (KeyIsAfterNode(key, next)) { //比next key 要大
          
    // Keep searching in this list
          x = next;
        } 
    else { //比next key小,查找下一層
          
    //標記當前level的前置節點
          if (prev != NULL) prev[level] = x;
          
    if (level == 0) {
            
    return next;
          } 
    else {
            level
    --;
          }
        }
      }
    }

    template
    <typename Key, class Comparator>
    bool SkipList<Key,Comparator>::Contains(const Key& key) const {
      Node
    * x = FindGreaterOrEqual(key, NULL);
      
    if (x != NULL && Equal(key, x->key)) {
        
    return true;
      } 
    else {
        
    return false;
      }
    }


    接著我們看看leveldb MemTable的實現,很簡單了,基本是對SkipList訪問一個封裝
    <db/memtable.h>
    class MemTable {
     
    public:
      
    explicit MemTable(const InternalKeyComparator& comparator);

      
    //增加引用計數
      void Ref() { ++refs_; }

      
    //減少引用計數
      void Unref() {
        
    --refs_;
        assert(refs_ 
    >= 0);
        
    if (refs_ <= 0) {
          delete 
    this;
        }
      }

      
    //內存使用量
      size_t ApproximateMemoryUsage();

      
    //遍歷操作
      Iterator* NewIterator();

      
    //插入
      void Add(SequenceNumber seq, ValueType type,
               
    const Slice& key,
               
    const Slice& value);

      
    //查詢
      bool Get(const LookupKey& key, std::string* value, Status* s);

     
    private:
      
    ~MemTable();  // Private since only Unref() should be used to delete it

      
    //key compartor,用于排序
      struct KeyComparator {
        
    const InternalKeyComparator comparator;
        
    explicit KeyComparator(const InternalKeyComparator& c) : comparator(c) { }
        
    int operator()(const char* a, const char* b) const;
      };
      friend 
    class MemTableIterator;
      friend 
    class MemTableBackwardIterator;

      typedef SkipList
    <const char*, KeyComparator> Table;

      KeyComparator comparator_;
      
    int refs_; //引用計數
      Arena arena_; //內存分配器
      Table table_; //數據存放SkipList

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

    先看看插入
    <db/memtable.cc>
    void MemTable::Add(SequenceNumber s, ValueType type,
                       
    const Slice& key,
                       
    const Slice& value) {
      
    //數據結構:
      
    //1.internal key size : Varint32 (length of 2+3)
      
    //2.key data
      
    //3.SequenceNumber+Key type: 8 bytes
      
    //4 value size: Varint32
      
    //5 value data
      size_t key_size = key.size();
      size_t val_size 
    = value.size();
      size_t internal_key_size 
    = key_size + 8;
      
    const size_t encoded_len =
          VarintLength(internal_key_size) 
    + internal_key_size +
          VarintLength(val_size) 
    + val_size;
      
    char* buf = arena_.Allocate(encoded_len);
      
    char* p = EncodeVarint32(buf, internal_key_size);
      memcpy(p, key.data(), key_size);
      p 
    += key_size;
      EncodeFixed64(p, (s 
    << 8| type);
      p 
    += 8;
      p 
    = EncodeVarint32(p, val_size);
      memcpy(p, value.data(), val_size);
      assert((p 
    + val_size) - buf == encoded_len);
      table_.Insert(buf);
    }

    查詢
    <db/memtable.cc>
    bool MemTable::Get(const LookupKey& key, std::string* value, Status* s) {
      Slice memkey 
    = key.memtable_key();
      Table::Iterator iter(
    &table_);
      iter.Seek(memkey.data());
      
    if (iter.Valid()) {
        
    // entry format is:
        
    //    klength  varint32
        
    //    userkey  char[klength]
        
    //    tag      uint64
        
    //    vlength  varint32
        
    //    value    char[vlength]
        
    // Check that it belongs to same user key.  We do not check the
        
    // sequence number since the Seek() call above should have skipped
        
    // all entries with overly large sequence numbers.
        const char* entry = iter.key();
        uint32_t key_length;
        
    const char* key_ptr = GetVarint32Ptr(entry, entry+5&key_length);
        
    if (comparator_.comparator.user_comparator()->Compare(
                Slice(key_ptr, key_length 
    - 8),
                key.user_key()) 
    == 0) {
          
    // Correct user key
          const uint64_t tag = DecodeFixed64(key_ptr + key_length - 8);
          
    switch (static_cast<ValueType>(tag & 0xff)) {
            
    case kTypeValue: {
              Slice v 
    = GetLengthPrefixedSlice(key_ptr + key_length);
              value
    ->assign(v.data(), v.size());
              
    return true;
            }
            
    case kTypeDeletion:
              
    *= Status::NotFound(Slice());
              
    return true;
          }
        }
      }
      
    return false;
    }
    主站蜘蛛池模板: 人成午夜免费大片在线观看| 成人免费的性色视频| 午夜精品在线免费观看| 亚洲精品成人无限看| 亚洲sm另类一区二区三区| 99精品一区二区免费视频| 无码专区一va亚洲v专区在线| 亚洲小视频在线播放| 国产成人无码区免费内射一片色欲| 日韩黄色免费观看| 亚洲视频在线观看地址| 一级毛片免费在线播放| 女性自慰aⅴ片高清免费| 亚洲最大福利视频网站| 国产99视频精品免费视频76| 成人免费在线观看网站| 亚洲精品乱码久久久久久下载 | 亚洲国产综合无码一区二区二三区 | XXX2高清在线观看免费视频| 国产日产成人免费视频在线观看| 亚洲国产精品免费在线观看| 久久永久免费人妻精品| 亚洲中文字幕无码爆乳AV| 亚洲AV无码男人的天堂| 黄页免费的网站勿入免费直接进入| 亚洲成a人片在线观看无码| 一级做a爱过程免费视频高清| 国产精品四虎在线观看免费| 亚洲视频在线观看2018| 91精品啪在线观看国产线免费| 亚洲欧洲自拍拍偷午夜色无码| 一区二区三区免费精品视频 | 成全高清在线观看免费| 国产精品亚洲mnbav网站| 免费毛片毛片网址| 日韩一区二区三区免费体验| 亚洲码和欧洲码一码二码三码 | 免费a级毛片无码av| 亚洲国产精品日韩av不卡在线| 成人毛片免费播放| 亚洲中文无码亚洲人成影院|