diff --git a/nano/node/wallet.cpp b/nano/node/wallet.cpp index 2fd0f190..ebd7c4b4 100644 --- a/nano/node/wallet.cpp +++ b/nano/node/wallet.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -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 (&entry_a)), 0)); + nano::store::lmdb::db_val pub_key (pub_a); + nano::store::lmdb::db_val entry_val (sizeof (entry_a), const_cast (&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::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::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 (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 (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 (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 (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 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 diff --git a/nano/secure/common.hpp b/nano/secure/common.hpp index 60b7ef31..f9f19fba 100644 --- a/nano/secure/common.hpp +++ b/nano/secure/common.hpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include diff --git a/nano/secure/ledger_set_any.cpp b/nano/secure/ledger_set_any.cpp index 5691cb39..6763264b 100644 --- a/nano/secure/ledger_set_any.cpp +++ b/nano/secure/ledger_set_any.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include diff --git a/nano/secure/ledger_set_confirmed.cpp b/nano/secure/ledger_set_confirmed.cpp index 655f04ed..76cb58e1 100644 --- a/nano/secure/ledger_set_confirmed.cpp +++ b/nano/secure/ledger_set_confirmed.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include diff --git a/nano/store/CMakeLists.txt b/nano/store/CMakeLists.txt index e3f4ef17..53504cb6 100644 --- a/nano/store/CMakeLists.txt +++ b/nano/store/CMakeLists.txt @@ -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 diff --git a/nano/store/account.hpp b/nano/store/account.hpp index dab7556b..34ba21e4 100644 --- a/nano/store/account.hpp +++ b/nano/store/account.hpp @@ -2,7 +2,7 @@ #include #include -#include +#include #include #include diff --git a/nano/store/db_val.cpp b/nano/store/db_val.cpp deleted file mode 100644 index cab8d8ef..00000000 --- a/nano/store/db_val.cpp +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/nano/store/db_val.hpp b/nano/store/db_val.hpp index 12b81a14..fe7de26a 100644 --- a/nano/store/db_val.hpp +++ b/nano/store/db_val.hpp @@ -3,11 +3,9 @@ #include #include #include -#include -#include -#include #include +#include 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 -class db_val +class db_val final { public: - db_val (Val const & value_a) : - value (value_a) + db_val () = default; + + db_val (std::span span) noexcept : + span_view{ span } { } - db_val () : - db_val (0, nullptr) + db_val (size_t size, void const * data) noexcept : + span_view{ static_cast (data), size } { } - db_val (std::nullptr_t) : - db_val (0, this) + db_val (std::nullptr_t) noexcept : + span_view{ reinterpret_cast (""), 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 (&val_a)) + db_val (std::shared_ptr> buffer) noexcept : + buffer{ buffer } { - } - - db_val (nano::uint256_union const & val_a) : - db_val (sizeof (val_a), const_cast (&val_a)) - { - } - - db_val (nano::uint512_union const & val_a) : - db_val (sizeof (val_a), const_cast (&val_a)) - { - } - - db_val (nano::qualified_root const & val_a) : - db_val (sizeof (val_a), const_cast (&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> ()) - { - { - 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 (&val_a)) - { - static_assert (std::is_standard_layout::value, "Standard layout is required"); - } - - db_val (nano::endpoint_key const & val_a) : - db_val (sizeof (val_a), const_cast (&val_a)) - { - static_assert (std::is_standard_layout::value, "Standard layout is required"); - } - - db_val (std::shared_ptr const & val_a); - - db_val (uint64_t val_a) : - buffer (std::make_shared> ()) - { - { - 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 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 (data ()), reinterpret_cast (data ()) + sizeof (result), reinterpret_cast (&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 (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 (); - } - - explicit operator nano::amount () const - { - return convert (); - } - - explicit operator nano::block_hash () const - { - return convert (); - } - - explicit operator nano::public_key () const - { - return convert (); - } - - explicit operator nano::qualified_root () const - { - return convert (); - } - - explicit operator nano::uint256_union () const - { - return convert (); - } - - explicit operator nano::uint512_union () const - { - return convert (); - } - - explicit operator std::array () const - { - nano::bufferstream stream (reinterpret_cast (data ()), size ()); - std::array 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 (data ()), reinterpret_cast (data ()) + sizeof (result), reinterpret_cast (&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 () const; + explicit operator nano::amount () const; + explicit operator nano::block_hash () const; + explicit operator nano::public_key () const; + explicit operator std::array () const; + explicit operator block_w_sideband () const; + explicit operator std::shared_ptr () const; + explicit operator std::nullptr_t () const; + explicit operator nano::no_value () const; template - std::shared_ptr convert_to_block () const + auto convert_to_block () const -> std::shared_ptr; + + explicit operator std::shared_ptr () const; + explicit operator std::shared_ptr () const; + explicit operator std::shared_ptr () const; + explicit operator std::shared_ptr () const; + explicit operator std::shared_ptr () const; + + auto data () const noexcept -> void * { - nano::bufferstream stream (reinterpret_cast (data ()), size ()); - auto error (false); - auto result (std::make_shared (error, stream)); - debug_assert (!error); - return result; + return const_cast (static_cast (span_view.data ())); + } + auto size () const noexcept -> size_t + { + return span_view.size (); } - explicit operator std::shared_ptr () const - { - return convert_to_block (); - } + auto convert_buffer_to_value () noexcept -> void; - explicit operator std::shared_ptr () const - { - return convert_to_block (); - } - - explicit operator std::shared_ptr () const - { - return convert_to_block (); - } - - explicit operator std::shared_ptr () const - { - return convert_to_block (); - } - - explicit operator std::shared_ptr () const - { - return convert_to_block (); - } - - explicit operator std::shared_ptr () const - { - nano::bufferstream stream (reinterpret_cast (data ()), size ()); - auto error (false); - auto result (nano::make_shared (error, stream)); - debug_assert (!error); - return result; - } - - explicit operator uint64_t () const - { - uint64_t result; - nano::bufferstream stream (reinterpret_cast (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 (&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 span_view; std::shared_ptr> buffer; private: template - T convert () const - { - T result; - debug_assert (size () == sizeof (result)); - std::copy (reinterpret_cast (data ()), reinterpret_cast (data ()) + sizeof (result), result.bytes.data ()); - return result; - } + auto convert () const -> T; }; -} // namespace nano::store +} diff --git a/nano/store/db_val_impl.hpp b/nano/store/db_val_impl.hpp deleted file mode 100644 index f2eaf488..00000000 --- a/nano/store/db_val_impl.hpp +++ /dev/null @@ -1,100 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -template -nano::store::db_val::db_val (nano::account_info const & val_a) : - db_val (val_a.db_size (), const_cast (&val_a)) -{ -} - -template -nano::store::db_val::db_val (nano::account_info_v22 const & val_a) : - db_val (val_a.db_size (), const_cast (&val_a)) -{ -} - -template -nano::store::db_val::db_val (std::shared_ptr const & val_a) : - buffer (std::make_shared> ()) -{ - { - nano::vectorstream stream (*buffer); - nano::serialize_block (stream, *val_a); - } - convert_buffer_to_value (); -} - -template -nano::store::db_val::db_val (nano::pending_info const & val_a) : - db_val (val_a.db_size (), const_cast (&val_a)) -{ - static_assert (std::is_standard_layout::value, "Standard layout is required"); -} - -template -nano::store::db_val::db_val (nano::pending_key const & val_a) : - db_val (sizeof (val_a), const_cast (&val_a)) -{ - static_assert (std::is_standard_layout::value, "Standard layout is required"); -} - -template -nano::store::db_val::operator nano::account_info () const -{ - nano::account_info result; - debug_assert (size () == result.db_size ()); - std::copy (reinterpret_cast (data ()), reinterpret_cast (data ()) + result.db_size (), reinterpret_cast (&result)); - return result; -} - -template -nano::store::db_val::operator nano::account_info_v22 () const -{ - nano::account_info_v22 result; - debug_assert (size () == result.db_size ()); - std::copy (reinterpret_cast (data ()), reinterpret_cast (data ()) + result.db_size (), reinterpret_cast (&result)); - return result; -} - -template -nano::store::db_val::operator std::shared_ptr () const -{ - nano::bufferstream stream (reinterpret_cast (data ()), size ()); - std::shared_ptr result (nano::deserialize_block (stream)); - return result; -} - -template -nano::store::db_val::operator nano::store::block_w_sideband () const -{ - nano::bufferstream stream (reinterpret_cast (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 -nano::store::db_val::operator nano::pending_info () const -{ - nano::pending_info result; - debug_assert (size () == result.db_size ()); - std::copy (reinterpret_cast (data ()), reinterpret_cast (data ()) + result.db_size (), reinterpret_cast (&result)); - return result; -} - -template -nano::store::db_val::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 (data ()), reinterpret_cast (data ()) + sizeof (result), reinterpret_cast (&result)); - return result; -} diff --git a/nano/store/db_val_templ.hpp b/nano/store/db_val_templ.hpp new file mode 100644 index 00000000..8955ab23 --- /dev/null +++ b/nano/store/db_val_templ.hpp @@ -0,0 +1,308 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +namespace nano::store +{ +// Constructor implementations + +inline db_val::db_val (uint64_t value) : + buffer{ std::make_shared> () } +{ + { + 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 (&value), sizeof (value) } +{ +} + +inline db_val::db_val (nano::account_info const & value) : + span_view{ reinterpret_cast (&value), value.db_size () } +{ +} + +inline db_val::db_val (nano::account_info_v22 const & value) : + span_view{ reinterpret_cast (&value), value.db_size () } +{ +} + +inline db_val::db_val (nano::pending_info const & value) : + span_view{ reinterpret_cast (&value), value.db_size () } +{ + static_assert (std::is_standard_layout::value, "Standard layout is required"); +} + +inline db_val::db_val (nano::pending_key const & value) : + span_view{ reinterpret_cast (&value), sizeof (value) } +{ + static_assert (std::is_standard_layout::value, "Standard layout is required"); +} + +inline db_val::db_val (nano::confirmation_height_info const & value) : + buffer{ std::make_shared> () } +{ + { + 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 (&value), sizeof (value) } +{ + static_assert (std::is_standard_layout::value, "Standard layout is required"); +} + +inline db_val::db_val (nano::endpoint_key const & value) : + span_view{ reinterpret_cast (&value), sizeof (value) } +{ + static_assert (std::is_standard_layout::value, "Standard layout is required"); +} + +inline db_val::db_val (std::shared_ptr const & block) : + buffer{ std::make_shared> () } +{ + { + 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 (); +} + +inline db_val::operator nano::uint256_union () const +{ + return convert (); +} + +inline db_val::operator nano::uint512_union () const +{ + return convert (); +} + +inline db_val::operator nano::qualified_root () const +{ + return convert (); +} + +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 (&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 (&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 (&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 (&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 (&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 (&result)); + return result; +} + +inline db_val::operator std::shared_ptr () const +{ + nano::bufferstream stream{ span_view.data (), span_view.size () }; + std::shared_ptr result{ nano::deserialize_block (stream) }; + return result; +} + +inline db_val::operator nano::amount () const +{ + return convert (); +} + +inline db_val::operator nano::block_hash () const +{ + return convert (); +} + +inline db_val::operator nano::public_key () const +{ + return convert (); +} + +inline db_val::operator std::array () const +{ + nano::bufferstream stream{ span_view.data (), span_view.size () }; + std::array 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 () const +{ + nano::bufferstream stream{ span_view.data (), span_view.size () }; + auto error{ false }; + auto result{ nano::make_shared (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 +inline auto db_val::convert_to_block () const -> std::shared_ptr +{ + nano::bufferstream stream{ span_view.data (), span_view.size () }; + auto error{ false }; + auto result{ nano::make_shared (error, stream) }; + debug_assert (!error); + return result; +} + +inline db_val::operator std::shared_ptr () const +{ + return convert_to_block (); +} + +inline db_val::operator std::shared_ptr () const +{ + return convert_to_block (); +} + +inline db_val::operator std::shared_ptr () const +{ + return convert_to_block (); +} + +inline db_val::operator std::shared_ptr () const +{ + return convert_to_block (); +} + +inline db_val::operator std::shared_ptr () const +{ + return convert_to_block (); +} + +// Member function implementations + +inline auto db_val::convert_buffer_to_value () noexcept -> void +{ + if (buffer) + { + span_view = std::span{ buffer->data (), buffer->size () }; + } +} + +template +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; +} +} \ No newline at end of file diff --git a/nano/store/lmdb/account.cpp b/nano/store/lmdb/account.cpp index c84b6ec1..58072a42 100644 --- a/nano/store/lmdb/account.cpp +++ b/nano/store/lmdb/account.cpp @@ -2,6 +2,7 @@ #include #include #include +#include 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 diff --git a/nano/store/lmdb/block.cpp b/nano/store/lmdb/block.cpp index fe698808..f0f81a16 100644 --- a/nano/store/lmdb/block.cpp +++ b/nano/store/lmdb/block.cpp @@ -1,7 +1,8 @@ #include -#include +#include #include #include +#include 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 diff --git a/nano/store/lmdb/confirmation_height.cpp b/nano/store/lmdb/confirmation_height.cpp index 48e319b1..f175d33c 100644 --- a/nano/store/lmdb/confirmation_height.cpp +++ b/nano/store/lmdb/confirmation_height.cpp @@ -1,6 +1,7 @@ #include #include #include +#include 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 diff --git a/nano/store/lmdb/db_val.cpp b/nano/store/lmdb/db_val.cpp deleted file mode 100644 index 7896bbaa..00000000 --- a/nano/store/lmdb/db_val.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#include - -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 (buffer->data ()) }; -} diff --git a/nano/store/lmdb/db_val.hpp b/nano/store/lmdb/db_val.hpp index 3b4966f5..463b6f4f 100644 --- a/nano/store/lmdb/db_val.hpp +++ b/nano/store/lmdb/db_val.hpp @@ -2,9 +2,7 @@ #include -#include - namespace nano::store::lmdb { -using db_val = store::db_val; +using db_val = store::db_val; } diff --git a/nano/store/lmdb/final_vote.cpp b/nano/store/lmdb/final_vote.cpp index e6e0ea77..c27f3f70 100644 --- a/nano/store/lmdb/final_vote.cpp +++ b/nano/store/lmdb/final_vote.cpp @@ -1,6 +1,7 @@ #include #include #include +#include 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 diff --git a/nano/store/lmdb/lmdb.cpp b/nano/store/lmdb/lmdb.cpp index 9fc1cb74..bbfa6b76 100644 --- a/nano/store/lmdb/lmdb.cpp +++ b/nano/store/lmdb/lmdb.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -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 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 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 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 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)); diff --git a/nano/store/lmdb/pending.cpp b/nano/store/lmdb/pending.cpp index 7daedcc4..fb9b17e9 100644 --- a/nano/store/lmdb/pending.cpp +++ b/nano/store/lmdb/pending.cpp @@ -1,6 +1,7 @@ #include #include #include +#include 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 diff --git a/nano/store/lmdb/pruned.cpp b/nano/store/lmdb/pruned.cpp index ca853bca..2eeedf91 100644 --- a/nano/store/lmdb/pruned.cpp +++ b/nano/store/lmdb/pruned.cpp @@ -1,6 +1,7 @@ #include #include #include +#include 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 diff --git a/nano/store/lmdb/rep_weight.cpp b/nano/store/lmdb/rep_weight.cpp index e9068ac0..d5e180d3 100644 --- a/nano/store/lmdb/rep_weight.cpp +++ b/nano/store/lmdb/rep_weight.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -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 diff --git a/nano/store/lmdb/utility.hpp b/nano/store/lmdb/utility.hpp new file mode 100644 index 00000000..bbf4d0b5 --- /dev/null +++ b/nano/store/lmdb/utility.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include + +#include + +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{ static_cast (val.mv_data), val.mv_size }; + return nano::store::db_val (span); +} +} \ No newline at end of file diff --git a/nano/store/lmdb/wallet_value.cpp b/nano/store/lmdb/wallet_value.cpp index 60aefabe..32beb245 100644 --- a/nano/store/lmdb/wallet_value.cpp +++ b/nano/store/lmdb/wallet_value.cpp @@ -1,6 +1,6 @@ #include -nano::wallet_value::wallet_value (nano::store::db_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 (val_a.data ()), reinterpret_cast (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 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 (sizeof (*this), const_cast (this)); + return nano::store::db_val (sizeof (*this), const_cast (this)); } diff --git a/nano/store/lmdb/wallet_value.hpp b/nano/store/lmdb/wallet_value.hpp index d272ae96..669b777a 100644 --- a/nano/store/lmdb/wallet_value.hpp +++ b/nano/store/lmdb/wallet_value.hpp @@ -11,9 +11,9 @@ class wallet_value { public: wallet_value () = default; - wallet_value (store::db_val const &); + wallet_value (store::db_val const &); wallet_value (nano::raw_key const &, uint64_t); - store::db_val val () const; + store::db_val val () const; nano::raw_key key; uint64_t work; }; diff --git a/nano/store/rocksdb/account.cpp b/nano/store/rocksdb/account.cpp index 579dff95..0ba2e4cb 100644 --- a/nano/store/rocksdb/account.cpp +++ b/nano/store/rocksdb/account.cpp @@ -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 diff --git a/nano/store/rocksdb/block.cpp b/nano/store/rocksdb/block.cpp index 6b9cd670..c73f48f9 100644 --- a/nano/store/rocksdb/block.cpp +++ b/nano/store/rocksdb/block.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include #include #include @@ -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 diff --git a/nano/store/rocksdb/confirmation_height.cpp b/nano/store/rocksdb/confirmation_height.cpp index 2cc21131..d76d7b81 100644 --- a/nano/store/rocksdb/confirmation_height.cpp +++ b/nano/store/rocksdb/confirmation_height.cpp @@ -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 diff --git a/nano/store/rocksdb/db_val.cpp b/nano/store/rocksdb/db_val.cpp deleted file mode 100644 index e31654bb..00000000 --- a/nano/store/rocksdb/db_val.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#include - -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 (data_a), size_a) -{ -} - -template <> -void nano::store::rocksdb::db_val::convert_buffer_to_value () -{ - value = ::rocksdb::Slice (reinterpret_cast (buffer->data ()), buffer->size ()); -} diff --git a/nano/store/rocksdb/db_val.hpp b/nano/store/rocksdb/db_val.hpp index 9c1085ee..04b5754d 100644 --- a/nano/store/rocksdb/db_val.hpp +++ b/nano/store/rocksdb/db_val.hpp @@ -2,9 +2,7 @@ #include -#include - namespace nano::store::rocksdb { -using db_val = store::db_val<::rocksdb::Slice>; +using db_val = store::db_val; } diff --git a/nano/store/rocksdb/final_vote.cpp b/nano/store/rocksdb/final_vote.cpp index 614df9f2..7de8f991 100644 --- a/nano/store/rocksdb/final_vote.cpp +++ b/nano/store/rocksdb/final_vote.cpp @@ -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 diff --git a/nano/store/rocksdb/pending.cpp b/nano/store/rocksdb/pending.cpp index b9555b5a..ab958883 100644 --- a/nano/store/rocksdb/pending.cpp +++ b/nano/store/rocksdb/pending.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include #include @@ -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 diff --git a/nano/store/rocksdb/pending.hpp b/nano/store/rocksdb/pending.hpp index 061d0031..45274975 100644 --- a/nano/store/rocksdb/pending.hpp +++ b/nano/store/rocksdb/pending.hpp @@ -2,6 +2,10 @@ #include +namespace nano::store::rocksdb +{ +class component; +} namespace nano::store::rocksdb { class pending : public nano::store::pending diff --git a/nano/store/rocksdb/pruned.cpp b/nano/store/rocksdb/pruned.cpp index b85eae1a..0a2f869b 100644 --- a/nano/store/rocksdb/pruned.cpp +++ b/nano/store/rocksdb/pruned.cpp @@ -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 diff --git a/nano/store/rocksdb/rep_weight.cpp b/nano/store/rocksdb/rep_weight.cpp index ee081a58..eeb1b560 100644 --- a/nano/store/rocksdb/rep_weight.cpp +++ b/nano/store/rocksdb/rep_weight.cpp @@ -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 diff --git a/nano/store/rocksdb/rocksdb.cpp b/nano/store/rocksdb/rocksdb.cpp index 4ef2c798..fa69b66d 100644 --- a/nano/store/rocksdb/rocksdb.cpp +++ b/nano/store/rocksdb/rocksdb.cpp @@ -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; @@ -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) { - 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; if constexpr (std::is_same_v) { - return ptr->Get (options, handle, key_a, &slice); + return ptr->Get (options, handle, key_slice, &slice); } else if constexpr (std::is_same_v) { - 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> (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 diff --git a/nano/store/rocksdb/utility.hpp b/nano/store/rocksdb/utility.hpp index 7686b6b4..aff0e32d 100644 --- a/nano/store/rocksdb/utility.hpp +++ b/nano/store/rocksdb/utility.hpp @@ -1,7 +1,10 @@ #pragma once +#include + #include +#include #include 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 (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> ( + reinterpret_cast (slice.data ()), + reinterpret_cast (slice.data ()) + slice.size ()); + return nano::store::db_val (buffer); +} } diff --git a/nano/store/typed_iterator_templ.hpp b/nano/store/typed_iterator_templ.hpp index 9ce464c1..bb55f159 100644 --- a/nano/store/typed_iterator_templ.hpp +++ b/nano/store/typed_iterator_templ.hpp @@ -1,6 +1,5 @@ #include -#include -#include +#include #include namespace nano::store @@ -10,10 +9,9 @@ void typed_iterator::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 (reinterpret_cast (data.first.data ())) } }; - lmdb::db_val value_val{ MDB_val{ data.second.size (), const_cast (reinterpret_cast (data.second.data ())) } }; + db_val key_val{ data.first }; + db_val value_val{ data.second }; current = std::make_pair (static_cast (key_val), static_cast (value_val)); } else