Skip to content

Commit

Permalink
base:types add BufferSpan, ConstBufferSpan and use it in io:file and …
Browse files Browse the repository at this point in the history
…db:sstable
  • Loading branch information
iceboy233 committed Jun 10, 2022
1 parent 188bcfa commit 85ca927
Show file tree
Hide file tree
Showing 11 changed files with 122 additions and 72 deletions.
6 changes: 6 additions & 0 deletions base/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,9 @@ cc_library(
name = "packed",
hdrs = ["packed.h"],
)

cc_library(
name = "types",
hdrs = ["types.h"],
deps = ["@com_google_absl//absl/types:span"],
)
62 changes: 62 additions & 0 deletions base/types.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#ifndef _BASE_TYPES_H
#define _BASE_TYPES_H

#include <array>
#include <cstddef>
#include <cstdint>
#include <string>
#include <string_view>

#include "absl/types/span.h"

class BufferSpan : public absl::Span<uint8_t> {
public:
constexpr BufferSpan() = default;
BufferSpan(void *data, size_t size)
: Span(reinterpret_cast<uint8_t *>(data), size) {}

BufferSpan(absl::Span<uint8_t> span) : Span(span) {}
BufferSpan(std::vector<uint8_t> &v) : Span(v) {}

template <size_t N>
constexpr BufferSpan(std::array<uint8_t, N> &a) : Span(a) {}

BufferSpan(std::string &s) : BufferSpan(s.data(), s.size()) {}

template <size_t N>
BufferSpan(std::array<char, N> &a) : BufferSpan(a.data(), N) {}

operator std::string_view() const {
return std::string_view(reinterpret_cast<char *>(data()), size());
}
};

class ConstBufferSpan : public absl::Span<const uint8_t> {
public:
constexpr ConstBufferSpan() = default;
ConstBufferSpan(const void *data, size_t size)
: Span(reinterpret_cast<const uint8_t *>(data), size) {}

constexpr ConstBufferSpan(absl::Span<const uint8_t> span) : Span(span) {}
constexpr ConstBufferSpan(absl::Span<uint8_t> span) : Span(span) {}
constexpr ConstBufferSpan(const std::vector<uint8_t> &v) : Span(v) {}

template <size_t N>
constexpr ConstBufferSpan(const std::array<uint8_t, N> &a) : Span(a) {}

ConstBufferSpan(const std::string &s)
: ConstBufferSpan(s.data(), s.size()) {}

ConstBufferSpan(std::string_view s) : ConstBufferSpan(s.data(), s.size()) {}
ConstBufferSpan(const char *c) : ConstBufferSpan(std::string_view(c)) {}

template <size_t N>
ConstBufferSpan(const std::array<char, N> &a)
: ConstBufferSpan(a.data(), N) {}

operator std::string_view() const {
return std::string_view(reinterpret_cast<const char *>(data()), size());
}
};

#endif // _BASE_TYPES_H
1 change: 1 addition & 0 deletions db/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ cc_library(
srcs = ["sstable.cc"],
hdrs = ["sstable.h"],
deps = [
"//base:types",
"//io:file",
"@com_google_absl//absl/algorithm:container",
"@org_boost_boost//:endian",
Expand Down
42 changes: 18 additions & 24 deletions db/sstable.cc
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "db/sstable.h"

#include <string_view>

#include "absl/algorithm/container.h"
#include "boost/endian/conversion.hpp"

Expand All @@ -24,22 +26,20 @@ std::error_code SSTable::init() {
}
std::array<uint8_t, 8> buffer;
size_t size;
ec = file_.pread(file_size - 8, absl::MakeSpan(buffer), size);
ec = file_.pread(file_size - 8, buffer, size);
int32_t num_blocks = boost::endian::load_little_s32(&buffer[0]);
int32_t keys_size = boost::endian::load_little_s32(&buffer[4]);
if (file_size < num_blocks * 16 + keys_size + 8) {
return make_error_code(std::errc::no_buffer_space);
}
std::vector<uint8_t> blocks_buffer(num_blocks * 16);
ec = file_.pread(
file_size - (num_blocks * 16 + keys_size + 8),
absl::MakeSpan(blocks_buffer), size);
file_size - (num_blocks * 16 + keys_size + 8), blocks_buffer, size);
if (ec) {
return ec;
}
keys_buffer_.resize(keys_size);
ec = file_.pread(
file_size - (keys_size + 8), absl::MakeSpan(keys_buffer_), size);
ec = file_.pread(file_size - (keys_size + 8), keys_buffer_, size);
if (ec) {
return ec;
}
Expand All @@ -53,10 +53,9 @@ std::error_code SSTable::init() {
if (blocks_.back().size <= 0 || blocks_.back().size > max_block_size) {
return make_error_code(std::errc::bad_message);
}
size_t key_size =
int32_t key_size =
boost::endian::load_little_s32(&blocks_buffer[index * 16 + 12]);
keys_.push_back({reinterpret_cast<char *>(&keys_buffer_[keys_offset]),
key_size});
keys_.push_back(ConstBufferSpan(&keys_buffer_[keys_offset], key_size));
keys_offset += key_size;
if (keys_offset > keys_buffer_.size()) {
return make_error_code(std::errc::no_buffer_space);
Expand All @@ -65,14 +64,13 @@ std::error_code SSTable::init() {
return {};
}

std::error_code SSTable::lookup(
std::string_view key, std::string &value) const {
std::error_code SSTable::lookup(ConstBufferSpan key, std::string &value) const {
Iterator iterator(*this);
std::error_code ec = iterator.seek(key);
if (ec) {
return ec;
}
if (iterator.key() != key) {
if (std::string_view(iterator.key()) != key) {
return make_error_code(std::errc::no_message_available);
}
value = iterator.value();
Expand All @@ -91,8 +89,8 @@ std::error_code SSTable::Iterator::start() {
return read();
}

std::error_code SSTable::Iterator::seek(std::string_view key) {
auto iter = absl::c_lower_bound(sstable_.keys_, key);
std::error_code SSTable::Iterator::seek(ConstBufferSpan key) {
auto iter = absl::c_lower_bound(sstable_.keys_, std::string_view(key));
if (iter == sstable_.keys_.end()) {
return make_error_code(std::errc::no_message_available);
}
Expand All @@ -102,7 +100,7 @@ std::error_code SSTable::Iterator::seek(std::string_view key) {
if (ec) {
return ec;
}
while (this->key() < key) {
while (std::string_view(this->key()) < key) {
ec = next();
if (ec) {
return ec;
Expand Down Expand Up @@ -131,26 +129,22 @@ std::error_code SSTable::Iterator::next() {
return {};
}

std::string_view SSTable::Iterator::key() const {
ConstBufferSpan SSTable::Iterator::key() const {
int32_t key_size = boost::endian::load_little_s32(&buffer_[offset_]);
return std::string_view(
reinterpret_cast<const char *>(&buffer_[offset_ + 8]), key_size);
return ConstBufferSpan(&buffer_[offset_ + 8], key_size);
}

std::string_view SSTable::Iterator::value() const {
ConstBufferSpan SSTable::Iterator::value() const {
int32_t key_size = boost::endian::load_little_s32(&buffer_[offset_]);
int32_t value_size = boost::endian::load_little_s32(&buffer_[offset_ + 4]);
return std::string_view(
reinterpret_cast<const char *>(&buffer_[offset_ + 8 + key_size]),
value_size);
return ConstBufferSpan(&buffer_[offset_ + 8 + key_size], value_size);
}

std::error_code SSTable::Iterator::read() {
const Block &block = *iter_;
buffer_.resize(block.size);
size_t size;
std::error_code ec = sstable_.file_.pread(
block.offset, absl::MakeSpan(buffer_), size);
std::error_code ec = sstable_.file_.pread(block.offset, buffer_, size);
if (ec) {
return ec;
}
Expand All @@ -163,7 +157,7 @@ SSTableBuilder::SSTableBuilder(io::File &file, const Options &options)
flush_size_(options.flush_size) {}

std::error_code SSTableBuilder::add(
std::string_view key, std::string_view value) {
ConstBufferSpan key, ConstBufferSpan value) {
size_t size = buffer_.size();
int32_t entry_size = 8 + key.size() + value.size();
buffer_.resize(size + entry_size);
Expand Down
14 changes: 7 additions & 7 deletions db/sstable.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@

#include <cstdint>
#include <string>
#include <string_view>
#include <system_error>
#include <vector>

#include "base/types.h"
#include "io/file.h"

namespace db {
Expand All @@ -18,7 +18,7 @@ class SSTable {
SSTable(io::File &file, const Options &options);

std::error_code init();
std::error_code lookup(std::string_view key, std::string &value) const;
std::error_code lookup(ConstBufferSpan key, std::string &value) const;

private:
struct Block {
Expand All @@ -32,10 +32,10 @@ class SSTable {
explicit Iterator(const SSTable &sstable);

std::error_code start();
std::error_code seek(std::string_view key);
std::error_code seek(ConstBufferSpan key);
std::error_code next();
std::string_view key() const;
std::string_view value() const;
ConstBufferSpan key() const;
ConstBufferSpan value() const;

private:
std::error_code read();
Expand All @@ -49,7 +49,7 @@ class SSTable {
private:
io::File &file_;
std::vector<Block> blocks_;
std::vector<std::string_view> keys_;
std::vector<ConstBufferSpan> keys_;
std::vector<uint8_t> keys_buffer_;
};

Expand All @@ -62,7 +62,7 @@ class SSTableBuilder {

SSTableBuilder(io::File &file, const Options &options);

std::error_code add(std::string_view key, std::string_view value);
std::error_code add(ConstBufferSpan key, ConstBufferSpan value);
std::error_code finish();

private:
Expand Down
12 changes: 6 additions & 6 deletions db/sstable_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -52,21 +52,21 @@ TEST(SSTableTest, basic) {
ASSERT_TRUE(iterator.next());
ASSERT_FALSE(iterator.start());
for (int i = 1; i < 100; ++i) {
ASSERT_EQ(iterator.key(), absl::StrFormat("k%03d", i));
EXPECT_EQ(iterator.value(), absl::StrFormat("v%03d", i));
ASSERT_EQ(std::string_view(iterator.key()), absl::StrFormat("k%03d", i));
EXPECT_EQ(std::string_view(iterator.value()), absl::StrFormat("v%03d", i));
ASSERT_FALSE(iterator.next());
}
ASSERT_EQ(iterator.key(), "k100");
EXPECT_EQ(iterator.value(), "v100");
ASSERT_EQ(std::string_view(iterator.key()), "k100");
EXPECT_EQ(std::string_view(iterator.value()), "v100");
ASSERT_TRUE(iterator.next());

// Test seek.
for (int i = 0; i < 100; ++i) {
SSTable::Iterator iterator(sstable);
ec = iterator.seek(absl::StrFormat("k%03da", i));
ASSERT_FALSE(ec);
ASSERT_EQ(iterator.key(), absl::StrFormat("k%03d", i + 1));
EXPECT_EQ(iterator.value(), absl::StrFormat("v%03d", i + 1));
ASSERT_EQ(std::string_view(iterator.key()), absl::StrFormat("k%03d", i + 1));
EXPECT_EQ(std::string_view(iterator.value()), absl::StrFormat("v%03d", i + 1));
}
ec = iterator.seek("k100a");
ASSERT_TRUE(ec);
Expand Down
2 changes: 1 addition & 1 deletion io/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package(default_visibility = ["//visibility:public"])
cc_library(
name = "file",
hdrs = ["file.h"],
deps = ["@com_google_absl//absl/types:span"],
deps = ["//base:types"],
)

cc_library(
Expand Down
11 changes: 5 additions & 6 deletions io/file.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#include <cstdint>
#include <system_error>

#include "absl/types/span.h"
#include "base/types.h"

namespace io {

Expand All @@ -14,13 +14,12 @@ class File {
File() = default;
virtual ~File() = default;

virtual std::error_code read(absl::Span<uint8_t> buffer, size_t &size) = 0;
virtual std::error_code write(
absl::Span<const uint8_t> buffer, size_t &size) = 0;
virtual std::error_code read(BufferSpan buffer, size_t &size) = 0;
virtual std::error_code write(ConstBufferSpan buffer, size_t &size) = 0;
virtual std::error_code pread(
int64_t position, absl::Span<uint8_t> buffer, size_t &size) = 0;
int64_t position, BufferSpan buffer, size_t &size) = 0;
virtual std::error_code pwrite(
int64_t position, absl::Span<const uint8_t> buffer, size_t &size) = 0;
int64_t position, ConstBufferSpan buffer, size_t &size) = 0;
virtual std::error_code seek(int64_t position) = 0;
virtual std::error_code tell(int64_t &position) = 0;
virtual std::error_code size(int64_t &size) = 0;
Expand Down
9 changes: 4 additions & 5 deletions io/posix/file.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ SharedFile stdin(STDIN_FILENO);
SharedFile stdout(STDOUT_FILENO);
SharedFile stderr(STDERR_FILENO);

std::error_code SharedFile::read(absl::Span<uint8_t> buffer, size_t &size) {
std::error_code SharedFile::read(BufferSpan buffer, size_t &size) {
ssize_t ret = ::read(fd_, buffer.data(), buffer.size());
if (ret < 0) {
return {errno, std::system_category()};
Expand All @@ -21,8 +21,7 @@ std::error_code SharedFile::read(absl::Span<uint8_t> buffer, size_t &size) {
return {};
}

std::error_code SharedFile::write(
absl::Span<const uint8_t> buffer, size_t &size) {
std::error_code SharedFile::write(ConstBufferSpan buffer, size_t &size) {
ssize_t ret = ::write(fd_, buffer.data(), buffer.size());
if (ret < 0) {
return {errno, std::system_category()};
Expand All @@ -32,7 +31,7 @@ std::error_code SharedFile::write(
}

std::error_code SharedFile::pread(
int64_t position, absl::Span<uint8_t> buffer, size_t &size) {
int64_t position, BufferSpan buffer, size_t &size) {
ssize_t ret = pread64(fd_, buffer.data(), buffer.size(), position);
if (ret < 0) {
return {errno, std::system_category()};
Expand All @@ -42,7 +41,7 @@ std::error_code SharedFile::pread(
}

std::error_code SharedFile::pwrite(
int64_t position, absl::Span<const uint8_t> buffer, size_t &size) {
int64_t position, ConstBufferSpan buffer, size_t &size) {
ssize_t ret = pwrite64(fd_, buffer.data(), buffer.size(), position);
if (ret < 0) {
return {errno, std::system_category()};
Expand Down
11 changes: 4 additions & 7 deletions io/posix/file.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,12 @@ class SharedFile : public io::File {
explicit SharedFile(int fd) : fd_(fd) {}
~SharedFile() override = default;

std::error_code read(absl::Span<uint8_t> buffer, size_t &size) override;
std::error_code write(
absl::Span<const uint8_t> buffer, size_t &size) override;
std::error_code read(BufferSpan buffer, size_t &size) override;
std::error_code write(ConstBufferSpan buffer, size_t &size) override;
std::error_code pread(
int64_t position, absl::Span<uint8_t> buffer, size_t &size) override;
int64_t position, BufferSpan buffer, size_t &size) override;
std::error_code pwrite(
int64_t position,
absl::Span<const uint8_t> buffer,
size_t &size) override;
int64_t position, ConstBufferSpan buffer, size_t &size) override;
std::error_code seek(int64_t position) override;
std::error_code tell(int64_t &position) override;
std::error_code size(int64_t &size) override;
Expand Down
Loading

0 comments on commit 85ca927

Please sign in to comment.