Skip to content

Commit

Permalink
rename leveldb_wrapper to sortdb_wrapper (suggested in review comment)
Browse files Browse the repository at this point in the history
  • Loading branch information
ban-nobuhiro committed Jul 18, 2023
1 parent cfe0c0e commit bb33daf
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 44 deletions.
20 changes: 10 additions & 10 deletions src/limestone/datastore_snapshot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@

#include <limestone/api/datastore.h>
#include "log_entry.h"
#include "leveldb_wrapper.h"
#include "sortdb_wrapper.h"

namespace limestone::api {

Expand Down Expand Up @@ -95,21 +95,21 @@ static int comp_twisted_key(const std::string_view& a, const std::string_view& b
void datastore::create_snapshot() noexcept {
auto& from_dir = location_;
#if defined SORT_METHOD_PUT_ONLY
auto lvldb = std::make_unique<leveldb_wrapper>(from_dir, comp_twisted_key);
auto sortdb = std::make_unique<sortdb_wrapper>(from_dir, comp_twisted_key);
#else
auto lvldb = std::make_unique<leveldb_wrapper>(from_dir);
auto sortdb = std::make_unique<sortdb_wrapper>(from_dir);
#endif

epoch_id_type ld_epoch = last_durable_epoch_in_dir();
epoch_id_switched_.store(ld_epoch + 1);

[[maybe_unused]]
auto insert_entry_or_update_to_max = [&lvldb](log_entry& e){
auto insert_entry_or_update_to_max = [&sortdb](log_entry& e){
bool need_write = true;

// skip older entry than already inserted
std::string value;
if (lvldb->get(e.key_sid(), &value)) {
if (sortdb->get(e.key_sid(), &value)) {
write_version_type write_version;
e.write_version(write_version);
if (write_version < write_version_type(value.substr(1))) {
Expand All @@ -121,11 +121,11 @@ void datastore::create_snapshot() noexcept {
std::string db_value;
db_value.append(1, static_cast<char>(e.type()));
db_value.append(e.value_etc());
lvldb->put(e.key_sid(), db_value);
sortdb->put(e.key_sid(), db_value);
}
};
[[maybe_unused]]
auto insert_twisted_entry = [&lvldb](log_entry& e){
auto insert_twisted_entry = [&sortdb](log_entry& e){
// key_sid: storage_id[8] key[*], value_etc: epoch[8]LE minor_version[8]LE value[*], type: type[1]
// db_key: epoch[8]BE minor_version[8]BE storage_id[8] key[*], db_value: type[1] value[*]
std::string db_key(write_version_size + e.key_sid().size(), '\0');
Expand All @@ -134,7 +134,7 @@ void datastore::create_snapshot() noexcept {
std::memcpy(&db_key[write_version_size], e.key_sid().data(), e.key_sid().size());
std::string db_value(1, static_cast<char>(e.type()));
db_value.append(e.value_etc().substr(write_version_size));
lvldb->put(db_key, db_value);
sortdb->put(db_key, db_value);
};
#if defined SORT_METHOD_PUT_ONLY
auto add_entry = insert_twisted_entry;
Expand Down Expand Up @@ -222,7 +222,7 @@ void datastore::create_snapshot() noexcept {
}
static_assert(sizeof(log_entry::entry_type) == 1);
#if defined SORT_METHOD_PUT_ONLY
lvldb->each([&ostrm, last_key = std::string{}](std::string_view db_key, std::string_view db_value) mutable {
sortdb->each([&ostrm, last_key = std::string{}](std::string_view db_key, std::string_view db_value) mutable {
// using the first entry in GROUP BY (original-)key
// NB: max versions comes first (by the custom-comparator)
std::string_view key(db_key.data() + write_version_size, db_key.size() - write_version_size);
Expand All @@ -249,7 +249,7 @@ void datastore::create_snapshot() noexcept {
}
});
#else
lvldb->each([&ostrm](std::string_view db_key, std::string_view db_value) {
sortdb->each([&ostrm](std::string_view db_key, std::string_view db_value) {
auto entry_type = static_cast<log_entry::entry_type>(db_value[0]);
db_value.remove_prefix(1);
switch (entry_type) {
Expand Down
71 changes: 37 additions & 34 deletions src/limestone/leveldb_wrapper.h → src/limestone/sortdb_wrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
#ifdef SORT_METHOD_USE_ROCKSDB
#include <rocksdb/db.h>
#include <rocksdb/comparator.h>
namespace leveldb = rocksdb;
#else
#include <leveldb/db.h>
#include <leveldb/comparator.h>
Expand All @@ -29,98 +28,102 @@ namespace leveldb = rocksdb;
#include <limestone/logging.h>

namespace limestone::api {
#ifdef SORT_METHOD_USE_ROCKSDB
using namespace rocksdb;
#else
using namespace leveldb;
#endif

static constexpr const std::string_view leveldb_dir = "leveldb";
static constexpr const std::string_view sortdb_dir = "sorting";

// leveldb_wrapper : the wrapper for LevelDB or compatible one (e.g. RocksDB)
class leveldb_wrapper {
class sortdb_wrapper {
public:
// type of user-defined key-comparator function
using keycomp = int(*)(const std::string_view& a, const std::string_view& b);

/**
* @brief create new object
* @param dir the directory where LevelDB files will be placed
* @param dir the directory where DB library files will be placed
* @param keycomp (optional) user-defined comparator
*/
explicit leveldb_wrapper(const boost::filesystem::path& dir, keycomp keycomp = nullptr)
: lvldb_path_(dir / boost::filesystem::path(std::string(leveldb_dir))) {
explicit sortdb_wrapper(const boost::filesystem::path& dir, keycomp keycomp = nullptr)
: workdir_path_(dir / boost::filesystem::path(std::string(sortdb_dir))) {
clear_directory();

leveldb::Options options;
Options options;
options.create_if_missing = true;
if (keycomp != nullptr) {
comp_ = std::make_unique<comparator>(keycomp);
options.comparator = comp_.get();
}
if (leveldb::Status status = leveldb::DB::Open(options, lvldb_path_.string(), &lvldb_); !status.ok()) {
LOG_LP(ERROR) << "Unable to open/create LevelDB database, status = " << status.ToString();
if (Status status = DB::Open(options, workdir_path_.string(), &sortdb_); !status.ok()) {
LOG_LP(ERROR) << "Unable to open/create database working files, status = " << status.ToString();
std::abort();
}
}

/**
* @brief destruct object
*/
~leveldb_wrapper() {
delete lvldb_;
~sortdb_wrapper() {
delete sortdb_;
clear_directory();
}

leveldb_wrapper() noexcept = delete;
leveldb_wrapper(leveldb_wrapper const& other) noexcept = delete;
leveldb_wrapper& operator=(leveldb_wrapper const& other) noexcept = delete;
leveldb_wrapper(leveldb_wrapper&& other) noexcept = delete;
leveldb_wrapper& operator=(leveldb_wrapper&& other) noexcept = delete;
sortdb_wrapper() noexcept = delete;
sortdb_wrapper(sortdb_wrapper const& other) noexcept = delete;
sortdb_wrapper& operator=(sortdb_wrapper const& other) noexcept = delete;
sortdb_wrapper(sortdb_wrapper&& other) noexcept = delete;
sortdb_wrapper& operator=(sortdb_wrapper&& other) noexcept = delete;

bool put(const std::string& key, const std::string& value) {
leveldb::WriteOptions write_options{};
auto status = lvldb_->Put(write_options, key, value);
WriteOptions write_options{};
auto status = sortdb_->Put(write_options, key, value);
return status.ok();
}

bool get(const std::string& key, std::string* value) {
leveldb::ReadOptions read_options{};
auto status = lvldb_->Get(read_options, key, value);
ReadOptions read_options{};
auto status = sortdb_->Get(read_options, key, value);
return status.ok();
}

void each(const std::function<void(std::string_view, std::string_view)>& fun) {
leveldb::Iterator* it = lvldb_->NewIterator(leveldb::ReadOptions()); // NOLINT (typical usage of leveldb)
Iterator* it = sortdb_->NewIterator(ReadOptions()); // NOLINT (typical usage of API)
for (it->SeekToFirst(); it->Valid(); it->Next()) {
leveldb::Slice key = it->key();
leveldb::Slice value = it->value();
Slice key = it->key();
Slice value = it->value();
fun(std::string_view(key.data(), key.size()), std::string_view(value.data(), value.size()));
}
delete it; // NOLINT (typical usage of leveldb)
delete it; // NOLINT (typical usage of API)
}

private:
leveldb::DB* lvldb_{};
DB* sortdb_{};

// user-defined comparator wrapper
class comparator : public leveldb::Comparator {
class comparator : public Comparator {
keycomp keycomp_;
public:
explicit comparator(keycomp keycomp) : keycomp_(keycomp) {}
[[nodiscard]] const char *Name() const override { return "custom comparator"; }
void FindShortestSeparator(std::string *, const leveldb::Slice&) const override {}
void FindShortestSeparator(std::string *, const Slice&) const override {}
void FindShortSuccessor(std::string *) const override {}
[[nodiscard]] int Compare(const leveldb::Slice& a, const leveldb::Slice& b) const override {
[[nodiscard]] int Compare(const Slice& a, const Slice& b) const override {
return keycomp_(std::string_view{a.data(), a.size()}, std::string_view{b.data(), b.size()});
}
};

std::unique_ptr<comparator> comp_{};

boost::filesystem::path lvldb_path_;
boost::filesystem::path workdir_path_;

void clear_directory() const noexcept {
if (boost::filesystem::exists(lvldb_path_)) {
if (boost::filesystem::is_directory(lvldb_path_)) {
boost::filesystem::remove_all(lvldb_path_);
if (boost::filesystem::exists(workdir_path_)) {
if (boost::filesystem::is_directory(workdir_path_)) {
boost::filesystem::remove_all(workdir_path_);
} else {
LOG_LP(ERROR) << lvldb_path_.string() << " is not a directory";
LOG_LP(ERROR) << workdir_path_.string() << " is not a directory";
std::abort();
}
}
Expand Down

0 comments on commit bb33daf

Please sign in to comment.