Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor storage interface #1435

Merged
merged 20 commits into from
Dec 6, 2022
18 changes: 7 additions & 11 deletions core/api/service/child_state/impl/child_state_api_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,7 @@ namespace kagome::api {
OUTCOME_TRY(initial_trie_reader,
storage_->getEphemeralBatchAt(header.state_root));
OUTCOME_TRY(child_root, initial_trie_reader->get(child_storage_key));
OUTCOME_TRY(child_root_hash,
common::Hash256::fromSpan(gsl::make_span(child_root.get())));
OUTCOME_TRY(child_root_hash, common::Hash256::fromSpan(child_root));
OUTCOME_TRY(child_storage_trie_reader,
storage_->getEphemeralBatchAt(child_root_hash));
auto cursor = child_storage_trie_reader->trieCursor();
Expand Down Expand Up @@ -90,8 +89,7 @@ namespace kagome::api {
OUTCOME_TRY(initial_trie_reader,
storage_->getEphemeralBatchAt(header.state_root));
OUTCOME_TRY(child_root, initial_trie_reader->get(child_storage_key));
OUTCOME_TRY(child_root_hash,
common::Hash256::fromSpan(gsl::make_span(child_root.get())));
OUTCOME_TRY(child_root_hash, common::Hash256::fromSpan(child_root));
OUTCOME_TRY(child_storage_trie_reader,
storage_->getEphemeralBatchAt(child_root_hash));
auto cursor = child_storage_trie_reader->trieCursor();
Expand Down Expand Up @@ -132,13 +130,12 @@ namespace kagome::api {
OUTCOME_TRY(header, header_repo_->getBlockHeader(at));
OUTCOME_TRY(trie_reader, storage_->getEphemeralBatchAt(header.state_root));
OUTCOME_TRY(child_root, trie_reader->get(child_storage_key));
OUTCOME_TRY(child_root_hash,
common::Hash256::fromSpan(gsl::make_span(child_root.get())));
OUTCOME_TRY(child_root_hash, common::Hash256::fromSpan(child_root));
OUTCOME_TRY(child_storage_trie_reader,
storage_->getEphemeralBatchAt(child_root_hash));
auto res = child_storage_trie_reader->tryGet(key);
return common::map_result_optional(res,
[](const auto &r) { return r.get(); });
return common::map_result_optional(
std::move(res), [](common::BufferOrView &&r) { return r.into(); });
}

outcome::result<std::optional<primitives::BlockHash>>
Expand All @@ -164,11 +161,10 @@ namespace kagome::api {
OUTCOME_TRY(header, header_repo_->getBlockHeader(at));
OUTCOME_TRY(trie_reader, storage_->getEphemeralBatchAt(header.state_root));
OUTCOME_TRY(child_root, trie_reader->get(child_storage_key));
OUTCOME_TRY(child_root_hash,
common::Hash256::fromSpan(gsl::make_span(child_root.get())));
OUTCOME_TRY(child_root_hash, common::Hash256::fromSpan(child_root));
OUTCOME_TRY(child_storage_trie_reader,
storage_->getEphemeralBatchAt(child_root_hash));
OUTCOME_TRY(value, child_storage_trie_reader->get(key));
return value.get().size();
return value.size();
}
} // namespace kagome::api
15 changes: 7 additions & 8 deletions core/api/service/state/impl/state_api_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,8 @@ namespace kagome::api {
OUTCOME_TRY(header, header_repo_->getBlockHeader(at));
OUTCOME_TRY(trie_reader, storage_->getEphemeralBatchAt(header.state_root));
auto res = trie_reader->tryGet(key);
return common::map_result_optional(res,
[](const auto &r) { return r.get(); });
return common::map_result_optional(
std::move(res), [](common::BufferOrView &&r) { return r.into(); });
}

outcome::result<std::vector<StateApiImpl::StorageChangeSet>>
Expand Down Expand Up @@ -164,14 +164,13 @@ namespace kagome::api {
OUTCOME_TRY(batch, storage_->getEphemeralBatchAt(header.state_root));
StorageChangeSet change{block, {}};
for (auto &key : keys) {
OUTCOME_TRY(opt_value, batch->tryGet(key));
OUTCOME_TRY(opt_get, batch->tryGet(key));
auto opt_value = common::map_optional(
std::move(opt_get),
[](common::BufferOrView &&r) { return r.into(); });
auto it = last_values.find(key);
if (it == last_values.end() || it->second != opt_value) {
std::optional<common::Buffer> opt_buffer =
opt_value ? std::make_optional(opt_value.value().get())
: std::nullopt;
change.changes.push_back(
StorageChangeSet::Change{common::Buffer{key}, opt_buffer});
change.changes.push_back(StorageChangeSet::Change{key, opt_value});
}
last_values[key] = std::move(opt_value);
}
Expand Down
6 changes: 2 additions & 4 deletions core/blockchain/impl/block_storage_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@
namespace kagome::blockchain {
using primitives::Block;
using primitives::BlockId;
using storage::face::MapCursor;
using storage::face::WriteBatch;
using Buffer = common::Buffer;
using Prefix = prefix::Prefix;

Expand Down Expand Up @@ -256,7 +254,7 @@ namespace kagome::blockchain {

auto num_to_idx_key =
prependPrefix(numberToIndexKey(block.number), Prefix::ID_TO_LOOKUP_KEY);
OUTCOME_TRY(num_to_idx_val_opt, storage_->tryLoad(num_to_idx_key.view()));
OUTCOME_TRY(num_to_idx_val_opt, storage_->tryGet(num_to_idx_key.view()));
if (num_to_idx_val_opt == block_lookup_key) {
if (auto res = storage_->remove(num_to_idx_key); res.has_error()) {
SL_ERROR(logger_,
Expand Down Expand Up @@ -301,7 +299,7 @@ namespace kagome::blockchain {
}

OUTCOME_TRY(leaves_opt,
storage_->tryLoad(storage::kBlockTreeLeavesLookupKey));
storage_->tryGet(storage::kBlockTreeLeavesLookupKey));
if (not leaves_opt.has_value()) {
return BlockStorageError::BLOCK_TREE_LEAVES_NOT_FOUND;
}
Expand Down
6 changes: 3 additions & 3 deletions core/blockchain/impl/common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

namespace kagome::blockchain {

outcome::result<std::optional<common::Buffer>> idToLookupKey(
outcome::result<std::optional<common::BufferOrView>> idToLookupKey(
const ReadableBufferStorage &map, const primitives::BlockId &id) {
auto key = visit_in_place(
id,
Expand All @@ -24,7 +24,7 @@ namespace kagome::blockchain {
return prependPrefix(hash, prefix::Prefix::ID_TO_LOOKUP_KEY);
});

OUTCOME_TRY(key_opt, map.tryLoad(key));
OUTCOME_TRY(key_opt, map.tryGet(key));

return std::move(key_opt);
}
Expand All @@ -35,7 +35,7 @@ namespace kagome::blockchain {
auto codec = storage::trie::PolkadotCodec();

for (const auto &[key, val] : key_vals) {
[[maybe_unused]] auto res = trie.put(key, val);
[[maybe_unused]] auto res = trie.put(key, common::BufferView{val});
BOOST_ASSERT_MSG(res.has_value(), "Insertion into trie failed");
}
auto root = trie.getRoot();
Expand Down
4 changes: 2 additions & 2 deletions core/blockchain/impl/common.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@
namespace kagome::blockchain {

using ReadableBufferStorage =
storage::face::ReadableStorage<common::BufferView, common::Buffer>;
storage::face::Readable<common::Buffer, common::Buffer>;

/**
* Convert a block ID into a key, which is a first part of a key, by which the
* columns are stored in the database
*/
outcome::result<std::optional<common::Buffer>> idToLookupKey(
outcome::result<std::optional<common::BufferOrView>> idToLookupKey(
const ReadableBufferStorage &map, const primitives::BlockId &id);

/**
Expand Down
13 changes: 6 additions & 7 deletions core/blockchain/impl/storage_util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,22 +30,21 @@ namespace kagome::blockchain {
auto num_to_idx_key =
prependPrefix(numberToIndexKey(block.number), Prefix::ID_TO_LOOKUP_KEY);
auto block_lookup_key = numberAndHashToLookupKey(block.number, block.hash);
return map.put(num_to_idx_key, block_lookup_key);
return map.put(num_to_idx_key, std::move(block_lookup_key));
}

outcome::result<void> putWithPrefix(storage::BufferStorage &map,
prefix::Prefix prefix,
BlockNumber num,
Hash256 block_hash,
const common::Buffer &value) {
common::BufferOrView &&value) {
auto block_lookup_key = numberAndHashToLookupKey(num, block_hash);

auto hash_to_idx_key = prependPrefix(block_hash, Prefix::ID_TO_LOOKUP_KEY);
OUTCOME_TRY(map.put(hash_to_idx_key, block_lookup_key));

auto value_lookup_key = prependPrefix(block_lookup_key, prefix);
OUTCOME_TRY(map.put(hash_to_idx_key, std::move(block_lookup_key)));

return map.put(value_lookup_key, value);
return map.put(value_lookup_key, std::move(value));
}

outcome::result<bool> hasWithPrefix(const storage::BufferStorage &map,
Expand All @@ -56,13 +55,13 @@ namespace kagome::blockchain {
return map.contains(prependPrefix(key.value(), prefix));
}

outcome::result<std::optional<common::Buffer>> getWithPrefix(
outcome::result<std::optional<common::BufferOrView>> getWithPrefix(
const storage::BufferStorage &map,
prefix::Prefix prefix,
const primitives::BlockId &block_id) {
OUTCOME_TRY(key, idToLookupKey(map, block_id));
if (!key.has_value()) return std::nullopt;
return map.tryLoad(prependPrefix(key.value(), prefix));
return map.tryGet(prependPrefix(key.value(), prefix));
}

common::Buffer numberToIndexKey(primitives::BlockNumber n) {
Expand Down
4 changes: 2 additions & 2 deletions core/blockchain/impl/storage_util.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ namespace kagome::blockchain {
prefix::Prefix prefix,
primitives::BlockNumber num,
common::Hash256 block_hash,
const common::Buffer &value);
common::BufferOrView &&value);

/**
* Chech if an entry from the database
Expand All @@ -86,7 +86,7 @@ namespace kagome::blockchain {
* @param block_id - id of the block to get entry for
* @return error, or an encoded entry, if any, or std::nullopt, if none
*/
outcome::result<std::optional<common::Buffer>> getWithPrefix(
outcome::result<std::optional<common::BufferOrView>> getWithPrefix(
const storage::BufferStorage &storage,
prefix::Prefix prefix,
const primitives::BlockId &block_id);
Expand Down
3 changes: 0 additions & 3 deletions core/common/buffer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -245,9 +245,6 @@ namespace kagome::common {

static inline const Buffer kEmptyBuffer{};

using BufferMutRef = std::reference_wrapper<Buffer>;
using BufferConstRef = std::reference_wrapper<const Buffer>;

namespace literals {
/// creates a buffer filled with characters from the original string
/// mind that it does not perform unhexing, there is ""_unhex for it
Expand Down
107 changes: 107 additions & 0 deletions core/common/buffer_or_view.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/**
* Copyright Soramitsu Co., Ltd. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

#ifndef KAGOME_COMMON_BUFFER_OR_VIEW_HPP
#define KAGOME_COMMON_BUFFER_OR_VIEW_HPP

#include <boost/variant/get.hpp>
#include <boost/variant/variant.hpp>
#include <type_traits>

#include "common/buffer.hpp"

namespace kagome::common {
/// Moved owned buffer or readonly view.
class BufferOrView {
turuslan marked this conversation as resolved.
Show resolved Hide resolved
using Span = gsl::span<const uint8_t>;
template <typename T>
using AsSpan = std::enable_if_t<std::is_convertible_v<T, Span>>;

struct Moved {};

public:
BufferOrView() = default;

BufferOrView(const BufferView &view) : variant{view} {}

BufferOrView(const std::vector<uint8_t> &vector) = delete;
BufferOrView(std::vector<uint8_t> &&vector)
: variant{Buffer{std::move(vector)}} {}

BufferOrView(const BufferOrView &) = delete;
BufferOrView(BufferOrView &&) = default;

BufferOrView &operator=(const BufferOrView &) = delete;
BufferOrView &operator=(BufferOrView &&) = default;

/// Is buffer owned.
bool owned() const {
if (variant.which() == 2) {
throw std::logic_error{"Tried to use moved BufferOrView"};
}
return variant.which() == 1;
}

/// Get view.
BufferView view() const {
if (!owned()) {
return boost::get<BufferView>(variant);
}
return BufferView{boost::get<Buffer>(variant)};
}

/// Get view.
operator BufferView() const {
return view();
}

/// Byte size.
size_t size() const {
return view().size();
}

/// Get mutable buffer reference. Copy once if view.
Buffer &mut() {
if (!owned()) {
auto view = boost::get<BufferView>(variant);
variant = Buffer{view};
}
return boost::get<Buffer>(variant);
}

/// Move buffer away. Copy once if view.
Buffer into() {
auto buffer = std::move(mut());
variant = Moved{};
return buffer;
}

private:
boost::variant<BufferView, Buffer, Moved> variant;

template <typename T, typename = AsSpan<T>>
friend bool operator==(const BufferOrView &l, const T &r) {
return l.view() == Span{r};
}
template <typename T, typename = AsSpan<T>>
friend bool operator!=(const BufferOrView &l, const T &r) {
return l.view() != Span{r};
}
template <typename T, typename = AsSpan<T>>
friend bool operator==(const T &l, const BufferOrView &r) {
return Span{l} == r.view();
}
template <typename T, typename = AsSpan<T>>
friend bool operator!=(const T &l, const BufferOrView &r) {
return Span{l} != r.view();
}
};
} // namespace kagome::common

template <>
struct fmt::formatter<kagome::common::BufferOrView>
: fmt::formatter<kagome::common::BufferView> {};

#endif // KAGOME_COMMON_BUFFER_OR_VIEW_HPP
5 changes: 3 additions & 2 deletions core/common/monadic_utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,9 @@ namespace kagome::common {
template <typename T, typename F, typename R = std::invoke_result_t<F, T &&>>
outcome::result<std::optional<R>> map_result_optional(
outcome::result<std::optional<T>> &&res_opt, F const &f) {
return map_result(res_opt, [&f](auto &opt) {
return map_optional(opt, [&f](auto &v) { return f(std::move(v)); });
return map_result(std::move(res_opt), [&f](std::optional<T> &&opt) {
return map_optional(std::move(opt),
[&f](T &&v) { return f(std::move(v)); });
});
}

Expand Down
4 changes: 2 additions & 2 deletions core/consensus/babe/impl/babe_config_repository_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ namespace kagome::consensus::babe {

// 1. Load last state
OUTCOME_TRY(encoded_last_state_opt,
persistent_storage_->tryLoad(
persistent_storage_->tryGet(
storage::kBabeConfigRepoStateLookupKey("last")));

if (encoded_last_state_opt.has_value()) {
Expand Down Expand Up @@ -138,7 +138,7 @@ namespace kagome::consensus::babe {
block_number > 0;
block_number -= kSavepointBlockInterval) {
OUTCOME_TRY(encoded_saved_state_opt,
persistent_storage_->tryLoad(
persistent_storage_->tryGet(
storage::kBabeConfigRepoStateLookupKey(block_number)));

if (not encoded_saved_state_opt.has_value()) {
Expand Down
4 changes: 2 additions & 2 deletions core/consensus/babe/impl/consistency_keeper_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ namespace kagome::consensus::babe {

bool ConsistencyKeeperImpl::prepare() {
// try to get record
auto buf_opt_res = storage_->tryLoad(storage::kApplyingBlockInfoLookupKey);
auto buf_opt_res = storage_->tryGet(storage::kApplyingBlockInfoLookupKey);
if (buf_opt_res.has_error()) {
SL_WARN(logger_,
"Can't check existence of partial applied block",
Expand All @@ -41,7 +41,7 @@ namespace kagome::consensus::babe {
}

// check if record exists
auto buf_opt = buf_opt_res.value();
auto &buf_opt = buf_opt_res.value();
if (not buf_opt.has_value()) {
return true;
}
Expand Down
4 changes: 2 additions & 2 deletions core/consensus/grandpa/impl/authority_manager_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ namespace kagome::consensus::grandpa {

// 1. Load last state
OUTCOME_TRY(encoded_last_state_opt,
persistent_storage_->tryLoad(
persistent_storage_->tryGet(
storage::kAuthorityManagerStateLookupKey("last")));

if (encoded_last_state_opt.has_value()) {
Expand Down Expand Up @@ -142,7 +142,7 @@ namespace kagome::consensus::grandpa {
block_number -= kSavepointBlockInterval) {
OUTCOME_TRY(
encoded_saved_state_opt,
persistent_storage_->tryLoad(
persistent_storage_->tryGet(
storage::kAuthorityManagerStateLookupKey(block_number)));

if (not encoded_saved_state_opt.has_value()) {
Expand Down
Loading