| @ -0,0 +1,96 @@ | |||||
| #include "vlog_reader.h" | |||||
| #include "leveldb/env.h" | |||||
| #include "util/coding.h" | |||||
| namespace leveldb { | |||||
| namespace log { | |||||
| VlogReader::VlogReader(SequentialFile *file, Reporter* reporter) | |||||
| : file_(file), | |||||
| file_random_(nullptr), | |||||
| reporter_(reporter), | |||||
| backing_store_(new char[kBlockSize]), | |||||
| buffer_(), | |||||
| eof_(false), | |||||
| last_record_offset_(0) {} | |||||
| VlogReader::VlogReader(RandomAccessFile *file, Reporter* reporter) | |||||
| : file_(nullptr), | |||||
| file_random_(file), | |||||
| reporter_(reporter), | |||||
| backing_store_(new char[kBlockSize]), | |||||
| buffer_(), | |||||
| eof_(false), | |||||
| last_record_offset_(0) {} | |||||
| VlogReader::~VlogReader() { delete[] backing_store_; } | |||||
| bool VlogReader::ReadValue(uint64_t offset, size_t length, Slice *key_value, char *scratch) { | |||||
| if (file_random_ == nullptr) { | |||||
| return false; | |||||
| } | |||||
| Status status = file_random_->Read(offset, length, key_value, scratch); | |||||
| if (!status.ok()) { | |||||
| return false; | |||||
| } | |||||
| return true; | |||||
| } | |||||
| bool VlogReader::ReadRecord(Slice *record, std::string *scratch) { | |||||
| if (ReadPhysicalRecord(scratch)) { | |||||
| *record = *scratch; | |||||
| return true; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| uint64_t VlogReader::LastRecordOffset() const { | |||||
| return last_record_offset_; | |||||
| } | |||||
| void VlogReader::ReportCorruption(uint64_t bytes, const Status &reason) { | |||||
| if (reporter_ != nullptr) { | |||||
| reporter_->Corruption(static_cast<size_t>(bytes), reason); | |||||
| } | |||||
| } | |||||
| bool VlogReader::ReadPhysicalRecord(std::string *result) { | |||||
| result->clear(); | |||||
| buffer_.clear(); | |||||
| char* tmp_head = new char[vHeaderSize]; | |||||
| Status status = file_->Read(vHeaderSize, &buffer_, tmp_head); | |||||
| if (!status.ok()) { | |||||
| buffer_.clear(); | |||||
| ReportCorruption(kBlockSize, status); | |||||
| eof_ = true; | |||||
| return false; | |||||
| } else if (buffer_.size() < vHeaderSize) { | |||||
| eof_ = true; | |||||
| } | |||||
| if (!eof_) { | |||||
| result->assign(buffer_.data(),buffer_.size()); | |||||
| uint32_t length = DecodeFixed32(buffer_.data()); | |||||
| buffer_.clear(); | |||||
| char* tmp = new char[length]; | |||||
| status = file_->Read(length, &buffer_, tmp); | |||||
| if (status.ok() && buffer_.size() == length) { | |||||
| *result += buffer_.ToString(); | |||||
| } else { | |||||
| eof_ = true; | |||||
| } | |||||
| delete [] tmp; | |||||
| } | |||||
| delete [] tmp_head; | |||||
| if (eof_) { | |||||
| result->clear(); | |||||
| return false; | |||||
| } | |||||
| return true; | |||||
| } | |||||
| } // namespace log | |||||
| } // namespace leveldb | |||||
| @ -1,96 +0,0 @@ | |||||
| #include "vlog_reader.h" | |||||
| #include "leveldb/env.h" | |||||
| #include "util/coding.h" | |||||
| namespace leveldb { | |||||
| namespace log { | |||||
| VlogReader::VlogReader(SequentialFile *file, Reporter* reporter) | |||||
| : file_(file), | |||||
| file_random_(nullptr), | |||||
| reporter_(reporter), | |||||
| backing_store_(new char[kBlockSize]), | |||||
| buffer_(), | |||||
| eof_(false), | |||||
| last_record_offset_(0) {} | |||||
| VlogReader::VlogReader(RandomAccessFile *file, Reporter* reporter) | |||||
| : file_(nullptr), | |||||
| file_random_(file), | |||||
| reporter_(reporter), | |||||
| backing_store_(new char[kBlockSize]), | |||||
| buffer_(), | |||||
| eof_(false), | |||||
| last_record_offset_(0) {} | |||||
| VlogReader::~VlogReader() { delete[] backing_store_; } | |||||
| bool VlogReader::ReadValue(uint64_t offset, size_t length, Slice *key_value, char *scratch) { | |||||
| if (file_random_ == nullptr) { | |||||
| return false; | |||||
| } | |||||
| Status status = file_random_->Read(offset, length, key_value, scratch); | |||||
| if (!status.ok()) { | |||||
| return false; | |||||
| } | |||||
| return true; | |||||
| } | |||||
| bool VlogReader::ReadRecord(Slice *record, std::string *scratch) { | |||||
| if (ReadPhysicalRecord(scratch)) { | |||||
| *record = *scratch; | |||||
| return true; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| uint64_t VlogReader::LastRecordOffset() const { | |||||
| return last_record_offset_; | |||||
| } | |||||
| void VlogReader::ReportCorruption(uint64_t bytes, const Status &reason) { | |||||
| if (reporter_ != nullptr) { | |||||
| reporter_->Corruption(static_cast<size_t>(bytes), reason); | |||||
| } | |||||
| } | |||||
| bool VlogReader::ReadPhysicalRecord(std::string *result) { | |||||
| result->clear(); | |||||
| buffer_.clear(); | |||||
| char* tmp_head = new char[vHeaderSize]; | |||||
| Status status = file_->Read(vHeaderSize, &buffer_, tmp_head); | |||||
| if (!status.ok()) { | |||||
| buffer_.clear(); | |||||
| ReportCorruption(kBlockSize, status); | |||||
| eof_ = true; | |||||
| return false; | |||||
| } else if (buffer_.size() < vHeaderSize) { | |||||
| eof_ = true; | |||||
| } | |||||
| if (!eof_) { | |||||
| result->assign(buffer_.data(),buffer_.size()); | |||||
| uint32_t length = DecodeFixed32(buffer_.data()); | |||||
| buffer_.clear(); | |||||
| char* tmp = new char[length]; | |||||
| status = file_->Read(length, &buffer_, tmp); | |||||
| if (status.ok() && buffer_.size() == length) { | |||||
| *result += buffer_.ToString(); | |||||
| } else { | |||||
| eof_ = true; | |||||
| } | |||||
| delete [] tmp; | |||||
| } | |||||
| delete [] tmp_head; | |||||
| if (eof_) { | |||||
| result->clear(); | |||||
| return false; | |||||
| } | |||||
| return true; | |||||
| } | |||||
| } // namespace log | |||||
| } // namespace leveldb | |||||
| @ -0,0 +1,42 @@ | |||||
| #include "db/vlog_writer.h" | |||||
| #include <cstdint> | |||||
| #include "leveldb/env.h" | |||||
| #include "util/coding.h" | |||||
| namespace leveldb { | |||||
| namespace log { | |||||
| VlogWriter::VlogWriter(WritableFile* dest) : dest_(dest), head_(0) {} | |||||
| VlogWriter::VlogWriter(WritableFile* dest, uint64_t dest_length) | |||||
| : dest_(dest), head_(0) {} | |||||
| Status VlogWriter::AddRecord(const Slice& slice, uint64_t& offset) { | |||||
| const char* ptr = slice.data(); | |||||
| size_t left = slice.size(); | |||||
| Status s; | |||||
| s = EmitPhysicalRecord(ptr, left, offset); | |||||
| return s; | |||||
| } | |||||
| Status VlogWriter::EmitPhysicalRecord(const char* ptr, size_t length, | |||||
| uint64_t& offset) { | |||||
| assert(length <= 0xffff); | |||||
| char buf[4]; | |||||
| EncodeFixed32(buf, length); | |||||
| Status s = dest_->Append(Slice(buf, 4)); | |||||
| if (s.ok()) { | |||||
| s = dest_->Append(Slice(ptr, length)); | |||||
| if (s.ok()) { | |||||
| s = dest_->Flush(); | |||||
| offset = head_ + 4; | |||||
| head_ += 4 + length; | |||||
| } | |||||
| } | |||||
| return s; | |||||
| } | |||||
| } // namespace log | |||||
| } // namespace leveldb | |||||
| @ -0,0 +1,44 @@ | |||||
| #ifndef LEVELDB_DB_VLOG_WRITER_H_ | |||||
| #define LEVELDB_DB_VLOG_WRITER_H_ | |||||
| #include "db/log_format.h" | |||||
| #include <cstdint> | |||||
| #include "leveldb/slice.h" | |||||
| #include "leveldb/status.h" | |||||
| namespace leveldb { | |||||
| class WritableFile; | |||||
| namespace log { | |||||
| class VlogWriter { | |||||
| public: | |||||
| // Create a writer that will append data to "*dest". | |||||
| // "*dest" must be initially empty. | |||||
| // "*dest" must remain live while this Writer is in use. | |||||
| explicit VlogWriter(WritableFile* dest); | |||||
| // Create a writer that will append data to "*dest". | |||||
| // "*dest" must have initial length "dest_length". | |||||
| // "*dest" must remain live while this Writer is in use. | |||||
| VlogWriter(WritableFile* dest, uint64_t dest_length); | |||||
| VlogWriter(const VlogWriter&) = delete; | |||||
| VlogWriter& operator=(const VlogWriter&) = delete; | |||||
| ~VlogWriter() = default; | |||||
| Status AddRecord(const Slice& slice, uint64_t& offset); | |||||
| private: | |||||
| Status EmitPhysicalRecord(const char* ptr, size_t length, uint64_t& offset); | |||||
| size_t head_; | |||||
| WritableFile* dest_; | |||||
| }; | |||||
| } // namespace log | |||||
| } // namespace leveldb | |||||
| #endif // LEVELDB_DB_VLOG_WRITER_H_ | |||||