@ -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 |