Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions silkworm/db/datastore/snapshots/btree/btree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,15 @@ BTree::BTree(
cache_{decode_nodes(encoded_nodes)} {
}

using CompareResult = std::pair<int, Bytes>;
using CompareResult = std::pair<int, BytesOrByteView>;

static CompareResult compare_key(
ByteView key,
BTree::DataIndex key_index,
const BTree::KeyValueIndex& index) {
auto data_key = index.lookup_key(key_index);
ensure(data_key.has_value(), [&] { return "out-of-bounds key=" + to_hex(key) + " data_index=" + std::to_string(key_index); });
int cmp = data_key->compare(key);
int cmp = ByteView{*data_key}.compare(key);
return {cmp, std::move(*data_key)};
}

Expand Down Expand Up @@ -106,7 +106,7 @@ BTree::SeekResult BTree::seek(ByteView seek_key, const KeyValueIndex& index) {
return {found, std::move(kv_pair->first), std::move(kv_pair->second), left_index};
}

std::optional<Bytes> BTree::get(ByteView key, const KeyValueIndex& index) {
std::optional<BytesOrByteView> BTree::get(ByteView key, const KeyValueIndex& index) {
if (key.empty() && num_nodes_ > 0) {
auto kv_pair = index.lookup_key_value(0);
if (!kv_pair) {
Expand Down Expand Up @@ -172,7 +172,7 @@ void BTree::warmup(const KeyValueIndex& index) {
const size_t data_index = i - 1;
auto [_, key] = compare_key({}, data_index, index);
cache_.emplace_back(Node{data_index, Bytes{key}});
cached_bytes += sizeof(Node) + key.length();
cached_bytes += sizeof(Node) + ByteView{key}.length();
}
SILK_DEBUG << "BTree::warmup finished M=" << fanout_ << " N=" << num_nodes_ << " cache_size=" << cached_bytes;
}
Expand Down
18 changes: 9 additions & 9 deletions silkworm/db/datastore/snapshots/btree/btree.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,23 +27,23 @@ namespace silkworm::snapshots::btree {
class BTree {
public:
using DataIndex = uint64_t;
using KeyValue = std::pair<Bytes, Bytes>;
using KeyValue = std::pair<BytesOrByteView, BytesOrByteView>;

struct KeyValueIndex {
virtual ~KeyValueIndex() = default;
virtual std::optional<KeyValue> lookup_key_value(DataIndex) const = 0;
virtual std::optional<Bytes> lookup_key(DataIndex) const = 0;
virtual std::optional<BytesOrByteView> lookup_key(DataIndex) const = 0;

using LookupResult = std::pair<int, std::optional<Bytes>>;
using LookupResult = std::pair<int, std::optional<BytesOrByteView>>;
virtual std::optional<LookupResult> lookup_key_value(DataIndex, ByteView) const = 0;
virtual std::optional<Bytes> advance_key_value(DataIndex, ByteView, size_t skip_max_count) const = 0;
virtual std::optional<BytesOrByteView> advance_key_value(DataIndex, ByteView, size_t skip_max_count) const = 0;
};

struct SeekResult {
bool found;
Bytes key;
Bytes value;
DataIndex key_index;
bool found{false};
BytesOrByteView key;
BytesOrByteView value;
DataIndex key_index{0};
};

BTree(
Expand All @@ -68,7 +68,7 @@ class BTree {
//! \brief Search and return key equal to the given \p key
//! \param key the key to look for
//! \param index the key-value data sequence
std::optional<Bytes> get(ByteView key, const KeyValueIndex& index);
std::optional<BytesOrByteView> get(ByteView key, const KeyValueIndex& index);

void check_against_data_keys(const KeyValueIndex& index);

Expand Down
27 changes: 13 additions & 14 deletions silkworm/db/datastore/snapshots/btree/btree_index.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ MemoryMappedRegion BTreeIndex::memory_file_region() const {
std::optional<BTreeIndex::Cursor> BTreeIndex::seek(ByteView seek_key, const KVSegmentReader& kv_segment) const {
KeyValueIndex index{kv_segment, data_offsets_, file_path_};
auto [found, key, value, data_index] = btree_->seek(seek_key, index);
if (key.compare(seek_key) >= 0) {
if (ByteView{key}.compare(seek_key) >= 0) {
return BTreeIndex::Cursor{
this,
std::move(key),
Expand All @@ -85,7 +85,7 @@ std::optional<BTreeIndex::Cursor> BTreeIndex::seek(ByteView seek_key, const KVSe
return std::nullopt;
}

std::optional<Bytes> BTreeIndex::get(ByteView key, const KVSegmentReader& kv_segment) const {
std::optional<BytesOrByteView> BTreeIndex::get(ByteView key, const KVSegmentReader& kv_segment) const {
const KeyValueIndex index{kv_segment, data_offsets_, file_path_};
return btree_->get(key, index);
}
Expand All @@ -96,30 +96,29 @@ std::optional<BTree::KeyValue> BTreeIndex::KeyValueIndex::lookup_key_value(DataI
}
const auto data_offset = data_offsets_->at(data_index);

segment::KVSegmentReader<RawDecoder<Bytes>, RawDecoder<Bytes>> reader{kv_segment_};
segment::KVSegmentReader<RawDecoder<BytesOrByteView>, RawDecoder<BytesOrByteView>> reader{kv_segment_};
auto data_it = reader.seek(data_offset);
if (data_it == reader.end()) {
throw std::runtime_error{"key/value not found data_index=" + std::to_string(data_index) + " for " + file_path_.string()};
}
auto kv_pair = *data_it;

return BTree::KeyValue{std::move(kv_pair.first), std::move(kv_pair.second)};
return BTree::KeyValue{kv_pair.first, kv_pair.second};
}

std::optional<Bytes> BTreeIndex::KeyValueIndex::lookup_key(DataIndex data_index) const {
std::optional<BytesOrByteView> BTreeIndex::KeyValueIndex::lookup_key(DataIndex data_index) const {
if (data_index >= data_offsets_->size()) {
return std::nullopt;
}
const auto data_offset = data_offsets_->at(data_index);

segment::KVSegmentKeysReader<RawDecoder<Bytes>> reader{kv_segment_};
auto data_it = reader.seek(data_offset);
segment::KVSegmentKeysReader<RawDecoder<BytesOrByteView>> reader{kv_segment_};
const auto data_it = reader.seek(data_offset);
if (data_it == reader.end()) {
throw std::runtime_error{"key not found data_index=" + std::to_string(data_index) + " for " + file_path_.string()};
}
Bytes key = std::move(*data_it);

return key;
return *data_it;
}

std::optional<BTreeIndex::KeyValueIndex::LookupResult> BTreeIndex::KeyValueIndex::lookup_key_value(DataIndex data_index, ByteView k) const {
Expand All @@ -130,15 +129,15 @@ std::optional<BTreeIndex::KeyValueIndex::LookupResult> BTreeIndex::KeyValueIndex

const auto& decompressor = kv_segment_.decompressor();
auto it = decompressor.seek(data_offset);
if ((it == decompressor.end()) || !it.has_next()) {
if (it == decompressor.end() || !it.has_next()) {
throw std::runtime_error{"key not found data_index=" + std::to_string(data_index) + " for " + file_path_.string()};
}

const int key_compare = ByteView{*it}.compare(k);
if (key_compare != 0) {
if (const int key_compare = ByteView{*it}.compare(k); key_compare != 0) {
return LookupResult{key_compare, std::nullopt};
}

// Key matches: advance and read value
++it;
return LookupResult{0, std::move(*it)};
}
Expand Down Expand Up @@ -178,7 +177,7 @@ static seg::Decompressor::Iterator kv_decompressor_seek_to_key(
return it;
}

std::optional<Bytes> BTreeIndex::KeyValueIndex::advance_key_value(const DataIndex data_index, const ByteView k, const size_t skip_max_count) const {
std::optional<BytesOrByteView> BTreeIndex::KeyValueIndex::advance_key_value(const DataIndex data_index, const ByteView k, const size_t skip_max_count) const {
if (data_index >= data_offsets_->size()) {
return std::nullopt;
}
Expand All @@ -191,7 +190,7 @@ std::optional<Bytes> BTreeIndex::KeyValueIndex::advance_key_value(const DataInde
}

++it;
return std::optional<Bytes>{std::move(*it)};
return std::move(*it);
}

bool BTreeIndex::Cursor::next() {
Expand Down
12 changes: 6 additions & 6 deletions silkworm/db/datastore/snapshots/btree/btree_index.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class BTreeIndex {

class Cursor {
public:
using value_type = std::pair<Bytes, Bytes>;
using value_type = std::pair<BytesOrByteView, BytesOrByteView>;
using iterator_category [[maybe_unused]] = std::input_iterator_tag;
using difference_type = std::ptrdiff_t;
using pointer = value_type*;
Expand Down Expand Up @@ -86,8 +86,8 @@ class BTreeIndex {

Cursor(
const BTreeIndex* index,
Bytes key,
Bytes value,
BytesOrByteView key,
BytesOrByteView value,
DataIndex data_index,
const KVSegmentReader* kv_segment)
: index_{index},
Expand Down Expand Up @@ -130,7 +130,7 @@ class BTreeIndex {
//! \param key the data key to match exactly
//! \param kv_segment reader of the key-value data sequence
//! \return the value associated at \p key or std::nullopt if not found
std::optional<Bytes> get(ByteView key, const KVSegmentReader& kv_segment) const;
std::optional<BytesOrByteView> get(ByteView key, const KVSegmentReader& kv_segment) const;

private:
class KeyValueIndex : public BTree::KeyValueIndex {
Expand All @@ -145,9 +145,9 @@ class BTreeIndex {
~KeyValueIndex() override = default;

std::optional<BTree::KeyValue> lookup_key_value(DataIndex data_index) const override;
std::optional<Bytes> lookup_key(DataIndex data_index) const override;
std::optional<BytesOrByteView> lookup_key(DataIndex data_index) const override;
std::optional<LookupResult> lookup_key_value(DataIndex, ByteView) const override;
std::optional<Bytes> advance_key_value(DataIndex, ByteView, size_t skip_max_count) const override;
std::optional<BytesOrByteView> advance_key_value(DataIndex, ByteView, size_t skip_max_count) const override;

private:
const KVSegmentReader& kv_segment_;
Expand Down
2 changes: 1 addition & 1 deletion silkworm/db/datastore/snapshots/btree/btree_index_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ TEST_CASE("BTreeIndex", "[snapshots][btree]") {
SECTION("BTreeIndex::get") {
// Check that all values retrieved through BT index match
size_t key_count{0};
segment::KVSegmentReader<RawDecoder<Bytes>, RawDecoder<Bytes>> reader{kv_segment};
segment::KVSegmentReader<RawDecoder<ByteView>, RawDecoder<ByteView>> reader{kv_segment};
for (const auto [key, value] : reader) {
const auto v = bt_index.get(key, kv_segment);
CHECK(v == value);
Expand Down
12 changes: 11 additions & 1 deletion silkworm/db/datastore/snapshots/common/raw_codec.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
namespace silkworm::snapshots {

template <class TBytes>
concept BytesOrByteViewConcept = std::same_as<TBytes, Bytes> || std::same_as<TBytes, ByteView>;
concept BytesOrByteViewConcept = std::same_as<TBytes, Bytes> || std::same_as<TBytes, ByteView> || std::same_as<TBytes, BytesOrByteView>;

template <BytesOrByteViewConcept TBytes>
struct RawDecoder : public Decoder {
Expand All @@ -41,8 +41,18 @@ struct RawDecoder : public Decoder {
}
};

template <>
struct RawDecoder<BytesOrByteView> : public Decoder {
BytesOrByteView value;
~RawDecoder() override = default;
void decode_word(Word& word) override {
value = std::move(word);
}
};

static_assert(DecoderConcept<RawDecoder<Bytes>>);
static_assert(DecoderConcept<RawDecoder<ByteView>>);
static_assert(DecoderConcept<RawDecoder<BytesOrByteView>>);

template <BytesOrByteViewConcept TBytes>
struct RawEncoder : public Encoder {
Expand Down
5 changes: 2 additions & 3 deletions silkworm/db/datastore/snapshots/domain_get_latest_query.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,13 @@ struct DomainGetLatestSegmentQuery {
return std::nullopt;
}

std::optional<Bytes> value_data = entity_.btree_index.get(key_data, entity_.kv_segment);
std::optional<Word> value_data = entity_.btree_index.get(key_data, entity_.kv_segment);
if (!value_data) {
return std::nullopt;
}

TValueDecoder value_decoder;
Word value{std::move(*value_data)};
value_decoder.decode_word(value);
value_decoder.decode_word(*value_data);
return std::move(value_decoder.value);
}

Expand Down
16 changes: 7 additions & 9 deletions silkworm/db/datastore/snapshots/domain_range_latest_query.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ struct DomainRangeLatestSegmentQuery {
auto begin_it = entity_.btree_index.seek(key_start, entity_.kv_segment).value_or(btree::BTreeIndex::Cursor{});

return std::ranges::subrange{std::move(begin_it), std::default_sentinel} |
std::views::take_while([key_end = std::move(key_end)](const auto& kv_pair) { return kv_pair.first < key_end; });
std::views::take_while([key_end = std::move(key_end)](const auto& kv_pair) { return ByteView{kv_pair.first} < key_end; });
}

auto exec(Bytes key_start, Bytes key_end, bool ascending) {
Expand All @@ -77,27 +77,25 @@ struct DomainRangeLatestQuery {
using ResultItemKey = decltype(TKeyDecoder::value);
using ResultItemValue = decltype(TValueDecoder::value);
using ResultItem = std::pair<ResultItemKey, ResultItemValue>;
using Word = snapshots::Decoder::Word;
using Word = Decoder::Word;

static ResultItem decode_kv_pair(std::pair<Bytes, Bytes>&& kv_pair) {
if constexpr (std::same_as<ResultItem, std::pair<Bytes, Bytes>>) {
static ResultItem decode_kv_pair(std::pair<Word, Word>&& kv_pair) {
if constexpr (std::same_as<ResultItem, std::pair<Word, Word>>) {
return std::move(kv_pair);
}

TKeyDecoder key_decoder;
Word key_byte_word{std::move(kv_pair.first)};
key_decoder.decode_word(key_byte_word);
key_decoder.decode_word(kv_pair.first);
ResultItemKey& key = key_decoder.value;

TValueDecoder value_decoder;
Word value_byte_word{std::move(kv_pair.second)};
value_decoder.decode_word(value_byte_word);
value_decoder.decode_word(kv_pair.second);
ResultItemValue& value = value_decoder.value;

return ResultItem{std::move(key), std::move(value)};
}

static constexpr auto kDecodeKVPairFunc = [](std::pair<Bytes, Bytes>& kv_pair) -> ResultItem {
static constexpr auto kDecodeKVPairFunc = [](std::pair<Word, Word>& kv_pair) -> ResultItem {
return decode_kv_pair(std::move(kv_pair));
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@

#include "../common/codec.hpp"
#include "../common/snapshot_path.hpp"
#include "../common/util/iterator/iterator_read_into_vector.hpp"
#include "seg/decompressor.hpp"

namespace silkworm::snapshots::segment {
Expand Down
Loading