#include #include "db/vlog_reader.h" #include "leveldb/slice.h" #include "leveldb/env.h" #include "util/coding.h" namespace leveldb{ namespace vlog{ VReader::VReader(SequentialFile* file) // A file abstraction for reading sequentially through a file :file_(file){} Status VReader::ReadRecord(uint64_t vfile_offset, std::string* record){ Status s; Slice size_slice; char size_buf[11]; uint64_t rec_size = 0; s = file_->SkipFromHead(vfile_offset); // 将文件的读取位置移动到 vfile_offset if(s.ok()) s = file_ -> Read(10, &size_slice, size_buf); // 先把Record 长度读出来, 最长10字节. if(s.ok()){ if(GetVarint64(&size_slice, &rec_size) == false){ // 解析变长整数,得到记录的长度 rec_size return Status::Corruption("Failed to decode vlog record size."); } std::string rec; char* c_rec = new char[rec_size]; // 为记录分配一个临时缓冲区 //TODO: Should delete c_rec? rec.resize(rec_size); Slice rec_slice; s = file_->SkipFromHead(vfile_offset + (size_slice.data() - size_buf)); // 将文件的读取位置移动 if(!s.ok()) return s; s = file_-> Read(rec_size, &rec_slice, c_rec); // 从文件中读取 rec_size 字节的数据到 c_rec 中,并用 rec_slice 包装这些数据 if(!s.ok()) return s; rec = std::string(c_rec, rec_size); *record = std::move(std::string(rec)); } return s; } Status VReader::ReadKV(uint64_t vfile_offset, std::string* key, std::string* val){ std::string record_str; Status s = ReadRecord(vfile_offset, &record_str); if(s.ok()){ Slice record = Slice(record_str); //File the val uint64_t key_size; bool decode_flag = true; decode_flag &= GetVarint64(&record, &key_size); // 获取键的长度 if(decode_flag){ *key = Slice(record.data(), key_size).ToString(); // 从record中截取键值 record = Slice(record.data() + key_size, record.size() - key_size); // 截取剩余的record } uint64_t val_size; decode_flag &= GetVarint64(&record, &val_size); // 获取value的长度 if(decode_flag) *val = Slice(record.data(), val_size).ToString(); // 截取value的值 if(!decode_flag || val->size() != record.size()){ s = Status::Corruption("Failed to decode Record Read From vlog."); } } return s; } }// namespace vlog. }