#include "kv_sep/kvlog.h" #include "db/dbformat.h" #include "db/filename.h" #include "db/write_batch_internal.h" #include #include "leveldb/env.h" #include "leveldb/slice.h" #include "leveldb/status.h" #include "util/coding.h" namespace leveldb { void EncodeFP(const struct FilePointer &fp, char *scratch) { EncodeFixed64(scratch, fp.FileNumber); EncodeFixed64(scratch + 8, fp.FileOffset); EncodeFixed64(scratch + 16, fp.Size); } void DecodeFp(struct FilePointer &fp, char *src) { fp.FileNumber = DecodeFixed64(src); fp.FileOffset = DecodeFixed64(src + 8); fp.Size = DecodeFixed64(src + 16); } KVLog::KVLog(WritableFile *dest,uint64_t file_number): dest_(dest),pos_(0),file_number(file_number) {} KVLog::KVLog(WritableFile *dest, uint64_t dest_length,uint64_t file_number): dest_(dest),pos_(dest_length),file_number(file_number) {} Status KVLog::AddRecord(const Slice &slice, FilePointer &fp) { //写入slice大小 EncodeFixed64(buf, slice.size()); Status s = dest_->Append(Slice(buf,8)); pos_ += 8; //写入slice fp.FileNumber = file_number; fp.FileOffset = pos_; fp.Size = slice.size(); s = dest_->Append(slice); pos_ += slice.size(); if(s.ok()) { s = dest_->Flush(); } return s; } void KVLogReader::Next() { if(input.empty()) { NextWriteBatch(); if(!Valid()) return; } NextKV(); } void KVLogReader::NextWriteBatch() { Slice num; file->Read(8, &num, number); if(num.size() !=8) { valid = false; return; } uint64_t batch_size = DecodeFixed64(number); if(batch_size > rep_size) { delete[] rep_; rep_ = new char[batch_size]; rep_size = batch_size; } input.clear(); file->Read(batch_size,&input,rep_); if(input.size() != batch_size) { valid = false; return; } seq = DecodeFixed64(input.data()) - 1;//-1是为了和后面的nextkv的实现对齐 input.remove_prefix(12); //remove writebatch header } void KVLogReader::NextKV() { seq++; type = (ValueType)input[0]; input.remove_prefix(1); switch (type) { case kTypeValue: if(GetLengthPrefixedSlice(&input, &key) && GetLengthPrefixedSlice(&input, &value)) { } else { valid = false; return; } break; case kTypeDeletion: if(GetLengthPrefixedSlice(&input, &key)) { } else { valid = false; return; } break; default: valid = false; return; } } }