天天看點

leveldb學習筆記之五——include/leveldb/write_batch.h

WriteBatch主要是用來對多個資料進行批量寫入。

依賴關系

writeBatch類主要依賴于以下幾個類,如圖:

leveldb學習筆記之五——include/leveldb/write_batch.h

其中,Handler為抽象類,定義了put和delete接口。WriteBatchInternal類為writebatch的實作。

MemTableInserter為Handler的具體實作,實作具體的put和delete操作。此處使用了抽象工廠模式,即Handler為抽象工廠,MemTableInserter定義了具體的工廠。在MemTableInserter中定義了MemTable的成員,通過此成員實作put和delete操作。

writeBatch的資料結構

leveldb學習筆記之五——include/leveldb/write_batch.h

一個Batch結構前8個位元組是序列号,接下來4個位元組是寫入資料的總長度,再接下來是資料。資料的格式按照 類型,key,value的方式來排列。

類型主要分兩種,一種是寫入資料,另一種是删除資料。删除資料可以看成是一種特殊的寫入。

相關函數

  • 此函數用于疊代處理writebatch中的資料。即寫入
Status WriteBatch::Iterate(Handler* handler) const {
  Slice input(rep_);
    if (input.size() < kHeader) {
      return Status::Corruption("malformed WriteBatch (too small)");
    }

    input.remove_prefix(kHeader); //删除字首,8個位元組的序列号,4個位元組的長度,一共12個位元組
    Slice key, value;
    int found = 0;
    while (!input.empty()) {
      found++;
      char tag = input[0];
      input.remove_prefix(1);
      switch (tag) {
          case kTypeValue:  //正常的寫入資料
            if (GetLengthPrefixedSlice(&input, &key) &&
                GetLengthPrefixedSlice(&input, &value)) {
                handler->Put(key, value);
            } else {
                return Status::Corruption("bad WriteBatch Put");
            }
            break;
          case kTypeDeletion: //删除的資料
            if (GetLengthPrefixedSlice(&input, &key)) {
                handler->Delete(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();
    }
}      
  • 求長度,資料的長度加上8個位元組序列号的長度即可
int WriteBatchInternal::Count(const WriteBatch* b) {
    return DecodeFixed32(b->rep_.data() + 8);
}      
  • 設定長度值
void WriteBatchInternal::SetCount(WriteBatch* b, int n) {
    EncodeFixed32(&b->rep_[8], n);
}      
  • 擷取序列号
SequenceNumber WriteBatchInternal::Sequence(const WriteBatch* b) {
    return SequenceNumber(DecodeFixed64(b->rep_.data()));
}      
  • 設定序列号
void WriteBatchInternal::SetSequence(WriteBatch* b, SequenceNumber seq) {
    EncodeFixed64(&b->rep_[0], seq);
}      
  • 寫入
//寫入實際上是先寫入到batch裡面
void WriteBatch::Put(const Slice& key, const Slice& value) {
    WriteBatchInternal::SetCount(this, WriteBatchInternal::Count(this) + 1);
    rep_.push_back(static_cast<char>(kTypeValue));
    PutLengthPrefixedSlice(&rep_, key);
    PutLengthPrefixedSlice(&rep_, value);
}      
  • 删除
//删除實際上是将key寫入,同時在key之前标注此key對應的資料删除
void WriteBatch::Delete(const Slice& key) {
    WriteBatchInternal::SetCount(this, WriteBatchInternal::Count(this) + 1);
    rep_.push_back(static_cast<char>(kTypeDeletion));
    PutLengthPrefixedSlice(&rep_, key);
}      
  • writebatch追加
//兩個batch進行追加
void WriteBatch::Append(const WriteBatch &source) {
    WriteBatchInternal::Append(this, &source);
}