leveldb深度剖析-存儲流程(2)

繼續上一篇內容,本篇繼續說明leveldb是如何將數據插入到MemTable中。

一、Iterate循環處理

插入到MemTable使用該接口WriteBatchInternal::InsertInto,具體實現是:

Status WriteBatchInternal::InsertInto(const WriteBatch* b,
                                      MemTable* memtable) {
  //初始化 Handler 
  MemTableInserter inserter;
  inserter.sequence_ = WriteBatchInternal::Sequence(b);//獲取序號
  inserter.mem_ = memtable;
  return b->Iterate(&inserter);
}

在WriteBatch中可能存在多個key-value對,所以在WriteBatch類中提供了一個迭代器方法Iterate,具體實現如下:

/**
 * 將key-value一個一個存儲到Memtable中
 * @param handler 真正執行存儲操作
 * 特別說明:
 *     rep_是數據保存地方,格式爲seq number|count|key-value|...|key-value
 *     Iterate方法主要工作是將一個一個key-value對解析出來 插入到Memtable中
 */
Status WriteBatch::Iterate(Handler* handler) const {
  Slice input(rep_);
  if (input.size() < kHeader) {
    return Status::Corruption("malformed WriteBatch (too small)");
  }

  input.remove_prefix(kHeader);//跳過頭部信息 seq number | count
  Slice key, value;
  int found = 0;
  while (!input.empty()) {
    found++;
    char tag = input[0]; // 獲取type
    input.remove_prefix(1);
    switch (tag) {
      case kTypeValue://添加操作
        if (GetLengthPrefixedSlice(&input, &key) &&
            GetLengthPrefixedSlice(&input, &value)) {//解析出key - value
          handler->Put(key, value);// MemTableInserter  此處的key value就是用輸入的key和value
        } else {
          return Status::Corruption("bad WriteBatch Put");
        }
        break;
      case kTypeDeletion://刪除操作
        if (GetLengthPrefixedSlice(&input, &key)) {
          handler->Delete(key);//這裏key爲用戶輸入key
        } else {
          return Status::Corruption("bad WriteBatch Delete");
        }
        break;
      default:
        return Status::Corruption("unknown WriteBatch tag");
    }
  }

  //最後再次判斷是否已經完全處理完
  if (found != WriteBatchInternal::Count(this)) {
    return Status::Corruption("WriteBatch has wrong count");
  } else {
    return Status::OK();
  }
}

通過上面代碼可知,調用handler中的Put和Delete方法進行插入和刪除。通過上面可知handler實際爲MemTableInserter,下面是Put和Delete實現,比較簡單:

  virtual void Put(const Slice& key, const Slice& value) {
    mem_->Add(sequence_, kTypeValue, key, value);
    sequence_++;
  }

  /**
   * Memtable只有插入操作 並沒有真正刪除操作   
   */
  virtual void Delete(const Slice& key) {
    mem_->Add(sequence_, kTypeDeletion, key, Slice());// value是空字符串
    sequence_++;
  }

這裏需要強調一下:

1) 這裏的key/value是用戶輸入的key/value,後面在MemTable中leveldb會對其再次封裝成InternalKey。

2) 這裏的sequence_ 是獨立計數器。

二、MemTable插入操作

對於MemTable插入流程可參考本篇《leveldb深度剖析-MemTable》。當MemTable佔用內存空間超過4M就會將MemTable中數據flush到level0文件中,下一篇將介紹是如何寫入到level0中

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章