Merge pull request #4915 from pwojcikdev/db-val-refactor

Refactor `db_val`
This commit is contained in:
Piotr Wójcik 2025-06-25 01:01:55 +02:00 committed by GitHub
commit 617fae56ad
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
36 changed files with 555 additions and 471 deletions

View file

@ -12,6 +12,7 @@
#include <nano/secure/ledger_set_any.hpp>
#include <nano/secure/ledger_set_confirmed.hpp>
#include <nano/store/lmdb/iterator.hpp>
#include <nano/store/lmdb/utility.hpp>
#include <nano/store/typed_iterator_templ.hpp>
#include <boost/format.hpp>
@ -279,7 +280,9 @@ nano::wallet_store::wallet_store (bool & init_a, nano::kdf & kdf_a, store::trans
if (!init_a)
{
MDB_val junk;
debug_assert (mdb_get (env.tx (transaction_a), handle, nano::store::lmdb::db_val (version_special), &junk) == MDB_NOTFOUND);
nano::store::lmdb::db_val version_key (version_special);
auto mdb_version_key = nano::store::lmdb::to_mdb_val (version_key);
debug_assert (mdb_get (env.tx (transaction_a), handle, &mdb_version_key, &junk) == MDB_NOTFOUND);
boost::property_tree::ptree wallet_l;
std::stringstream istream (json_a);
try
@ -312,11 +315,20 @@ nano::wallet_store::wallet_store (bool & init_a, nano::kdf & kdf_a, store::trans
init_a = true;
}
}
init_a |= mdb_get (env.tx (transaction_a), handle, nano::store::lmdb::db_val (version_special), &junk) != 0;
init_a |= mdb_get (env.tx (transaction_a), handle, nano::store::lmdb::db_val (wallet_key_special), &junk) != 0;
init_a |= mdb_get (env.tx (transaction_a), handle, nano::store::lmdb::db_val (salt_special), &junk) != 0;
init_a |= mdb_get (env.tx (transaction_a), handle, nano::store::lmdb::db_val (check_special), &junk) != 0;
init_a |= mdb_get (env.tx (transaction_a), handle, nano::store::lmdb::db_val (representative_special), &junk) != 0;
nano::store::lmdb::db_val wallet_key_key (wallet_key_special);
nano::store::lmdb::db_val salt_key (salt_special);
nano::store::lmdb::db_val check_key (check_special);
auto mdb_version_key2 = nano::store::lmdb::to_mdb_val (version_key);
auto mdb_wallet_key_key = nano::store::lmdb::to_mdb_val (wallet_key_key);
auto mdb_salt_key = nano::store::lmdb::to_mdb_val (salt_key);
auto mdb_check_key = nano::store::lmdb::to_mdb_val (check_key);
init_a |= mdb_get (env.tx (transaction_a), handle, &mdb_version_key2, &junk) != 0;
init_a |= mdb_get (env.tx (transaction_a), handle, &mdb_wallet_key_key, &junk) != 0;
init_a |= mdb_get (env.tx (transaction_a), handle, &mdb_salt_key, &junk) != 0;
init_a |= mdb_get (env.tx (transaction_a), handle, &mdb_check_key, &junk) != 0;
nano::store::lmdb::db_val rep_key (representative_special);
auto mdb_rep_key = nano::store::lmdb::to_mdb_val (rep_key);
init_a |= mdb_get (env.tx (transaction_a), handle, &mdb_rep_key, &junk) != 0;
nano::raw_key key;
key.clear ();
password.value_set (key);
@ -337,7 +349,9 @@ nano::wallet_store::wallet_store (bool & init_a, nano::kdf & kdf_a, store::trans
{
int version_status;
MDB_val version_value;
version_status = mdb_get (env.tx (transaction_a), handle, nano::store::lmdb::db_val (version_special), &version_value);
nano::store::lmdb::db_val version_lookup_key (version_special);
auto mdb_version_lookup_key = nano::store::lmdb::to_mdb_val (version_lookup_key);
version_status = mdb_get (env.tx (transaction_a), handle, &mdb_version_lookup_key, &version_value);
if (version_status == MDB_NOTFOUND)
{
version_put (transaction_a, version_current);
@ -439,7 +453,9 @@ bool nano::wallet_store::insert_watch (store::transaction const & transaction_a,
void nano::wallet_store::erase (store::transaction const & transaction_a, nano::account const & pub)
{
auto status (mdb_del (env.tx (transaction_a), handle, nano::store::lmdb::db_val (pub), nullptr));
nano::store::lmdb::db_val pub_key (pub);
MDB_val mdb_pub_key{ pub_key.size (), pub_key.data () };
auto status (mdb_del (env.tx (transaction_a), handle, &mdb_pub_key, nullptr));
(void)status;
debug_assert (status == 0);
}
@ -448,9 +464,13 @@ nano::wallet_value nano::wallet_store::entry_get_raw (store::transaction const &
{
nano::wallet_value result;
nano::store::lmdb::db_val value;
auto status (mdb_get (env.tx (transaction_a), handle, nano::store::lmdb::db_val (pub_a), value));
nano::store::lmdb::db_val pub_key (pub_a);
auto mdb_pub_key = nano::store::lmdb::to_mdb_val (pub_key);
MDB_val mdb_value{};
auto status (mdb_get (env.tx (transaction_a), handle, &mdb_pub_key, &mdb_value));
if (status == 0)
{
value = nano::store::lmdb::from_mdb_val (mdb_value);
result = nano::wallet_value (value);
}
else
@ -463,7 +483,11 @@ nano::wallet_value nano::wallet_store::entry_get_raw (store::transaction const &
void nano::wallet_store::entry_put_raw (store::transaction const & transaction_a, nano::account const & pub_a, nano::wallet_value const & entry_a)
{
auto status (mdb_put (env.tx (transaction_a), handle, nano::store::lmdb::db_val (pub_a), nano::store::lmdb::db_val (sizeof (entry_a), const_cast<nano::wallet_value *> (&entry_a)), 0));
nano::store::lmdb::db_val pub_key (pub_a);
nano::store::lmdb::db_val entry_val (sizeof (entry_a), const_cast<nano::wallet_value *> (&entry_a));
auto mdb_pub_key = nano::store::lmdb::to_mdb_val (pub_key);
auto mdb_entry_val = nano::store::lmdb::to_mdb_val (entry_val);
auto status (mdb_put (env.tx (transaction_a), handle, &mdb_pub_key, &mdb_entry_val, 0));
(void)status;
debug_assert (status == 0);
}
@ -1003,9 +1027,12 @@ std::shared_ptr<nano::block> nano::wallet::send_action (nano::account const & so
if (id_mdb_val)
{
nano::store::lmdb::db_val result;
auto status (mdb_get (wallets.env.tx (transaction), wallets.node.wallets.send_action_ids, *id_mdb_val, result));
MDB_val mdb_id_key{ id_mdb_val->size (), id_mdb_val->data () };
MDB_val mdb_result{};
auto status (mdb_get (wallets.env.tx (transaction), wallets.node.wallets.send_action_ids, &mdb_id_key, &mdb_result));
if (status == 0)
{
result = nano::store::lmdb::from_mdb_val (mdb_result);
nano::block_hash hash (result);
block = wallets.node.ledger.any.block_get (block_transaction, hash);
if (block != nullptr)
@ -1058,7 +1085,10 @@ std::shared_ptr<nano::block> nano::wallet::send_action (nano::account const & so
details.epoch = info->epoch ();
if (id_mdb_val && block != nullptr)
{
auto status (mdb_put (wallets.env.tx (transaction), wallets.node.wallets.send_action_ids, *id_mdb_val, nano::store::lmdb::db_val (block->hash ()), 0));
nano::store::lmdb::db_val hash_val (block->hash ());
auto mdb_id_key = nano::store::lmdb::to_mdb_val (*id_mdb_val);
auto mdb_hash_val = nano::store::lmdb::to_mdb_val (hash_val);
auto status (mdb_put (wallets.env.tx (transaction), wallets.node.wallets.send_action_ids, &mdb_id_key, &mdb_hash_val, 0));
if (status != 0)
{
block = nullptr;
@ -1444,8 +1474,10 @@ nano::wallets::wallets (bool error_a, nano::node & node_a) :
nano::store::lmdb::db_val beginning_val{ beginning.size (), const_cast<char *> (beginning.c_str ()) };
std::string end ((nano::uint256_union (nano::uint256_t (0) - nano::uint256_t (1))).to_string ());
nano::store::lmdb::db_val end_val{ end.size (), const_cast<char *> (end.c_str ()) };
store::iterator i{ store::lmdb::iterator::lower_bound (env.tx (transaction), handle, beginning_val) };
store::iterator n{ store::lmdb::iterator::lower_bound (env.tx (transaction), handle, end_val) };
auto mdb_beginning_val = nano::store::lmdb::to_mdb_val (beginning_val);
auto mdb_end_val = nano::store::lmdb::to_mdb_val (end_val);
store::iterator i{ store::lmdb::iterator::lower_bound (env.tx (transaction), handle, mdb_beginning_val) };
store::iterator n{ store::lmdb::iterator::lower_bound (env.tx (transaction), handle, mdb_end_val) };
for (; i != n; ++i)
{
nano::wallet_id id;
@ -1604,8 +1636,10 @@ void nano::wallets::reload ()
nano::store::lmdb::db_val beginning_val{ beginning.size (), const_cast<char *> (beginning.c_str ()) };
std::string end ((nano::uint256_union (nano::uint256_t (0) - nano::uint256_t (1))).to_string ());
nano::store::lmdb::db_val end_val{ end.size (), const_cast<char *> (end.c_str ()) };
store::iterator i{ store::lmdb::iterator::lower_bound (env.tx (transaction), handle, beginning_val) };
store::iterator n{ store::lmdb::iterator::lower_bound (env.tx (transaction), handle, end_val) };
auto mdb_beginning_val = nano::store::lmdb::to_mdb_val (beginning_val);
auto mdb_end_val = nano::store::lmdb::to_mdb_val (end_val);
store::iterator i{ store::lmdb::iterator::lower_bound (env.tx (transaction), handle, mdb_beginning_val) };
store::iterator n{ store::lmdb::iterator::lower_bound (env.tx (transaction), handle, mdb_end_val) };
for (; i != n; ++i)
{
nano::wallet_id id;
@ -1849,15 +1883,13 @@ nano::uint128_t const nano::wallets::high_priority = std::numeric_limits<nano::u
auto nano::wallet_store::begin (store::transaction const & transaction_a) -> iterator
{
nano::account account{ special_count };
nano::store::lmdb::db_val val{ account };
return iterator{ store::iterator{ store::lmdb::iterator::lower_bound (env.tx (transaction_a), handle, val) } };
return iterator{ store::iterator{ store::lmdb::iterator::lower_bound (env.tx (transaction_a), handle, store::lmdb::to_mdb_val (account)) } };
}
auto nano::wallet_store::begin (store::transaction const & transaction_a, nano::account const & key) -> iterator
{
nano::account account (key);
nano::store::lmdb::db_val val{ account };
return iterator{ store::iterator{ store::lmdb::iterator::lower_bound (env.tx (transaction_a), handle, val) } };
return iterator{ store::iterator{ store::lmdb::iterator::lower_bound (env.tx (transaction_a), handle, store::lmdb::to_mdb_val (account)) } };
}
auto nano::wallet_store::find (store::transaction const & transaction_a, nano::account const & key) -> iterator

View file

@ -11,6 +11,7 @@
#include <nano/lib/object_stream.hpp>
#include <nano/lib/timer.hpp>
#include <nano/lib/utility.hpp>
#include <nano/store/block_w_sideband.hpp>
#include <array>
#include <unordered_map>

View file

@ -1,6 +1,7 @@
#include <nano/secure/ledger.hpp>
#include <nano/secure/ledger_set_any.hpp>
#include <nano/store/account.hpp>
#include <nano/store/block.hpp>
#include <nano/store/component.hpp>
#include <nano/store/pending.hpp>
#include <nano/store/pruned.hpp>

View file

@ -1,6 +1,7 @@
#include <nano/secure/ledger.hpp>
#include <nano/secure/ledger_set_confirmed.hpp>
#include <nano/store/account.hpp>
#include <nano/store/block.hpp>
#include <nano/store/component.hpp>
#include <nano/store/confirmation_height.hpp>
#include <nano/store/pending.hpp>

View file

@ -6,7 +6,7 @@ add_library(
component.hpp
confirmation_height.hpp
db_val.hpp
db_val_impl.hpp
db_val_templ.hpp
iterator.hpp
final_vote.hpp
fwd.hpp
@ -61,13 +61,11 @@ add_library(
block.cpp
component.cpp
confirmation_height.cpp
db_val.cpp
iterator.cpp
final_vote.cpp
lmdb/account.cpp
lmdb/block.cpp
lmdb/confirmation_height.cpp
lmdb/db_val.cpp
lmdb/final_vote.cpp
lmdb/iterator.cpp
lmdb/lmdb.cpp
@ -88,7 +86,6 @@ add_library(
rocksdb/account.cpp
rocksdb/block.cpp
rocksdb/confirmation_height.cpp
rocksdb/db_val.cpp
rocksdb/final_vote.cpp
rocksdb/iterator.cpp
rocksdb/online_weight.cpp

View file

@ -2,7 +2,7 @@
#include <nano/lib/numbers.hpp>
#include <nano/store/component.hpp>
#include <nano/store/db_val_impl.hpp>
#include <nano/store/db_val_templ.hpp>
#include <nano/store/reverse_iterator.hpp>
#include <nano/store/typed_iterator.hpp>

View file

@ -1 +0,0 @@
#include <nano/store/db_val.hpp>

View file

@ -3,11 +3,9 @@
#include <nano/lib/numbers.hpp>
#include <nano/lib/stream.hpp>
#include <nano/secure/common.hpp>
#include <nano/store/block.hpp>
#include <nano/store/component.hpp>
#include <nano/store/versioning.hpp>
#include <cstddef>
#include <span>
namespace nano
{
@ -22,265 +20,95 @@ class vote;
namespace nano::store
{
/**
* Encapsulates database specific container
* Encapsulates database values using std::span for type safety and backend independence
*/
template <typename Val>
class db_val
class db_val final
{
public:
db_val (Val const & value_a) :
value (value_a)
db_val () = default;
db_val (std::span<uint8_t const> span) noexcept :
span_view{ span }
{
}
db_val () :
db_val (0, nullptr)
db_val (size_t size, void const * data) noexcept :
span_view{ static_cast<uint8_t const *> (data), size }
{
}
db_val (std::nullptr_t) :
db_val (0, this)
db_val (std::nullptr_t) noexcept :
span_view{ reinterpret_cast<uint8_t const *> (""), 0 } // Use empty string literal to provide valid pointer for zero-size memcpy
{
}
db_val (nano::uint128_union const & val_a) :
db_val (sizeof (val_a), const_cast<nano::uint128_union *> (&val_a))
db_val (std::shared_ptr<std::vector<uint8_t>> buffer) noexcept :
buffer{ buffer }
{
}
db_val (nano::uint256_union const & val_a) :
db_val (sizeof (val_a), const_cast<nano::uint256_union *> (&val_a))
{
}
db_val (nano::uint512_union const & val_a) :
db_val (sizeof (val_a), const_cast<nano::uint512_union *> (&val_a))
{
}
db_val (nano::qualified_root const & val_a) :
db_val (sizeof (val_a), const_cast<nano::qualified_root *> (&val_a))
{
}
db_val (nano::account_info const & val_a);
db_val (nano::account_info_v22 const & val_a);
db_val (nano::pending_info const & val_a);
db_val (nano::pending_key const & val_a);
db_val (nano::confirmation_height_info const & val_a) :
buffer (std::make_shared<std::vector<uint8_t>> ())
{
{
nano::vectorstream stream (*buffer);
val_a.serialize (stream);
}
convert_buffer_to_value ();
}
db_val (nano::block_info const & val_a) :
db_val (sizeof (val_a), const_cast<nano::block_info *> (&val_a))
{
static_assert (std::is_standard_layout<nano::block_info>::value, "Standard layout is required");
}
db_val (nano::endpoint_key const & val_a) :
db_val (sizeof (val_a), const_cast<nano::endpoint_key *> (&val_a))
{
static_assert (std::is_standard_layout<nano::endpoint_key>::value, "Standard layout is required");
}
db_val (std::shared_ptr<nano::block> const & val_a);
db_val (uint64_t val_a) :
buffer (std::make_shared<std::vector<uint8_t>> ())
{
{
boost::endian::native_to_big_inplace (val_a);
nano::vectorstream stream (*buffer);
nano::write (stream, val_a);
}
convert_buffer_to_value ();
}
db_val (uint64_t value);
db_val (nano::uint128_union const &);
db_val (nano::uint256_union const &);
db_val (nano::uint512_union const &);
db_val (nano::qualified_root const &);
db_val (nano::account_info const &);
db_val (nano::account_info_v22 const &);
db_val (nano::pending_info const &);
db_val (nano::pending_key const &);
db_val (nano::confirmation_height_info const &);
db_val (nano::block_info const &);
db_val (nano::endpoint_key const &);
db_val (std::shared_ptr<nano::block> const &);
explicit operator uint64_t () const;
explicit operator nano::uint128_union () const;
explicit operator nano::uint256_union () const;
explicit operator nano::uint512_union () const;
explicit operator nano::qualified_root () const;
explicit operator nano::account_info () const;
explicit operator nano::account_info_v22 () const;
explicit operator block_info () const
{
nano::block_info result;
debug_assert (size () == sizeof (result));
static_assert (sizeof (nano::block_info::account) + sizeof (nano::block_info::balance) == sizeof (result), "Packed class");
std::copy (reinterpret_cast<uint8_t const *> (data ()), reinterpret_cast<uint8_t const *> (data ()) + sizeof (result), reinterpret_cast<uint8_t *> (&result));
return result;
}
explicit operator nano::pending_info () const;
explicit operator nano::pending_key () const;
explicit operator nano::confirmation_height_info () const
{
nano::bufferstream stream (reinterpret_cast<uint8_t const *> (data ()), size ());
nano::confirmation_height_info result;
bool error (result.deserialize (stream));
(void)error;
debug_assert (!error);
return result;
}
explicit operator nano::uint128_union () const
{
return convert<nano::uint128_union> ();
}
explicit operator nano::amount () const
{
return convert<nano::amount> ();
}
explicit operator nano::block_hash () const
{
return convert<nano::block_hash> ();
}
explicit operator nano::public_key () const
{
return convert<nano::public_key> ();
}
explicit operator nano::qualified_root () const
{
return convert<nano::qualified_root> ();
}
explicit operator nano::uint256_union () const
{
return convert<nano::uint256_union> ();
}
explicit operator nano::uint512_union () const
{
return convert<nano::uint512_union> ();
}
explicit operator std::array<char, 64> () const
{
nano::bufferstream stream (reinterpret_cast<uint8_t const *> (data ()), size ());
std::array<char, 64> result;
auto error = nano::try_read (stream, result);
(void)error;
debug_assert (!error);
return result;
}
explicit operator nano::endpoint_key () const
{
nano::endpoint_key result;
std::copy (reinterpret_cast<uint8_t const *> (data ()), reinterpret_cast<uint8_t const *> (data ()) + sizeof (result), reinterpret_cast<uint8_t *> (&result));
return result;
}
explicit operator block_w_sideband () const;
explicit operator std::nullptr_t () const
{
return nullptr;
}
explicit operator nano::no_value () const
{
return no_value::dummy;
}
explicit operator nano::confirmation_height_info () const;
explicit operator nano::block_info () const;
explicit operator nano::endpoint_key () const;
explicit operator std::shared_ptr<nano::block> () const;
explicit operator nano::amount () const;
explicit operator nano::block_hash () const;
explicit operator nano::public_key () const;
explicit operator std::array<char, 64> () const;
explicit operator block_w_sideband () const;
explicit operator std::shared_ptr<nano::vote> () const;
explicit operator std::nullptr_t () const;
explicit operator nano::no_value () const;
template <typename Block>
std::shared_ptr<Block> convert_to_block () const
auto convert_to_block () const -> std::shared_ptr<Block>;
explicit operator std::shared_ptr<nano::send_block> () const;
explicit operator std::shared_ptr<nano::receive_block> () const;
explicit operator std::shared_ptr<nano::open_block> () const;
explicit operator std::shared_ptr<nano::change_block> () const;
explicit operator std::shared_ptr<nano::state_block> () const;
auto data () const noexcept -> void *
{
nano::bufferstream stream (reinterpret_cast<uint8_t const *> (data ()), size ());
auto error (false);
auto result (std::make_shared<Block> (error, stream));
debug_assert (!error);
return result;
return const_cast<void *> (static_cast<void const *> (span_view.data ()));
}
auto size () const noexcept -> size_t
{
return span_view.size ();
}
explicit operator std::shared_ptr<nano::send_block> () const
{
return convert_to_block<nano::send_block> ();
}
auto convert_buffer_to_value () noexcept -> void;
explicit operator std::shared_ptr<nano::receive_block> () const
{
return convert_to_block<nano::receive_block> ();
}
explicit operator std::shared_ptr<nano::open_block> () const
{
return convert_to_block<nano::open_block> ();
}
explicit operator std::shared_ptr<nano::change_block> () const
{
return convert_to_block<nano::change_block> ();
}
explicit operator std::shared_ptr<nano::state_block> () const
{
return convert_to_block<nano::state_block> ();
}
explicit operator std::shared_ptr<nano::vote> () const
{
nano::bufferstream stream (reinterpret_cast<uint8_t const *> (data ()), size ());
auto error (false);
auto result (nano::make_shared<nano::vote> (error, stream));
debug_assert (!error);
return result;
}
explicit operator uint64_t () const
{
uint64_t result;
nano::bufferstream stream (reinterpret_cast<uint8_t const *> (data ()), size ());
auto error (nano::try_read (stream, result));
(void)error;
debug_assert (!error);
boost::endian::big_to_native_inplace (result);
return result;
}
operator Val * () const
{
// Allow passing a temporary to a non-c++ function which doesn't have constness
return const_cast<Val *> (&value);
}
operator Val const & () const
{
return value;
}
// Must be specialized
void * data () const;
size_t size () const;
db_val (size_t size_a, void * data_a);
void convert_buffer_to_value ();
Val value;
std::span<uint8_t const> span_view;
std::shared_ptr<std::vector<uint8_t>> buffer;
private:
template <typename T>
T convert () const
{
T result;
debug_assert (size () == sizeof (result));
std::copy (reinterpret_cast<uint8_t const *> (data ()), reinterpret_cast<uint8_t const *> (data ()) + sizeof (result), result.bytes.data ());
return result;
}
auto convert () const -> T;
};
} // namespace nano::store
}

View file

@ -1,100 +0,0 @@
#pragma once
#include <nano/lib/blocks.hpp>
#include <nano/secure/account_info.hpp>
#include <nano/secure/pending_info.hpp>
#include <nano/store/db_val.hpp>
template <typename T>
nano::store::db_val<T>::db_val (nano::account_info const & val_a) :
db_val (val_a.db_size (), const_cast<nano::account_info *> (&val_a))
{
}
template <typename T>
nano::store::db_val<T>::db_val (nano::account_info_v22 const & val_a) :
db_val (val_a.db_size (), const_cast<nano::account_info_v22 *> (&val_a))
{
}
template <typename T>
nano::store::db_val<T>::db_val (std::shared_ptr<nano::block> const & val_a) :
buffer (std::make_shared<std::vector<uint8_t>> ())
{
{
nano::vectorstream stream (*buffer);
nano::serialize_block (stream, *val_a);
}
convert_buffer_to_value ();
}
template <typename T>
nano::store::db_val<T>::db_val (nano::pending_info const & val_a) :
db_val (val_a.db_size (), const_cast<nano::pending_info *> (&val_a))
{
static_assert (std::is_standard_layout<nano::pending_info>::value, "Standard layout is required");
}
template <typename T>
nano::store::db_val<T>::db_val (nano::pending_key const & val_a) :
db_val (sizeof (val_a), const_cast<nano::pending_key *> (&val_a))
{
static_assert (std::is_standard_layout<nano::pending_key>::value, "Standard layout is required");
}
template <typename T>
nano::store::db_val<T>::operator nano::account_info () const
{
nano::account_info result;
debug_assert (size () == result.db_size ());
std::copy (reinterpret_cast<uint8_t const *> (data ()), reinterpret_cast<uint8_t const *> (data ()) + result.db_size (), reinterpret_cast<uint8_t *> (&result));
return result;
}
template <typename T>
nano::store::db_val<T>::operator nano::account_info_v22 () const
{
nano::account_info_v22 result;
debug_assert (size () == result.db_size ());
std::copy (reinterpret_cast<uint8_t const *> (data ()), reinterpret_cast<uint8_t const *> (data ()) + result.db_size (), reinterpret_cast<uint8_t *> (&result));
return result;
}
template <typename T>
nano::store::db_val<T>::operator std::shared_ptr<nano::block> () const
{
nano::bufferstream stream (reinterpret_cast<uint8_t const *> (data ()), size ());
std::shared_ptr<nano::block> result (nano::deserialize_block (stream));
return result;
}
template <typename T>
nano::store::db_val<T>::operator nano::store::block_w_sideband () const
{
nano::bufferstream stream (reinterpret_cast<uint8_t const *> (data ()), size ());
nano::store::block_w_sideband block_w_sideband;
block_w_sideband.block = (nano::deserialize_block (stream));
auto error = block_w_sideband.sideband.deserialize (stream, block_w_sideband.block->type ());
release_assert (!error);
block_w_sideband.block->sideband_set (block_w_sideband.sideband);
return block_w_sideband;
}
template <typename T>
nano::store::db_val<T>::operator nano::pending_info () const
{
nano::pending_info result;
debug_assert (size () == result.db_size ());
std::copy (reinterpret_cast<uint8_t const *> (data ()), reinterpret_cast<uint8_t const *> (data ()) + result.db_size (), reinterpret_cast<uint8_t *> (&result));
return result;
}
template <typename T>
nano::store::db_val<T>::operator nano::pending_key () const
{
nano::pending_key result;
debug_assert (size () == sizeof (result));
static_assert (sizeof (nano::pending_key::account) + sizeof (nano::pending_key::hash) == sizeof (result), "Packed class");
std::copy (reinterpret_cast<uint8_t const *> (data ()), reinterpret_cast<uint8_t const *> (data ()) + sizeof (result), reinterpret_cast<uint8_t *> (&result));
return result;
}

308
nano/store/db_val_templ.hpp Normal file
View file

@ -0,0 +1,308 @@
#pragma once
#include <nano/lib/blocks.hpp>
#include <nano/lib/memory.hpp>
#include <nano/lib/stream.hpp>
#include <nano/secure/account_info.hpp>
#include <nano/secure/pending_info.hpp>
#include <nano/secure/vote.hpp>
#include <nano/store/db_val.hpp>
namespace nano::store
{
// Constructor implementations
inline db_val::db_val (uint64_t value) :
buffer{ std::make_shared<std::vector<uint8_t>> () }
{
{
boost::endian::native_to_big_inplace (value);
nano::vectorstream stream{ *buffer };
nano::write (stream, value);
}
convert_buffer_to_value ();
}
inline db_val::db_val (nano::uint128_union const & value) :
span_view{ value.bytes.data (), sizeof (value) }
{
}
inline db_val::db_val (nano::uint256_union const & value) :
span_view{ value.bytes.data (), sizeof (value) }
{
}
inline db_val::db_val (nano::uint512_union const & value) :
span_view{ value.bytes.data (), sizeof (value) }
{
}
inline db_val::db_val (nano::qualified_root const & value) :
span_view{ reinterpret_cast<uint8_t const *> (&value), sizeof (value) }
{
}
inline db_val::db_val (nano::account_info const & value) :
span_view{ reinterpret_cast<uint8_t const *> (&value), value.db_size () }
{
}
inline db_val::db_val (nano::account_info_v22 const & value) :
span_view{ reinterpret_cast<uint8_t const *> (&value), value.db_size () }
{
}
inline db_val::db_val (nano::pending_info const & value) :
span_view{ reinterpret_cast<uint8_t const *> (&value), value.db_size () }
{
static_assert (std::is_standard_layout<nano::pending_info>::value, "Standard layout is required");
}
inline db_val::db_val (nano::pending_key const & value) :
span_view{ reinterpret_cast<uint8_t const *> (&value), sizeof (value) }
{
static_assert (std::is_standard_layout<nano::pending_key>::value, "Standard layout is required");
}
inline db_val::db_val (nano::confirmation_height_info const & value) :
buffer{ std::make_shared<std::vector<uint8_t>> () }
{
{
nano::vectorstream stream{ *buffer };
value.serialize (stream);
}
convert_buffer_to_value ();
}
inline db_val::db_val (nano::block_info const & value) :
span_view{ reinterpret_cast<uint8_t const *> (&value), sizeof (value) }
{
static_assert (std::is_standard_layout<nano::block_info>::value, "Standard layout is required");
}
inline db_val::db_val (nano::endpoint_key const & value) :
span_view{ reinterpret_cast<uint8_t const *> (&value), sizeof (value) }
{
static_assert (std::is_standard_layout<nano::endpoint_key>::value, "Standard layout is required");
}
inline db_val::db_val (std::shared_ptr<nano::block> const & block) :
buffer{ std::make_shared<std::vector<uint8_t>> () }
{
{
nano::vectorstream stream{ *buffer };
nano::serialize_block (stream, *block);
}
convert_buffer_to_value ();
}
// Conversion operator implementations
inline db_val::operator uint64_t () const
{
uint64_t result;
nano::bufferstream stream{ span_view.data (), span_view.size () };
auto error{ nano::try_read (stream, result) };
(void)error;
debug_assert (!error);
boost::endian::big_to_native_inplace (result);
return result;
}
inline db_val::operator nano::uint128_union () const
{
return convert<nano::uint128_union> ();
}
inline db_val::operator nano::uint256_union () const
{
return convert<nano::uint256_union> ();
}
inline db_val::operator nano::uint512_union () const
{
return convert<nano::uint512_union> ();
}
inline db_val::operator nano::qualified_root () const
{
return convert<nano::qualified_root> ();
}
inline db_val::operator nano::account_info () const
{
nano::account_info result;
debug_assert (span_view.size () == result.db_size ());
std::copy (span_view.begin (), span_view.end (), reinterpret_cast<uint8_t *> (&result));
return result;
}
inline db_val::operator nano::account_info_v22 () const
{
nano::account_info_v22 result;
debug_assert (span_view.size () == result.db_size ());
std::copy (span_view.begin (), span_view.end (), reinterpret_cast<uint8_t *> (&result));
return result;
}
inline db_val::operator nano::pending_info () const
{
nano::pending_info result;
debug_assert (span_view.size () == result.db_size ());
std::copy (span_view.begin (), span_view.end (), reinterpret_cast<uint8_t *> (&result));
return result;
}
inline db_val::operator nano::pending_key () const
{
nano::pending_key result;
debug_assert (span_view.size () == sizeof (result));
static_assert (sizeof (nano::pending_key::account) + sizeof (nano::pending_key::hash) == sizeof (result), "Packed class");
std::copy (span_view.begin (), span_view.end (), reinterpret_cast<uint8_t *> (&result));
return result;
}
inline db_val::operator nano::confirmation_height_info () const
{
nano::bufferstream stream{ span_view.data (), span_view.size () };
nano::confirmation_height_info result;
bool error{ result.deserialize (stream) };
(void)error;
debug_assert (!error);
return result;
}
inline db_val::operator block_info () const
{
nano::block_info result;
debug_assert (size () == sizeof (result));
static_assert (sizeof (nano::block_info::account) + sizeof (nano::block_info::balance) == sizeof (result), "Packed class");
std::copy (span_view.begin (), span_view.end (), reinterpret_cast<uint8_t *> (&result));
return result;
}
inline db_val::operator nano::endpoint_key () const
{
nano::endpoint_key result;
debug_assert (span_view.size () == sizeof (result));
std::copy (span_view.begin (), span_view.end (), reinterpret_cast<uint8_t *> (&result));
return result;
}
inline db_val::operator std::shared_ptr<nano::block> () const
{
nano::bufferstream stream{ span_view.data (), span_view.size () };
std::shared_ptr<nano::block> result{ nano::deserialize_block (stream) };
return result;
}
inline db_val::operator nano::amount () const
{
return convert<nano::amount> ();
}
inline db_val::operator nano::block_hash () const
{
return convert<nano::block_hash> ();
}
inline db_val::operator nano::public_key () const
{
return convert<nano::public_key> ();
}
inline db_val::operator std::array<char, 64> () const
{
nano::bufferstream stream{ span_view.data (), span_view.size () };
std::array<char, 64> result;
auto error = nano::try_read (stream, result);
(void)error;
debug_assert (!error);
return result;
}
inline db_val::operator nano::store::block_w_sideband () const
{
nano::bufferstream stream{ span_view.data (), span_view.size () };
nano::store::block_w_sideband block_w_sideband;
block_w_sideband.block = (nano::deserialize_block (stream));
auto error = block_w_sideband.sideband.deserialize (stream, block_w_sideband.block->type ());
release_assert (!error);
block_w_sideband.block->sideband_set (block_w_sideband.sideband);
return block_w_sideband;
}
inline db_val::operator std::shared_ptr<nano::vote> () const
{
nano::bufferstream stream{ span_view.data (), span_view.size () };
auto error{ false };
auto result{ nano::make_shared<nano::vote> (error, stream) };
debug_assert (!error);
return result;
}
inline db_val::operator std::nullptr_t () const
{
return nullptr;
}
inline db_val::operator nano::no_value () const
{
return no_value::dummy;
}
template <typename Block>
inline auto db_val::convert_to_block () const -> std::shared_ptr<Block>
{
nano::bufferstream stream{ span_view.data (), span_view.size () };
auto error{ false };
auto result{ nano::make_shared<Block> (error, stream) };
debug_assert (!error);
return result;
}
inline db_val::operator std::shared_ptr<nano::send_block> () const
{
return convert_to_block<nano::send_block> ();
}
inline db_val::operator std::shared_ptr<nano::receive_block> () const
{
return convert_to_block<nano::receive_block> ();
}
inline db_val::operator std::shared_ptr<nano::open_block> () const
{
return convert_to_block<nano::open_block> ();
}
inline db_val::operator std::shared_ptr<nano::change_block> () const
{
return convert_to_block<nano::change_block> ();
}
inline db_val::operator std::shared_ptr<nano::state_block> () const
{
return convert_to_block<nano::state_block> ();
}
// Member function implementations
inline auto db_val::convert_buffer_to_value () noexcept -> void
{
if (buffer)
{
span_view = std::span<uint8_t const>{ buffer->data (), buffer->size () };
}
}
template <typename T>
inline auto db_val::convert () const -> T
{
T result;
debug_assert (span_view.size () == sizeof (result));
std::copy (span_view.begin (), span_view.end (), result.bytes.data ());
return result;
}
}

View file

@ -2,6 +2,7 @@
#include <nano/store/lmdb/account.hpp>
#include <nano/store/lmdb/db_val.hpp>
#include <nano/store/lmdb/lmdb.hpp>
#include <nano/store/lmdb/utility.hpp>
nano::store::lmdb::account::account (nano::store::lmdb::component & store_a) :
store (store_a){};
@ -45,8 +46,7 @@ size_t nano::store::lmdb::account::count (store::transaction const & transaction
auto nano::store::lmdb::account::begin (store::transaction const & transaction, nano::account const & account) const -> iterator
{
lmdb::db_val val{ account };
return iterator{ store::iterator{ lmdb::iterator::lower_bound (store.env.tx (transaction), accounts_handle, val) } };
return iterator{ store::iterator{ lmdb::iterator::lower_bound (store.env.tx (transaction), accounts_handle, to_mdb_val (account)) } };
}
auto nano::store::lmdb::account::begin (store::transaction const & transaction) const -> iterator

View file

@ -1,7 +1,8 @@
#include <nano/secure/parallel_traversal.hpp>
#include <nano/store/db_val_impl.hpp>
#include <nano/store/db_val_templ.hpp>
#include <nano/store/lmdb/block.hpp>
#include <nano/store/lmdb/lmdb.hpp>
#include <nano/store/lmdb/utility.hpp>
namespace nano::store::lmdb
{
@ -129,8 +130,7 @@ auto nano::store::lmdb::block::begin (store::transaction const & transaction) co
auto nano::store::lmdb::block::begin (store::transaction const & transaction, nano::block_hash const & hash) const -> iterator
{
lmdb::db_val val{ hash };
return iterator{ store::iterator{ lmdb::iterator::lower_bound (store.env.tx (transaction), blocks_handle, val) } };
return iterator{ store::iterator{ lmdb::iterator::lower_bound (store.env.tx (transaction), blocks_handle, to_mdb_val (hash)) } };
}
auto nano::store::lmdb::block::end (store::transaction const & transaction_a) const -> iterator

View file

@ -1,6 +1,7 @@
#include <nano/secure/parallel_traversal.hpp>
#include <nano/store/lmdb/confirmation_height.hpp>
#include <nano/store/lmdb/lmdb.hpp>
#include <nano/store/lmdb/utility.hpp>
nano::store::lmdb::confirmation_height::confirmation_height (nano::store::lmdb::component & store) :
store{ store }
@ -61,8 +62,7 @@ void nano::store::lmdb::confirmation_height::clear (store::write_transaction con
auto nano::store::lmdb::confirmation_height::begin (store::transaction const & transaction, nano::account const & account) const -> iterator
{
lmdb::db_val val{ account };
return iterator{ store::iterator{ lmdb::iterator::lower_bound (store.env.tx (transaction), confirmation_height_handle, val) } };
return iterator{ store::iterator{ lmdb::iterator::lower_bound (store.env.tx (transaction), confirmation_height_handle, to_mdb_val (account)) } };
}
auto nano::store::lmdb::confirmation_height::begin (store::transaction const & transaction) const -> iterator

View file

@ -1,25 +0,0 @@
#include <nano/store/lmdb/db_val.hpp>
template <>
void * nano::store::lmdb::db_val::data () const
{
return value.mv_data;
}
template <>
std::size_t nano::store::lmdb::db_val::size () const
{
return value.mv_size;
}
template <>
nano::store::lmdb::db_val::db_val (std::size_t size_a, void * data_a) :
value ({ size_a, data_a })
{
}
template <>
void nano::store::lmdb::db_val::convert_buffer_to_value ()
{
value = { buffer->size (), const_cast<uint8_t *> (buffer->data ()) };
}

View file

@ -2,9 +2,7 @@
#include <nano/store/db_val.hpp>
#include <lmdb/libraries/liblmdb/lmdb.h>
namespace nano::store::lmdb
{
using db_val = store::db_val<MDB_val>;
using db_val = store::db_val;
}

View file

@ -1,6 +1,7 @@
#include <nano/secure/parallel_traversal.hpp>
#include <nano/store/lmdb/final_vote.hpp>
#include <nano/store/lmdb/lmdb.hpp>
#include <nano/store/lmdb/utility.hpp>
nano::store::lmdb::final_vote::final_vote (nano::store::lmdb::component & store) :
store{ store } {};
@ -53,8 +54,7 @@ void nano::store::lmdb::final_vote::clear (store::write_transaction const & tran
auto nano::store::lmdb::final_vote::begin (store::transaction const & transaction, nano::qualified_root const & root) const -> iterator
{
lmdb::db_val val{ root };
return iterator{ store::iterator{ lmdb::iterator::lower_bound (store.env.tx (transaction), final_votes_handle, val) } };
return iterator{ store::iterator{ lmdb::iterator::lower_bound (store.env.tx (transaction), final_votes_handle, to_mdb_val (root)) } };
}
auto nano::store::lmdb::final_vote::begin (store::transaction const & transaction) const -> iterator

View file

@ -5,6 +5,7 @@
#include <nano/secure/parallel_traversal.hpp>
#include <nano/store/lmdb/iterator.hpp>
#include <nano/store/lmdb/lmdb.hpp>
#include <nano/store/lmdb/utility.hpp>
#include <nano/store/lmdb/wallet_value.hpp>
#include <nano/store/typed_iterator_templ.hpp>
#include <nano/store/version.hpp>
@ -405,17 +406,28 @@ bool nano::store::lmdb::component::exists (store::transaction const & transactio
int nano::store::lmdb::component::get (store::transaction const & transaction_a, tables table_a, nano::store::lmdb::db_val const & key_a, nano::store::lmdb::db_val & value_a) const
{
return mdb_get (env.tx (transaction_a), table_to_dbi (table_a), key_a, value_a);
auto mdb_key = to_mdb_val (key_a);
MDB_val mdb_value{};
auto result = mdb_get (env.tx (transaction_a), table_to_dbi (table_a), &mdb_key, &mdb_value);
if (result == MDB_SUCCESS)
{
value_a = from_mdb_val (mdb_value);
}
return result;
}
int nano::store::lmdb::component::put (store::write_transaction const & transaction_a, tables table_a, nano::store::lmdb::db_val const & key_a, nano::store::lmdb::db_val const & value_a) const
{
return (mdb_put (env.tx (transaction_a), table_to_dbi (table_a), key_a, value_a, 0));
auto mdb_key = to_mdb_val (key_a);
auto mdb_value = to_mdb_val (value_a);
return (mdb_put (env.tx (transaction_a), table_to_dbi (table_a), &mdb_key, &mdb_value, 0));
}
int nano::store::lmdb::component::del (store::write_transaction const & transaction_a, tables table_a, nano::store::lmdb::db_val const & key_a) const
{
return (mdb_del (env.tx (transaction_a), table_to_dbi (table_a), key_a, nullptr));
auto mdb_key = to_mdb_val (key_a);
return (mdb_del (env.tx (transaction_a), table_to_dbi (table_a), &mdb_key, nullptr));
}
int nano::store::lmdb::component::drop (store::write_transaction const & transaction_a, tables table_a)
@ -502,7 +514,10 @@ void nano::store::lmdb::component::rebuild_db (store::write_transaction const &
// Copy all values to temporary table
for (typed_iterator<nano::uint256_union, nano::store::lmdb::db_val> i{ store::iterator{ iterator::begin (env.tx (transaction_a), table) } }, n{ store::iterator{ iterator::end (env.tx (transaction_a), table) } }; i != n; ++i)
{
auto s = mdb_put (env.tx (transaction_a), temp, nano::store::lmdb::db_val (i->first), i->second, MDB_APPEND);
nano::store::lmdb::db_val key_val (i->first);
auto mdb_key = to_mdb_val (key_val);
auto mdb_value = to_mdb_val (i->second);
auto s = mdb_put (env.tx (transaction_a), temp, &mdb_key, &mdb_value, MDB_APPEND);
release_assert_success (s);
}
release_assert (count (transaction_a, table) == count (transaction_a, temp));
@ -511,7 +526,10 @@ void nano::store::lmdb::component::rebuild_db (store::write_transaction const &
// Put values from copy
for (typed_iterator<nano::uint256_union, nano::store::lmdb::db_val> i{ store::iterator{ iterator::begin (env.tx (transaction_a), temp) } }, n{ store::iterator{ iterator::end (env.tx (transaction_a), temp) } }; i != n; ++i)
{
auto s = mdb_put (env.tx (transaction_a), table, nano::store::lmdb::db_val (i->first), i->second, MDB_APPEND);
nano::store::lmdb::db_val key_val (i->first);
auto mdb_key = to_mdb_val (key_val);
auto mdb_value = to_mdb_val (i->second);
auto s = mdb_put (env.tx (transaction_a), table, &mdb_key, &mdb_value, MDB_APPEND);
release_assert_success (s);
}
release_assert (count (transaction_a, table) == count (transaction_a, temp));
@ -525,7 +543,11 @@ void nano::store::lmdb::component::rebuild_db (store::write_transaction const &
// Copy all values to temporary table
for (typed_iterator<nano::pending_key, nano::pending_info> i{ store::iterator{ iterator::begin (env.tx (transaction_a), pending_store.pending_handle) } }, n{ store::iterator{ iterator::end (env.tx (transaction_a), pending_store.pending_handle) } }; i != n; ++i)
{
auto s = mdb_put (env.tx (transaction_a), temp, nano::store::lmdb::db_val (i->first), nano::store::lmdb::db_val (i->second), MDB_APPEND);
nano::store::lmdb::db_val key_val (i->first);
nano::store::lmdb::db_val value_val (i->second);
auto mdb_key = to_mdb_val (key_val);
auto mdb_value = to_mdb_val (value_val);
auto s = mdb_put (env.tx (transaction_a), temp, &mdb_key, &mdb_value, MDB_APPEND);
release_assert_success (s);
}
release_assert (count (transaction_a, pending_store.pending_handle) == count (transaction_a, temp));
@ -533,7 +555,11 @@ void nano::store::lmdb::component::rebuild_db (store::write_transaction const &
// Put values from copy
for (typed_iterator<nano::pending_key, nano::pending_info> i{ store::iterator{ iterator::begin (env.tx (transaction_a), temp) } }, n{ store::iterator{ iterator::end (env.tx (transaction_a), temp) } }; i != n; ++i)
{
auto s = mdb_put (env.tx (transaction_a), pending_store.pending_handle, nano::store::lmdb::db_val (i->first), nano::store::lmdb::db_val (i->second), MDB_APPEND);
nano::store::lmdb::db_val key_val (i->first);
nano::store::lmdb::db_val value_val (i->second);
auto mdb_key = to_mdb_val (key_val);
auto mdb_value = to_mdb_val (value_val);
auto s = mdb_put (env.tx (transaction_a), pending_store.pending_handle, &mdb_key, &mdb_value, MDB_APPEND);
release_assert_success (s);
}
release_assert (count (transaction_a, pending_store.pending_handle) == count (transaction_a, temp));

View file

@ -1,6 +1,7 @@
#include <nano/secure/parallel_traversal.hpp>
#include <nano/store/lmdb/lmdb.hpp>
#include <nano/store/lmdb/pending.hpp>
#include <nano/store/lmdb/utility.hpp>
nano::store::lmdb::pending::pending (nano::store::lmdb::component & store) :
store{ store } {};
@ -47,8 +48,7 @@ bool nano::store::lmdb::pending::any (store::transaction const & transaction_a,
auto nano::store::lmdb::pending::begin (store::transaction const & transaction_a, nano::pending_key const & key_a) const -> iterator
{
lmdb::db_val val{ key_a };
return iterator{ store::iterator{ lmdb::iterator::lower_bound (store.env.tx (transaction_a), pending_handle, val) } };
return iterator{ store::iterator{ lmdb::iterator::lower_bound (store.env.tx (transaction_a), pending_handle, to_mdb_val (key_a)) } };
}
auto nano::store::lmdb::pending::begin (store::transaction const & transaction_a) const -> iterator

View file

@ -1,6 +1,7 @@
#include <nano/secure/parallel_traversal.hpp>
#include <nano/store/lmdb/lmdb.hpp>
#include <nano/store/lmdb/pruned.hpp>
#include <nano/store/lmdb/utility.hpp>
nano::store::lmdb::pruned::pruned (nano::store::lmdb::component & store_a) :
store{ store_a } {};
@ -47,8 +48,7 @@ void nano::store::lmdb::pruned::clear (store::write_transaction const & transact
auto nano::store::lmdb::pruned::begin (store::transaction const & transaction, nano::block_hash const & hash) const -> iterator
{
lmdb::db_val val{ hash };
return iterator{ store::iterator{ lmdb::iterator::lower_bound (store.env.tx (transaction), pruned_handle, val) } };
return iterator{ store::iterator{ lmdb::iterator::lower_bound (store.env.tx (transaction), pruned_handle, to_mdb_val (hash)) } };
}
auto nano::store::lmdb::pruned::begin (store::transaction const & transaction) const -> iterator

View file

@ -2,6 +2,7 @@
#include <nano/secure/parallel_traversal.hpp>
#include <nano/store/lmdb/lmdb.hpp>
#include <nano/store/lmdb/rep_weight.hpp>
#include <nano/store/lmdb/utility.hpp>
#include <iostream>
#include <stdexcept>
@ -45,8 +46,7 @@ void nano::store::lmdb::rep_weight::del (store::write_transaction const & txn_a,
auto nano::store::lmdb::rep_weight::begin (store::transaction const & transaction_a, nano::account const & representative_a) const -> iterator
{
lmdb::db_val val{ representative_a };
return iterator{ store::iterator{ lmdb::iterator::lower_bound (store.env.tx (transaction_a), rep_weights_handle, val) } };
return iterator{ store::iterator{ lmdb::iterator::lower_bound (store.env.tx (transaction_a), rep_weights_handle, to_mdb_val (representative_a)) } };
}
auto nano::store::lmdb::rep_weight::begin (store::transaction const & transaction_a) const -> iterator

View file

@ -0,0 +1,25 @@
#pragma once
#include <nano/store/db_val.hpp>
#include <lmdb/libraries/liblmdb/lmdb.h>
namespace nano::store::lmdb
{
/**
* Converts a db_val to MDB_val for LMDB operations
*/
inline MDB_val to_mdb_val (nano::store::db_val const & val)
{
return MDB_val{ val.size (), val.data () };
}
/**
* Creates a db_val from MDB_val for read operations
*/
inline nano::store::db_val from_mdb_val (MDB_val const & val)
{
auto span = std::span<uint8_t const>{ static_cast<uint8_t const *> (val.mv_data), val.mv_size };
return nano::store::db_val (span);
}
}

View file

@ -1,6 +1,6 @@
#include <nano/store/lmdb/wallet_value.hpp>
nano::wallet_value::wallet_value (nano::store::db_val<MDB_val> const & val_a)
nano::wallet_value::wallet_value (nano::store::db_val const & val_a)
{
debug_assert (val_a.size () == sizeof (*this));
std::copy (reinterpret_cast<uint8_t const *> (val_a.data ()), reinterpret_cast<uint8_t const *> (val_a.data ()) + sizeof (key), key.chars.begin ());
@ -13,8 +13,8 @@ nano::wallet_value::wallet_value (nano::raw_key const & key_a, uint64_t work_a)
{
}
nano::store::db_val<MDB_val> nano::wallet_value::val () const
nano::store::db_val nano::wallet_value::val () const
{
static_assert (sizeof (*this) == sizeof (key) + sizeof (work), "Class not packed");
return nano::store::db_val<MDB_val> (sizeof (*this), const_cast<nano::wallet_value *> (this));
return nano::store::db_val (sizeof (*this), const_cast<nano::wallet_value *> (this));
}

View file

@ -11,9 +11,9 @@ class wallet_value
{
public:
wallet_value () = default;
wallet_value (store::db_val<MDB_val> const &);
wallet_value (store::db_val const &);
wallet_value (nano::raw_key const &, uint64_t);
store::db_val<MDB_val> val () const;
store::db_val val () const;
nano::raw_key key;
uint64_t work;
};

View file

@ -45,8 +45,7 @@ size_t nano::store::rocksdb::account::count (store::transaction const & transact
auto nano::store::rocksdb::account::begin (store::transaction const & transaction, nano::account const & account) const -> iterator
{
rocksdb::db_val val{ account };
return iterator{ store::iterator{ rocksdb::iterator::lower_bound (store.db.get (), rocksdb::tx (transaction), store.table_to_column_family (tables::accounts), val) } };
return iterator{ store::iterator{ rocksdb::iterator::lower_bound (store.db.get (), rocksdb::tx (transaction), store.table_to_column_family (tables::accounts), to_slice (account)) } };
}
auto nano::store::rocksdb::account::begin (store::transaction const & transaction) const -> iterator

View file

@ -1,5 +1,5 @@
#include <nano/secure/parallel_traversal.hpp>
#include <nano/store/db_val_impl.hpp>
#include <nano/store/db_val_templ.hpp>
#include <nano/store/rocksdb/block.hpp>
#include <nano/store/rocksdb/rocksdb.hpp>
#include <nano/store/rocksdb/utility.hpp>
@ -130,8 +130,7 @@ auto nano::store::rocksdb::block::begin (store::transaction const & transaction)
auto nano::store::rocksdb::block::begin (store::transaction const & transaction, nano::block_hash const & hash) const -> iterator
{
rocksdb::db_val val{ hash };
return iterator{ store::iterator{ rocksdb::iterator::lower_bound (store.db.get (), rocksdb::tx (transaction), store.table_to_column_family (tables::blocks), val) } };
return iterator{ store::iterator{ rocksdb::iterator::lower_bound (store.db.get (), rocksdb::tx (transaction), store.table_to_column_family (tables::blocks), to_slice (hash)) } };
}
auto nano::store::rocksdb::block::end (store::transaction const & transaction_a) const -> iterator

View file

@ -62,8 +62,7 @@ void nano::store::rocksdb::confirmation_height::clear (store::write_transaction
auto nano::store::rocksdb::confirmation_height::begin (store::transaction const & transaction, nano::account const & account) const -> iterator
{
rocksdb::db_val val{ account };
return iterator{ store::iterator{ rocksdb::iterator::lower_bound (store.db.get (), rocksdb::tx (transaction), store.table_to_column_family (tables::confirmation_height), val) } };
return iterator{ store::iterator{ rocksdb::iterator::lower_bound (store.db.get (), rocksdb::tx (transaction), store.table_to_column_family (tables::confirmation_height), to_slice (account)) } };
}
auto nano::store::rocksdb::confirmation_height::begin (store::transaction const & transaction) const -> iterator

View file

@ -1,25 +0,0 @@
#include <nano/store/rocksdb/db_val.hpp>
template <>
void * nano::store::rocksdb::db_val::data () const
{
return (void *)value.data ();
}
template <>
std::size_t nano::store::rocksdb::db_val::size () const
{
return value.size ();
}
template <>
nano::store::rocksdb::db_val::db_val (std::size_t size_a, void * data_a) :
value (static_cast<char const *> (data_a), size_a)
{
}
template <>
void nano::store::rocksdb::db_val::convert_buffer_to_value ()
{
value = ::rocksdb::Slice (reinterpret_cast<char const *> (buffer->data ()), buffer->size ());
}

View file

@ -2,9 +2,7 @@
#include <nano/store/db_val.hpp>
#include <rocksdb/slice.h>
namespace nano::store::rocksdb
{
using db_val = store::db_val<::rocksdb::Slice>;
using db_val = store::db_val;
}

View file

@ -54,8 +54,7 @@ void nano::store::rocksdb::final_vote::clear (store::write_transaction const & t
auto nano::store::rocksdb::final_vote::begin (store::transaction const & transaction, nano::qualified_root const & root) const -> iterator
{
rocksdb::db_val val{ root };
return iterator{ store::iterator{ rocksdb::iterator::lower_bound (store.db.get (), rocksdb::tx (transaction), store.table_to_column_family (tables::final_votes), val) } };
return iterator{ store::iterator{ rocksdb::iterator::lower_bound (store.db.get (), rocksdb::tx (transaction), store.table_to_column_family (tables::final_votes), to_slice (root)) } };
}
auto nano::store::rocksdb::final_vote::begin (store::transaction const & transaction) const -> iterator

View file

@ -1,5 +1,5 @@
#include <nano/secure/parallel_traversal.hpp>
#include <nano/store/lmdb/pending.hpp>
#include <nano/store/rocksdb/pending.hpp>
#include <nano/store/rocksdb/rocksdb.hpp>
#include <nano/store/rocksdb/utility.hpp>
@ -48,8 +48,7 @@ bool nano::store::rocksdb::pending::any (store::transaction const & transaction_
auto nano::store::rocksdb::pending::begin (store::transaction const & transaction_a, nano::pending_key const & key_a) const -> iterator
{
rocksdb::db_val val{ key_a };
return iterator{ store::iterator{ rocksdb::iterator::lower_bound (store.db.get (), rocksdb::tx (transaction_a), store.table_to_column_family (tables::pending), val) } };
return iterator{ store::iterator{ rocksdb::iterator::lower_bound (store.db.get (), rocksdb::tx (transaction_a), store.table_to_column_family (tables::pending), to_slice (key_a)) } };
}
auto nano::store::rocksdb::pending::begin (store::transaction const & transaction_a) const -> iterator

View file

@ -2,6 +2,10 @@
#include <nano/store/pending.hpp>
namespace nano::store::rocksdb
{
class component;
}
namespace nano::store::rocksdb
{
class pending : public nano::store::pending

View file

@ -48,8 +48,7 @@ void nano::store::rocksdb::pruned::clear (store::write_transaction const & trans
auto nano::store::rocksdb::pruned::begin (store::transaction const & transaction_a, nano::block_hash const & hash_a) const -> iterator
{
rocksdb::db_val val{ hash_a };
return iterator{ store::iterator{ rocksdb::iterator::lower_bound (store.db.get (), rocksdb::tx (transaction_a), store.table_to_column_family (tables::pruned), val) } };
return iterator{ store::iterator{ rocksdb::iterator::lower_bound (store.db.get (), rocksdb::tx (transaction_a), store.table_to_column_family (tables::pruned), to_slice (hash_a)) } };
}
auto nano::store::rocksdb::pruned::begin (store::transaction const & transaction_a) const -> iterator

View file

@ -45,8 +45,7 @@ void nano::store::rocksdb::rep_weight::del (store::write_transaction const & txn
auto nano::store::rocksdb::rep_weight::begin (store::transaction const & txn_a, nano::account const & representative_a) const -> iterator
{
rocksdb::db_val val{ representative_a };
return iterator{ store::iterator{ rocksdb::iterator::lower_bound (store.db.get (), rocksdb::tx (txn_a), store.table_to_column_family (tables::rep_weights), val) } };
return iterator{ store::iterator{ rocksdb::iterator::lower_bound (store.db.get (), rocksdb::tx (txn_a), store.table_to_column_family (tables::rep_weights), to_slice (representative_a)) } };
}
auto nano::store::rocksdb::rep_weight::begin (store::transaction const & txn_a) const -> iterator

View file

@ -533,6 +533,7 @@ rocksdb::ColumnFamilyHandle * nano::store::rocksdb::component::table_to_column_f
bool nano::store::rocksdb::component::exists (store::transaction const & transaction_a, tables table_a, nano::store::rocksdb::db_val const & key_a) const
{
::rocksdb::PinnableSlice slice;
auto key_slice = to_slice (key_a);
auto internals = rocksdb::tx (transaction_a);
auto status = std::visit ([&] (auto && ptr) {
using V = std::remove_cvref_t<decltype (ptr)>;
@ -540,11 +541,11 @@ bool nano::store::rocksdb::component::exists (store::transaction const & transac
{
::rocksdb::ReadOptions options;
options.fill_cache = false;
return ptr->Get (options, table_to_column_family (table_a), key_a, &slice);
return ptr->Get (options, table_to_column_family (table_a), key_slice, &slice);
}
else if constexpr (std::is_same_v<V, ::rocksdb::ReadOptions *>)
{
return db->Get (*ptr, table_to_column_family (table_a), key_a, &slice);
return db->Get (*ptr, table_to_column_family (table_a), key_slice, &slice);
}
else
{
@ -562,7 +563,8 @@ int nano::store::rocksdb::component::del (store::write_transaction const & trans
// RocksDB does not report not_found status, it is a pre-condition that the key exists
debug_assert (exists (transaction_a, table_a, key_a));
flush_tombstones_check (table_a);
return std::get<::rocksdb::Transaction *> (rocksdb::tx (transaction_a))->Delete (table_to_column_family (table_a), key_a).code ();
auto key_slice = to_slice (key_a);
return std::get<::rocksdb::Transaction *> (rocksdb::tx (transaction_a))->Delete (table_to_column_family (table_a), key_slice).code ();
}
void nano::store::rocksdb::component::flush_tombstones_check (tables table_a)
@ -589,17 +591,18 @@ int nano::store::rocksdb::component::get (store::transaction const & transaction
{
::rocksdb::ReadOptions options;
::rocksdb::PinnableSlice slice;
auto key_slice = to_slice (key_a);
auto handle = table_to_column_family (table_a);
auto internals = rocksdb::tx (transaction_a);
auto status = std::visit ([&] (auto && ptr) {
using V = std::remove_cvref_t<decltype (ptr)>;
if constexpr (std::is_same_v<V, ::rocksdb::Transaction *>)
{
return ptr->Get (options, handle, key_a, &slice);
return ptr->Get (options, handle, key_slice, &slice);
}
else if constexpr (std::is_same_v<V, ::rocksdb::ReadOptions *>)
{
return db->Get (*ptr, handle, key_a, &slice);
return db->Get (*ptr, handle, key_slice, &slice);
}
else
{
@ -610,9 +613,7 @@ int nano::store::rocksdb::component::get (store::transaction const & transaction
if (status.ok ())
{
value_a.buffer = std::make_shared<std::vector<uint8_t>> (slice.size ());
std::memcpy (value_a.buffer->data (), slice.data (), slice.size ());
value_a.convert_buffer_to_value ();
value_a = from_slice (slice);
}
return status.code ();
}
@ -620,7 +621,9 @@ int nano::store::rocksdb::component::get (store::transaction const & transaction
int nano::store::rocksdb::component::put (store::write_transaction const & transaction_a, tables table_a, nano::store::rocksdb::db_val const & key_a, nano::store::rocksdb::db_val const & value_a)
{
debug_assert (transaction_a.contains (table_a));
return std::get<::rocksdb::Transaction *> (rocksdb::tx (transaction_a))->Put (table_to_column_family (table_a), key_a, value_a).code ();
auto key_slice = to_slice (key_a);
auto value_slice = to_slice (value_a);
return std::get<::rocksdb::Transaction *> (rocksdb::tx (transaction_a))->Put (table_to_column_family (table_a), key_slice, value_slice).code ();
}
bool nano::store::rocksdb::component::not_found (int status) const

View file

@ -1,7 +1,10 @@
#pragma once
#include <nano/store/rocksdb/db_val.hpp>
#include <variant>
#include <rocksdb/slice.h>
#include <rocksdb/utilities/transaction_db.h>
namespace nano::store
@ -12,4 +15,23 @@ class transaction;
namespace nano::store::rocksdb
{
auto tx (store::transaction const & transaction_a) -> std::variant<::rocksdb::Transaction *, ::rocksdb::ReadOptions *>;
/**
* Converts a db_val to rocksdb::Slice for RocksDB operations
*/
inline ::rocksdb::Slice to_slice (nano::store::db_val const & val)
{
return ::rocksdb::Slice{ reinterpret_cast<char const *> (val.data ()), val.size () };
}
/**
* Creates a db_val from rocksdb::Slice for read operations
*/
inline nano::store::db_val from_slice (::rocksdb::Slice const & slice)
{
auto buffer = std::make_shared<std::vector<uint8_t>> (
reinterpret_cast<uint8_t const *> (slice.data ()),
reinterpret_cast<uint8_t const *> (slice.data ()) + slice.size ());
return nano::store::db_val (buffer);
}
}

View file

@ -1,6 +1,5 @@
#include <nano/lib/utility.hpp>
#include <nano/store/db_val_impl.hpp>
#include <nano/store/lmdb/db_val.hpp>
#include <nano/store/db_val_templ.hpp>
#include <nano/store/typed_iterator.hpp>
namespace nano::store
@ -10,10 +9,9 @@ void typed_iterator<Key, Value>::update ()
{
if (!iter.is_end ())
{
// FIXME Don't convert via lmdb::db_val, this is just a placeholder
auto const & data = *iter;
lmdb::db_val key_val{ MDB_val{ data.first.size (), const_cast<void *> (reinterpret_cast<void const *> (data.first.data ())) } };
lmdb::db_val value_val{ MDB_val{ data.second.size (), const_cast<void *> (reinterpret_cast<void const *> (data.second.data ())) } };
db_val key_val{ data.first };
db_val value_val{ data.second };
current = std::make_pair (static_cast<Key> (key_val), static_cast<Value> (value_val));
}
else