@ -0,0 +1,15 @@ | |||||
#include "table/vtable_builder.h" | |||||
namespace leveldb { | |||||
VTableBuilder::VTableBuilder(const Options& options, WritableFile* file) | |||||
: file_(file) {} | |||||
void VTableBuilder::Add(const VTableRecord& record, VTableHandle* handle) { | |||||
if (!ok()) return; | |||||
} | |||||
} // namespace leveldb |
@ -0,0 +1,36 @@ | |||||
#ifndef VTABLE_BUILDER_H | |||||
#define VTABLE_BUILDER_H | |||||
#include "leveldb/options.h" | |||||
#include "leveldb/slice.h" | |||||
#include "table/vtable_format.h" | |||||
#include "util/coding.h" | |||||
namespace leveldb { | |||||
class VTableBuilder { | |||||
public: | |||||
VTableBuilder(const Options& options, WritableFile* file); | |||||
// Add a record to the vTable | |||||
void Add(const VTableRecord& record, VTableHandle* handle); | |||||
// Builder status, return non-ok iff some error occurs | |||||
Status status() const { return status_; } | |||||
// Finish building the vTable | |||||
Status Finish(); | |||||
// Abandon building the vTable | |||||
void Abandon(); | |||||
private: | |||||
bool ok() const { return status().ok(); } | |||||
WritableFile* file_; | |||||
Status status_; | |||||
}; | |||||
} // namespace leveldb | |||||
#endif //VTABLE_BUILDER_H |
@ -0,0 +1,82 @@ | |||||
#include "table/vtable_format.h" | |||||
#include <locale> | |||||
#include "util/coding.h" | |||||
namespace leveldb { | |||||
namespace { | |||||
bool GetChar(Slice* input, unsigned char* value) { | |||||
if (input->empty()) { | |||||
return false; | |||||
} | |||||
*value = *input->data(); | |||||
input->remove_prefix(1); | |||||
return true; | |||||
} | |||||
} | |||||
void VTableRecord::Encode(std::string* target) const { | |||||
PutLengthPrefixedSlice(target, key); | |||||
PutLengthPrefixedSlice(target, value); | |||||
} | |||||
Status VTableRecord::Decode(Slice* input) { | |||||
if (!GetLengthPrefixedSlice(input, &key) || | |||||
!GetLengthPrefixedSlice(input, &value)) { | |||||
return Status::Corruption("Error decode VTableRecord"); | |||||
} | |||||
return Status::OK(); | |||||
} | |||||
void RecordEncoder::Encode(const VTableRecord& record) { | |||||
record_buff_.clear(); | |||||
record.Encode(&record_buff_); | |||||
record_ = Slice(record_buff_.data(), record_buff_.size()); | |||||
assert(record.size() < std::numeric_limits<uint32_t>::max()); | |||||
} | |||||
Status RecordDecoder::Decode(Slice* input, VTableRecord* record) { | |||||
} | |||||
void VTableHandle::Encode(std::string* target) const { | |||||
PutVarint64(target, offset); | |||||
PutVarint64(target, size); | |||||
} | |||||
Status VTableHandle::Decode(Slice* input) { | |||||
if (!GetVarint64(input, &offset) || !GetVarint64(input, &size)) { | |||||
return Status::Corruption("Error decode VTableHandle"); | |||||
} | |||||
return Status::OK(); | |||||
} | |||||
void VTableIndex::Encode(std::string* target) const { | |||||
target->push_back(kVTableIndex); | |||||
PutVarint64(target, file_number); | |||||
vtable_handle.Encode(target); | |||||
} | |||||
Status VTableIndex::Decode(Slice* input) { | |||||
unsigned char type; | |||||
if (!GetChar(input, &type) || type != kVTableIndex || | |||||
!GetVarint64(input, &file_number)) { | |||||
return Status::Corruption("Error decode VTableIndex"); | |||||
} | |||||
Status s = vtable_handle.Decode(input); | |||||
if (!s.ok()) { | |||||
return Status::Corruption("Error decode VTableHandle", s.ToString()); | |||||
} | |||||
return s; | |||||
} | |||||
} // namespace leveldb |
@ -0,0 +1,79 @@ | |||||
#ifndef VTABLE_FORMAT_H | |||||
#define VTABLE_FORMAT_H | |||||
#include "leveldb/slice.h" | |||||
#include "leveldb/status.h" | |||||
#include "table/format.h" | |||||
namespace leveldb { | |||||
struct VTableRecord { | |||||
Slice key; | |||||
Slice value; | |||||
void Encode(std::string* target) const; | |||||
Status Decode(Slice* input); | |||||
size_t size() const { return key.size() + value.size(); } | |||||
friend bool operator==(const VTableRecord& a, const VTableRecord& b) { | |||||
return a.key == b.key && a.value == b.value; | |||||
} | |||||
}; | |||||
class RecordEncoder { | |||||
public: | |||||
// TODO: Support compression while encoding a record | |||||
RecordEncoder() = default; | |||||
// Encode a vTable record | |||||
void Encode(const VTableRecord& record); | |||||
// Get the size of encoded record | |||||
size_t GetEncodedSize() const { return record_.size(); } | |||||
private: | |||||
Slice record_; | |||||
std::string record_buff_; | |||||
}; | |||||
class RecordDecoder { | |||||
public: | |||||
Status Decode(Slice* input, VTableRecord* record); | |||||
size_t GetDecodedSize() const { return record_size_; } | |||||
private: | |||||
uint32_t record_size_{0}; | |||||
}; | |||||
struct VTableHandle { | |||||
uint64_t offset{0}; | |||||
uint64_t size{0}; | |||||
void Encode(std::string* target) const; | |||||
Status Decode(Slice* input); | |||||
friend bool operator==(const VTableHandle& a, const VTableHandle& b) { | |||||
return a.offset == b.offset && a.size == b.size; | |||||
} | |||||
}; | |||||
struct VTableIndex { | |||||
enum Type : unsigned char { | |||||
kVTableIndex = 1, | |||||
}; | |||||
uint64_t file_number{0}; | |||||
VTableHandle vtable_handle; | |||||
void Encode(std::string* target) const; | |||||
Status Decode(Slice* input); | |||||
friend bool operator==(const VTableIndex& a, const VTableIndex& b) { | |||||
return a.file_number == b.file_number && a.vtable_handle == b.vtable_handle; | |||||
} | |||||
}; | |||||
} // namespace leveldb | |||||
#endif //VTABLE_FORMAT_H |