#include <cstdint>
|
|
#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.
|
|
}
|