Rewrite nano::store iterators to use variants instead of polymorphism.
This commit is contained in:
parent
db7405f580
commit
37f4f5c2d6
62 changed files with 978 additions and 742 deletions
|
|
@ -798,7 +798,7 @@ TEST (block_store, large_iteration)
|
||||||
// Reverse iteration
|
// Reverse iteration
|
||||||
std::unordered_set<nano::account> accounts3;
|
std::unordered_set<nano::account> accounts3;
|
||||||
previous = std::numeric_limits<nano::uint256_t>::max ();
|
previous = std::numeric_limits<nano::uint256_t>::max ();
|
||||||
for (auto i (store->account.rbegin (transaction)), n (store->account.end (transaction)); i != n; --i)
|
for (auto i (store->account.rbegin (transaction)), n (store->account.rend (transaction)); i != n; ++i)
|
||||||
{
|
{
|
||||||
nano::account current (i->first);
|
nano::account current (i->first);
|
||||||
ASSERT_LT (current.number (), previous.number ());
|
ASSERT_LT (current.number (), previous.number ());
|
||||||
|
|
@ -1254,7 +1254,7 @@ TEST (block_store, online_weight)
|
||||||
auto transaction (store->tx_begin_write ());
|
auto transaction (store->tx_begin_write ());
|
||||||
ASSERT_EQ (0, store->online_weight.count (transaction));
|
ASSERT_EQ (0, store->online_weight.count (transaction));
|
||||||
ASSERT_EQ (store->online_weight.end (transaction), store->online_weight.begin (transaction));
|
ASSERT_EQ (store->online_weight.end (transaction), store->online_weight.begin (transaction));
|
||||||
ASSERT_EQ (store->online_weight.end (transaction), store->online_weight.rbegin (transaction));
|
ASSERT_EQ (store->online_weight.rend (transaction), store->online_weight.rbegin (transaction));
|
||||||
store->online_weight.put (transaction, 1, 2);
|
store->online_weight.put (transaction, 1, 2);
|
||||||
store->online_weight.put (transaction, 3, 4);
|
store->online_weight.put (transaction, 3, 4);
|
||||||
}
|
}
|
||||||
|
|
@ -1266,18 +1266,18 @@ TEST (block_store, online_weight)
|
||||||
ASSERT_EQ (1, item->first);
|
ASSERT_EQ (1, item->first);
|
||||||
ASSERT_EQ (2, item->second.number ());
|
ASSERT_EQ (2, item->second.number ());
|
||||||
auto item_last (store->online_weight.rbegin (transaction));
|
auto item_last (store->online_weight.rbegin (transaction));
|
||||||
ASSERT_NE (store->online_weight.end (transaction), item_last);
|
ASSERT_NE (store->online_weight.rend (transaction), item_last);
|
||||||
ASSERT_EQ (3, item_last->first);
|
ASSERT_EQ (3, item_last->first);
|
||||||
ASSERT_EQ (4, item_last->second.number ());
|
ASSERT_EQ (4, item_last->second.number ());
|
||||||
store->online_weight.del (transaction, 1);
|
store->online_weight.del (transaction, 1);
|
||||||
ASSERT_EQ (1, store->online_weight.count (transaction));
|
ASSERT_EQ (1, store->online_weight.count (transaction));
|
||||||
ASSERT_EQ (store->online_weight.begin (transaction), store->online_weight.rbegin (transaction));
|
ASSERT_EQ (*store->online_weight.begin (transaction), *store->online_weight.rbegin (transaction));
|
||||||
store->online_weight.del (transaction, 3);
|
store->online_weight.del (transaction, 3);
|
||||||
}
|
}
|
||||||
auto transaction (store->tx_begin_read ());
|
auto transaction (store->tx_begin_read ());
|
||||||
ASSERT_EQ (0, store->online_weight.count (transaction));
|
ASSERT_EQ (0, store->online_weight.count (transaction));
|
||||||
ASSERT_EQ (store->online_weight.end (transaction), store->online_weight.begin (transaction));
|
ASSERT_EQ (store->online_weight.end (transaction), store->online_weight.begin (transaction));
|
||||||
ASSERT_EQ (store->online_weight.end (transaction), store->online_weight.rbegin (transaction));
|
ASSERT_EQ (store->online_weight.rend (transaction), store->online_weight.rbegin (transaction));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST (block_store, pruned_blocks)
|
TEST (block_store, pruned_blocks)
|
||||||
|
|
|
||||||
|
|
@ -755,7 +755,7 @@ void nano::node::long_inactivity_cleanup ()
|
||||||
if (store.online_weight.count (transaction) > 0)
|
if (store.online_weight.count (transaction) > 0)
|
||||||
{
|
{
|
||||||
auto sample (store.online_weight.rbegin (transaction));
|
auto sample (store.online_weight.rbegin (transaction));
|
||||||
auto n (store.online_weight.end (transaction));
|
auto n (store.online_weight.rend (transaction));
|
||||||
debug_assert (sample != n);
|
debug_assert (sample != n);
|
||||||
auto const one_week_ago = static_cast<std::size_t> ((std::chrono::system_clock::now () - std::chrono::hours (7 * 24)).time_since_epoch ().count ());
|
auto const one_week_ago = static_cast<std::size_t> ((std::chrono::system_clock::now () - std::chrono::hours (7 * 24)).time_since_epoch ().count ());
|
||||||
perform_cleanup = sample->first < one_week_ago;
|
perform_cleanup = sample->first < one_week_ago;
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
#include <nano/secure/ledger_set_any.hpp>
|
#include <nano/secure/ledger_set_any.hpp>
|
||||||
#include <nano/secure/ledger_set_confirmed.hpp>
|
#include <nano/secure/ledger_set_confirmed.hpp>
|
||||||
#include <nano/store/lmdb/iterator.hpp>
|
#include <nano/store/lmdb/iterator.hpp>
|
||||||
|
#include <nano/store/typed_iterator_templ.hpp>
|
||||||
|
|
||||||
#include <boost/format.hpp>
|
#include <boost/format.hpp>
|
||||||
#include <boost/polymorphic_cast.hpp>
|
#include <boost/polymorphic_cast.hpp>
|
||||||
|
|
@ -19,6 +20,8 @@
|
||||||
|
|
||||||
#include <argon2.h>
|
#include <argon2.h>
|
||||||
|
|
||||||
|
template class nano::store::typed_iterator<nano::account, nano::wallet_value>;
|
||||||
|
|
||||||
nano::uint256_union nano::wallet_store::check (store::transaction const & transaction_a)
|
nano::uint256_union nano::wallet_store::check (store::transaction const & transaction_a)
|
||||||
{
|
{
|
||||||
nano::wallet_value value (entry_get_raw (transaction_a, nano::wallet_store::check_special));
|
nano::wallet_value value (entry_get_raw (transaction_a, nano::wallet_store::check_special));
|
||||||
|
|
@ -548,7 +551,8 @@ bool nano::wallet_store::exists (store::transaction const & transaction_a, nano:
|
||||||
void nano::wallet_store::serialize_json (store::transaction const & transaction_a, std::string & string_a)
|
void nano::wallet_store::serialize_json (store::transaction const & transaction_a, std::string & string_a)
|
||||||
{
|
{
|
||||||
boost::property_tree::ptree tree;
|
boost::property_tree::ptree tree;
|
||||||
for (store::iterator<nano::uint256_union, nano::wallet_value> i (std::make_unique<nano::store::lmdb::iterator<nano::uint256_union, nano::wallet_value>> (transaction_a, env, handle)), n (nullptr); i != n; ++i)
|
using iterator = store::typed_iterator<nano::uint256_union, nano::wallet_value>;
|
||||||
|
for (iterator i{ store::iterator{ store::lmdb::iterator::begin (env.tx (transaction_a), handle) } }, n{ store::iterator{ store::lmdb::iterator::end (env.tx (transaction_a), handle) } }; i != n; ++i)
|
||||||
{
|
{
|
||||||
tree.put (i->first.to_string (), i->second.key.to_string ());
|
tree.put (i->first.to_string (), i->second.key.to_string ());
|
||||||
}
|
}
|
||||||
|
|
@ -1359,13 +1363,15 @@ nano::wallets::wallets (bool error_a, nano::node & node_a) :
|
||||||
status |= mdb_dbi_open (env.tx (transaction), "send_action_ids", MDB_CREATE, &send_action_ids);
|
status |= mdb_dbi_open (env.tx (transaction), "send_action_ids", MDB_CREATE, &send_action_ids);
|
||||||
release_assert (status == 0);
|
release_assert (status == 0);
|
||||||
std::string beginning (nano::uint256_union (0).to_string ());
|
std::string beginning (nano::uint256_union (0).to_string ());
|
||||||
|
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 ());
|
std::string end ((nano::uint256_union (nano::uint256_t (0) - nano::uint256_t (1))).to_string ());
|
||||||
store::iterator<std::array<char, 64>, nano::no_value> i (std::make_unique<nano::store::lmdb::iterator<std::array<char, 64>, nano::no_value>> (transaction, env, handle, nano::store::lmdb::db_val (beginning.size (), const_cast<char *> (beginning.c_str ()))));
|
nano::store::lmdb::db_val end_val{ end.size (), const_cast<char *> (end.c_str ()) };
|
||||||
store::iterator<std::array<char, 64>, nano::no_value> n (std::make_unique<nano::store::lmdb::iterator<std::array<char, 64>, nano::no_value>> (transaction, env, handle, nano::store::lmdb::db_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) };
|
||||||
for (; i != n; ++i)
|
for (; i != n; ++i)
|
||||||
{
|
{
|
||||||
nano::wallet_id id;
|
nano::wallet_id id;
|
||||||
std::string text (i->first.data (), i->first.size ());
|
std::string text (reinterpret_cast<char const *> (i->first.data ()), i->first.size ());
|
||||||
auto error (id.decode_hex (text));
|
auto error (id.decode_hex (text));
|
||||||
release_assert (!error);
|
release_assert (!error);
|
||||||
release_assert (items.find (id) == items.end ());
|
release_assert (items.find (id) == items.end ());
|
||||||
|
|
@ -1488,13 +1494,15 @@ void nano::wallets::reload ()
|
||||||
auto transaction (tx_begin_write ());
|
auto transaction (tx_begin_write ());
|
||||||
std::unordered_set<nano::uint256_union> stored_items;
|
std::unordered_set<nano::uint256_union> stored_items;
|
||||||
std::string beginning (nano::uint256_union (0).to_string ());
|
std::string beginning (nano::uint256_union (0).to_string ());
|
||||||
|
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 ());
|
std::string end ((nano::uint256_union (nano::uint256_t (0) - nano::uint256_t (1))).to_string ());
|
||||||
store::iterator<std::array<char, 64>, nano::no_value> i (std::make_unique<nano::store::lmdb::iterator<std::array<char, 64>, nano::no_value>> (transaction, env, handle, nano::store::lmdb::db_val (beginning.size (), const_cast<char *> (beginning.c_str ()))));
|
nano::store::lmdb::db_val end_val{ end.size (), const_cast<char *> (end.c_str ()) };
|
||||||
store::iterator<std::array<char, 64>, nano::no_value> n (std::make_unique<nano::store::lmdb::iterator<std::array<char, 64>, nano::no_value>> (transaction, env, handle, nano::store::lmdb::db_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) };
|
||||||
for (; i != n; ++i)
|
for (; i != n; ++i)
|
||||||
{
|
{
|
||||||
nano::wallet_id id;
|
nano::wallet_id id;
|
||||||
std::string text (i->first.data (), i->first.size ());
|
std::string text (reinterpret_cast<char const *> (i->first.data ()), i->first.size ());
|
||||||
auto error (id.decode_hex (text));
|
auto error (id.decode_hex (text));
|
||||||
debug_assert (!error);
|
debug_assert (!error);
|
||||||
// New wallet
|
// New wallet
|
||||||
|
|
@ -1755,20 +1763,22 @@ nano::uint128_t const nano::wallets::high_priority = std::numeric_limits<nano::u
|
||||||
|
|
||||||
auto nano::wallet_store::begin (store::transaction const & transaction_a) -> iterator
|
auto nano::wallet_store::begin (store::transaction const & transaction_a) -> iterator
|
||||||
{
|
{
|
||||||
iterator result (std::make_unique<nano::store::lmdb::iterator<nano::account, nano::wallet_value>> (transaction_a, env, handle, nano::store::lmdb::db_val (nano::account (special_count))));
|
nano::account account{ special_count };
|
||||||
return result;
|
nano::store::lmdb::db_val val{ account };
|
||||||
|
return iterator{ store::iterator{ store::lmdb::iterator::lower_bound (env.tx (transaction_a), handle, val) } };
|
||||||
}
|
}
|
||||||
|
|
||||||
auto nano::wallet_store::begin (store::transaction const & transaction_a, nano::account const & key) -> iterator
|
auto nano::wallet_store::begin (store::transaction const & transaction_a, nano::account const & key) -> iterator
|
||||||
{
|
{
|
||||||
iterator result (std::make_unique<nano::store::lmdb::iterator<nano::account, nano::wallet_value>> (transaction_a, env, handle, nano::store::lmdb::db_val (key)));
|
nano::account account (key);
|
||||||
return result;
|
nano::store::lmdb::db_val val{ account };
|
||||||
|
return iterator{ store::iterator{ store::lmdb::iterator::lower_bound (env.tx (transaction_a), handle, val) } };
|
||||||
}
|
}
|
||||||
|
|
||||||
auto nano::wallet_store::find (store::transaction const & transaction_a, nano::account const & key) -> iterator
|
auto nano::wallet_store::find (store::transaction const & transaction_a, nano::account const & key) -> iterator
|
||||||
{
|
{
|
||||||
auto result (begin (transaction_a, key));
|
auto result = begin (transaction_a, key);
|
||||||
iterator end{ nullptr };
|
auto end = this->end (transaction_a);
|
||||||
if (result != end)
|
if (result != end)
|
||||||
{
|
{
|
||||||
if (result->first == key)
|
if (result->first == key)
|
||||||
|
|
@ -1789,7 +1799,7 @@ auto nano::wallet_store::find (store::transaction const & transaction_a, nano::a
|
||||||
|
|
||||||
auto nano::wallet_store::end (store::transaction const & transaction_a) -> iterator
|
auto nano::wallet_store::end (store::transaction const & transaction_a) -> iterator
|
||||||
{
|
{
|
||||||
return iterator{ nullptr };
|
return iterator{ store::iterator{ store::lmdb::iterator::end (env.tx (transaction_a), handle) } };
|
||||||
}
|
}
|
||||||
|
|
||||||
nano::mdb_wallets_store::mdb_wallets_store (std::filesystem::path const & path_a, nano::lmdb_config const & lmdb_config_a) :
|
nano::mdb_wallets_store::mdb_wallets_store (std::filesystem::path const & path_a, nano::lmdb_config const & lmdb_config_a) :
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
#include <nano/store/component.hpp>
|
#include <nano/store/component.hpp>
|
||||||
#include <nano/store/lmdb/lmdb.hpp>
|
#include <nano/store/lmdb/lmdb.hpp>
|
||||||
#include <nano/store/lmdb/wallet_value.hpp>
|
#include <nano/store/lmdb/wallet_value.hpp>
|
||||||
|
#include <nano/store/typed_iterator.hpp>
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
@ -58,7 +59,7 @@ enum class key_type
|
||||||
class wallet_store final
|
class wallet_store final
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using iterator = store::iterator<nano::account, nano::wallet_value>;
|
using iterator = store::typed_iterator<nano::account, nano::wallet_value>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
wallet_store (bool &, nano::kdf &, store::transaction &, store::lmdb::env &, nano::account, unsigned, std::string const &);
|
wallet_store (bool &, nano::kdf &, store::transaction &, store::lmdb::env &, nano::account, unsigned, std::string const &);
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ add_library(
|
||||||
db_val.hpp
|
db_val.hpp
|
||||||
db_val_impl.hpp
|
db_val_impl.hpp
|
||||||
iterator.hpp
|
iterator.hpp
|
||||||
iterator_impl.hpp
|
|
||||||
final_vote.hpp
|
final_vote.hpp
|
||||||
lmdb/account.hpp
|
lmdb/account.hpp
|
||||||
lmdb/block.hpp
|
lmdb/block.hpp
|
||||||
|
|
@ -33,6 +32,8 @@ add_library(
|
||||||
pending.hpp
|
pending.hpp
|
||||||
pruned.hpp
|
pruned.hpp
|
||||||
rep_weight.hpp
|
rep_weight.hpp
|
||||||
|
reverse_iterator.hpp
|
||||||
|
reverse_iterator_templ.hpp
|
||||||
rocksdb/account.hpp
|
rocksdb/account.hpp
|
||||||
rocksdb/block.hpp
|
rocksdb/block.hpp
|
||||||
rocksdb/confirmation_height.hpp
|
rocksdb/confirmation_height.hpp
|
||||||
|
|
@ -51,6 +52,8 @@ add_library(
|
||||||
rocksdb/version.hpp
|
rocksdb/version.hpp
|
||||||
tables.hpp
|
tables.hpp
|
||||||
transaction.hpp
|
transaction.hpp
|
||||||
|
typed_iterator.hpp
|
||||||
|
typed_iterator_templ.hpp
|
||||||
version.hpp
|
version.hpp
|
||||||
versioning.hpp
|
versioning.hpp
|
||||||
account.cpp
|
account.cpp
|
||||||
|
|
@ -59,13 +62,13 @@ add_library(
|
||||||
confirmation_height.cpp
|
confirmation_height.cpp
|
||||||
db_val.cpp
|
db_val.cpp
|
||||||
iterator.cpp
|
iterator.cpp
|
||||||
iterator_impl.cpp
|
|
||||||
final_vote.cpp
|
final_vote.cpp
|
||||||
lmdb/account.cpp
|
lmdb/account.cpp
|
||||||
lmdb/block.cpp
|
lmdb/block.cpp
|
||||||
lmdb/confirmation_height.cpp
|
lmdb/confirmation_height.cpp
|
||||||
lmdb/db_val.cpp
|
lmdb/db_val.cpp
|
||||||
lmdb/final_vote.cpp
|
lmdb/final_vote.cpp
|
||||||
|
lmdb/iterator.cpp
|
||||||
lmdb/lmdb.cpp
|
lmdb/lmdb.cpp
|
||||||
lmdb/lmdb_env.cpp
|
lmdb/lmdb_env.cpp
|
||||||
lmdb/transaction.cpp
|
lmdb/transaction.cpp
|
||||||
|
|
@ -80,11 +83,13 @@ add_library(
|
||||||
peer.cpp
|
peer.cpp
|
||||||
pending.cpp
|
pending.cpp
|
||||||
pruned.cpp
|
pruned.cpp
|
||||||
|
rep_weight.cpp
|
||||||
rocksdb/account.cpp
|
rocksdb/account.cpp
|
||||||
rocksdb/block.cpp
|
rocksdb/block.cpp
|
||||||
rocksdb/confirmation_height.cpp
|
rocksdb/confirmation_height.cpp
|
||||||
rocksdb/db_val.cpp
|
rocksdb/db_val.cpp
|
||||||
rocksdb/final_vote.cpp
|
rocksdb/final_vote.cpp
|
||||||
|
rocksdb/iterator.cpp
|
||||||
rocksdb/online_weight.cpp
|
rocksdb/online_weight.cpp
|
||||||
rocksdb/peer.cpp
|
rocksdb/peer.cpp
|
||||||
rocksdb/pending.cpp
|
rocksdb/pending.cpp
|
||||||
|
|
@ -95,6 +100,7 @@ add_library(
|
||||||
rocksdb/utility.cpp
|
rocksdb/utility.cpp
|
||||||
rocksdb/version.cpp
|
rocksdb/version.cpp
|
||||||
transaction.cpp
|
transaction.cpp
|
||||||
|
typed_iterator.cpp
|
||||||
version.cpp
|
version.cpp
|
||||||
versioning.cpp
|
versioning.cpp
|
||||||
write_queue.hpp
|
write_queue.hpp
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,9 @@
|
||||||
#include <nano/store/account.hpp>
|
#include <nano/store/account.hpp>
|
||||||
|
#include <nano/store/reverse_iterator_templ.hpp>
|
||||||
|
#include <nano/store/typed_iterator_templ.hpp>
|
||||||
|
|
||||||
|
template class nano::store::typed_iterator<nano::account, nano::account_info>;
|
||||||
|
template class nano::store::reverse_iterator<nano::store::typed_iterator<nano::account, nano::account_info>>;
|
||||||
|
|
||||||
std::optional<nano::account_info> nano::store::account::get (store::transaction const & transaction, nano::account const & account)
|
std::optional<nano::account_info> nano::store::account::get (store::transaction const & transaction, nano::account const & account)
|
||||||
{
|
{
|
||||||
|
|
@ -13,3 +18,15 @@ std::optional<nano::account_info> nano::store::account::get (store::transaction
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto nano::store::account::rbegin (store::transaction const & tx) const -> reverse_iterator
|
||||||
|
{
|
||||||
|
auto iter = end (tx);
|
||||||
|
--iter;
|
||||||
|
return reverse_iterator{ std::move (iter) };
|
||||||
|
}
|
||||||
|
|
||||||
|
auto nano::store::account::rend (transaction const & tx) const -> reverse_iterator
|
||||||
|
{
|
||||||
|
return reverse_iterator{ end (tx) };
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,8 @@
|
||||||
#include <nano/lib/numbers.hpp>
|
#include <nano/lib/numbers.hpp>
|
||||||
#include <nano/store/component.hpp>
|
#include <nano/store/component.hpp>
|
||||||
#include <nano/store/db_val_impl.hpp>
|
#include <nano/store/db_val_impl.hpp>
|
||||||
#include <nano/store/iterator.hpp>
|
#include <nano/store/reverse_iterator.hpp>
|
||||||
|
#include <nano/store/typed_iterator.hpp>
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
|
|
@ -20,19 +21,21 @@ namespace nano::store
|
||||||
class account
|
class account
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using iterator = store::iterator<nano::account, nano::account_info>;
|
using iterator = typed_iterator<nano::account, nano::account_info>;
|
||||||
|
using reverse_iterator = store::reverse_iterator<iterator>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual void put (store::write_transaction const &, nano::account const &, nano::account_info const &) = 0;
|
virtual void put (write_transaction const & tx, nano::account const &, nano::account_info const &) = 0;
|
||||||
virtual bool get (store::transaction const &, nano::account const &, nano::account_info &) = 0;
|
virtual bool get (transaction const & tx, nano::account const &, nano::account_info &) = 0;
|
||||||
std::optional<nano::account_info> get (store::transaction const &, nano::account const &);
|
std::optional<nano::account_info> get (transaction const & tx, nano::account const &);
|
||||||
virtual void del (store::write_transaction const &, nano::account const &) = 0;
|
virtual void del (write_transaction const & tx, nano::account const &) = 0;
|
||||||
virtual bool exists (store::transaction const &, nano::account const &) = 0;
|
virtual bool exists (transaction const & tx, nano::account const &) = 0;
|
||||||
virtual size_t count (store::transaction const &) = 0;
|
virtual size_t count (transaction const & tx) = 0;
|
||||||
virtual iterator begin (store::transaction const &, nano::account const &) const = 0;
|
virtual iterator begin (transaction const & tx, nano::account const &) const = 0;
|
||||||
virtual iterator begin (store::transaction const &) const = 0;
|
virtual iterator begin (transaction const & tx) const = 0;
|
||||||
virtual iterator rbegin (store::transaction const &) const = 0;
|
reverse_iterator rbegin (transaction const & tx) const;
|
||||||
virtual iterator end (store::transaction const & transaction_a) const = 0;
|
reverse_iterator rend (transaction const & tx) const;
|
||||||
virtual void for_each_par (std::function<void (store::read_transaction const &, iterator, iterator)> const &) const = 0;
|
virtual iterator end (transaction const & tx) const = 0;
|
||||||
|
virtual void for_each_par (std::function<void (read_transaction const & tx, iterator, iterator)> const &) const = 0;
|
||||||
};
|
};
|
||||||
} // namespace nano::store
|
} // namespace nano::store
|
||||||
|
|
|
||||||
|
|
@ -1 +1,4 @@
|
||||||
#include <nano/store/block.hpp>
|
#include <nano/store/block.hpp>
|
||||||
|
#include <nano/store/typed_iterator_templ.hpp>
|
||||||
|
|
||||||
|
template class nano::store::typed_iterator<nano::block_hash, nano::store::block_w_sideband>;
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
#include <nano/lib/numbers.hpp>
|
#include <nano/lib/numbers.hpp>
|
||||||
#include <nano/store/block_w_sideband.hpp>
|
#include <nano/store/block_w_sideband.hpp>
|
||||||
#include <nano/store/component.hpp>
|
#include <nano/store/component.hpp>
|
||||||
#include <nano/store/iterator.hpp>
|
#include <nano/store/typed_iterator.hpp>
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
@ -22,21 +22,21 @@ namespace nano::store
|
||||||
class block
|
class block
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using iterator = store::iterator<nano::block_hash, block_w_sideband>;
|
using iterator = typed_iterator<nano::block_hash, block_w_sideband>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual void put (store::write_transaction const &, nano::block_hash const &, nano::block const &) = 0;
|
virtual void put (write_transaction const & tx, nano::block_hash const &, nano::block const &) = 0;
|
||||||
virtual void raw_put (store::write_transaction const &, std::vector<uint8_t> const &, nano::block_hash const &) = 0;
|
virtual void raw_put (write_transaction const & tx, std::vector<uint8_t> const &, nano::block_hash const &) = 0;
|
||||||
virtual std::optional<nano::block_hash> successor (store::transaction const &, nano::block_hash const &) const = 0;
|
virtual std::optional<nano::block_hash> successor (transaction const & tx, nano::block_hash const &) const = 0;
|
||||||
virtual void successor_clear (store::write_transaction const &, nano::block_hash const &) = 0;
|
virtual void successor_clear (write_transaction const & tx, nano::block_hash const &) = 0;
|
||||||
virtual std::shared_ptr<nano::block> get (store::transaction const &, nano::block_hash const &) const = 0;
|
virtual std::shared_ptr<nano::block> get (transaction const & tx, nano::block_hash const &) const = 0;
|
||||||
virtual std::shared_ptr<nano::block> random (store::transaction const &) = 0;
|
virtual std::shared_ptr<nano::block> random (transaction const & tx) = 0;
|
||||||
virtual void del (store::write_transaction const &, nano::block_hash const &) = 0;
|
virtual void del (write_transaction const & tx, nano::block_hash const &) = 0;
|
||||||
virtual bool exists (store::transaction const &, nano::block_hash const &) = 0;
|
virtual bool exists (transaction const & tx, nano::block_hash const &) = 0;
|
||||||
virtual uint64_t count (store::transaction const &) = 0;
|
virtual uint64_t count (transaction const & tx) = 0;
|
||||||
virtual iterator begin (store::transaction const &, nano::block_hash const &) const = 0;
|
virtual iterator begin (transaction const & tx, nano::block_hash const &) const = 0;
|
||||||
virtual iterator begin (store::transaction const &) const = 0;
|
virtual iterator begin (transaction const & tx) const = 0;
|
||||||
virtual iterator end (store::transaction const &) const = 0;
|
virtual iterator end (transaction const & tx) const = 0;
|
||||||
virtual void for_each_par (std::function<void (store::read_transaction const &, iterator, iterator)> const & action_a) const = 0;
|
virtual void for_each_par (std::function<void (read_transaction const & tx, iterator, iterator)> const & action_a) const = 0;
|
||||||
};
|
};
|
||||||
} // namespace nano::store
|
} // namespace nano::store
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,7 @@
|
||||||
#include <nano/store/confirmation_height.hpp>
|
#include <nano/store/confirmation_height.hpp>
|
||||||
|
#include <nano/store/typed_iterator_templ.hpp>
|
||||||
|
|
||||||
|
template class nano::store::typed_iterator<nano::account, nano::confirmation_height_info>;
|
||||||
|
|
||||||
std::optional<nano::confirmation_height_info> nano::store::confirmation_height::get (store::transaction const & transaction, nano::account const & account)
|
std::optional<nano::confirmation_height_info> nano::store::confirmation_height::get (store::transaction const & transaction, nano::account const & account)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#include <nano/lib/numbers.hpp>
|
#include <nano/lib/numbers.hpp>
|
||||||
#include <nano/store/component.hpp>
|
#include <nano/store/component.hpp>
|
||||||
#include <nano/store/iterator.hpp>
|
#include <nano/store/typed_iterator.hpp>
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
|
|
@ -18,7 +18,7 @@ namespace nano::store
|
||||||
class confirmation_height
|
class confirmation_height
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using iterator = store::iterator<nano::account, nano::confirmation_height_info>;
|
using iterator = typed_iterator<nano::account, nano::confirmation_height_info>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual void put (store::write_transaction const & transaction_a, nano::account const & account_a, nano::confirmation_height_info const & confirmation_height_info_a) = 0;
|
virtual void put (store::write_transaction const & transaction_a, nano::account const & account_a, nano::confirmation_height_info const & confirmation_height_info_a) = 0;
|
||||||
|
|
|
||||||
|
|
@ -1 +1,4 @@
|
||||||
#include <nano/store/final_vote.hpp>
|
#include <nano/store/final_vote.hpp>
|
||||||
|
#include <nano/store/typed_iterator_templ.hpp>
|
||||||
|
|
||||||
|
template class nano::store::typed_iterator<nano::qualified_root, nano::block_hash>;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#include <nano/lib/numbers.hpp>
|
#include <nano/lib/numbers.hpp>
|
||||||
#include <nano/store/component.hpp>
|
#include <nano/store/component.hpp>
|
||||||
#include <nano/store/iterator.hpp>
|
#include <nano/store/typed_iterator.hpp>
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
|
|
@ -18,7 +18,7 @@ namespace nano::store
|
||||||
class final_vote
|
class final_vote
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using iterator = store::iterator<nano::qualified_root, nano::block_hash>;
|
using iterator = typed_iterator<nano::qualified_root, nano::block_hash>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual bool put (store::write_transaction const & transaction_a, nano::qualified_root const & root_a, nano::block_hash const & hash_a) = 0;
|
virtual bool put (store::write_transaction const & transaction_a, nano::qualified_root const & root_a, nano::block_hash const & hash_a) = 0;
|
||||||
|
|
|
||||||
|
|
@ -1 +1,81 @@
|
||||||
|
#include <nano/lib/utility.hpp>
|
||||||
#include <nano/store/iterator.hpp>
|
#include <nano/store/iterator.hpp>
|
||||||
|
|
||||||
|
namespace nano::store
|
||||||
|
{
|
||||||
|
void iterator::update ()
|
||||||
|
{
|
||||||
|
std::visit ([&] (auto && arg) {
|
||||||
|
if (!arg.is_end ())
|
||||||
|
{
|
||||||
|
this->current = arg.span ();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
current = std::monostate{};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
internals);
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator::iterator (std::variant<lmdb::iterator, rocksdb::iterator> && internals) noexcept :
|
||||||
|
internals{ std::move (internals) }
|
||||||
|
{
|
||||||
|
update ();
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator::iterator (iterator && other) noexcept :
|
||||||
|
internals{ std::move (other.internals) }
|
||||||
|
{
|
||||||
|
current = std::move (other.current);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto iterator::operator= (iterator && other) noexcept -> iterator &
|
||||||
|
{
|
||||||
|
internals = std::move (other.internals);
|
||||||
|
current = std::move (other.current);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto iterator::operator++ () -> iterator &
|
||||||
|
{
|
||||||
|
std::visit ([] (auto && arg) {
|
||||||
|
++arg;
|
||||||
|
},
|
||||||
|
internals);
|
||||||
|
update ();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto iterator::operator-- () -> iterator &
|
||||||
|
{
|
||||||
|
std::visit ([] (auto && arg) {
|
||||||
|
--arg;
|
||||||
|
},
|
||||||
|
internals);
|
||||||
|
update ();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto iterator::operator->() const -> const_pointer
|
||||||
|
{
|
||||||
|
release_assert (!is_end ());
|
||||||
|
return std::get_if<value_type> (¤t);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto iterator::operator* () const -> const_reference
|
||||||
|
{
|
||||||
|
release_assert (!is_end ());
|
||||||
|
return std::get<value_type> (current);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto iterator::operator== (iterator const & other) const -> bool
|
||||||
|
{
|
||||||
|
return internals == other.internals;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool iterator::is_end () const
|
||||||
|
{
|
||||||
|
return std::holds_alternative<std::monostate> (current);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,69 +1,57 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <nano/store/iterator_impl.hpp>
|
#include <nano/store/lmdb/iterator.hpp>
|
||||||
|
#include <nano/store/rocksdb/iterator.hpp>
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <iterator>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <span>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
namespace nano::store
|
namespace nano::store
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Iterates the key/value pairs of a transaction
|
* @class iterator
|
||||||
|
* @brief A generic database iterator for LMDB or RocksDB.
|
||||||
|
*
|
||||||
|
* This class represents an iterator for either LMDB or RocksDB (Persistent Key-Value Store) databases.
|
||||||
|
* It is a circular iterator, meaning that the end() sentinel value is always in the iteration cycle.
|
||||||
|
*
|
||||||
|
* Key characteristics:
|
||||||
|
* - Decrementing the end iterator points to the last key in the database.
|
||||||
|
* - Incrementing the end iterator points to the first key in the database.
|
||||||
|
* - Internally uses either an LMDB or RocksDB iterator, abstracted through a std::variant.
|
||||||
*/
|
*/
|
||||||
template <typename T, typename U>
|
|
||||||
class iterator final
|
class iterator final
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
iterator (std::nullptr_t)
|
using iterator_category = std::bidirectional_iterator_tag;
|
||||||
{
|
using value_type = std::pair<std::span<uint8_t const>, std::span<uint8_t const>>;
|
||||||
}
|
using pointer = value_type *;
|
||||||
iterator (std::unique_ptr<iterator_impl<T, U>> impl_a) :
|
using const_pointer = value_type const *;
|
||||||
impl (std::move (impl_a))
|
using reference = value_type &;
|
||||||
{
|
using const_reference = value_type const &;
|
||||||
impl->fill (current);
|
|
||||||
}
|
|
||||||
iterator (iterator<T, U> && other_a) :
|
|
||||||
current (std::move (other_a.current)),
|
|
||||||
impl (std::move (other_a.impl))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
iterator<T, U> & operator++ ()
|
|
||||||
{
|
|
||||||
++*impl;
|
|
||||||
impl->fill (current);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
iterator<T, U> & operator-- ()
|
|
||||||
{
|
|
||||||
--*impl;
|
|
||||||
impl->fill (current);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
iterator<T, U> & operator= (iterator<T, U> && other_a) noexcept
|
|
||||||
{
|
|
||||||
impl = std::move (other_a.impl);
|
|
||||||
current = std::move (other_a.current);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
iterator<T, U> & operator= (iterator<T, U> const &) = delete;
|
|
||||||
std::pair<T, U> * operator->()
|
|
||||||
{
|
|
||||||
return ¤t;
|
|
||||||
}
|
|
||||||
std::pair<T, U> const & operator* () const
|
|
||||||
{
|
|
||||||
return current;
|
|
||||||
}
|
|
||||||
bool operator== (iterator<T, U> const & other_a) const
|
|
||||||
{
|
|
||||||
return (impl == nullptr && other_a.impl == nullptr) || (impl != nullptr && *impl == other_a.impl.get ()) || (other_a.impl != nullptr && *other_a.impl == impl.get ());
|
|
||||||
}
|
|
||||||
bool operator!= (iterator<T, U> const & other_a) const
|
|
||||||
{
|
|
||||||
return !(*this == other_a);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::pair<T, U> current;
|
std::variant<lmdb::iterator, rocksdb::iterator> internals;
|
||||||
std::unique_ptr<iterator_impl<T, U>> impl;
|
std::variant<std::monostate, value_type> current;
|
||||||
|
void update ();
|
||||||
|
|
||||||
|
public:
|
||||||
|
iterator (std::variant<lmdb::iterator, rocksdb::iterator> && internals) noexcept;
|
||||||
|
|
||||||
|
iterator (iterator const &) = delete;
|
||||||
|
auto operator= (iterator const &) -> iterator & = delete;
|
||||||
|
|
||||||
|
iterator (iterator && other) noexcept;
|
||||||
|
auto operator= (iterator && other) noexcept -> iterator &;
|
||||||
|
|
||||||
|
auto operator++ () -> iterator &;
|
||||||
|
auto operator-- () -> iterator &;
|
||||||
|
auto operator->() const -> const_pointer;
|
||||||
|
auto operator* () const -> const_reference;
|
||||||
|
auto operator== (iterator const & other) const -> bool;
|
||||||
|
bool is_end () const;
|
||||||
};
|
};
|
||||||
} // namespace nano::store
|
} // namespace nano::store
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
#include <nano/store/iterator_impl.hpp>
|
|
||||||
|
|
@ -1,43 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <nano/lib/utility.hpp>
|
|
||||||
#include <nano/store/transaction.hpp>
|
|
||||||
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
namespace nano::store
|
|
||||||
{
|
|
||||||
template <typename T, typename U>
|
|
||||||
class iterator_impl
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit iterator_impl (transaction const & transaction_a) :
|
|
||||||
txn{ transaction_a },
|
|
||||||
transaction_epoch{ transaction_a.epoch () }
|
|
||||||
{
|
|
||||||
}
|
|
||||||
virtual ~iterator_impl ()
|
|
||||||
{
|
|
||||||
debug_assert (transaction_epoch == txn.epoch (), "invalid iterator-transaction lifetime detected");
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual iterator_impl<T, U> & operator++ () = 0;
|
|
||||||
virtual iterator_impl<T, U> & operator-- () = 0;
|
|
||||||
virtual bool operator== (iterator_impl<T, U> const & other_a) const = 0;
|
|
||||||
virtual bool is_end_sentinal () const = 0;
|
|
||||||
virtual void fill (std::pair<T, U> &) const = 0;
|
|
||||||
iterator_impl<T, U> & operator= (iterator_impl<T, U> const &) = delete;
|
|
||||||
bool operator== (iterator_impl<T, U> const * other_a) const
|
|
||||||
{
|
|
||||||
return (other_a != nullptr && *this == *other_a) || (other_a == nullptr && is_end_sentinal ());
|
|
||||||
}
|
|
||||||
bool operator!= (iterator_impl<T, U> const & other_a) const
|
|
||||||
{
|
|
||||||
return !(*this == other_a);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
transaction const & txn;
|
|
||||||
transaction::epoch_t const transaction_epoch;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -45,22 +45,18 @@ 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
|
auto nano::store::lmdb::account::begin (store::transaction const & transaction, nano::account const & account) const -> iterator
|
||||||
{
|
{
|
||||||
return store.make_iterator<nano::account, nano::account_info> (transaction, tables::accounts, account);
|
lmdb::db_val val{ account };
|
||||||
|
return iterator{ store::iterator{ lmdb::iterator::lower_bound (store.env.tx (transaction), accounts_handle, val) } };
|
||||||
}
|
}
|
||||||
|
|
||||||
auto nano::store::lmdb::account::begin (store::transaction const & transaction) const -> iterator
|
auto nano::store::lmdb::account::begin (store::transaction const & transaction) const -> iterator
|
||||||
{
|
{
|
||||||
return store.make_iterator<nano::account, nano::account_info> (transaction, tables::accounts);
|
return iterator{ store::iterator{ lmdb::iterator::begin (store.env.tx (transaction), accounts_handle) } };
|
||||||
}
|
}
|
||||||
|
|
||||||
auto nano::store::lmdb::account::rbegin (store::transaction const & transaction_a) const -> iterator
|
auto nano::store::lmdb::account::end (store::transaction const & tx) const -> iterator
|
||||||
{
|
{
|
||||||
return store.make_iterator<nano::account, nano::account_info> (transaction_a, tables::accounts, false);
|
return iterator{ store::iterator{ lmdb::iterator::end (store.env.tx (tx), accounts_handle) } };
|
||||||
}
|
|
||||||
|
|
||||||
auto nano::store::lmdb::account::end (store::transaction const & transaction_a) const -> iterator
|
|
||||||
{
|
|
||||||
return iterator{ nullptr };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void nano::store::lmdb::account::for_each_par (std::function<void (store::read_transaction const &, iterator, iterator)> const & action_a) const
|
void nano::store::lmdb::account::for_each_par (std::function<void (store::read_transaction const &, iterator, iterator)> const & action_a) const
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@ public:
|
||||||
size_t count (store::transaction const & transaction_a) override;
|
size_t count (store::transaction const & transaction_a) override;
|
||||||
iterator begin (store::transaction const & transaction_a, nano::account const & account_a) const override;
|
iterator begin (store::transaction const & transaction_a, nano::account const & account_a) const override;
|
||||||
iterator begin (store::transaction const & transaction_a) const override;
|
iterator begin (store::transaction const & transaction_a) const override;
|
||||||
iterator rbegin (store::transaction const & transaction_a) const override;
|
|
||||||
iterator end (store::transaction const & transaction_a) const override;
|
iterator end (store::transaction const & transaction_a) const override;
|
||||||
void for_each_par (std::function<void (store::read_transaction const &, iterator, iterator)> const & action_a) const override;
|
void for_each_par (std::function<void (store::read_transaction const &, iterator, iterator)> const & action_a) const override;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -137,17 +137,18 @@ uint64_t nano::store::lmdb::block::count (store::transaction const & transaction
|
||||||
|
|
||||||
auto nano::store::lmdb::block::begin (store::transaction const & transaction) const -> iterator
|
auto nano::store::lmdb::block::begin (store::transaction const & transaction) const -> iterator
|
||||||
{
|
{
|
||||||
return store.make_iterator<nano::block_hash, nano::store::block_w_sideband> (transaction, tables::blocks);
|
return iterator{ store::iterator{ lmdb::iterator::begin (store.env.tx (transaction), blocks_handle) } };
|
||||||
}
|
}
|
||||||
|
|
||||||
auto nano::store::lmdb::block::begin (store::transaction const & transaction, nano::block_hash const & hash) const -> iterator
|
auto nano::store::lmdb::block::begin (store::transaction const & transaction, nano::block_hash const & hash) const -> iterator
|
||||||
{
|
{
|
||||||
return store.make_iterator<nano::block_hash, nano::store::block_w_sideband> (transaction, tables::blocks, hash);
|
lmdb::db_val val{ hash };
|
||||||
|
return iterator{ store::iterator{ lmdb::iterator::lower_bound (store.env.tx (transaction), blocks_handle, val) } };
|
||||||
}
|
}
|
||||||
|
|
||||||
auto nano::store::lmdb::block::end (store::transaction const & transaction_a) const -> iterator
|
auto nano::store::lmdb::block::end (store::transaction const & transaction_a) const -> iterator
|
||||||
{
|
{
|
||||||
return iterator{ nullptr };
|
return iterator{ store::iterator{ lmdb::iterator::end (store.env.tx (transaction_a), blocks_handle) } };
|
||||||
}
|
}
|
||||||
|
|
||||||
void nano::store::lmdb::block::for_each_par (std::function<void (store::read_transaction const &, iterator, iterator)> const & action_a) const
|
void nano::store::lmdb::block::for_each_par (std::function<void (store::read_transaction const &, iterator, iterator)> const & action_a) const
|
||||||
|
|
|
||||||
|
|
@ -61,17 +61,18 @@ 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
|
auto nano::store::lmdb::confirmation_height::begin (store::transaction const & transaction, nano::account const & account) const -> iterator
|
||||||
{
|
{
|
||||||
return store.make_iterator<nano::account, nano::confirmation_height_info> (transaction, tables::confirmation_height, account);
|
lmdb::db_val val{ account };
|
||||||
|
return iterator{ store::iterator{ lmdb::iterator::lower_bound (store.env.tx (transaction), confirmation_height_handle, val) } };
|
||||||
}
|
}
|
||||||
|
|
||||||
auto nano::store::lmdb::confirmation_height::begin (store::transaction const & transaction) const -> iterator
|
auto nano::store::lmdb::confirmation_height::begin (store::transaction const & transaction) const -> iterator
|
||||||
{
|
{
|
||||||
return store.make_iterator<nano::account, nano::confirmation_height_info> (transaction, tables::confirmation_height);
|
return iterator{ store::iterator{ lmdb::iterator::begin (store.env.tx (transaction), confirmation_height_handle) } };
|
||||||
}
|
}
|
||||||
|
|
||||||
auto nano::store::lmdb::confirmation_height::end (store::transaction const & transaction_a) const -> iterator
|
auto nano::store::lmdb::confirmation_height::end (store::transaction const & transaction_a) const -> iterator
|
||||||
{
|
{
|
||||||
return iterator{ nullptr };
|
return iterator{ store::iterator{ lmdb::iterator::end (store.env.tx (transaction_a), confirmation_height_handle) } };
|
||||||
}
|
}
|
||||||
|
|
||||||
void nano::store::lmdb::confirmation_height::for_each_par (std::function<void (store::read_transaction const &, iterator, iterator)> const & action_a) const
|
void nano::store::lmdb::confirmation_height::for_each_par (std::function<void (store::read_transaction const &, iterator, iterator)> const & action_a) const
|
||||||
|
|
|
||||||
|
|
@ -66,17 +66,18 @@ 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
|
auto nano::store::lmdb::final_vote::begin (store::transaction const & transaction, nano::qualified_root const & root) const -> iterator
|
||||||
{
|
{
|
||||||
return store.make_iterator<nano::qualified_root, nano::block_hash> (transaction, tables::final_votes, root);
|
lmdb::db_val val{ root };
|
||||||
|
return iterator{ store::iterator{ lmdb::iterator::lower_bound (store.env.tx (transaction), final_votes_handle, val) } };
|
||||||
}
|
}
|
||||||
|
|
||||||
auto nano::store::lmdb::final_vote::begin (store::transaction const & transaction) const -> iterator
|
auto nano::store::lmdb::final_vote::begin (store::transaction const & transaction) const -> iterator
|
||||||
{
|
{
|
||||||
return store.make_iterator<nano::qualified_root, nano::block_hash> (transaction, tables::final_votes);
|
return iterator{ store::iterator{ lmdb::iterator::begin (store.env.tx (transaction), final_votes_handle) } };
|
||||||
}
|
}
|
||||||
|
|
||||||
auto nano::store::lmdb::final_vote::end (store::transaction const & transaction_a) const -> iterator
|
auto nano::store::lmdb::final_vote::end (store::transaction const & transaction_a) const -> iterator
|
||||||
{
|
{
|
||||||
return iterator{ nullptr };
|
return iterator{ store::iterator{ lmdb::iterator::end (store.env.tx (transaction_a), final_votes_handle) } };
|
||||||
}
|
}
|
||||||
|
|
||||||
void nano::store::lmdb::final_vote::for_each_par (std::function<void (store::read_transaction const &, iterator, iterator)> const & action_a) const
|
void nano::store::lmdb::final_vote::for_each_par (std::function<void (store::read_transaction const &, iterator, iterator)> const & action_a) const
|
||||||
|
|
|
||||||
133
nano/store/lmdb/iterator.cpp
Normal file
133
nano/store/lmdb/iterator.cpp
Normal file
|
|
@ -0,0 +1,133 @@
|
||||||
|
#include <nano/lib/utility.hpp>
|
||||||
|
#include <nano/store/lmdb/iterator.hpp>
|
||||||
|
|
||||||
|
namespace nano::store::lmdb
|
||||||
|
{
|
||||||
|
auto iterator::span () const -> std::pair<std::span<uint8_t const>, std::span<uint8_t const>>
|
||||||
|
{
|
||||||
|
auto & current = operator* ();
|
||||||
|
std::span<uint8_t const> key{ reinterpret_cast<uint8_t const *> (current.first.mv_data), current.first.mv_size };
|
||||||
|
std::span<uint8_t const> value{ reinterpret_cast<uint8_t const *> (current.second.mv_data), current.second.mv_size };
|
||||||
|
return std::make_pair (key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto iterator::is_end () const -> bool
|
||||||
|
{
|
||||||
|
return std::holds_alternative<std::monostate> (current);
|
||||||
|
}
|
||||||
|
|
||||||
|
void iterator::update (int status)
|
||||||
|
{
|
||||||
|
if (status == MDB_SUCCESS)
|
||||||
|
{
|
||||||
|
value_type init;
|
||||||
|
auto status = mdb_cursor_get (cursor, &init.first, &init.second, MDB_GET_CURRENT);
|
||||||
|
release_assert (status == MDB_SUCCESS);
|
||||||
|
current = init;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
current = std::monostate{};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator::iterator (MDB_txn * tx, MDB_dbi dbi) noexcept
|
||||||
|
{
|
||||||
|
auto open_status = mdb_cursor_open (tx, dbi, &cursor);
|
||||||
|
release_assert (open_status == MDB_SUCCESS);
|
||||||
|
this->current = std::monostate{};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto iterator::begin (MDB_txn * tx, MDB_dbi dbi) -> iterator
|
||||||
|
{
|
||||||
|
iterator result{ tx, dbi };
|
||||||
|
++result;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto iterator::end (MDB_txn * tx, MDB_dbi dbi) -> iterator
|
||||||
|
{
|
||||||
|
return iterator{ tx, dbi };
|
||||||
|
}
|
||||||
|
|
||||||
|
auto iterator::lower_bound (MDB_txn * tx, MDB_dbi dbi, MDB_val const & lower_bound) -> iterator
|
||||||
|
{
|
||||||
|
iterator result{ tx, dbi };
|
||||||
|
auto status = mdb_cursor_get (result.cursor, const_cast<MDB_val *> (&lower_bound), nullptr, MDB_SET_RANGE);
|
||||||
|
result.update (status);
|
||||||
|
return std::move (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator::iterator (iterator && other) noexcept
|
||||||
|
{
|
||||||
|
*this = std::move (other);
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator::~iterator ()
|
||||||
|
{
|
||||||
|
if (cursor)
|
||||||
|
{
|
||||||
|
mdb_cursor_close (cursor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto iterator::operator= (iterator && other) noexcept -> iterator &
|
||||||
|
{
|
||||||
|
cursor = other.cursor;
|
||||||
|
other.cursor = nullptr;
|
||||||
|
current = other.current;
|
||||||
|
other.current = std::monostate{};
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto iterator::operator++ () -> iterator &
|
||||||
|
{
|
||||||
|
auto operation = is_end () ? MDB_FIRST : MDB_NEXT;
|
||||||
|
auto status = mdb_cursor_get (cursor, nullptr, nullptr, operation);
|
||||||
|
release_assert (status == MDB_SUCCESS || status == MDB_NOTFOUND);
|
||||||
|
update (status);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto iterator::operator-- () -> iterator &
|
||||||
|
{
|
||||||
|
auto operation = is_end () ? MDB_LAST : MDB_PREV;
|
||||||
|
auto status = mdb_cursor_get (cursor, nullptr, nullptr, operation);
|
||||||
|
release_assert (status == MDB_SUCCESS || status == MDB_NOTFOUND);
|
||||||
|
update (status);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto iterator::operator->() const -> const_pointer
|
||||||
|
{
|
||||||
|
release_assert (!is_end ());
|
||||||
|
return std::get_if<value_type> (¤t);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto iterator::operator* () const -> const_reference
|
||||||
|
{
|
||||||
|
release_assert (!is_end ());
|
||||||
|
return std::get<value_type> (current);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto iterator::operator== (iterator const & other) const -> bool
|
||||||
|
{
|
||||||
|
if (is_end () != other.is_end ())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (is_end ())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
auto & lhs = std::get<value_type> (current);
|
||||||
|
auto & rhs = std::get<value_type> (other.current);
|
||||||
|
auto result = lhs.first.mv_data == rhs.first.mv_data;
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
debug_assert (std::make_pair (lhs.first.mv_data, lhs.first.mv_size) == std::make_pair (rhs.first.mv_data, rhs.first.mv_size) && std::make_pair (lhs.second.mv_data, lhs.second.mv_size) == std::make_pair (rhs.second.mv_data, rhs.second.mv_size));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
} // namespace nano::store::lmdb
|
||||||
|
|
@ -1,310 +1,58 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <nano/store/component.hpp>
|
#include <iterator>
|
||||||
#include <nano/store/db_val.hpp>
|
#include <span>
|
||||||
#include <nano/store/iterator.hpp>
|
#include <utility>
|
||||||
#include <nano/store/lmdb/lmdb_env.hpp>
|
#include <variant>
|
||||||
#include <nano/store/transaction.hpp>
|
|
||||||
|
|
||||||
#include <lmdb/libraries/liblmdb/lmdb.h>
|
#include <lmdb/libraries/liblmdb/lmdb.h>
|
||||||
|
|
||||||
namespace nano::store::lmdb
|
namespace nano::store::lmdb
|
||||||
{
|
{
|
||||||
template <typename T, typename U>
|
|
||||||
class iterator : public iterator_impl<T, U>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
iterator (transaction const & transaction_a, env const & env_a, MDB_dbi db_a, MDB_val const & val_a = MDB_val{}, bool const direction_asc = true) :
|
|
||||||
iterator_impl<T, U> (transaction_a)
|
|
||||||
{
|
|
||||||
auto status (mdb_cursor_open (env_a.tx (transaction_a), db_a, &cursor));
|
|
||||||
release_assert (status == 0);
|
|
||||||
auto operation (MDB_SET_RANGE);
|
|
||||||
if (val_a.mv_size != 0)
|
|
||||||
{
|
|
||||||
current.first = val_a;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
operation = direction_asc ? MDB_FIRST : MDB_LAST;
|
|
||||||
}
|
|
||||||
auto status2 (mdb_cursor_get (cursor, ¤t.first.value, ¤t.second.value, operation));
|
|
||||||
release_assert (status2 == 0 || status2 == MDB_NOTFOUND);
|
|
||||||
if (status2 != MDB_NOTFOUND)
|
|
||||||
{
|
|
||||||
auto status3 (mdb_cursor_get (cursor, ¤t.first.value, ¤t.second.value, MDB_GET_CURRENT));
|
|
||||||
release_assert (status3 == 0 || status3 == MDB_NOTFOUND);
|
|
||||||
if (current.first.size () != sizeof (T))
|
|
||||||
{
|
|
||||||
clear ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
clear ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
iterator () = default;
|
|
||||||
|
|
||||||
iterator (iterator<T, U> && other_a)
|
|
||||||
{
|
|
||||||
cursor = other_a.cursor;
|
|
||||||
other_a.cursor = nullptr;
|
|
||||||
current = other_a.current;
|
|
||||||
}
|
|
||||||
|
|
||||||
iterator (iterator<T, U> const &) = delete;
|
|
||||||
|
|
||||||
~iterator ()
|
|
||||||
{
|
|
||||||
if (cursor != nullptr)
|
|
||||||
{
|
|
||||||
mdb_cursor_close (cursor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
iterator_impl<T, U> & operator++ () override
|
|
||||||
{
|
|
||||||
debug_assert (cursor != nullptr);
|
|
||||||
auto status (mdb_cursor_get (cursor, ¤t.first.value, ¤t.second.value, MDB_NEXT));
|
|
||||||
release_assert (status == 0 || status == MDB_NOTFOUND);
|
|
||||||
if (status == MDB_NOTFOUND)
|
|
||||||
{
|
|
||||||
clear ();
|
|
||||||
}
|
|
||||||
if (current.first.size () != sizeof (T))
|
|
||||||
{
|
|
||||||
clear ();
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
iterator_impl<T, U> & operator-- () override
|
|
||||||
{
|
|
||||||
debug_assert (cursor != nullptr);
|
|
||||||
auto status (mdb_cursor_get (cursor, ¤t.first.value, ¤t.second.value, MDB_PREV));
|
|
||||||
release_assert (status == 0 || status == MDB_NOTFOUND);
|
|
||||||
if (status == MDB_NOTFOUND)
|
|
||||||
{
|
|
||||||
clear ();
|
|
||||||
}
|
|
||||||
if (current.first.size () != sizeof (T))
|
|
||||||
{
|
|
||||||
clear ();
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<store::db_val<MDB_val>, store::db_val<MDB_val>> * operator->()
|
|
||||||
{
|
|
||||||
return ¤t;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator== (iterator<T, U> const & base_a) const
|
|
||||||
{
|
|
||||||
auto const other_a (boost::polymorphic_downcast<iterator<T, U> const *> (&base_a));
|
|
||||||
auto result (current.first.data () == other_a->current.first.data ());
|
|
||||||
debug_assert (!result || (current.first.size () == other_a->current.first.size ()));
|
|
||||||
debug_assert (!result || (current.second.data () == other_a->current.second.data ()));
|
|
||||||
debug_assert (!result || (current.second.size () == other_a->current.second.size ()));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator== (iterator_impl<T, U> const & base_a) const override
|
|
||||||
{
|
|
||||||
auto const other_a (boost::polymorphic_downcast<iterator<T, U> const *> (&base_a));
|
|
||||||
auto result (current.first.data () == other_a->current.first.data ());
|
|
||||||
debug_assert (!result || (current.first.size () == other_a->current.first.size ()));
|
|
||||||
debug_assert (!result || (current.second.data () == other_a->current.second.data ()));
|
|
||||||
debug_assert (!result || (current.second.size () == other_a->current.second.size ()));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_end_sentinal () const override
|
|
||||||
{
|
|
||||||
return current.first.size () == 0;
|
|
||||||
}
|
|
||||||
void fill (std::pair<T, U> & value_a) const override
|
|
||||||
{
|
|
||||||
if (current.first.size () != 0)
|
|
||||||
{
|
|
||||||
value_a.first = static_cast<T> (current.first);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
value_a.first = T ();
|
|
||||||
}
|
|
||||||
if (current.second.size () != 0)
|
|
||||||
{
|
|
||||||
value_a.second = static_cast<U> (current.second);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
value_a.second = U ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void clear ()
|
|
||||||
{
|
|
||||||
current.first = store::db_val<MDB_val> ();
|
|
||||||
current.second = store::db_val<MDB_val> ();
|
|
||||||
debug_assert (is_end_sentinal ());
|
|
||||||
}
|
|
||||||
|
|
||||||
iterator<T, U> & operator= (iterator<T, U> && other_a)
|
|
||||||
{
|
|
||||||
if (cursor != nullptr)
|
|
||||||
{
|
|
||||||
mdb_cursor_close (cursor);
|
|
||||||
}
|
|
||||||
cursor = other_a.cursor;
|
|
||||||
other_a.cursor = nullptr;
|
|
||||||
current = other_a.current;
|
|
||||||
other_a.clear ();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
iterator_impl<T, U> & operator= (iterator_impl<T, U> const &) = delete;
|
|
||||||
MDB_cursor * cursor{ nullptr };
|
|
||||||
std::pair<store::db_val<MDB_val>, store::db_val<MDB_val>> current;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Iterates the key/value pairs of two stores merged together
|
* @class iterator
|
||||||
|
* @brief An LMDB database iterator.
|
||||||
|
*
|
||||||
|
* This class represents an iterator for LMDB (Lightning Memory-Mapped Database) databases.
|
||||||
|
* It is a circular iterator, meaning that the end() sentinel value is always in the iteration cycle.
|
||||||
|
*
|
||||||
|
* Key characteristics:
|
||||||
|
* - Decrementing the end iterator points to the last key in the database.
|
||||||
|
* - Incrementing the end iterator points to the first key in the database.
|
||||||
*/
|
*/
|
||||||
template <typename T, typename U>
|
class iterator
|
||||||
class merge_iterator : public iterator_impl<T, U>
|
|
||||||
{
|
{
|
||||||
|
MDB_cursor * cursor{ nullptr };
|
||||||
|
std::variant<std::monostate, std::pair<MDB_val, MDB_val>> current;
|
||||||
|
void update (int status);
|
||||||
|
iterator (MDB_txn * tx, MDB_dbi dbi) noexcept;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
merge_iterator (transaction const & transaction_a, MDB_dbi db1_a, MDB_dbi db2_a) :
|
using iterator_category = std::bidirectional_iterator_tag;
|
||||||
impl1 (std::make_unique<iterator<T, U>> (transaction_a, db1_a)),
|
using value_type = std::pair<MDB_val, MDB_val>;
|
||||||
impl2 (std::make_unique<iterator<T, U>> (transaction_a, db2_a))
|
using pointer = value_type *;
|
||||||
{
|
using const_pointer = value_type const *;
|
||||||
}
|
using reference = value_type &;
|
||||||
|
using const_reference = value_type const &;
|
||||||
|
|
||||||
merge_iterator () :
|
static auto begin (MDB_txn * tx, MDB_dbi dbi) -> iterator;
|
||||||
impl1 (std::make_unique<iterator<T, U>> ()),
|
static auto end (MDB_txn * tx, MDB_dbi dbi) -> iterator;
|
||||||
impl2 (std::make_unique<iterator<T, U>> ())
|
static auto lower_bound (MDB_txn * tx, MDB_dbi dbi, MDB_val const & lower_bound) -> iterator;
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
merge_iterator (transaction const & transaction_a, MDB_dbi db1_a, MDB_dbi db2_a, MDB_val const & val_a) :
|
~iterator ();
|
||||||
impl1 (std::make_unique<iterator<T, U>> (transaction_a, db1_a, val_a)),
|
|
||||||
impl2 (std::make_unique<iterator<T, U>> (transaction_a, db2_a, val_a))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
merge_iterator (merge_iterator<T, U> && other_a)
|
iterator (iterator const &) = delete;
|
||||||
{
|
auto operator= (iterator const &) -> iterator & = delete;
|
||||||
impl1 = std::move (other_a.impl1);
|
|
||||||
impl2 = std::move (other_a.impl2);
|
|
||||||
}
|
|
||||||
|
|
||||||
merge_iterator (merge_iterator<T, U> const &) = delete;
|
iterator (iterator && other_a) noexcept;
|
||||||
|
auto operator= (iterator && other) noexcept -> iterator &;
|
||||||
|
|
||||||
iterator_impl<T, U> & operator++ () override
|
auto operator++ () -> iterator &;
|
||||||
{
|
auto operator-- () -> iterator &;
|
||||||
++least_iterator ();
|
auto operator->() const -> const_pointer;
|
||||||
return *this;
|
auto operator* () const -> const_reference;
|
||||||
}
|
auto operator== (iterator const & other) const -> bool;
|
||||||
|
auto span () const -> std::pair<std::span<uint8_t const>, std::span<uint8_t const>>;
|
||||||
iterator_impl<T, U> & operator-- () override
|
bool is_end () const;
|
||||||
{
|
|
||||||
--least_iterator ();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<store::db_val<MDB_val>, store::db_val<MDB_val>> * operator->()
|
|
||||||
{
|
|
||||||
return least_iterator ().operator->();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator== (merge_iterator<T, U> const & other) const
|
|
||||||
{
|
|
||||||
return *impl1 == *other.impl1 && *impl2 == *other.impl2;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator!= (merge_iterator<T, U> const & base_a) const
|
|
||||||
{
|
|
||||||
return !(*this == base_a);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator== (iterator_impl<T, U> const & base_a) const override
|
|
||||||
{
|
|
||||||
debug_assert ((dynamic_cast<merge_iterator<T, U> const *> (&base_a) != nullptr) && "Incompatible iterator comparison");
|
|
||||||
auto & other (static_cast<merge_iterator<T, U> const &> (base_a));
|
|
||||||
return *this == other;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_end_sentinal () const override
|
|
||||||
{
|
|
||||||
return least_iterator ().is_end_sentinal ();
|
|
||||||
}
|
|
||||||
|
|
||||||
void fill (std::pair<T, U> & value_a) const override
|
|
||||||
{
|
|
||||||
auto & current (least_iterator ());
|
|
||||||
if (current->first.size () != 0)
|
|
||||||
{
|
|
||||||
value_a.first = static_cast<T> (current->first);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
value_a.first = T ();
|
|
||||||
}
|
|
||||||
if (current->second.size () != 0)
|
|
||||||
{
|
|
||||||
value_a.second = static_cast<U> (current->second);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
value_a.second = U ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
merge_iterator<T, U> & operator= (merge_iterator<T, U> &&) = default;
|
|
||||||
merge_iterator<T, U> & operator= (merge_iterator<T, U> const &) = delete;
|
|
||||||
|
|
||||||
mutable bool from_first_database{ false };
|
|
||||||
|
|
||||||
private:
|
|
||||||
iterator<T, U> & least_iterator () const
|
|
||||||
{
|
|
||||||
iterator<T, U> * result;
|
|
||||||
if (impl1->is_end_sentinal ())
|
|
||||||
{
|
|
||||||
result = impl2.get ();
|
|
||||||
from_first_database = false;
|
|
||||||
}
|
|
||||||
else if (impl2->is_end_sentinal ())
|
|
||||||
{
|
|
||||||
result = impl1.get ();
|
|
||||||
from_first_database = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto key_cmp (mdb_cmp (mdb_cursor_txn (impl1->cursor), mdb_cursor_dbi (impl1->cursor), impl1->current.first, impl2->current.first));
|
|
||||||
|
|
||||||
if (key_cmp < 0)
|
|
||||||
{
|
|
||||||
result = impl1.get ();
|
|
||||||
from_first_database = true;
|
|
||||||
}
|
|
||||||
else if (key_cmp > 0)
|
|
||||||
{
|
|
||||||
result = impl2.get ();
|
|
||||||
from_first_database = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto val_cmp (mdb_cmp (mdb_cursor_txn (impl1->cursor), mdb_cursor_dbi (impl1->cursor), impl1->current.second, impl2->current.second));
|
|
||||||
result = val_cmp < 0 ? impl1.get () : impl2.get ();
|
|
||||||
from_first_database = (result == impl1.get ());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return *result;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<iterator<T, U>> impl1;
|
|
||||||
std::unique_ptr<iterator<T, U>> impl2;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
#include <nano/store/lmdb/iterator.hpp>
|
#include <nano/store/lmdb/iterator.hpp>
|
||||||
#include <nano/store/lmdb/lmdb.hpp>
|
#include <nano/store/lmdb/lmdb.hpp>
|
||||||
#include <nano/store/lmdb/wallet_value.hpp>
|
#include <nano/store/lmdb/wallet_value.hpp>
|
||||||
|
#include <nano/store/typed_iterator_templ.hpp>
|
||||||
#include <nano/store/version.hpp>
|
#include <nano/store/version.hpp>
|
||||||
#include <nano/store/versioning.hpp>
|
#include <nano/store/versioning.hpp>
|
||||||
|
|
||||||
|
|
@ -14,6 +15,8 @@
|
||||||
|
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
|
template class nano::store::typed_iterator<nano::account, nano::account_info_v22>;
|
||||||
|
|
||||||
nano::store::lmdb::component::component (nano::logger & logger_a, std::filesystem::path const & path_a, nano::ledger_constants & constants, nano::txn_tracking_config const & txn_tracking_config_a, std::chrono::milliseconds block_processor_batch_max_time_a, nano::lmdb_config const & lmdb_config_a, bool backup_before_upgrade_a) :
|
nano::store::lmdb::component::component (nano::logger & logger_a, std::filesystem::path const & path_a, nano::ledger_constants & constants, nano::txn_tracking_config const & txn_tracking_config_a, std::chrono::milliseconds block_processor_batch_max_time_a, nano::lmdb_config const & lmdb_config_a, bool backup_before_upgrade_a) :
|
||||||
// clang-format off
|
// clang-format off
|
||||||
nano::store::component{
|
nano::store::component{
|
||||||
|
|
@ -264,8 +267,8 @@ void nano::store::lmdb::component::upgrade_v22_to_v23 (store::write_transaction
|
||||||
auto transaction = tx_begin_read ();
|
auto transaction = tx_begin_read ();
|
||||||
|
|
||||||
// Manually create v22 compatible iterator to read accounts
|
// Manually create v22 compatible iterator to read accounts
|
||||||
auto it = make_iterator<nano::account, nano::account_info_v22> (transaction, tables::accounts);
|
auto it = typed_iterator<nano::account, nano::account_info_v22>{ store::iterator{ iterator::begin (env.tx (transaction), account_store.accounts_handle) } };
|
||||||
auto const end = store::iterator<nano::account, nano::account_info_v22> (nullptr);
|
auto const end = typed_iterator<nano::account, nano::account_info_v22>{ store::iterator{ iterator::end (env.tx (transaction), account_store.accounts_handle) } };
|
||||||
|
|
||||||
for (; it != end; ++it)
|
for (; it != end; ++it)
|
||||||
{
|
{
|
||||||
|
|
@ -457,7 +460,7 @@ void nano::store::lmdb::component::rebuild_db (store::write_transaction const &
|
||||||
MDB_dbi temp;
|
MDB_dbi temp;
|
||||||
mdb_dbi_open (env.tx (transaction_a), "temp_table", MDB_CREATE, &temp);
|
mdb_dbi_open (env.tx (transaction_a), "temp_table", MDB_CREATE, &temp);
|
||||||
// Copy all values to temporary table
|
// Copy all values to temporary table
|
||||||
for (auto i (store::iterator<nano::uint256_union, nano::store::lmdb::db_val> (std::make_unique<nano::store::lmdb::iterator<nano::uint256_union, nano::store::lmdb::db_val>> (transaction_a, env, table))), n (store::iterator<nano::uint256_union, nano::store::lmdb::db_val> (nullptr)); i != n; ++i)
|
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);
|
auto s = mdb_put (env.tx (transaction_a), temp, nano::store::lmdb::db_val (i->first), i->second, MDB_APPEND);
|
||||||
release_assert_success (s);
|
release_assert_success (s);
|
||||||
|
|
@ -466,7 +469,7 @@ void nano::store::lmdb::component::rebuild_db (store::write_transaction const &
|
||||||
// Clear existing table
|
// Clear existing table
|
||||||
mdb_drop (env.tx (transaction_a), table, 0);
|
mdb_drop (env.tx (transaction_a), table, 0);
|
||||||
// Put values from copy
|
// Put values from copy
|
||||||
for (auto i (store::iterator<nano::uint256_union, nano::store::lmdb::db_val> (std::make_unique<nano::store::lmdb::iterator<nano::uint256_union, nano::store::lmdb::db_val>> (transaction_a, env, temp))), n (store::iterator<nano::uint256_union, nano::store::lmdb::db_val> (nullptr)); i != n; ++i)
|
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);
|
auto s = mdb_put (env.tx (transaction_a), table, nano::store::lmdb::db_val (i->first), i->second, MDB_APPEND);
|
||||||
release_assert_success (s);
|
release_assert_success (s);
|
||||||
|
|
@ -480,7 +483,7 @@ void nano::store::lmdb::component::rebuild_db (store::write_transaction const &
|
||||||
MDB_dbi temp;
|
MDB_dbi temp;
|
||||||
mdb_dbi_open (env.tx (transaction_a), "temp_table", MDB_CREATE, &temp);
|
mdb_dbi_open (env.tx (transaction_a), "temp_table", MDB_CREATE, &temp);
|
||||||
// Copy all values to temporary table
|
// Copy all values to temporary table
|
||||||
for (auto i (store::iterator<nano::pending_key, nano::pending_info> (std::make_unique<nano::store::lmdb::iterator<nano::pending_key, nano::pending_info>> (transaction_a, env, pending_store.pending_handle))), n (store::iterator<nano::pending_key, nano::pending_info> (nullptr)); i != n; ++i)
|
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);
|
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);
|
||||||
release_assert_success (s);
|
release_assert_success (s);
|
||||||
|
|
@ -488,7 +491,7 @@ void nano::store::lmdb::component::rebuild_db (store::write_transaction const &
|
||||||
release_assert (count (transaction_a, pending_store.pending_handle) == count (transaction_a, temp));
|
release_assert (count (transaction_a, pending_store.pending_handle) == count (transaction_a, temp));
|
||||||
mdb_drop (env.tx (transaction_a), pending_store.pending_handle, 0);
|
mdb_drop (env.tx (transaction_a), pending_store.pending_handle, 0);
|
||||||
// Put values from copy
|
// Put values from copy
|
||||||
for (auto i (store::iterator<nano::pending_key, nano::pending_info> (std::make_unique<nano::store::lmdb::iterator<nano::pending_key, nano::pending_info>> (transaction_a, env, temp))), n (store::iterator<nano::pending_key, nano::pending_info> (nullptr)); i != n; ++i)
|
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);
|
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);
|
||||||
release_assert_success (s);
|
release_assert_success (s);
|
||||||
|
|
|
||||||
|
|
@ -93,18 +93,6 @@ public:
|
||||||
bool copy_db (std::filesystem::path const & destination_file) override;
|
bool copy_db (std::filesystem::path const & destination_file) override;
|
||||||
void rebuild_db (store::write_transaction const & transaction_a) override;
|
void rebuild_db (store::write_transaction const & transaction_a) override;
|
||||||
|
|
||||||
template <typename Key, typename Value>
|
|
||||||
store::iterator<Key, Value> make_iterator (store::transaction const & transaction_a, tables table_a, bool const direction_asc = true) const
|
|
||||||
{
|
|
||||||
return store::iterator<Key, Value> (std::make_unique<nano::store::lmdb::iterator<Key, Value>> (transaction_a, env, table_to_dbi (table_a), nano::store::lmdb::db_val{}, direction_asc));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Key, typename Value>
|
|
||||||
store::iterator<Key, Value> make_iterator (store::transaction const & transaction_a, tables table_a, nano::store::lmdb::db_val const & key) const
|
|
||||||
{
|
|
||||||
return store::iterator<Key, Value> (std::make_unique<nano::store::lmdb::iterator<Key, Value>> (transaction_a, env, table_to_dbi (table_a), key));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool init_error () const override;
|
bool init_error () const override;
|
||||||
|
|
||||||
uint64_t count (store::transaction const &, MDB_dbi) const;
|
uint64_t count (store::transaction const &, MDB_dbi) const;
|
||||||
|
|
|
||||||
|
|
@ -20,17 +20,12 @@ void nano::store::lmdb::online_weight::del (store::write_transaction const & tra
|
||||||
|
|
||||||
auto nano::store::lmdb::online_weight::begin (store::transaction const & transaction) const -> iterator
|
auto nano::store::lmdb::online_weight::begin (store::transaction const & transaction) const -> iterator
|
||||||
{
|
{
|
||||||
return store.make_iterator<uint64_t, nano::amount> (transaction, tables::online_weight);
|
return iterator{ store::iterator{ lmdb::iterator::begin (store.env.tx (transaction), online_weight_handle) } };
|
||||||
}
|
|
||||||
|
|
||||||
auto nano::store::lmdb::online_weight::rbegin (store::transaction const & transaction) const -> iterator
|
|
||||||
{
|
|
||||||
return store.make_iterator<uint64_t, nano::amount> (transaction, tables::online_weight, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto nano::store::lmdb::online_weight::end (store::transaction const & transaction_a) const -> iterator
|
auto nano::store::lmdb::online_weight::end (store::transaction const & transaction_a) const -> iterator
|
||||||
{
|
{
|
||||||
return iterator{ nullptr };
|
return iterator{ store::iterator{ lmdb::iterator::end (store.env.tx (transaction_a), online_weight_handle) } };
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t nano::store::lmdb::online_weight::count (store::transaction const & transaction) const
|
size_t nano::store::lmdb::online_weight::count (store::transaction const & transaction) const
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,6 @@ public:
|
||||||
void put (store::write_transaction const & transaction_a, uint64_t time_a, nano::amount const & amount_a) override;
|
void put (store::write_transaction const & transaction_a, uint64_t time_a, nano::amount const & amount_a) override;
|
||||||
void del (store::write_transaction const & transaction_a, uint64_t time_a) override;
|
void del (store::write_transaction const & transaction_a, uint64_t time_a) override;
|
||||||
iterator begin (store::transaction const & transaction_a) const override;
|
iterator begin (store::transaction const & transaction_a) const override;
|
||||||
iterator rbegin (store::transaction const & transaction_a) const override;
|
|
||||||
iterator end (store::transaction const & transaction_a) const override;
|
iterator end (store::transaction const & transaction_a) const override;
|
||||||
size_t count (store::transaction const & transaction_a) const override;
|
size_t count (store::transaction const & transaction_a) const override;
|
||||||
void clear (store::write_transaction const & transaction_a) override;
|
void clear (store::write_transaction const & transaction_a) override;
|
||||||
|
|
|
||||||
|
|
@ -47,10 +47,10 @@ void nano::store::lmdb::peer::clear (store::write_transaction const & transactio
|
||||||
|
|
||||||
auto nano::store::lmdb::peer::begin (store::transaction const & transaction) const -> iterator
|
auto nano::store::lmdb::peer::begin (store::transaction const & transaction) const -> iterator
|
||||||
{
|
{
|
||||||
return store.make_iterator<nano::endpoint_key, nano::millis_t> (transaction, tables::peers);
|
return iterator{ store::iterator{ lmdb::iterator::begin (store.env.tx (transaction), peers_handle) } };
|
||||||
}
|
}
|
||||||
|
|
||||||
auto nano::store::lmdb::peer::end (store::transaction const & transaction_a) const -> iterator
|
auto nano::store::lmdb::peer::end (store::transaction const & transaction_a) const -> iterator
|
||||||
{
|
{
|
||||||
return iterator{ nullptr };
|
return iterator{ store::iterator{ lmdb::iterator::end (store.env.tx (transaction_a), peers_handle) } };
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -47,17 +47,18 @@ 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
|
auto nano::store::lmdb::pending::begin (store::transaction const & transaction_a, nano::pending_key const & key_a) const -> iterator
|
||||||
{
|
{
|
||||||
return store.make_iterator<nano::pending_key, nano::pending_info> (transaction_a, tables::pending, key_a);
|
lmdb::db_val val{ key_a };
|
||||||
|
return iterator{ store::iterator{ lmdb::iterator::lower_bound (store.env.tx (transaction_a), pending_handle, val) } };
|
||||||
}
|
}
|
||||||
|
|
||||||
auto nano::store::lmdb::pending::begin (store::transaction const & transaction_a) const -> iterator
|
auto nano::store::lmdb::pending::begin (store::transaction const & transaction_a) const -> iterator
|
||||||
{
|
{
|
||||||
return store.make_iterator<nano::pending_key, nano::pending_info> (transaction_a, tables::pending);
|
return iterator{ store::iterator{ lmdb::iterator::begin (store.env.tx (transaction_a), pending_handle) } };
|
||||||
}
|
}
|
||||||
|
|
||||||
auto nano::store::lmdb::pending::end (store::transaction const & transaction_a) const -> iterator
|
auto nano::store::lmdb::pending::end (store::transaction const & transaction_a) const -> iterator
|
||||||
{
|
{
|
||||||
return iterator{ nullptr };
|
return iterator{ store::iterator{ lmdb::iterator::end (store.env.tx (transaction_a), pending_handle) } };
|
||||||
}
|
}
|
||||||
|
|
||||||
void nano::store::lmdb::pending::for_each_par (std::function<void (store::read_transaction const &, iterator, iterator)> const & action_a) const
|
void nano::store::lmdb::pending::for_each_par (std::function<void (store::read_transaction const &, iterator, iterator)> const & action_a) const
|
||||||
|
|
|
||||||
|
|
@ -47,17 +47,18 @@ 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
|
auto nano::store::lmdb::pruned::begin (store::transaction const & transaction, nano::block_hash const & hash) const -> iterator
|
||||||
{
|
{
|
||||||
return store.make_iterator<nano::block_hash, std::nullptr_t> (transaction, tables::pruned, hash);
|
lmdb::db_val val{ hash };
|
||||||
|
return iterator{ store::iterator{ lmdb::iterator::lower_bound (store.env.tx (transaction), pruned_handle, val) } };
|
||||||
}
|
}
|
||||||
|
|
||||||
auto nano::store::lmdb::pruned::begin (store::transaction const & transaction) const -> iterator
|
auto nano::store::lmdb::pruned::begin (store::transaction const & transaction) const -> iterator
|
||||||
{
|
{
|
||||||
return store.make_iterator<nano::block_hash, std::nullptr_t> (transaction, tables::pruned);
|
return iterator{ store::iterator{ lmdb::iterator::begin (store.env.tx (transaction), pruned_handle) } };
|
||||||
}
|
}
|
||||||
|
|
||||||
auto nano::store::lmdb::pruned::end (store::transaction const & transaction_a) const -> iterator
|
auto nano::store::lmdb::pruned::end (store::transaction const & transaction_a) const -> iterator
|
||||||
{
|
{
|
||||||
return iterator{ nullptr };
|
return iterator{ store::iterator{ lmdb::iterator::end (store.env.tx (transaction_a), pruned_handle) } };
|
||||||
}
|
}
|
||||||
|
|
||||||
void nano::store::lmdb::pruned::for_each_par (std::function<void (store::read_transaction const &, iterator, iterator)> const & action_a) const
|
void nano::store::lmdb::pruned::for_each_par (std::function<void (store::read_transaction const &, iterator, iterator)> const & action_a) const
|
||||||
|
|
|
||||||
|
|
@ -45,17 +45,18 @@ 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
|
auto nano::store::lmdb::rep_weight::begin (store::transaction const & transaction_a, nano::account const & representative_a) const -> iterator
|
||||||
{
|
{
|
||||||
return store.make_iterator<nano::account, nano::uint128_union> (transaction_a, tables::rep_weights, representative_a);
|
lmdb::db_val val{ representative_a };
|
||||||
|
return iterator{ store::iterator{ lmdb::iterator::lower_bound (store.env.tx (transaction_a), rep_weights_handle, val) } };
|
||||||
}
|
}
|
||||||
|
|
||||||
auto nano::store::lmdb::rep_weight::begin (store::transaction const & transaction_a) const -> iterator
|
auto nano::store::lmdb::rep_weight::begin (store::transaction const & transaction_a) const -> iterator
|
||||||
{
|
{
|
||||||
return store.make_iterator<nano::account, nano::uint128_union> (transaction_a, tables::rep_weights);
|
return iterator{ store::iterator{ lmdb::iterator::begin (store.env.tx (transaction_a), rep_weights_handle) } };
|
||||||
}
|
}
|
||||||
|
|
||||||
auto nano::store::lmdb::rep_weight::end (store::transaction const & transaction_a) const -> iterator
|
auto nano::store::lmdb::rep_weight::end (store::transaction const & transaction_a) const -> iterator
|
||||||
{
|
{
|
||||||
return iterator{ nullptr };
|
return iterator{ store::iterator{ lmdb::iterator::end (store.env.tx (transaction_a), rep_weights_handle) } };
|
||||||
}
|
}
|
||||||
|
|
||||||
void nano::store::lmdb::rep_weight::for_each_par (std::function<void (store::read_transaction const &, iterator, iterator)> const & action_a) const
|
void nano::store::lmdb::rep_weight::for_each_par (std::function<void (store::read_transaction const &, iterator, iterator)> const & action_a) const
|
||||||
|
|
|
||||||
|
|
@ -1 +1,18 @@
|
||||||
#include <nano/store/online_weight.hpp>
|
#include <nano/store/online_weight.hpp>
|
||||||
|
#include <nano/store/reverse_iterator_templ.hpp>
|
||||||
|
#include <nano/store/typed_iterator_templ.hpp>
|
||||||
|
|
||||||
|
template class nano::store::typed_iterator<uint64_t, nano::amount>;
|
||||||
|
template class nano::store::reverse_iterator<nano::store::typed_iterator<uint64_t, nano::amount>>;
|
||||||
|
|
||||||
|
auto nano::store::online_weight::rbegin (store::transaction const & tx) const -> reverse_iterator
|
||||||
|
{
|
||||||
|
auto iter = end (tx);
|
||||||
|
--iter;
|
||||||
|
return reverse_iterator{ std::move (iter) };
|
||||||
|
}
|
||||||
|
|
||||||
|
auto nano::store::online_weight::rend (transaction const & tx) const -> reverse_iterator
|
||||||
|
{
|
||||||
|
return reverse_iterator{ end (tx) };
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,8 @@
|
||||||
|
|
||||||
#include <nano/lib/numbers.hpp>
|
#include <nano/lib/numbers.hpp>
|
||||||
#include <nano/store/component.hpp>
|
#include <nano/store/component.hpp>
|
||||||
#include <nano/store/iterator.hpp>
|
#include <nano/store/reverse_iterator.hpp>
|
||||||
|
#include <nano/store/typed_iterator.hpp>
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
|
|
@ -18,13 +19,15 @@ namespace nano::store
|
||||||
class online_weight
|
class online_weight
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using iterator = store::iterator<uint64_t, nano::amount>;
|
using iterator = typed_iterator<uint64_t, nano::amount>;
|
||||||
|
using reverse_iterator = store::reverse_iterator<iterator>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual void put (store::write_transaction const &, uint64_t, nano::amount const &) = 0;
|
virtual void put (store::write_transaction const &, uint64_t, nano::amount const &) = 0;
|
||||||
virtual void del (store::write_transaction const &, uint64_t) = 0;
|
virtual void del (store::write_transaction const &, uint64_t) = 0;
|
||||||
virtual iterator begin (store::transaction const &) const = 0;
|
virtual iterator begin (store::transaction const &) const = 0;
|
||||||
virtual iterator rbegin (store::transaction const &) const = 0;
|
reverse_iterator rbegin (store::transaction const &) const;
|
||||||
|
reverse_iterator rend (store::transaction const &) const;
|
||||||
virtual iterator end (store::transaction const & transaction_a) const = 0;
|
virtual iterator end (store::transaction const & transaction_a) const = 0;
|
||||||
virtual size_t count (store::transaction const &) const = 0;
|
virtual size_t count (store::transaction const &) const = 0;
|
||||||
virtual void clear (store::write_transaction const &) = 0;
|
virtual void clear (store::write_transaction const &) = 0;
|
||||||
|
|
|
||||||
|
|
@ -1 +1,4 @@
|
||||||
#include <nano/store/peer.hpp>
|
#include <nano/store/peer.hpp>
|
||||||
|
#include <nano/store/typed_iterator_templ.hpp>
|
||||||
|
|
||||||
|
template class nano::store::typed_iterator<nano::endpoint_key, nano::millis_t>;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#include <nano/lib/numbers.hpp>
|
#include <nano/lib/numbers.hpp>
|
||||||
#include <nano/store/component.hpp>
|
#include <nano/store/component.hpp>
|
||||||
#include <nano/store/iterator.hpp>
|
#include <nano/store/typed_iterator.hpp>
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
|
|
@ -18,7 +18,7 @@ namespace nano::store
|
||||||
class peer
|
class peer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using iterator = store::iterator<nano::endpoint_key, nano::millis_t>;
|
using iterator = typed_iterator<nano::endpoint_key, nano::millis_t>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// Returns true if the peer was inserted, false if it was already in the container
|
/// Returns true if the peer was inserted, false if it was already in the container
|
||||||
|
|
|
||||||
|
|
@ -1 +1,5 @@
|
||||||
|
#include <nano/secure/pending_info.hpp>
|
||||||
#include <nano/store/pending.hpp>
|
#include <nano/store/pending.hpp>
|
||||||
|
#include <nano/store/typed_iterator_templ.hpp>
|
||||||
|
|
||||||
|
template class nano::store::typed_iterator<nano::pending_key, nano::pending_info>;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#include <nano/lib/numbers.hpp>
|
#include <nano/lib/numbers.hpp>
|
||||||
#include <nano/store/component.hpp>
|
#include <nano/store/component.hpp>
|
||||||
#include <nano/store/iterator.hpp>
|
#include <nano/store/typed_iterator.hpp>
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
@ -21,7 +21,7 @@ namespace nano::store
|
||||||
class pending
|
class pending
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using iterator = store::iterator<nano::pending_key, nano::pending_info>;
|
using iterator = typed_iterator<nano::pending_key, nano::pending_info>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual void put (store::write_transaction const &, nano::pending_key const &, nano::pending_info const &) = 0;
|
virtual void put (store::write_transaction const &, nano::pending_key const &, nano::pending_info const &) = 0;
|
||||||
|
|
|
||||||
|
|
@ -1 +1,4 @@
|
||||||
#include <nano/store/pruned.hpp>
|
#include <nano/store/pruned.hpp>
|
||||||
|
#include <nano/store/typed_iterator_templ.hpp>
|
||||||
|
|
||||||
|
template class nano::store::typed_iterator<nano::block_hash, std::nullptr_t>;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#include <nano/lib/numbers.hpp>
|
#include <nano/lib/numbers.hpp>
|
||||||
#include <nano/store/component.hpp>
|
#include <nano/store/component.hpp>
|
||||||
#include <nano/store/iterator.hpp>
|
#include <nano/store/typed_iterator.hpp>
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
|
|
@ -18,7 +18,7 @@ namespace nano::store
|
||||||
class pruned
|
class pruned
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using iterator = store::iterator<nano::block_hash, std::nullptr_t>;
|
using iterator = typed_iterator<nano::block_hash, std::nullptr_t>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual void put (store::write_transaction const & transaction_a, nano::block_hash const & hash_a) = 0;
|
virtual void put (store::write_transaction const & transaction_a, nano::block_hash const & hash_a) = 0;
|
||||||
|
|
|
||||||
4
nano/store/rep_weight.cpp
Normal file
4
nano/store/rep_weight.cpp
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
#include <nano/store/rep_weight.hpp>
|
||||||
|
#include <nano/store/typed_iterator_templ.hpp>
|
||||||
|
|
||||||
|
template class nano::store::typed_iterator<nano::account, nano::uint128_union>;
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#include <nano/lib/numbers.hpp>
|
#include <nano/lib/numbers.hpp>
|
||||||
#include <nano/store/component.hpp>
|
#include <nano/store/component.hpp>
|
||||||
#include <nano/store/iterator.hpp>
|
#include <nano/store/typed_iterator.hpp>
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
@ -19,7 +19,7 @@ namespace nano::store
|
||||||
class rep_weight
|
class rep_weight
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using iterator = store::iterator<nano::account, nano::uint128_union>;
|
using iterator = typed_iterator<nano::account, nano::uint128_union>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ~rep_weight (){};
|
virtual ~rep_weight (){};
|
||||||
|
|
|
||||||
48
nano/store/reverse_iterator.hpp
Normal file
48
nano/store/reverse_iterator.hpp
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace nano::store
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @class reverse_iterator
|
||||||
|
* @brief A reverse iterator adaptor for bidirectional iterators.
|
||||||
|
*
|
||||||
|
* This class template adapts any bidirectional iterator to reverse its direction of iteration.
|
||||||
|
* It inverts the semantics of increment and decrement operations.
|
||||||
|
*
|
||||||
|
* Key characteristics:
|
||||||
|
* - Incrementing (operator++) moves to the previous element in the sequence.
|
||||||
|
* - Decrementing (operator--) moves to the next element in the sequence.
|
||||||
|
* - Dereferencing refers to the same element as the adapted iterator.
|
||||||
|
* - Compatible with any bidirectional iterator, not limited to specific container types.
|
||||||
|
*/
|
||||||
|
template <typename Iter>
|
||||||
|
class reverse_iterator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using iterator_category = std::bidirectional_iterator_tag;
|
||||||
|
using value_type = Iter::value_type;
|
||||||
|
using pointer = value_type *;
|
||||||
|
using const_pointer = value_type const *;
|
||||||
|
using reference = value_type &;
|
||||||
|
using const_reference = value_type const &;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Iter internal;
|
||||||
|
|
||||||
|
public:
|
||||||
|
reverse_iterator (Iter && other) noexcept;
|
||||||
|
|
||||||
|
reverse_iterator (reverse_iterator const &) = delete;
|
||||||
|
auto operator= (reverse_iterator const &) -> reverse_iterator & = delete;
|
||||||
|
|
||||||
|
reverse_iterator (reverse_iterator && other) noexcept;
|
||||||
|
auto operator= (reverse_iterator && other) noexcept -> reverse_iterator &;
|
||||||
|
|
||||||
|
auto operator++ () -> reverse_iterator &;
|
||||||
|
auto operator-- () -> reverse_iterator &;
|
||||||
|
auto operator->() const -> const_pointer;
|
||||||
|
auto operator* () const -> const_reference;
|
||||||
|
auto operator== (reverse_iterator const & other) const -> bool;
|
||||||
|
bool is_end () const;
|
||||||
|
};
|
||||||
|
}
|
||||||
63
nano/store/reverse_iterator_templ.hpp
Normal file
63
nano/store/reverse_iterator_templ.hpp
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
#include <nano/store/reverse_iterator.hpp>
|
||||||
|
|
||||||
|
namespace nano::store
|
||||||
|
{
|
||||||
|
template <typename Iter>
|
||||||
|
reverse_iterator<Iter>::reverse_iterator (Iter && other) noexcept :
|
||||||
|
internal{ std::move (other) }
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Iter>
|
||||||
|
reverse_iterator<Iter>::reverse_iterator (reverse_iterator && other) noexcept :
|
||||||
|
internal{ std::move (other.internal) }
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Iter>
|
||||||
|
auto reverse_iterator<Iter>::operator= (reverse_iterator && other) noexcept -> reverse_iterator &
|
||||||
|
{
|
||||||
|
internal = std::move (other.internal);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Iter>
|
||||||
|
auto reverse_iterator<Iter>::operator++ () -> reverse_iterator &
|
||||||
|
{
|
||||||
|
--internal;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Iter>
|
||||||
|
auto reverse_iterator<Iter>::operator-- () -> reverse_iterator &
|
||||||
|
{
|
||||||
|
++internal;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Iter>
|
||||||
|
auto reverse_iterator<Iter>::operator->() const -> const_pointer
|
||||||
|
{
|
||||||
|
release_assert (!is_end ());
|
||||||
|
return internal.operator->();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Iter>
|
||||||
|
auto reverse_iterator<Iter>::operator* () const -> const_reference
|
||||||
|
{
|
||||||
|
release_assert (!is_end ());
|
||||||
|
return internal.operator* ();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Iter>
|
||||||
|
auto reverse_iterator<Iter>::operator== (reverse_iterator const & other) const -> bool
|
||||||
|
{
|
||||||
|
return internal == other.internal;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Iter>
|
||||||
|
bool reverse_iterator<Iter>::is_end () const
|
||||||
|
{
|
||||||
|
return internal.is_end ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#include <nano/secure/parallel_traversal.hpp>
|
#include <nano/secure/parallel_traversal.hpp>
|
||||||
#include <nano/store/rocksdb/account.hpp>
|
#include <nano/store/rocksdb/account.hpp>
|
||||||
#include <nano/store/rocksdb/rocksdb.hpp>
|
#include <nano/store/rocksdb/rocksdb.hpp>
|
||||||
|
#include <nano/store/rocksdb/utility.hpp>
|
||||||
|
|
||||||
nano::store::rocksdb::account::account (nano::store::rocksdb::component & store_a) :
|
nano::store::rocksdb::account::account (nano::store::rocksdb::component & store_a) :
|
||||||
store (store_a){};
|
store (store_a){};
|
||||||
|
|
@ -44,22 +45,18 @@ 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
|
auto nano::store::rocksdb::account::begin (store::transaction const & transaction, nano::account const & account) const -> iterator
|
||||||
{
|
{
|
||||||
return store.make_iterator<nano::account, nano::account_info> (transaction, tables::accounts, account);
|
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) } };
|
||||||
}
|
}
|
||||||
|
|
||||||
auto nano::store::rocksdb::account::begin (store::transaction const & transaction) const -> iterator
|
auto nano::store::rocksdb::account::begin (store::transaction const & transaction) const -> iterator
|
||||||
{
|
{
|
||||||
return store.make_iterator<nano::account, nano::account_info> (transaction, tables::accounts);
|
return iterator{ store::iterator{ rocksdb::iterator::begin (store.db.get (), rocksdb::tx (transaction), store.table_to_column_family (tables::accounts)) } };
|
||||||
}
|
}
|
||||||
|
|
||||||
auto nano::store::rocksdb::account::rbegin (store::transaction const & transaction_a) const -> iterator
|
auto nano::store::rocksdb::account::end (store::transaction const & transaction) const -> iterator
|
||||||
{
|
{
|
||||||
return store.make_iterator<nano::account, nano::account_info> (transaction_a, tables::accounts, false);
|
return iterator{ store::iterator{ rocksdb::iterator::end (store.db.get (), rocksdb::tx (transaction), store.table_to_column_family (tables::accounts)) } };
|
||||||
}
|
|
||||||
|
|
||||||
auto nano::store::rocksdb::account::end (store::transaction const & transaction_a) const -> iterator
|
|
||||||
{
|
|
||||||
return iterator{ nullptr };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void nano::store::rocksdb::account::for_each_par (std::function<void (store::read_transaction const &, iterator, iterator)> const & action_a) const
|
void nano::store::rocksdb::account::for_each_par (std::function<void (store::read_transaction const &, iterator, iterator)> const & action_a) const
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,6 @@ public:
|
||||||
size_t count (store::transaction const & transaction_a) override;
|
size_t count (store::transaction const & transaction_a) override;
|
||||||
iterator begin (store::transaction const & transaction_a, nano::account const & account_a) const override;
|
iterator begin (store::transaction const & transaction_a, nano::account const & account_a) const override;
|
||||||
iterator begin (store::transaction const & transaction_a) const override;
|
iterator begin (store::transaction const & transaction_a) const override;
|
||||||
iterator rbegin (store::transaction const & transaction_a) const override;
|
|
||||||
iterator end (store::transaction const & transaction_a) const override;
|
iterator end (store::transaction const & transaction_a) const override;
|
||||||
void for_each_par (std::function<void (store::read_transaction const &, iterator, iterator)> const & action_a) const override;
|
void for_each_par (std::function<void (store::read_transaction const &, iterator, iterator)> const & action_a) const override;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
#include <nano/store/db_val_impl.hpp>
|
#include <nano/store/db_val_impl.hpp>
|
||||||
#include <nano/store/rocksdb/block.hpp>
|
#include <nano/store/rocksdb/block.hpp>
|
||||||
#include <nano/store/rocksdb/rocksdb.hpp>
|
#include <nano/store/rocksdb/rocksdb.hpp>
|
||||||
|
#include <nano/store/rocksdb/utility.hpp>
|
||||||
|
|
||||||
namespace nano
|
namespace nano
|
||||||
{
|
{
|
||||||
|
|
@ -136,17 +137,18 @@ uint64_t nano::store::rocksdb::block::count (store::transaction const & transact
|
||||||
|
|
||||||
auto nano::store::rocksdb::block::begin (store::transaction const & transaction) const -> iterator
|
auto nano::store::rocksdb::block::begin (store::transaction const & transaction) const -> iterator
|
||||||
{
|
{
|
||||||
return store.make_iterator<nano::block_hash, nano::store::block_w_sideband> (transaction, tables::blocks);
|
return iterator{ store::iterator{ rocksdb::iterator::begin (store.db.get (), rocksdb::tx (transaction), store.table_to_column_family (tables::blocks)) } };
|
||||||
}
|
}
|
||||||
|
|
||||||
auto nano::store::rocksdb::block::begin (store::transaction const & transaction, nano::block_hash const & hash) const -> iterator
|
auto nano::store::rocksdb::block::begin (store::transaction const & transaction, nano::block_hash const & hash) const -> iterator
|
||||||
{
|
{
|
||||||
return store.make_iterator<nano::block_hash, nano::store::block_w_sideband> (transaction, tables::blocks, hash);
|
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) } };
|
||||||
}
|
}
|
||||||
|
|
||||||
auto nano::store::rocksdb::block::end (store::transaction const & transaction_a) const -> iterator
|
auto nano::store::rocksdb::block::end (store::transaction const & transaction_a) const -> iterator
|
||||||
{
|
{
|
||||||
return iterator{ nullptr };
|
return iterator{ store::iterator{ rocksdb::iterator::end (store.db.get (), rocksdb::tx (transaction_a), store.table_to_column_family (tables::blocks)) } };
|
||||||
}
|
}
|
||||||
|
|
||||||
void nano::store::rocksdb::block::for_each_par (std::function<void (store::read_transaction const &, iterator, iterator)> const & action_a) const
|
void nano::store::rocksdb::block::for_each_par (std::function<void (store::read_transaction const &, iterator, iterator)> const & action_a) const
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#include <nano/secure/parallel_traversal.hpp>
|
#include <nano/secure/parallel_traversal.hpp>
|
||||||
#include <nano/store/rocksdb/confirmation_height.hpp>
|
#include <nano/store/rocksdb/confirmation_height.hpp>
|
||||||
#include <nano/store/rocksdb/rocksdb.hpp>
|
#include <nano/store/rocksdb/rocksdb.hpp>
|
||||||
|
#include <nano/store/rocksdb/utility.hpp>
|
||||||
|
|
||||||
nano::store::rocksdb::confirmation_height::confirmation_height (nano::store::rocksdb::component & store) :
|
nano::store::rocksdb::confirmation_height::confirmation_height (nano::store::rocksdb::component & store) :
|
||||||
store{ store }
|
store{ store }
|
||||||
|
|
@ -61,17 +62,18 @@ 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
|
auto nano::store::rocksdb::confirmation_height::begin (store::transaction const & transaction, nano::account const & account) const -> iterator
|
||||||
{
|
{
|
||||||
return store.make_iterator<nano::account, nano::confirmation_height_info> (transaction, tables::confirmation_height, account);
|
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) } };
|
||||||
}
|
}
|
||||||
|
|
||||||
auto nano::store::rocksdb::confirmation_height::begin (store::transaction const & transaction) const -> iterator
|
auto nano::store::rocksdb::confirmation_height::begin (store::transaction const & transaction) const -> iterator
|
||||||
{
|
{
|
||||||
return store.make_iterator<nano::account, nano::confirmation_height_info> (transaction, tables::confirmation_height);
|
return iterator{ store::iterator{ rocksdb::iterator::begin (store.db.get (), rocksdb::tx (transaction), store.table_to_column_family (tables::confirmation_height)) } };
|
||||||
}
|
}
|
||||||
|
|
||||||
auto nano::store::rocksdb::confirmation_height::end (store::transaction const & transaction_a) const -> iterator
|
auto nano::store::rocksdb::confirmation_height::end (store::transaction const & transaction_a) const -> iterator
|
||||||
{
|
{
|
||||||
return iterator{ nullptr };
|
return iterator{ store::iterator{ rocksdb::iterator::end (store.db.get (), rocksdb::tx (transaction_a), store.table_to_column_family (tables::confirmation_height)) } };
|
||||||
}
|
}
|
||||||
|
|
||||||
void nano::store::rocksdb::confirmation_height::for_each_par (std::function<void (store::read_transaction const &, iterator, iterator)> const & action_a) const
|
void nano::store::rocksdb::confirmation_height::for_each_par (std::function<void (store::read_transaction const &, iterator, iterator)> const & action_a) const
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#include <nano/secure/parallel_traversal.hpp>
|
#include <nano/secure/parallel_traversal.hpp>
|
||||||
#include <nano/store/rocksdb/final_vote.hpp>
|
#include <nano/store/rocksdb/final_vote.hpp>
|
||||||
#include <nano/store/rocksdb/rocksdb.hpp>
|
#include <nano/store/rocksdb/rocksdb.hpp>
|
||||||
|
#include <nano/store/rocksdb/utility.hpp>
|
||||||
|
|
||||||
nano::store::rocksdb::final_vote::final_vote (nano::store::rocksdb::component & store) :
|
nano::store::rocksdb::final_vote::final_vote (nano::store::rocksdb::component & store) :
|
||||||
store{ store } {};
|
store{ store } {};
|
||||||
|
|
@ -66,17 +67,18 @@ 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
|
auto nano::store::rocksdb::final_vote::begin (store::transaction const & transaction, nano::qualified_root const & root) const -> iterator
|
||||||
{
|
{
|
||||||
return store.make_iterator<nano::qualified_root, nano::block_hash> (transaction, tables::final_votes, root);
|
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) } };
|
||||||
}
|
}
|
||||||
|
|
||||||
auto nano::store::rocksdb::final_vote::begin (store::transaction const & transaction) const -> iterator
|
auto nano::store::rocksdb::final_vote::begin (store::transaction const & transaction) const -> iterator
|
||||||
{
|
{
|
||||||
return store.make_iterator<nano::qualified_root, nano::block_hash> (transaction, tables::final_votes);
|
return iterator{ store::iterator{ rocksdb::iterator::begin (store.db.get (), rocksdb::tx (transaction), store.table_to_column_family (tables::final_votes)) } };
|
||||||
}
|
}
|
||||||
|
|
||||||
auto nano::store::rocksdb::final_vote::end (store::transaction const & transaction_a) const -> iterator
|
auto nano::store::rocksdb::final_vote::end (store::transaction const & transaction_a) const -> iterator
|
||||||
{
|
{
|
||||||
return iterator{ nullptr };
|
return iterator{ store::iterator{ rocksdb::iterator::end (store.db.get (), rocksdb::tx (transaction_a), store.table_to_column_family (tables::final_votes)) } };
|
||||||
}
|
}
|
||||||
|
|
||||||
void nano::store::rocksdb::final_vote::for_each_par (std::function<void (store::read_transaction const &, iterator, iterator)> const & action_a) const
|
void nano::store::rocksdb::final_vote::for_each_par (std::function<void (store::read_transaction const &, iterator, iterator)> const & action_a) const
|
||||||
|
|
|
||||||
146
nano/store/rocksdb/iterator.cpp
Normal file
146
nano/store/rocksdb/iterator.cpp
Normal file
|
|
@ -0,0 +1,146 @@
|
||||||
|
#include <nano/lib/utility.hpp>
|
||||||
|
#include <nano/store/rocksdb/iterator.hpp>
|
||||||
|
|
||||||
|
#include <rocksdb/iterator.h>
|
||||||
|
|
||||||
|
namespace nano::store::rocksdb
|
||||||
|
{
|
||||||
|
auto iterator::span () const -> std::pair<std::span<uint8_t const>, std::span<uint8_t const>>
|
||||||
|
{
|
||||||
|
auto & current = operator* ();
|
||||||
|
std::span<uint8_t const> key{ reinterpret_cast<uint8_t const *> (current.first.data ()), current.first.size () };
|
||||||
|
std::span<uint8_t const> value{ reinterpret_cast<uint8_t const *> (current.second.data ()), current.second.size () };
|
||||||
|
return std::make_pair (key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto iterator::is_end () const -> bool
|
||||||
|
{
|
||||||
|
return std::holds_alternative<std::monostate> (current);
|
||||||
|
}
|
||||||
|
|
||||||
|
void iterator::update ()
|
||||||
|
{
|
||||||
|
if (iter->Valid ())
|
||||||
|
{
|
||||||
|
current = std::make_pair (iter->key (), iter->value ());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
current = std::monostate{};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator::iterator (decltype (iter) && iter) :
|
||||||
|
iter{ std::move (iter) }
|
||||||
|
{
|
||||||
|
update ();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto iterator::begin (::rocksdb::DB * db, std::variant<::rocksdb::Transaction *, ::rocksdb::ReadOptions *> snapshot, ::rocksdb::ColumnFamilyHandle * table) -> iterator
|
||||||
|
{
|
||||||
|
auto result = iterator{ make_iterator (db, snapshot, table) };
|
||||||
|
++result;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto iterator::end (::rocksdb::DB * db, std::variant<::rocksdb::Transaction *, ::rocksdb::ReadOptions *> snapshot, ::rocksdb::ColumnFamilyHandle * table) -> iterator
|
||||||
|
{
|
||||||
|
return iterator{ make_iterator (db, snapshot, table) };
|
||||||
|
}
|
||||||
|
|
||||||
|
auto iterator::lower_bound (::rocksdb::DB * db, std::variant<::rocksdb::Transaction *, ::rocksdb::ReadOptions *> snapshot, ::rocksdb::ColumnFamilyHandle * table, ::rocksdb::Slice const & lower_bound) -> iterator
|
||||||
|
{
|
||||||
|
auto iter = make_iterator (db, snapshot, table);
|
||||||
|
iter->Seek (lower_bound);
|
||||||
|
return iterator{ std::move (iter) };
|
||||||
|
}
|
||||||
|
|
||||||
|
auto iterator::make_iterator (::rocksdb::DB * db, std::variant<::rocksdb::Transaction *, ::rocksdb::ReadOptions *> snapshot, ::rocksdb::ColumnFamilyHandle * table) -> std::unique_ptr<::rocksdb::Iterator>
|
||||||
|
{
|
||||||
|
return std::unique_ptr<::rocksdb::Iterator>{ std::visit ([&] (auto && ptr) {
|
||||||
|
using V = std::remove_cvref_t<decltype (ptr)>;
|
||||||
|
if constexpr (std::is_same_v<V, ::rocksdb::Transaction *>)
|
||||||
|
{
|
||||||
|
::rocksdb::ReadOptions ropts;
|
||||||
|
ropts.fill_cache = false;
|
||||||
|
return ptr->GetIterator (ropts, table);
|
||||||
|
}
|
||||||
|
else if constexpr (std::is_same_v<V, ::rocksdb::ReadOptions *>)
|
||||||
|
{
|
||||||
|
ptr->fill_cache = false;
|
||||||
|
return db->NewIterator (*ptr, table);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
static_assert (sizeof (V) == 0, "Missing variant handler for type V");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
snapshot) };
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator::iterator (iterator && other) noexcept
|
||||||
|
{
|
||||||
|
*this = std::move (other);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto iterator::operator= (iterator && other) noexcept -> iterator &
|
||||||
|
{
|
||||||
|
iter = std::move (other.iter);
|
||||||
|
current = other.current;
|
||||||
|
other.current = std::monostate{};
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto iterator::operator++ () -> iterator &
|
||||||
|
{
|
||||||
|
if (!is_end ())
|
||||||
|
{
|
||||||
|
iter->Next ();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
iter->SeekToFirst ();
|
||||||
|
}
|
||||||
|
update ();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto iterator::operator-- () -> iterator &
|
||||||
|
{
|
||||||
|
if (!is_end ())
|
||||||
|
{
|
||||||
|
iter->Prev ();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
iter->SeekToLast ();
|
||||||
|
}
|
||||||
|
update ();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto iterator::operator->() const -> const_pointer
|
||||||
|
{
|
||||||
|
release_assert (!is_end ());
|
||||||
|
return std::get_if<value_type> (¤t);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto iterator::operator* () const -> const_reference
|
||||||
|
{
|
||||||
|
release_assert (!is_end ());
|
||||||
|
return std::get<value_type> (current);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto iterator::operator== (iterator const & other) const -> bool
|
||||||
|
{
|
||||||
|
if (is_end () != other.is_end ())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (is_end ())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return std::get<value_type> (current) == std::get<value_type> (other.current);
|
||||||
|
}
|
||||||
|
} // namespace nano::store::lmdb
|
||||||
|
|
@ -1,196 +1,60 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <nano/store/component.hpp>
|
#include <iterator>
|
||||||
#include <nano/store/iterator.hpp>
|
#include <memory>
|
||||||
#include <nano/store/rocksdb/db_val.hpp>
|
#include <span>
|
||||||
#include <nano/store/rocksdb/utility.hpp>
|
#include <utility>
|
||||||
#include <nano/store/transaction.hpp>
|
#include <variant>
|
||||||
|
|
||||||
#include <rocksdb/db.h>
|
#include <rocksdb/db.h>
|
||||||
#include <rocksdb/filter_policy.h>
|
|
||||||
#include <rocksdb/options.h>
|
|
||||||
#include <rocksdb/slice.h>
|
#include <rocksdb/slice.h>
|
||||||
#include <rocksdb/utilities/transaction.h>
|
#include <rocksdb/utilities/transaction.h>
|
||||||
|
|
||||||
namespace nano::store::rocksdb
|
namespace nano::store::rocksdb
|
||||||
{
|
{
|
||||||
template <typename T, typename U>
|
/**
|
||||||
class iterator : public iterator_impl<T, U>
|
* @class iterator
|
||||||
|
* @brief A RocksDB database iterator.
|
||||||
|
*
|
||||||
|
* This class represents an iterator for RocksDB (Persistent Key-Value Store) databases.
|
||||||
|
* It is a circular iterator, meaning that the end() sentinel value is always in the iteration cycle.
|
||||||
|
*
|
||||||
|
* Key characteristics:
|
||||||
|
* - Decrementing the end iterator points to the last key in the database.
|
||||||
|
* - Incrementing the end iterator points to the first key in the database.
|
||||||
|
*/
|
||||||
|
class iterator
|
||||||
{
|
{
|
||||||
|
std::unique_ptr<::rocksdb::Iterator> iter;
|
||||||
|
std::variant<std::monostate, std::pair<::rocksdb::Slice, ::rocksdb::Slice>> current;
|
||||||
|
void update ();
|
||||||
|
iterator (decltype (iter) && iter);
|
||||||
|
static auto make_iterator (::rocksdb::DB * db, std::variant<::rocksdb::Transaction *, ::rocksdb::ReadOptions *> snapshot, ::rocksdb::ColumnFamilyHandle * table) -> std::unique_ptr<::rocksdb::Iterator>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
iterator () = default;
|
using iterator_category = std::bidirectional_iterator_tag;
|
||||||
|
using value_type = std::pair<::rocksdb::Slice, ::rocksdb::Slice>;
|
||||||
|
using pointer = value_type *;
|
||||||
|
using const_pointer = value_type const *;
|
||||||
|
using reference = value_type &;
|
||||||
|
using const_reference = value_type const &;
|
||||||
|
|
||||||
iterator (::rocksdb::DB * db, transaction const & transaction_a, ::rocksdb::ColumnFamilyHandle * handle_a, db_val const * val_a, bool const direction_asc) :
|
static auto begin (::rocksdb::DB * db, std::variant<::rocksdb::Transaction *, ::rocksdb::ReadOptions *> snapshot, ::rocksdb::ColumnFamilyHandle * table) -> iterator;
|
||||||
iterator_impl<T, U> (transaction_a)
|
static auto end (::rocksdb::DB * db, std::variant<::rocksdb::Transaction *, ::rocksdb::ReadOptions *> snapshot, ::rocksdb::ColumnFamilyHandle * table) -> iterator;
|
||||||
{
|
static auto lower_bound (::rocksdb::DB * db, std::variant<::rocksdb::Transaction *, ::rocksdb::ReadOptions *> snapshot, ::rocksdb::ColumnFamilyHandle * table, ::rocksdb::Slice const & lower_bound) -> iterator;
|
||||||
auto internals = rocksdb::tx (transaction_a);
|
|
||||||
auto iterator = std::visit ([&] (auto && ptr) {
|
|
||||||
using V = std::remove_cvref_t<decltype (ptr)>;
|
|
||||||
if constexpr (std::is_same_v<V, ::rocksdb::Transaction *>)
|
|
||||||
{
|
|
||||||
::rocksdb::ReadOptions ropts;
|
|
||||||
ropts.fill_cache = false;
|
|
||||||
return ptr->GetIterator (ropts, handle_a);
|
|
||||||
}
|
|
||||||
else if constexpr (std::is_same_v<V, ::rocksdb::ReadOptions *>)
|
|
||||||
{
|
|
||||||
ptr->fill_cache = false;
|
|
||||||
return db->NewIterator (*ptr, handle_a);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
static_assert (sizeof (V) == 0, "Missing variant handler for type V");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
internals);
|
|
||||||
cursor.reset (iterator);
|
|
||||||
|
|
||||||
if (val_a)
|
iterator (iterator const &) = delete;
|
||||||
{
|
auto operator= (iterator const &) -> iterator & = delete;
|
||||||
cursor->Seek (*val_a);
|
|
||||||
}
|
|
||||||
else if (direction_asc)
|
|
||||||
{
|
|
||||||
cursor->SeekToFirst ();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cursor->SeekToLast ();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cursor->Valid ())
|
iterator (iterator && other_a) noexcept;
|
||||||
{
|
auto operator= (iterator && other) noexcept -> iterator &;
|
||||||
current.first = cursor->key ();
|
|
||||||
current.second = cursor->value ();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
clear ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
iterator (::rocksdb::DB * db, store::transaction const & transaction_a, ::rocksdb::ColumnFamilyHandle * handle_a) :
|
auto operator++ () -> iterator &;
|
||||||
iterator (db, transaction_a, handle_a, nullptr)
|
auto operator-- () -> iterator &;
|
||||||
{
|
auto operator->() const -> const_pointer;
|
||||||
}
|
auto operator* () const -> const_reference;
|
||||||
|
auto operator== (iterator const & other) const -> bool;
|
||||||
iterator (iterator<T, U> && other_a)
|
auto span () const -> std::pair<std::span<uint8_t const>, std::span<uint8_t const>>;
|
||||||
{
|
bool is_end () const;
|
||||||
cursor = other_a.cursor;
|
|
||||||
other_a.cursor = nullptr;
|
|
||||||
current = other_a.current;
|
|
||||||
}
|
|
||||||
|
|
||||||
iterator (iterator<T, U> const &) = delete;
|
|
||||||
|
|
||||||
iterator_impl<T, U> & operator++ () override
|
|
||||||
{
|
|
||||||
cursor->Next ();
|
|
||||||
if (cursor->Valid ())
|
|
||||||
{
|
|
||||||
current.first = cursor->key ();
|
|
||||||
current.second = cursor->value ();
|
|
||||||
|
|
||||||
if (current.first.size () != sizeof (T))
|
|
||||||
{
|
|
||||||
clear ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
clear ();
|
|
||||||
}
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
iterator_impl<T, U> & operator-- () override
|
|
||||||
{
|
|
||||||
cursor->Prev ();
|
|
||||||
if (cursor->Valid ())
|
|
||||||
{
|
|
||||||
current.first = cursor->key ();
|
|
||||||
current.second = cursor->value ();
|
|
||||||
|
|
||||||
if (current.first.size () != sizeof (T))
|
|
||||||
{
|
|
||||||
clear ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
clear ();
|
|
||||||
}
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<nano::store::rocksdb::db_val, nano::store::rocksdb::db_val> * operator->()
|
|
||||||
{
|
|
||||||
return ¤t;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator== (iterator_impl<T, U> const & base_a) const override
|
|
||||||
{
|
|
||||||
auto const other_a (boost::polymorphic_downcast<iterator<T, U> const *> (&base_a));
|
|
||||||
|
|
||||||
if (!current.first.data () && !other_a->current.first.data ())
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (!current.first.data () || !other_a->current.first.data ())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto result (std::memcmp (current.first.data (), other_a->current.first.data (), current.first.size ()) == 0);
|
|
||||||
debug_assert (!result || (current.first.size () == other_a->current.first.size ()));
|
|
||||||
debug_assert (!result || std::memcmp (current.second.data (), other_a->current.second.data (), current.second.size ()) == 0);
|
|
||||||
debug_assert (!result || (current.second.size () == other_a->current.second.size ()));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_end_sentinal () const override
|
|
||||||
{
|
|
||||||
return current.first.size () == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void fill (std::pair<T, U> & value_a) const override
|
|
||||||
{
|
|
||||||
{
|
|
||||||
if (current.first.size () != 0)
|
|
||||||
{
|
|
||||||
value_a.first = static_cast<T> (current.first);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
value_a.first = T ();
|
|
||||||
}
|
|
||||||
if (current.second.size () != 0)
|
|
||||||
{
|
|
||||||
value_a.second = static_cast<U> (current.second);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
value_a.second = U ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void clear ()
|
|
||||||
{
|
|
||||||
current.first = nano::store::rocksdb::db_val{};
|
|
||||||
current.second = nano::store::rocksdb::db_val{};
|
|
||||||
debug_assert (is_end_sentinal ());
|
|
||||||
}
|
|
||||||
iterator<T, U> & operator= (iterator<T, U> && other_a)
|
|
||||||
{
|
|
||||||
cursor = std::move (other_a.cursor);
|
|
||||||
current = other_a.current;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
iterator_impl<T, U> & operator= (iterator_impl<T, U> const &) = delete;
|
|
||||||
|
|
||||||
std::unique_ptr<::rocksdb::Iterator> cursor;
|
|
||||||
std::pair<nano::store::rocksdb::db_val, nano::store::rocksdb::db_val> current;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
#include <nano/store/rocksdb/online_weight.hpp>
|
#include <nano/store/rocksdb/online_weight.hpp>
|
||||||
#include <nano/store/rocksdb/rocksdb.hpp>
|
#include <nano/store/rocksdb/rocksdb.hpp>
|
||||||
|
#include <nano/store/rocksdb/utility.hpp>
|
||||||
|
|
||||||
nano::store::rocksdb::online_weight::online_weight (nano::store::rocksdb::component & store_a) :
|
nano::store::rocksdb::online_weight::online_weight (nano::store::rocksdb::component & store_a) :
|
||||||
store{ store_a }
|
store{ store_a }
|
||||||
|
|
@ -20,17 +21,12 @@ void nano::store::rocksdb::online_weight::del (store::write_transaction const &
|
||||||
|
|
||||||
auto nano::store::rocksdb::online_weight::begin (store::transaction const & transaction) const -> iterator
|
auto nano::store::rocksdb::online_weight::begin (store::transaction const & transaction) const -> iterator
|
||||||
{
|
{
|
||||||
return store.make_iterator<uint64_t, nano::amount> (transaction, tables::online_weight);
|
return iterator{ store::iterator{ rocksdb::iterator::begin (store.db.get (), rocksdb::tx (transaction), store.table_to_column_family (tables::online_weight)) } };
|
||||||
}
|
|
||||||
|
|
||||||
auto nano::store::rocksdb::online_weight::rbegin (store::transaction const & transaction) const -> iterator
|
|
||||||
{
|
|
||||||
return store.make_iterator<uint64_t, nano::amount> (transaction, tables::online_weight, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto nano::store::rocksdb::online_weight::end (store::transaction const & transaction_a) const -> iterator
|
auto nano::store::rocksdb::online_weight::end (store::transaction const & transaction_a) const -> iterator
|
||||||
{
|
{
|
||||||
return iterator{ nullptr };
|
return iterator{ store::iterator{ rocksdb::iterator::end (store.db.get (), rocksdb::tx (transaction_a), store.table_to_column_family (tables::online_weight)) } };
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t nano::store::rocksdb::online_weight::count (store::transaction const & transaction) const
|
size_t nano::store::rocksdb::online_weight::count (store::transaction const & transaction) const
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@ public:
|
||||||
void put (store::write_transaction const & transaction_a, uint64_t time_a, nano::amount const & amount_a) override;
|
void put (store::write_transaction const & transaction_a, uint64_t time_a, nano::amount const & amount_a) override;
|
||||||
void del (store::write_transaction const & transaction_a, uint64_t time_a) override;
|
void del (store::write_transaction const & transaction_a, uint64_t time_a) override;
|
||||||
iterator begin (store::transaction const & transaction_a) const override;
|
iterator begin (store::transaction const & transaction_a) const override;
|
||||||
iterator rbegin (store::transaction const & transaction_a) const override;
|
|
||||||
iterator end (store::transaction const & transaction_a) const override;
|
iterator end (store::transaction const & transaction_a) const override;
|
||||||
size_t count (store::transaction const & transaction_a) const override;
|
size_t count (store::transaction const & transaction_a) const override;
|
||||||
void clear (store::write_transaction const & transaction_a) override;
|
void clear (store::write_transaction const & transaction_a) override;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
#include <nano/store/rocksdb/peer.hpp>
|
#include <nano/store/rocksdb/peer.hpp>
|
||||||
#include <nano/store/rocksdb/rocksdb.hpp>
|
#include <nano/store/rocksdb/rocksdb.hpp>
|
||||||
|
#include <nano/store/rocksdb/utility.hpp>
|
||||||
|
|
||||||
nano::store::rocksdb::peer::peer (nano::store::rocksdb::component & store) :
|
nano::store::rocksdb::peer::peer (nano::store::rocksdb::component & store) :
|
||||||
store{ store } {};
|
store{ store } {};
|
||||||
|
|
@ -47,10 +48,10 @@ void nano::store::rocksdb::peer::clear (store::write_transaction const & transac
|
||||||
|
|
||||||
auto nano::store::rocksdb::peer::begin (store::transaction const & transaction) const -> iterator
|
auto nano::store::rocksdb::peer::begin (store::transaction const & transaction) const -> iterator
|
||||||
{
|
{
|
||||||
return store.make_iterator<nano::endpoint_key, nano::millis_t> (transaction, tables::peers);
|
return iterator{ store::iterator{ rocksdb::iterator::begin (store.db.get (), rocksdb::tx (transaction), store.table_to_column_family (tables::peers)) } };
|
||||||
}
|
}
|
||||||
|
|
||||||
auto nano::store::rocksdb::peer::end (store::transaction const & transaction_a) const -> iterator
|
auto nano::store::rocksdb::peer::end (store::transaction const & transaction_a) const -> iterator
|
||||||
{
|
{
|
||||||
return iterator{ nullptr };
|
return iterator{ store::iterator{ rocksdb::iterator::end (store.db.get (), rocksdb::tx (transaction_a), store.table_to_column_family (tables::peers)) } };
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#include <nano/secure/parallel_traversal.hpp>
|
#include <nano/secure/parallel_traversal.hpp>
|
||||||
#include <nano/store/lmdb/pending.hpp>
|
#include <nano/store/lmdb/pending.hpp>
|
||||||
#include <nano/store/rocksdb/rocksdb.hpp>
|
#include <nano/store/rocksdb/rocksdb.hpp>
|
||||||
|
#include <nano/store/rocksdb/utility.hpp>
|
||||||
|
|
||||||
nano::store::rocksdb::pending::pending (nano::store::rocksdb::component & store) :
|
nano::store::rocksdb::pending::pending (nano::store::rocksdb::component & store) :
|
||||||
store{ store } {};
|
store{ store } {};
|
||||||
|
|
@ -47,17 +48,18 @@ 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
|
auto nano::store::rocksdb::pending::begin (store::transaction const & transaction_a, nano::pending_key const & key_a) const -> iterator
|
||||||
{
|
{
|
||||||
return store.template make_iterator<nano::pending_key, nano::pending_info> (transaction_a, tables::pending, key_a);
|
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) } };
|
||||||
}
|
}
|
||||||
|
|
||||||
auto nano::store::rocksdb::pending::begin (store::transaction const & transaction_a) const -> iterator
|
auto nano::store::rocksdb::pending::begin (store::transaction const & transaction_a) const -> iterator
|
||||||
{
|
{
|
||||||
return store.template make_iterator<nano::pending_key, nano::pending_info> (transaction_a, tables::pending);
|
return iterator{ store::iterator{ rocksdb::iterator::begin (store.db.get (), rocksdb::tx (transaction_a), store.table_to_column_family (tables::pending)) } };
|
||||||
}
|
}
|
||||||
|
|
||||||
auto nano::store::rocksdb::pending::end (store::transaction const & transaction_a) const -> iterator
|
auto nano::store::rocksdb::pending::end (store::transaction const & transaction_a) const -> iterator
|
||||||
{
|
{
|
||||||
return iterator{ nullptr };
|
return iterator{ store::iterator{ rocksdb::iterator::end (store.db.get (), rocksdb::tx (transaction_a), store.table_to_column_family (tables::pending)) } };
|
||||||
}
|
}
|
||||||
|
|
||||||
void nano::store::rocksdb::pending::for_each_par (std::function<void (store::read_transaction const &, iterator, iterator)> const & action_a) const
|
void nano::store::rocksdb::pending::for_each_par (std::function<void (store::read_transaction const &, iterator, iterator)> const & action_a) const
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#include <nano/secure/parallel_traversal.hpp>
|
#include <nano/secure/parallel_traversal.hpp>
|
||||||
#include <nano/store/rocksdb/pruned.hpp>
|
#include <nano/store/rocksdb/pruned.hpp>
|
||||||
#include <nano/store/rocksdb/rocksdb.hpp>
|
#include <nano/store/rocksdb/rocksdb.hpp>
|
||||||
|
#include <nano/store/rocksdb/utility.hpp>
|
||||||
|
|
||||||
nano::store::rocksdb::pruned::pruned (nano::store::rocksdb::component & store_a) :
|
nano::store::rocksdb::pruned::pruned (nano::store::rocksdb::component & store_a) :
|
||||||
store{ store_a } {};
|
store{ store_a } {};
|
||||||
|
|
@ -47,17 +48,18 @@ 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
|
auto nano::store::rocksdb::pruned::begin (store::transaction const & transaction_a, nano::block_hash const & hash_a) const -> iterator
|
||||||
{
|
{
|
||||||
return store.make_iterator<nano::block_hash, std::nullptr_t> (transaction_a, tables::pruned, hash_a);
|
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) } };
|
||||||
}
|
}
|
||||||
|
|
||||||
auto nano::store::rocksdb::pruned::begin (store::transaction const & transaction_a) const -> iterator
|
auto nano::store::rocksdb::pruned::begin (store::transaction const & transaction_a) const -> iterator
|
||||||
{
|
{
|
||||||
return store.make_iterator<nano::block_hash, std::nullptr_t> (transaction_a, tables::pruned);
|
return iterator{ store::iterator{ rocksdb::iterator::begin (store.db.get (), rocksdb::tx (transaction_a), store.table_to_column_family (tables::pruned)) } };
|
||||||
}
|
}
|
||||||
|
|
||||||
auto nano::store::rocksdb::pruned::end (store::transaction const & transaction_a) const -> iterator
|
auto nano::store::rocksdb::pruned::end (store::transaction const & transaction_a) const -> iterator
|
||||||
{
|
{
|
||||||
return iterator{ nullptr };
|
return iterator{ store::iterator{ rocksdb::iterator::end (store.db.get (), rocksdb::tx (transaction_a), store.table_to_column_family (tables::pruned)) } };
|
||||||
}
|
}
|
||||||
|
|
||||||
void nano::store::rocksdb::pruned::for_each_par (std::function<void (store::read_transaction const &, iterator, iterator)> const & action_a) const
|
void nano::store::rocksdb::pruned::for_each_par (std::function<void (store::read_transaction const &, iterator, iterator)> const & action_a) const
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
#include <nano/secure/parallel_traversal.hpp>
|
#include <nano/secure/parallel_traversal.hpp>
|
||||||
#include <nano/store/rocksdb/rep_weight.hpp>
|
#include <nano/store/rocksdb/rep_weight.hpp>
|
||||||
#include <nano/store/rocksdb/rocksdb.hpp>
|
#include <nano/store/rocksdb/rocksdb.hpp>
|
||||||
|
#include <nano/store/rocksdb/utility.hpp>
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
|
|
@ -44,17 +45,18 @@ 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
|
auto nano::store::rocksdb::rep_weight::begin (store::transaction const & txn_a, nano::account const & representative_a) const -> iterator
|
||||||
{
|
{
|
||||||
return store.make_iterator<nano::account, nano::uint128_union> (txn_a, tables::rep_weights, representative_a);
|
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) } };
|
||||||
}
|
}
|
||||||
|
|
||||||
auto nano::store::rocksdb::rep_weight::begin (store::transaction const & txn_a) const -> iterator
|
auto nano::store::rocksdb::rep_weight::begin (store::transaction const & txn_a) const -> iterator
|
||||||
{
|
{
|
||||||
return store.make_iterator<nano::account, nano::uint128_union> (txn_a, tables::rep_weights);
|
return iterator{ store::iterator{ rocksdb::iterator::begin (store.db.get (), rocksdb::tx (txn_a), store.table_to_column_family (tables::rep_weights)) } };
|
||||||
}
|
}
|
||||||
|
|
||||||
auto nano::store::rocksdb::rep_weight::end (store::transaction const & transaction_a) const -> iterator
|
auto nano::store::rocksdb::rep_weight::end (store::transaction const & transaction_a) const -> iterator
|
||||||
{
|
{
|
||||||
return iterator{ nullptr };
|
return iterator{ store::iterator{ rocksdb::iterator::end (store.db.get (), rocksdb::tx (transaction_a), store.table_to_column_family (tables::rep_weights)) } };
|
||||||
}
|
}
|
||||||
|
|
||||||
void nano::store::rocksdb::rep_weight::for_each_par (std::function<void (store::read_transaction const &, iterator, iterator)> const & action_a) const
|
void nano::store::rocksdb::rep_weight::for_each_par (std::function<void (store::read_transaction const &, iterator, iterator)> const & action_a) const
|
||||||
|
|
|
||||||
|
|
@ -302,8 +302,8 @@ void nano::store::rocksdb::component::upgrade_v22_to_v23 (store::write_transacti
|
||||||
auto transaction = tx_begin_read ();
|
auto transaction = tx_begin_read ();
|
||||||
|
|
||||||
// Manually create v22 compatible iterator to read accounts
|
// Manually create v22 compatible iterator to read accounts
|
||||||
auto it = make_iterator<nano::account, nano::account_info_v22> (transaction, tables::accounts);
|
auto it = typed_iterator<nano::account, nano::account_info_v22> (store::iterator{ rocksdb::iterator::begin (db.get (), rocksdb::tx (transaction), table_to_column_family (tables::accounts)) });
|
||||||
auto const end = store::iterator<nano::account, nano::account_info_v22> (nullptr);
|
auto const end = typed_iterator<nano::account, nano::account_info_v22>{ store::iterator{ rocksdb::iterator::end (db.get (), rocksdb::tx (transaction), table_to_column_family (tables::accounts)) } };
|
||||||
|
|
||||||
for (; it != end; ++it)
|
for (; it != end; ++it)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -85,18 +85,6 @@ public:
|
||||||
|
|
||||||
unsigned max_block_write_batch_num () const override;
|
unsigned max_block_write_batch_num () const override;
|
||||||
|
|
||||||
template <typename Key, typename Value>
|
|
||||||
store::iterator<Key, Value> make_iterator (store::transaction const & transaction_a, tables table_a, bool const direction_asc = true) const
|
|
||||||
{
|
|
||||||
return store::iterator<Key, Value> (std::make_unique<nano::store::rocksdb::iterator<Key, Value>> (db.get (), transaction_a, table_to_column_family (table_a), nullptr, direction_asc));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Key, typename Value>
|
|
||||||
store::iterator<Key, Value> make_iterator (store::transaction const & transaction_a, tables table_a, nano::store::rocksdb::db_val const & key) const
|
|
||||||
{
|
|
||||||
return store::iterator<Key, Value> (std::make_unique<nano::store::rocksdb::iterator<Key, Value>> (db.get (), transaction_a, table_to_column_family (table_a), &key, true));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool init_error () const override;
|
bool init_error () const override;
|
||||||
|
|
||||||
std::string error_string (int status) const override;
|
std::string error_string (int status) const override;
|
||||||
|
|
|
||||||
1
nano/store/typed_iterator.cpp
Normal file
1
nano/store/typed_iterator.cpp
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
|
||||||
63
nano/store/typed_iterator.hpp
Normal file
63
nano/store/typed_iterator.hpp
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <nano/store/iterator.hpp>
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <iterator>
|
||||||
|
#include <memory>
|
||||||
|
#include <span>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace nano::store
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @class typed_iterator
|
||||||
|
* @brief A generic typed iterator for key-value stores.
|
||||||
|
*
|
||||||
|
* This class represents a typed iterator for key-value store databases, such as RocksDB.
|
||||||
|
* It supports typing for both keys and values, providing type-safe access to the database contents.
|
||||||
|
*
|
||||||
|
* Key characteristics:
|
||||||
|
* - Generic: Works with various key-value store implementations.
|
||||||
|
* - Type-safe: Supports strongly typed keys and values.
|
||||||
|
* - Circular: The end() sentinel value is always in the iteration cycle.
|
||||||
|
* - Automatic deserialization: When pointing to a valid non-sentinel location, it loads and
|
||||||
|
* deserializes the database value into the appropriate type.
|
||||||
|
*
|
||||||
|
* Behavior:
|
||||||
|
* - Decrementing the end iterator points to the last key-value pair in the database.
|
||||||
|
* - Incrementing the end iterator points to the first key-value pair in the database.
|
||||||
|
*/
|
||||||
|
template <typename Key, typename Value>
|
||||||
|
class typed_iterator final
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using iterator_category = std::bidirectional_iterator_tag;
|
||||||
|
using value_type = std::pair<Key, Value>;
|
||||||
|
using pointer = value_type *;
|
||||||
|
using const_pointer = value_type const *;
|
||||||
|
using reference = value_type &;
|
||||||
|
using const_reference = value_type const &;
|
||||||
|
|
||||||
|
private:
|
||||||
|
iterator iter;
|
||||||
|
std::variant<std::monostate, value_type> current;
|
||||||
|
void update ();
|
||||||
|
|
||||||
|
public:
|
||||||
|
typed_iterator (iterator && iter) noexcept;
|
||||||
|
|
||||||
|
typed_iterator (typed_iterator const &) = delete;
|
||||||
|
auto operator= (typed_iterator const &) -> typed_iterator & = delete;
|
||||||
|
|
||||||
|
typed_iterator (typed_iterator && other) noexcept;
|
||||||
|
auto operator= (typed_iterator && other) noexcept -> typed_iterator &;
|
||||||
|
|
||||||
|
auto operator++ () -> typed_iterator &;
|
||||||
|
auto operator-- () -> typed_iterator &;
|
||||||
|
auto operator->() const -> const_pointer;
|
||||||
|
auto operator* () const -> const_reference;
|
||||||
|
auto operator== (typed_iterator const & other) const -> bool;
|
||||||
|
auto is_end () const -> bool;
|
||||||
|
};
|
||||||
|
} // namespace nano::store
|
||||||
88
nano/store/typed_iterator_templ.hpp
Normal file
88
nano/store/typed_iterator_templ.hpp
Normal file
|
|
@ -0,0 +1,88 @@
|
||||||
|
#include <nano/lib/utility.hpp>
|
||||||
|
#include <nano/store/db_val_impl.hpp>
|
||||||
|
#include <nano/store/lmdb/db_val.hpp>
|
||||||
|
#include <nano/store/typed_iterator.hpp>
|
||||||
|
|
||||||
|
namespace nano::store
|
||||||
|
{
|
||||||
|
template <typename Key, typename Value>
|
||||||
|
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 ())) } };
|
||||||
|
current = std::make_pair (static_cast<Key> (key_val), static_cast<Value> (value_val));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
current = std::monostate{};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Key, typename Value>
|
||||||
|
typed_iterator<Key, Value>::typed_iterator (iterator && iter) noexcept :
|
||||||
|
iter{ std::move (iter) }
|
||||||
|
{
|
||||||
|
update ();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Key, typename Value>
|
||||||
|
typed_iterator<Key, Value>::typed_iterator (typed_iterator && other) noexcept :
|
||||||
|
iter{ std::move (other.iter) },
|
||||||
|
current{ std::move (other.current) }
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Key, typename Value>
|
||||||
|
auto typed_iterator<Key, Value>::operator= (typed_iterator && other) noexcept -> typed_iterator &
|
||||||
|
{
|
||||||
|
iter = std::move (other.iter);
|
||||||
|
current = std::move (other.current);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Key, typename Value>
|
||||||
|
auto typed_iterator<Key, Value>::operator++ () -> typed_iterator<Key, Value> &
|
||||||
|
{
|
||||||
|
++iter;
|
||||||
|
update ();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Key, typename Value>
|
||||||
|
auto typed_iterator<Key, Value>::operator-- () -> typed_iterator<Key, Value> &
|
||||||
|
{
|
||||||
|
--iter;
|
||||||
|
update ();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Key, typename Value>
|
||||||
|
auto typed_iterator<Key, Value>::operator->() const -> const_pointer
|
||||||
|
{
|
||||||
|
release_assert (!is_end ());
|
||||||
|
return std::get_if<value_type> (¤t);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Key, typename Value>
|
||||||
|
auto typed_iterator<Key, Value>::operator* () const -> const_reference
|
||||||
|
{
|
||||||
|
release_assert (!is_end ());
|
||||||
|
return std::get<value_type> (current);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Key, typename Value>
|
||||||
|
auto typed_iterator<Key, Value>::operator== (typed_iterator<Key, Value> const & other) const -> bool
|
||||||
|
{
|
||||||
|
return iter == other.iter;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Key, typename Value>
|
||||||
|
auto typed_iterator<Key, Value>::is_end () const -> bool
|
||||||
|
{
|
||||||
|
return std::holds_alternative<std::monostate> (current);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue