Merge pull request #4925 from pwojcikdev/init-error

Use exceptions for store initialization errors
This commit is contained in:
Piotr Wójcik 2025-07-09 09:17:29 +02:00 committed by GitHub
commit aa281cfaf0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
28 changed files with 453 additions and 604 deletions

View file

@ -23,11 +23,6 @@ static void BM_ledger_iterate_accounts (benchmark::State & state)
auto store_impl{ nano::make_store (logger, application_path, network_params.ledger) };
auto & store{ *store_impl };
if (store.init_error ())
{
state.SkipWithError ("Store initialization failed. Make sure ledger files are present in the default location.");
}
auto ledger_impl{ std::make_unique<nano::ledger> (store, network_params.ledger, stats, logger, nano::generate_cache_flags::all_disabled ()) };
auto & ledger{ *ledger_impl };
@ -71,11 +66,6 @@ static void BM_store_iterate_accounts (benchmark::State & state)
auto store_impl{ nano::make_store (logger, application_path, network_params.ledger) };
auto & store{ *store_impl };
if (store.init_error ())
{
state.SkipWithError ("Store initialization failed. Make sure ledger files are present in the default location.");
}
auto transaction = store.tx_begin_read ();
nano::account current{ 0 };
nano::account_info current_info;

View file

@ -34,7 +34,6 @@ TEST (block_store, construction)
{
nano::logger logger;
auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
ASSERT_TRUE (!store->init_error ());
}
TEST (block_store, block_details)
@ -109,7 +108,7 @@ TEST (block_store, add_item)
{
nano::logger logger;
auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
ASSERT_TRUE (!store->init_error ());
nano::block_builder builder;
auto block = builder
.open ()
@ -140,7 +139,7 @@ TEST (block_store, clear_successor)
{
nano::logger logger;
auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
ASSERT_TRUE (!store->init_error ());
nano::block_builder builder;
auto block1 = builder
.open ()
@ -187,7 +186,7 @@ TEST (block_store, add_nonempty_block)
{
nano::logger logger;
auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
ASSERT_TRUE (!store->init_error ());
nano::keypair key1;
nano::block_builder builder;
auto block = builder
@ -214,7 +213,7 @@ TEST (block_store, add_two_items)
{
nano::logger logger;
auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
ASSERT_TRUE (!store->init_error ());
nano::keypair key1;
nano::block_builder builder;
auto block = builder
@ -260,7 +259,7 @@ TEST (block_store, add_receive)
{
nano::logger logger;
auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
ASSERT_TRUE (!store->init_error ());
nano::keypair key1;
nano::keypair key2;
nano::block_builder builder;
@ -296,7 +295,7 @@ TEST (block_store, add_pending)
{
nano::logger logger;
auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
ASSERT_TRUE (!store->init_error ());
nano::keypair key1;
nano::pending_key key2 (0, 0);
auto transaction (store->tx_begin_write ());
@ -314,7 +313,6 @@ TEST (block_store, pending_iterator)
{
nano::logger logger;
auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
ASSERT_TRUE (!store->init_error ());
auto transaction (store->tx_begin_write ());
ASSERT_EQ (store->pending.end (transaction), store->pending.begin (transaction));
store->pending.put (transaction, nano::pending_key (1, 2), { 2, 3, nano::epoch::epoch_1 });
@ -340,7 +338,7 @@ TEST (block_store, pending_iterator_comparison)
nano::test::system system;
auto store = nano::make_store (system.logger, nano::unique_path (), nano::dev::constants);
ASSERT_TRUE (!store->init_error ());
auto transaction (store->tx_begin_write ());
// Populate pending
store->pending.put (transaction, nano::pending_key (nano::account (3), nano::block_hash (1)), nano::pending_info (nano::account (10), nano::amount (1), nano::epoch::epoch_0));
@ -382,7 +380,6 @@ TEST (block_store, genesis)
{
nano::logger logger;
auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
ASSERT_TRUE (!store->init_error ());
auto transaction (store->tx_begin_write ());
store->initialize (transaction, nano::dev::constants);
nano::account_info info;
@ -409,7 +406,6 @@ TEST (block_store, empty_accounts)
{
nano::logger logger;
auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
ASSERT_TRUE (!store->init_error ());
auto transaction (store->tx_begin_read ());
auto begin (store->account.begin (transaction));
auto end (store->account.end (transaction));
@ -420,7 +416,7 @@ TEST (block_store, one_block)
{
nano::logger logger;
auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
ASSERT_TRUE (!store->init_error ());
nano::block_builder builder;
auto block1 = builder
.open ()
@ -453,7 +449,7 @@ TEST (block_store, unchecked_begin_search)
{
nano::logger logger;
auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
ASSERT_TRUE (!store->init_error ());
nano::keypair key0;
nano::block_builder builder;
auto block1 = builder
@ -478,7 +474,7 @@ TEST (block_store, frontier_retrieval)
{
nano::logger logger;
auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
ASSERT_TRUE (!store->init_error ());
nano::account account1{};
nano::account_info info1 (0, 0, 0, 0, 0, 0, nano::epoch::epoch_0);
auto transaction (store->tx_begin_write ());
@ -492,7 +488,7 @@ TEST (block_store, one_account)
{
nano::logger logger;
auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
ASSERT_TRUE (!store->init_error ());
nano::account account{};
nano::block_hash hash (0);
auto transaction (store->tx_begin_write ());
@ -519,7 +515,7 @@ TEST (block_store, two_block)
{
nano::logger logger;
auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
ASSERT_TRUE (!store->init_error ());
nano::block_builder builder;
auto block1 = builder
.open ()
@ -557,7 +553,7 @@ TEST (block_store, two_account)
{
nano::logger logger;
auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
ASSERT_TRUE (!store->init_error ());
nano::account account1 (1);
nano::block_hash hash1 (2);
nano::account account2 (3);
@ -599,7 +595,7 @@ TEST (block_store, latest_find)
{
nano::logger logger;
auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
ASSERT_TRUE (!store->init_error ());
nano::account account1 (1);
nano::block_hash hash1 (2);
nano::account account2 (3);
@ -616,8 +612,7 @@ TEST (block_store, latest_find)
ASSERT_EQ (second, find3);
}
namespace nano::store::lmdb
{
// TODO: Move to lmdb specific test file
TEST (mdb_block_store, supported_version_upgrades)
{
if (nano::rocksdb_config::using_rocksdb_in_tests ())
@ -640,8 +635,7 @@ TEST (mdb_block_store, supported_version_upgrades)
// Upgrade should fail
{
nano::store::lmdb::component store (logger, path, nano::dev::constants);
ASSERT_TRUE (store.init_error ());
ASSERT_THROW (nano::store::lmdb::component store (logger, path, nano::dev::constants), std::runtime_error);
}
auto path1 (nano::unique_path () / "data.ldb");
@ -657,12 +651,11 @@ TEST (mdb_block_store, supported_version_upgrades)
// Upgrade should work
{
nano::store::lmdb::component store (logger, path1, nano::dev::constants);
ASSERT_FALSE (store.init_error ());
ASSERT_NO_THROW (nano::store::lmdb::component store (logger, path1, nano::dev::constants));
}
}
}
// TODO: Move to lmdb specific test file
TEST (mdb_block_store, bad_path)
{
if (nano::rocksdb_config::using_rocksdb_in_tests ())
@ -671,21 +664,13 @@ TEST (mdb_block_store, bad_path)
GTEST_SKIP ();
}
nano::logger logger;
try
auto path = nano::unique_path ();
path /= "data.ldb";
{
auto path = nano::unique_path ();
path /= "data.ldb";
{
std::ofstream stream (path.c_str ());
}
std::filesystem::permissions (path, std::filesystem::perms::none);
nano::store::lmdb::component store (logger, path, nano::dev::constants);
std::ofstream stream (path.c_str ());
}
catch (std::runtime_error &)
{
return;
}
ASSERT_TRUE (false);
std::filesystem::permissions (path, std::filesystem::perms::none);
ASSERT_THROW (nano::store::lmdb::component store (logger, path, nano::dev::constants), std::runtime_error);
}
TEST (block_store, DISABLED_already_open) // File can be shared
@ -698,14 +683,13 @@ TEST (block_store, DISABLED_already_open) // File can be shared
ASSERT_TRUE (file.is_open ());
nano::logger logger;
auto store = nano::make_store (logger, path, nano::dev::constants);
ASSERT_TRUE (store->init_error ());
}
TEST (block_store, roots)
{
nano::logger logger;
auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
ASSERT_TRUE (!store->init_error ());
nano::block_builder builder;
auto send_block = builder
.send ()
@ -747,7 +731,7 @@ TEST (block_store, pending_exists)
{
nano::logger logger;
auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
ASSERT_TRUE (!store->init_error ());
nano::pending_key two (2, 0);
nano::pending_info pending;
auto transaction (store->tx_begin_write ());
@ -760,7 +744,7 @@ TEST (block_store, latest_exists)
{
nano::logger logger;
auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
ASSERT_TRUE (!store->init_error ());
nano::account two (2);
nano::account_info info;
auto transaction (store->tx_begin_write ());
@ -773,7 +757,7 @@ TEST (block_store, large_iteration)
{
nano::logger logger;
auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
ASSERT_TRUE (!store->init_error ());
std::unordered_set<nano::account> accounts1;
for (auto i (0); i < 1000; ++i)
{
@ -811,7 +795,6 @@ TEST (block_store, frontier)
{
nano::logger logger;
auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
ASSERT_TRUE (!store->init_error ());
auto transaction (store->tx_begin_write ());
nano::block_hash hash (100);
nano::account account (200);
@ -821,7 +804,7 @@ TEST (block_store, block_replace)
{
nano::logger logger;
auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
ASSERT_TRUE (!store->init_error ());
nano::block_builder builder;
auto send1 = builder
.send ()
@ -853,7 +836,6 @@ TEST (block_store, block_count)
{
nano::logger logger;
auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
ASSERT_TRUE (!store->init_error ());
{
auto transaction (store->tx_begin_write ());
ASSERT_EQ (0, store->block.count (transaction));
@ -878,7 +860,6 @@ TEST (block_store, account_count)
{
nano::logger logger;
auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
ASSERT_TRUE (!store->init_error ());
{
auto transaction (store->tx_begin_write ());
ASSERT_EQ (0, store->account.count (transaction));
@ -893,7 +874,6 @@ TEST (block_store, cemented_count_cache)
{
nano::logger logger;
auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
ASSERT_TRUE (!store->init_error ());
nano::stats stats{ logger };
nano::ledger ledger (*store, nano::dev::constants, stats, logger);
ASSERT_EQ (1, ledger.cemented_count ());
@ -903,7 +883,7 @@ TEST (block_store, pruned_random)
{
nano::logger logger;
auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
ASSERT_TRUE (!store->init_error ());
nano::block_builder builder;
auto block = builder
.open ()
@ -929,7 +909,7 @@ TEST (block_store, state_block)
{
nano::logger logger;
auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
ASSERT_FALSE (store->init_error ());
nano::keypair key1;
nano::block_builder builder;
auto block1 = builder
@ -978,7 +958,7 @@ TEST (mdb_block_store, sideband_height)
nano::keypair key2;
nano::keypair key3;
nano::store::lmdb::component store (logger, nano::unique_path () / "data.ldb", nano::dev::constants);
ASSERT_FALSE (store.init_error ());
nano::stats stats{ logger };
nano::ledger ledger (store, nano::dev::constants, stats, logger);
nano::block_builder builder;
@ -1127,7 +1107,6 @@ TEST (block_store, peers)
{
nano::logger logger;
auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
ASSERT_TRUE (!store->init_error ());
nano::endpoint_key endpoint (boost::asio::ip::address_v6::any ().to_bytes (), 100);
{
@ -1228,7 +1207,6 @@ TEST (block_store, online_weight)
{
nano::logger logger;
auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
ASSERT_FALSE (store->init_error ());
{
auto transaction (store->tx_begin_write ());
ASSERT_EQ (0, store->online_weight.count (transaction));
@ -1263,7 +1241,6 @@ TEST (block_store, pruned_blocks)
{
nano::logger logger;
auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
ASSERT_TRUE (!store->init_error ());
nano::keypair key1;
nano::block_builder builder;
@ -1535,7 +1512,7 @@ TEST (mdb_block_store, upgrade_backup)
// Now do the upgrade and confirm that backup is saved
nano::logger logger;
nano::store::lmdb::component store (logger, path, nano::dev::constants, nano::txn_tracking_config{}, std::chrono::seconds (5), nano::lmdb_config{}, true);
ASSERT_FALSE (store.init_error ());
auto transaction (store.tx_begin_read ());
ASSERT_LT (14, store.version.get (transaction));
ASSERT_NE (get_backup_path ().string (), dir.string ());
@ -1621,7 +1598,6 @@ TEST (block_store, incompatible_version)
nano::logger logger;
{
auto store = nano::make_store (logger, path, nano::dev::constants);
ASSERT_FALSE (store->init_error ());
// Put version to an unreachable number so that it should always be incompatible
auto transaction (store->tx_begin_write ());
@ -1629,17 +1605,13 @@ TEST (block_store, incompatible_version)
}
// Now try and read it, should give an error
{
auto store = nano::make_store (logger, path, nano::dev::constants, true);
ASSERT_TRUE (store->init_error ());
}
ASSERT_THROW (nano::make_store (logger, path, nano::dev::constants, true), std::runtime_error);
}
TEST (block_store, reset_renew_existing_transaction)
{
nano::logger logger;
auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
ASSERT_TRUE (!store->init_error ());
nano::keypair key1;
nano::block_builder builder;
@ -1709,7 +1681,7 @@ TEST (rocksdb_block_store, tombstone_count)
nano::test::system system;
nano::logger logger;
auto store = std::make_unique<nano::store::rocksdb::component> (logger, nano::unique_path () / "rocksdb", nano::dev::constants);
ASSERT_TRUE (!store->init_error ());
nano::block_builder builder;
auto block = builder
.send ()

View file

@ -875,7 +875,6 @@ TEST (ledger, double_open)
{
nano::logger logger;
auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
ASSERT_TRUE (!store->init_error ());
nano::stats stats{ logger };
nano::ledger ledger (*store, nano::dev::constants, stats, logger);
auto transaction = ledger.tx_begin_write ();
@ -4810,7 +4809,6 @@ TEST (ledger, dependents_confirmed_pruning)
{
nano::logger logger;
auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
ASSERT_FALSE (store->init_error ());
nano::stats stats{ logger };
nano::ledger ledger (*store, nano::dev::constants, stats, logger);
ledger.pruning = true;
@ -4986,7 +4984,6 @@ TEST (ledger, pruning_action)
{
nano::logger logger;
auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
ASSERT_TRUE (!store->init_error ());
nano::stats stats{ logger };
nano::ledger ledger (*store, nano::dev::constants, stats, logger);
ledger.pruning = true;
@ -5071,7 +5068,6 @@ TEST (ledger, pruning_large_chain)
{
nano::logger logger;
auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
ASSERT_TRUE (!store->init_error ());
nano::stats stats{ logger };
nano::ledger ledger (*store, nano::dev::constants, stats, logger);
ledger.pruning = true;
@ -5126,7 +5122,6 @@ TEST (ledger, pruning_source_rollback)
{
nano::logger logger;
auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
ASSERT_TRUE (!store->init_error ());
nano::stats stats{ logger };
nano::ledger ledger (*store, nano::dev::constants, stats, logger);
ledger.pruning = true;
@ -5214,7 +5209,6 @@ TEST (ledger, pruning_source_rollback_legacy)
{
nano::logger logger;
auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
ASSERT_TRUE (!store->init_error ());
nano::stats stats{ logger };
nano::ledger ledger (*store, nano::dev::constants, stats, logger);
ledger.pruning = true;
@ -5327,7 +5321,6 @@ TEST (ledger, pruning_legacy_blocks)
{
nano::logger logger;
auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
ASSERT_TRUE (!store->init_error ());
nano::stats stats{ logger };
nano::ledger ledger (*store, nano::dev::constants, stats, logger);
ledger.pruning = true;
@ -5413,7 +5406,6 @@ TEST (ledger, pruning_safe_functions)
{
nano::logger logger;
auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
ASSERT_TRUE (!store->init_error ());
nano::stats stats{ logger };
nano::ledger ledger (*store, nano::dev::constants, stats, logger);
ledger.pruning = true;
@ -5464,7 +5456,6 @@ TEST (ledger, random_blocks)
{
nano::logger logger;
auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
ASSERT_TRUE (!store->init_error ());
nano::stats stats{ logger };
nano::ledger ledger (*store, nano::dev::constants, stats, logger);
ledger.pruning = true;
@ -5571,7 +5562,6 @@ TEST (ledger, migrate_lmdb_to_rocksdb)
{
auto transaction = ledger.tx_begin_write ();
ASSERT_FALSE (store.init_error ());
// Lower the database to the max version unsupported for upgrades
store.confirmation_height.put (transaction, nano::dev::genesis_key.pub, { 2, send->hash () });

View file

@ -759,7 +759,7 @@ TEST (ledger_confirm, pruned_source)
auto path (nano::unique_path ());
auto store = nano::make_store (system.logger, path, nano::dev::constants);
ASSERT_TRUE (!store->init_error ());
nano::ledger ledger (*store, nano::dev::constants, system.stats, system.logger);
ledger.pruning = true;
nano::store::write_queue write_queue;
@ -843,7 +843,7 @@ TEST (ledger_confirmDeathTest, rollback_added_block)
auto path (nano::unique_path ());
auto store = nano::make_store (system.logger, path, nano::dev::constants);
ASSERT_TRUE (!store->init_error ());
nano::ledger ledger (*store, nano::dev::constants, system.stats, system.logger);
nano::store::write_queue write_queue;
nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits<unsigned>::max () };

View file

@ -164,7 +164,6 @@ TEST (network, multi_keepalive)
auto node0 = system.nodes[0];
ASSERT_EQ (0, node0->network.size ());
auto node1 (std::make_shared<nano::node> (system.io_ctx, system.get_available_port (), nano::unique_path (), system.work));
ASSERT_FALSE (node1->init_error ());
node1->start ();
system.nodes.push_back (node1);
ASSERT_EQ (0, node1->network.size ());
@ -172,7 +171,6 @@ TEST (network, multi_keepalive)
node1->network.tcp_channels.start_tcp (node0->network.endpoint ());
ASSERT_TIMELY (10s, node0->network.size () == 1 && node0->stats.count (nano::stat::type::message, nano::stat::detail::keepalive) >= 1);
auto node2 (std::make_shared<nano::node> (system.io_ctx, system.get_available_port (), nano::unique_path (), system.work));
ASSERT_FALSE (node2->init_error ());
node2->start ();
system.nodes.push_back (node2);
node2->network.tcp_channels.start_tcp (node0->network.endpoint ());

View file

@ -265,7 +265,6 @@ TEST (node, auto_bootstrap)
ASSERT_NE (nullptr, send1);
ASSERT_TIMELY_EQ (10s, node0->balance (key2.pub), node0->config.receive_minimum.number ());
auto node1 (std::make_shared<nano::node> (system.io_ctx, system.get_available_port (), nano::unique_path (), system.work, node_flags));
ASSERT_FALSE (node1->init_error ());
node1->start ();
system.nodes.push_back (node1);
ASSERT_NE (nullptr, nano::test::establish_tcp (system, *node1, node0->network.endpoint ()));
@ -290,7 +289,6 @@ TEST (node, auto_bootstrap_reverse)
system.wallet (0)->insert_adhoc (nano::dev::genesis_key.prv);
system.wallet (0)->insert_adhoc (key2.prv);
auto node1 (std::make_shared<nano::node> (system.io_ctx, system.get_available_port (), nano::unique_path (), system.work, node_flags));
ASSERT_FALSE (node1->init_error ());
ASSERT_NE (nullptr, system.wallet (0)->send_action (nano::dev::genesis_key.pub, key2.pub, node0->config.receive_minimum.number ()));
node1->start ();
system.nodes.push_back (node1);

View file

@ -17,7 +17,6 @@ TEST (processor_service, bad_send_signature)
nano::test::system system;
auto store = nano::make_store (system.logger, nano::unique_path (), nano::dev::constants);
ASSERT_FALSE (store->init_error ());
nano::ledger ledger (*store, nano::dev::constants, system.stats, system.logger);
auto transaction = ledger.tx_begin_write ();
nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits<unsigned>::max () };
@ -42,7 +41,6 @@ TEST (processor_service, bad_receive_signature)
nano::test::system system;
auto store = nano::make_store (system.logger, nano::unique_path (), nano::dev::constants);
ASSERT_FALSE (store->init_error ());
nano::ledger ledger (*store, nano::dev::constants, system.stats, system.logger);
auto transaction = ledger.tx_begin_write ();
nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits<unsigned>::max () };

View file

@ -11,7 +11,7 @@
TEST (rep_weight_store, empty)
{
auto store = nano::test::make_store ();
ASSERT_TRUE (!store->init_error ());
auto txn{ store->tx_begin_read () };
ASSERT_EQ (0, store->rep_weight.count (txn));
}
@ -19,7 +19,7 @@ TEST (rep_weight_store, empty)
TEST (rep_weight_store, add_item)
{
auto store = nano::test::make_store ();
ASSERT_TRUE (!store->init_error ());
auto txn{ store->tx_begin_write () };
nano::account representative{ 123 };
@ -33,7 +33,7 @@ TEST (rep_weight_store, add_item)
TEST (rep_weight_store, del)
{
auto store = nano::test::make_store ();
ASSERT_TRUE (!store->init_error ());
auto txn{ store->tx_begin_write () };
store->rep_weight.put (txn, 1, 100);
@ -49,7 +49,7 @@ TEST (rep_weight_store, del)
TEST (rep_weight_store, for_each_par)
{
auto store = nano::test::make_store ();
ASSERT_TRUE (!store->init_error ());
{
auto txn{ store->tx_begin_write () };
for (auto i = 0; i < 50; ++i)

View file

@ -18,8 +18,7 @@ unsigned constexpr nano::wallet_store::version_current;
TEST (wallet, no_special_keys_accounts)
{
bool init;
nano::store::lmdb::env env (init, nano::unique_path () / "wallet.ldb");
ASSERT_FALSE (init);
nano::store::lmdb::env env (nano::unique_path () / "wallet.ldb");
auto transaction (env.tx_begin_write ());
nano::kdf kdf{ nano::dev::network_params.kdf_work };
nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis_key.pub, 1, "0");
@ -39,8 +38,7 @@ TEST (wallet, no_special_keys_accounts)
TEST (wallet, no_key)
{
bool init;
nano::store::lmdb::env env (init, nano::unique_path () / "wallet.ldb");
ASSERT_FALSE (init);
nano::store::lmdb::env env (nano::unique_path () / "wallet.ldb");
auto transaction (env.tx_begin_write ());
nano::kdf kdf{ nano::dev::network_params.kdf_work };
nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis_key.pub, 1, "0");
@ -54,8 +52,7 @@ TEST (wallet, no_key)
TEST (wallet, fetch_locked)
{
bool init;
nano::store::lmdb::env env (init, nano::unique_path () / "wallet.ldb");
ASSERT_FALSE (init);
nano::store::lmdb::env env (nano::unique_path () / "wallet.ldb");
auto transaction (env.tx_begin_write ());
nano::kdf kdf{ nano::dev::network_params.kdf_work };
nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis_key.pub, 1, "0");
@ -76,8 +73,7 @@ TEST (wallet, fetch_locked)
TEST (wallet, retrieval)
{
bool init;
nano::store::lmdb::env env (init, nano::unique_path () / "wallet.ldb");
ASSERT_FALSE (init);
nano::store::lmdb::env env (nano::unique_path () / "wallet.ldb");
auto transaction (env.tx_begin_write ());
nano::kdf kdf{ nano::dev::network_params.kdf_work };
nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis_key.pub, 1, "0");
@ -98,8 +94,7 @@ TEST (wallet, retrieval)
TEST (wallet, empty_iteration)
{
bool init;
nano::store::lmdb::env env (init, nano::unique_path () / "wallet.ldb");
ASSERT_FALSE (init);
nano::store::lmdb::env env (nano::unique_path () / "wallet.ldb");
auto transaction (env.tx_begin_write ());
nano::kdf kdf{ nano::dev::network_params.kdf_work };
nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis_key.pub, 1, "0");
@ -112,8 +107,7 @@ TEST (wallet, empty_iteration)
TEST (wallet, one_item_iteration)
{
bool init;
nano::store::lmdb::env env (init, nano::unique_path () / "wallet.ldb");
ASSERT_FALSE (init);
nano::store::lmdb::env env (nano::unique_path () / "wallet.ldb");
auto transaction (env.tx_begin_write ());
nano::kdf kdf{ nano::dev::network_params.kdf_work };
nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis_key.pub, 1, "0");
@ -134,8 +128,7 @@ TEST (wallet, one_item_iteration)
TEST (wallet, two_item_iteration)
{
bool init;
nano::store::lmdb::env env (init, nano::unique_path () / "wallet.ldb");
ASSERT_FALSE (init);
nano::store::lmdb::env env (nano::unique_path () / "wallet.ldb");
nano::keypair key1;
nano::keypair key2;
ASSERT_NE (key1.pub, key2.pub);
@ -260,8 +253,7 @@ TEST (wallet, spend_no_previous)
TEST (wallet, find_none)
{
bool init;
nano::store::lmdb::env env (init, nano::unique_path () / "wallet.ldb");
ASSERT_FALSE (init);
nano::store::lmdb::env env (nano::unique_path () / "wallet.ldb");
auto transaction (env.tx_begin_write ());
nano::kdf kdf{ nano::dev::network_params.kdf_work };
nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis_key.pub, 1, "0");
@ -273,8 +265,7 @@ TEST (wallet, find_none)
TEST (wallet, find_existing)
{
bool init;
nano::store::lmdb::env env (init, nano::unique_path () / "wallet.ldb");
ASSERT_FALSE (init);
nano::store::lmdb::env env (nano::unique_path () / "wallet.ldb");
auto transaction (env.tx_begin_write ());
nano::kdf kdf{ nano::dev::network_params.kdf_work };
nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis_key.pub, 1, "0");
@ -292,8 +283,7 @@ TEST (wallet, find_existing)
TEST (wallet, rekey)
{
bool init;
nano::store::lmdb::env env (init, nano::unique_path () / "wallet.ldb");
ASSERT_FALSE (init);
nano::store::lmdb::env env (nano::unique_path () / "wallet.ldb");
auto transaction (env.tx_begin_write ());
nano::kdf kdf{ nano::dev::network_params.kdf_work };
nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis_key.pub, 1, "0");
@ -322,8 +312,7 @@ TEST (wallet, rekey)
TEST (wallet, hash_password)
{
bool init;
nano::store::lmdb::env env (init, nano::unique_path () / "wallet.ldb");
ASSERT_FALSE (init);
nano::store::lmdb::env env (nano::unique_path () / "wallet.ldb");
auto transaction (env.tx_begin_write ());
nano::kdf kdf{ nano::dev::network_params.kdf_work };
nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis_key.pub, 1, "0");
@ -371,9 +360,8 @@ TEST (fan, change)
TEST (wallet, reopen_default_password)
{
bool init;
nano::store::lmdb::env env (init, nano::unique_path () / "wallet.ldb");
nano::store::lmdb::env env (nano::unique_path () / "wallet.ldb");
auto transaction (env.tx_begin_write ());
ASSERT_FALSE (init);
nano::kdf kdf{ nano::dev::network_params.kdf_work };
{
nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis_key.pub, 1, "0");
@ -407,8 +395,7 @@ TEST (wallet, reopen_default_password)
TEST (wallet, representative)
{
auto error (false);
nano::store::lmdb::env env (error, nano::unique_path () / "wallet.ldb");
ASSERT_FALSE (error);
nano::store::lmdb::env env (nano::unique_path () / "wallet.ldb");
auto transaction (env.tx_begin_write ());
nano::kdf kdf{ nano::dev::network_params.kdf_work };
nano::wallet_store wallet (error, kdf, transaction, env, nano::dev::genesis_key.pub, 1, "0");
@ -428,8 +415,7 @@ TEST (wallet, representative)
TEST (wallet, serialize_json_empty)
{
auto error (false);
nano::store::lmdb::env env (error, nano::unique_path () / "wallet.ldb");
ASSERT_FALSE (error);
nano::store::lmdb::env env (nano::unique_path () / "wallet.ldb");
auto transaction (env.tx_begin_write ());
nano::kdf kdf{ nano::dev::network_params.kdf_work };
nano::wallet_store wallet1 (error, kdf, transaction, env, nano::dev::genesis_key.pub, 1, "0");
@ -453,8 +439,7 @@ TEST (wallet, serialize_json_empty)
TEST (wallet, serialize_json_one)
{
auto error (false);
nano::store::lmdb::env env (error, nano::unique_path () / "wallet.ldb");
ASSERT_FALSE (error);
nano::store::lmdb::env env (nano::unique_path () / "wallet.ldb");
auto transaction (env.tx_begin_write ());
nano::kdf kdf{ nano::dev::network_params.kdf_work };
nano::wallet_store wallet1 (error, kdf, transaction, env, nano::dev::genesis_key.pub, 1, "0");
@ -482,8 +467,7 @@ TEST (wallet, serialize_json_one)
TEST (wallet, serialize_json_password)
{
auto error (false);
nano::store::lmdb::env env (error, nano::unique_path () / "wallet.ldb");
ASSERT_FALSE (error);
nano::store::lmdb::env env (nano::unique_path () / "wallet.ldb");
auto transaction (env.tx_begin_write ());
nano::kdf kdf{ nano::dev::network_params.kdf_work };
nano::wallet_store wallet1 (error, kdf, transaction, env, nano::dev::genesis_key.pub, 1, "0");
@ -515,8 +499,7 @@ TEST (wallet, serialize_json_password)
TEST (wallet_store, move)
{
auto error (false);
nano::store::lmdb::env env (error, nano::unique_path () / "wallet.ldb");
ASSERT_FALSE (error);
nano::store::lmdb::env env (nano::unique_path () / "wallet.ldb");
auto transaction (env.tx_begin_write ());
nano::kdf kdf{ nano::dev::network_params.kdf_work };
nano::wallet_store wallet1 (error, kdf, transaction, env, nano::dev::genesis_key.pub, 1, "0");
@ -672,8 +655,7 @@ TEST (wallet, insert_locked)
TEST (wallet, deterministic_keys)
{
bool init;
nano::store::lmdb::env env (init, nano::unique_path () / "wallet.ldb");
ASSERT_FALSE (init);
nano::store::lmdb::env env (nano::unique_path () / "wallet.ldb");
auto transaction (env.tx_begin_write ());
nano::kdf kdf{ nano::dev::network_params.kdf_work };
nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis_key.pub, 1, "0");
@ -715,8 +697,7 @@ TEST (wallet, deterministic_keys)
TEST (wallet, reseed)
{
bool init;
nano::store::lmdb::env env (init, nano::unique_path () / "wallet.ldb");
ASSERT_FALSE (init);
nano::store::lmdb::env env (nano::unique_path () / "wallet.ldb");
auto transaction (env.tx_begin_write ());
nano::kdf kdf{ nano::dev::network_params.kdf_work };
nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis_key.pub, 1, "0");

View file

@ -121,98 +121,91 @@ void nano::daemon::run (std::filesystem::path const & data_path, nano::node_flag
}
auto node = std::make_shared<nano::node> (io_ctx, data_path, config.node, opencl_work, flags);
if (!node->init_error ())
// IO context runner should be started first and stopped last to allow asio handlers to execute during node start/stop
runner = std::make_unique<nano::thread_runner> (io_ctx, logger, node->config.io_threads, nano::thread_role::name::io_daemon);
node->start ();
std::atomic stopped{ false };
std::unique_ptr<nano::ipc::ipc_server> ipc_server = std::make_unique<nano::ipc::ipc_server> (*node, config.rpc);
std::unique_ptr<boost::process::child> rpc_process;
std::unique_ptr<nano::rpc_handler_interface> rpc_handler;
std::shared_ptr<nano::rpc> rpc;
if (config.rpc_enable)
{
// IO context runner should be started first and stopped last to allow asio handlers to execute during node start/stop
runner = std::make_unique<nano::thread_runner> (io_ctx, logger, node->config.io_threads, nano::thread_role::name::io_daemon);
node->start ();
std::atomic stopped{ false };
std::unique_ptr<nano::ipc::ipc_server> ipc_server = std::make_unique<nano::ipc::ipc_server> (*node, config.rpc);
std::unique_ptr<boost::process::child> rpc_process;
std::unique_ptr<nano::rpc_handler_interface> rpc_handler;
std::shared_ptr<nano::rpc> rpc;
if (config.rpc_enable)
// In process RPC
if (!config.rpc.child_process.enable)
{
// In process RPC
if (!config.rpc.child_process.enable)
auto stop_callback = [this, &stopped] () {
logger.warn (nano::log::type::daemon, "RPC stop request received, stopping...");
stopped = true;
stopped.notify_all ();
};
// Launch rpc in-process
nano::rpc_config rpc_config{ config.node.network_params.network };
if (auto error = nano::read_rpc_config_toml (data_path, rpc_config, flags.rpc_config_overrides))
{
auto stop_callback = [this, &stopped] () {
logger.warn (nano::log::type::daemon, "RPC stop request received, stopping...");
stopped = true;
stopped.notify_all ();
};
// Launch rpc in-process
nano::rpc_config rpc_config{ config.node.network_params.network };
if (auto error = nano::read_rpc_config_toml (data_path, rpc_config, flags.rpc_config_overrides))
{
logger.critical (nano::log::type::daemon, "Error deserializing RPC config: {}", error.get_message ());
std::exit (1);
}
rpc_handler = std::make_unique<nano::inprocess_rpc_handler> (*node, *ipc_server, config.rpc, stop_callback);
rpc = nano::get_rpc (io_ctx, rpc_config, *rpc_handler);
rpc->start ();
logger.critical (nano::log::type::daemon, "Error deserializing RPC config: {}", error.get_message ());
std::exit (1);
}
else
rpc_handler = std::make_unique<nano::inprocess_rpc_handler> (*node, *ipc_server, config.rpc, stop_callback);
rpc = nano::get_rpc (io_ctx, rpc_config, *rpc_handler);
rpc->start ();
}
else
{
// Spawn a child rpc process
if (!std::filesystem::exists (config.rpc.child_process.rpc_path))
{
// Spawn a child rpc process
if (!std::filesystem::exists (config.rpc.child_process.rpc_path))
{
throw std::runtime_error (std::string ("RPC is configured to spawn a new process however the file cannot be found at: ") + config.rpc.child_process.rpc_path);
}
logger.warn (nano::log::type::daemon, "RPC is configured to run in a separate process, this is experimental and is not recommended for production use. Please consider using the in-process RPC instead.");
std::string network{ node->network_params.network.get_current_network_as_string () };
rpc_process = std::make_unique<boost::process::child> (config.rpc.child_process.rpc_path, "--daemon", "--data_path", data_path.string (), "--network", network);
throw std::runtime_error (std::string ("RPC is configured to spawn a new process however the file cannot be found at: ") + config.rpc.child_process.rpc_path);
}
debug_assert (rpc || rpc_process);
}
auto signal_handler = [this, &stopped] (int signum) {
logger.warn (nano::log::type::daemon, "Interrupt signal received ({}), stopping...", to_signal_name (signum));
stopped = true;
stopped.notify_all ();
};
nano::signal_manager sigman;
// keep trapping Ctrl-C to avoid a second Ctrl-C interrupting tasks started by the first
sigman.register_signal_handler (SIGINT, signal_handler, true);
// sigterm is less likely to come in bunches so only trap it once
sigman.register_signal_handler (SIGTERM, signal_handler, false);
// Keep running until stopped flag is set
stopped.wait (false);
logger.info (nano::log::type::daemon, "Stopping...");
if (rpc)
{
rpc->stop ();
}
ipc_server->stop ();
node->stop ();
io_ctx->stop ();
runner->join ();
if (rpc_process)
{
rpc_process->wait ();
logger.warn (nano::log::type::daemon, "RPC is configured to run in a separate process, this is experimental and is not recommended for production use. Please consider using the in-process RPC instead.");
std::string network{ node->network_params.network.get_current_network_as_string () };
rpc_process = std::make_unique<boost::process::child> (config.rpc.child_process.rpc_path, "--daemon", "--data_path", data_path.string (), "--network", network);
}
debug_assert (rpc || rpc_process);
}
else
auto signal_handler = [this, &stopped] (int signum) {
logger.warn (nano::log::type::daemon, "Interrupt signal received ({}), stopping...", to_signal_name (signum));
stopped = true;
stopped.notify_all ();
};
nano::signal_manager sigman;
// keep trapping Ctrl-C to avoid a second Ctrl-C interrupting tasks started by the first
sigman.register_signal_handler (SIGINT, signal_handler, true);
// sigterm is less likely to come in bunches so only trap it once
sigman.register_signal_handler (SIGTERM, signal_handler, false);
// Keep running until stopped flag is set
stopped.wait (false);
logger.info (nano::log::type::daemon, "Stopping...");
if (rpc)
{
logger.critical (nano::log::type::daemon, "Error initializing node");
rpc->stop ();
}
ipc_server->stop ();
node->stop ();
io_ctx->stop ();
runner->join ();
if (rpc_process)
{
rpc_process->wait ();
}
}
catch (std::runtime_error const & e)
catch (std::exception const & ex)
{
logger.critical (nano::log::type::daemon, "Error while running node: {}", e.what ());
logger.critical (nano::log::type::daemon, "Error: {}", ex.what ());
}
logger.info (nano::log::type::daemon, "Stopped");

View file

@ -116,21 +116,21 @@ public:
nano::thread_runner runner (io_ctx, logger, config.node.io_threads, nano::thread_role::name::io_daemon);
std::shared_ptr<nano::node> node;
std::shared_ptr<nano_qt::wallet> gui;
nano::set_application_icon (application);
auto opencl = nano::opencl_work::create (config.opencl_enable, config.opencl, logger, config.node.network_params.work);
nano::opencl_work_func_t opencl_work_func;
if (opencl)
{
opencl_work_func = [&opencl] (nano::work_version const version_a, nano::root const & root_a, uint64_t difficulty_a, std::atomic<int> &) {
return opencl->generate_work (version_a, root_a, difficulty_a);
};
}
nano::work_pool work{ config.node.network_params.network, config.node.work_threads, config.node.pow_sleep_interval, opencl_work_func };
node = std::make_shared<nano::node> (io_ctx, data_path, config.node, work, flags);
if (!node->init_error ())
try
{
std::shared_ptr<nano::node> node;
std::shared_ptr<nano_qt::wallet> gui;
nano::set_application_icon (application);
auto opencl = nano::opencl_work::create (config.opencl_enable, config.opencl, logger, config.node.network_params.work);
nano::opencl_work_func_t opencl_work_func;
if (opencl)
{
opencl_work_func = [&opencl] (nano::work_version const version_a, nano::root const & root_a, uint64_t difficulty_a, std::atomic<int> &) {
return opencl->generate_work (version_a, root_a, difficulty_a);
};
}
nano::work_pool work{ config.node.network_params.network, config.node.work_threads, config.node.pow_sleep_interval, opencl_work_func };
node = std::make_shared<nano::node> (io_ctx, data_path, config.node, work, flags);
auto wallet (node->wallets.open (wallet_config.wallet));
if (wallet == nullptr)
{
@ -220,10 +220,10 @@ public:
result = QApplication::exec ();
runner.join ();
}
else
catch (std::exception const & e)
{
splash->hide ();
show_error ("Error initializing node");
show_error ("Error initializing node: " + std::string (e.what ()));
}
write_wallet_config (wallet_config, data_path);
}

View file

@ -238,9 +238,9 @@ bool copy_database (std::filesystem::path const & data_path, boost::program_opti
auto node_flags = nano::inactive_node_flag_defaults ();
node_flags.read_only = !needs_to_write;
nano::update_flags (node_flags, vm);
nano::inactive_node node (data_path, node_flags);
if (!node.node->init_error ())
try
{
nano::inactive_node node (data_path, node_flags);
auto & store (node.node->store);
if (vm.count ("unchecked_clear"))
{
@ -273,7 +273,7 @@ bool copy_database (std::filesystem::path const & data_path, boost::program_opti
success = node.node->copy_with_compaction (output_path);
}
else
catch (std::exception const &)
{
database_write_lock_error (ec);
}
@ -496,20 +496,18 @@ std::error_code nano::handle_node_options (boost::program_options::variables_map
auto node_flags = nano::inactive_node_flag_defaults ();
node_flags.config_overrides.push_back ("node.rocksdb.enable=false");
nano::update_flags (node_flags, vm);
nano::inactive_node node (data_path, node_flags);
auto error (false);
if (!node.node->init_error ())
try
{
error = node.node->ledger.migrate_lmdb_to_rocksdb (data_path);
nano::inactive_node node (data_path, node_flags);
auto error = node.node->ledger.migrate_lmdb_to_rocksdb (data_path);
if (error)
{
std::cerr << "There was an error migrating" << std::endl;
}
}
else
catch (std::exception const & e)
{
error = true;
}
if (error)
{
std::cerr << "There was an error migrating" << std::endl;
std::cerr << "Error initializing node for migration: " << e.what () << std::endl;
}
}
else if (vm.count ("rollback"))
@ -524,9 +522,9 @@ std::error_code nano::handle_node_options (boost::program_options::variables_map
node_flags.read_only = false;
nano::update_flags (node_flags, vm);
nano::inactive_node node (data_path, node_flags);
if (!node.node->init_error ())
try
{
nano::inactive_node node (data_path, node_flags);
auto transaction (node.node->ledger.tx_begin_write ());
auto block = node.node->ledger.any.block_get (transaction, block_hash);
if (block != nullptr)
@ -560,7 +558,7 @@ std::error_code nano::handle_node_options (boost::program_options::variables_map
ec = nano::error_cli::invalid_arguments;
}
}
else
catch (std::exception const &)
{
database_write_lock_error (ec);
}
@ -583,14 +581,14 @@ std::error_code nano::handle_node_options (boost::program_options::variables_map
auto node_flags = nano::inactive_node_flag_defaults ();
node_flags.read_only = false;
nano::update_flags (node_flags, vm);
nano::inactive_node node (data_path, node_flags);
if (!node.node->init_error ())
try
{
nano::inactive_node node (data_path, node_flags);
auto transaction (node.node->store.tx_begin_write ());
node.node->unchecked.clear ();
std::cout << "Unchecked blocks deleted" << std::endl;
}
else
catch (std::exception const &)
{
database_write_lock_error (ec);
}
@ -601,14 +599,14 @@ std::error_code nano::handle_node_options (boost::program_options::variables_map
auto node_flags = nano::inactive_node_flag_defaults ();
node_flags.read_only = false;
nano::update_flags (node_flags, vm);
nano::inactive_node node (data_path, node_flags);
if (!node.node->init_error ())
try
{
nano::inactive_node node (data_path, node_flags);
auto transaction (node.node->wallets.tx_begin_write ());
node.node->wallets.clear_send_ids (transaction);
std::cout << "Send IDs deleted" << std::endl;
}
else
catch (std::exception const &)
{
database_write_lock_error (ec);
}
@ -619,14 +617,14 @@ std::error_code nano::handle_node_options (boost::program_options::variables_map
auto node_flags = nano::inactive_node_flag_defaults ();
node_flags.read_only = false;
nano::update_flags (node_flags, vm);
nano::inactive_node node (data_path, node_flags);
if (!node.node->init_error ())
try
{
nano::inactive_node node (data_path, node_flags);
auto transaction (node.node->store.tx_begin_write ());
node.node->store.online_weight.clear (transaction);
std::cout << "Online weight records are removed" << std::endl;
}
else
catch (std::exception const &)
{
database_write_lock_error (ec);
}
@ -637,14 +635,14 @@ std::error_code nano::handle_node_options (boost::program_options::variables_map
auto node_flags = nano::inactive_node_flag_defaults ();
node_flags.read_only = false;
nano::update_flags (node_flags, vm);
nano::inactive_node node (data_path, node_flags);
if (!node.node->init_error ())
try
{
nano::inactive_node node (data_path, node_flags);
auto transaction (node.node->store.tx_begin_write ());
node.node->store.peer.clear (transaction);
std::cout << "Database peers are removed" << std::endl;
}
else
catch (std::exception const &)
{
database_write_lock_error (ec);
}
@ -655,9 +653,9 @@ std::error_code nano::handle_node_options (boost::program_options::variables_map
auto node_flags = nano::inactive_node_flag_defaults ();
node_flags.read_only = false;
nano::update_flags (node_flags, vm);
nano::inactive_node node (data_path, node_flags);
if (!node.node->init_error ())
try
{
nano::inactive_node node (data_path, node_flags);
if (vm.count ("account") == 1)
{
auto account_str = vm["account"].as<std::string> ();
@ -705,7 +703,7 @@ std::error_code nano::handle_node_options (boost::program_options::variables_map
ec = nano::error_cli::invalid_arguments;
}
}
else
catch (std::exception const &)
{
database_write_lock_error (ec);
}
@ -716,9 +714,9 @@ std::error_code nano::handle_node_options (boost::program_options::variables_map
auto node_flags = nano::inactive_node_flag_defaults ();
node_flags.read_only = false;
nano::update_flags (node_flags, vm);
nano::inactive_node node (data_path, node_flags);
if (!node.node->init_error ())
try
{
nano::inactive_node node (data_path, node_flags);
if (auto root_it = vm.find ("root"); root_it != vm.cend ())
{
auto root_str = root_it->second.as<std::string> ();
@ -745,7 +743,7 @@ std::error_code nano::handle_node_options (boost::program_options::variables_map
std::cerr << "Either specify a single --root to clear or --all to clear all final votes (not recommended)" << std::endl;
}
}
else
catch (std::exception const &)
{
database_write_lock_error (ec);
}

View file

@ -100,7 +100,7 @@ nano::node::node (std::shared_ptr<boost::asio::io_context> io_ctx_a, std::filesy
store{ *store_impl },
wallets_store_impl{ std::make_unique<nano::mdb_wallets_store> (application_path_a / "wallets.ldb", config_a.lmdb_config) },
wallets_store{ *wallets_store_impl },
wallets_impl{ std::make_unique<nano::wallets> (wallets_store.init_error (), *this) },
wallets_impl{ std::make_unique<nano::wallets> (false, *this) },
wallets{ *wallets_impl },
ledger_impl{ std::make_unique<nano::ledger> (store, network_params.ledger, stats, logger, flags_a.generate_cache, config.representative_vote_weight_minimum.number (), config.max_backlog) },
ledger{ *ledger_impl },
@ -287,156 +287,150 @@ nano::node::node (std::shared_ptr<boost::asio::io_context> io_ctx_a, std::filesy
}
});
if (!init_error ())
wallets.observer = [this] (bool active) {
observers.wallet.notify (active);
};
network.disconnect_observer = [this] () {
observers.disconnect.notify ();
};
observers.channel_connected.add ([this] (std::shared_ptr<nano::transport::channel> const & channel) {
network.send_keepalive_self (channel);
});
// Cancelling local work generation
observers.work_cancel.add ([this] (nano::root const & root_a) {
this->work.cancel (root_a);
this->distributed_work.cancel (root_a);
});
auto const network_label = network_params.network.get_current_network_as_string ();
logger.info (nano::log::type::node, "Version: {}", NANO_VERSION_STRING);
logger.info (nano::log::type::node, "Build information: {}", BUILD_INFO);
logger.info (nano::log::type::node, "Active network: {}", network_label);
logger.info (nano::log::type::node, "Database backend: {}", store.vendor_get ());
logger.info (nano::log::type::node, "Data path: {}", application_path.string ());
logger.info (nano::log::type::node, "Ledger path: {}", store.get_database_path ().string ());
logger.info (nano::log::type::node, "Work pool threads: {} ({})", work.threads.size (), (work.opencl ? "OpenCL" : "CPU"));
logger.info (nano::log::type::node, "Work peers: {}", config.work_peers.size ());
logger.info (nano::log::type::node, "Node ID: {}", node_id.pub.to_node_id ());
logger.info (nano::log::type::node, "Number of buckets: {}", bucketing.size ());
logger.info (nano::log::type::node, "Genesis block: {}", config.network_params.ledger.genesis->hash ().to_string ());
logger.info (nano::log::type::node, "Genesis account: {}", config.network_params.ledger.genesis->account ().to_account ());
if (!work_generation_enabled ())
{
wallets.observer = [this] (bool active) {
observers.wallet.notify (active);
};
network.disconnect_observer = [this] () {
observers.disconnect.notify ();
};
logger.warn (nano::log::type::node, "Work generation is disabled");
}
observers.channel_connected.add ([this] (std::shared_ptr<nano::transport::channel> const & channel) {
network.send_keepalive_self (channel);
});
logger.info (nano::log::type::node, "Outbound bandwidth limit: {} bytes/s, burst ratio: {}",
config.bandwidth_limit,
config.bandwidth_limit_burst_ratio);
// Cancelling local work generation
observers.work_cancel.add ([this] (nano::root const & root_a) {
this->work.cancel (root_a);
this->distributed_work.cancel (root_a);
});
if (!block_or_pruned_exists (config.network_params.ledger.genesis->hash ()))
{
logger.critical (nano::log::type::node, "Genesis block not found. This commonly indicates a configuration issue, check that the --network or --data_path command line arguments are correct, and also the ledger backend node config option. If using a read-only CLI command a ledger must already exist, start the node with --daemon first.");
auto const network_label = network_params.network.get_current_network_as_string ();
logger.info (nano::log::type::node, "Version: {}", NANO_VERSION_STRING);
logger.info (nano::log::type::node, "Build information: {}", BUILD_INFO);
logger.info (nano::log::type::node, "Active network: {}", network_label);
logger.info (nano::log::type::node, "Database backend: {}", store.vendor_get ());
logger.info (nano::log::type::node, "Data path: {}", application_path.string ());
logger.info (nano::log::type::node, "Ledger path: {}", store.get_database_path ().string ());
logger.info (nano::log::type::node, "Work pool threads: {} ({})", work.threads.size (), (work.opencl ? "OpenCL" : "CPU"));
logger.info (nano::log::type::node, "Work peers: {}", config.work_peers.size ());
logger.info (nano::log::type::node, "Node ID: {}", node_id.pub.to_node_id ());
logger.info (nano::log::type::node, "Number of buckets: {}", bucketing.size ());
logger.info (nano::log::type::node, "Genesis block: {}", config.network_params.ledger.genesis->hash ().to_string ());
logger.info (nano::log::type::node, "Genesis account: {}", config.network_params.ledger.genesis->account ().to_account ());
if (!work_generation_enabled ())
if (network_params.network.is_beta_network ())
{
logger.warn (nano::log::type::node, "Work generation is disabled");
logger.critical (nano::log::type::node, "Beta network may have reset, try clearing database files");
}
logger.info (nano::log::type::node, "Outbound bandwidth limit: {} bytes/s, burst ratio: {}",
config.bandwidth_limit,
config.bandwidth_limit_burst_ratio);
std::exit (1);
}
if (!block_or_pruned_exists (config.network_params.ledger.genesis->hash ()))
auto reps = wallets.reps ();
if (reps.half_principal)
{
logger.info (nano::log::type::node, "Found {} local representatives in wallets", reps.accounts.size ());
for (auto const & account : reps.accounts)
{
logger.critical (nano::log::type::node, "Genesis block not found. This commonly indicates a configuration issue, check that the --network or --data_path command line arguments are correct, and also the ledger backend node config option. If using a read-only CLI command a ledger must already exist, start the node with --daemon first.");
logger.info (nano::log::type::node, "Local representative: {}", account.to_account ());
}
}
if (network_params.network.is_beta_network ())
if (flags.enable_voting)
{
config.enable_voting = true;
}
if (config.enable_voting)
{
logger.info (nano::log::type::node, "Voting is enabled, more system resources will be used, local representatives: {}", reps.accounts.size ());
if (reps.accounts.size () > 1)
{
logger.warn (nano::log::type::node, "Voting with more than one representative can limit performance");
}
}
else if (reps.half_principal)
{
logger.warn (nano::log::type::node, "Found local representatives in wallets, but voting is disabled. To enable voting, set `[node] enable_voting=true` in the `config-node.toml` file or use `--enable_voting` command line argument");
}
if ((network_params.network.is_live_network () || network_params.network.is_beta_network ()) && !flags.inactive_node)
{
auto const bootstrap_weights = get_bootstrap_weights ();
ledger.bootstrap_weight_max_blocks = bootstrap_weights.first;
ledger.bootstrap_weights = bootstrap_weights.second;
logger.info (nano::log::type::node, "Initial bootstrap height: {:>10}", ledger.bootstrap_weight_max_blocks);
logger.info (nano::log::type::node, "Current ledger height: {:>10}", ledger.block_count ());
// Use bootstrap weights if initial bootstrap is not completed
const bool use_bootstrap_weight = !ledger.bootstrap_height_reached ();
if (use_bootstrap_weight)
{
logger.info (nano::log::type::node, "Using predefined representative weights, since block count is less than bootstrap threshold");
logger.info (nano::log::type::node, "******************************************** Bootstrap weights ********************************************");
// Sort the weights
std::vector<std::pair<nano::account, nano::uint128_t>> sorted_weights (ledger.bootstrap_weights.begin (), ledger.bootstrap_weights.end ());
std::sort (sorted_weights.begin (), sorted_weights.end (), [] (auto const & entry1, auto const & entry2) {
return entry1.second > entry2.second;
});
for (auto const & rep : sorted_weights)
{
logger.critical (nano::log::type::node, "Beta network may have reset, try clearing database files");
logger.info (nano::log::type::node, "Using bootstrap rep weight: {} -> {}",
rep.first.to_account (),
nano::uint128_union (rep.second).format_balance (nano_ratio, 0, true));
}
logger.info (nano::log::type::node, "******************************************** ================= ********************************************");
}
}
ledger.pruning = flags.enable_pruning || store.pruned.count (store.tx_begin_read ()) > 0;
if (ledger.pruning)
{
if (config.enable_voting && !flags.inactive_node)
{
logger.critical (nano::log::type::node, "Incompatibility detected between config node.enable_voting and existing pruned blocks");
std::exit (1);
}
if (!flags.enable_pruning && !flags.inactive_node)
{
logger.critical (nano::log::type::node, "To start node with existing pruned blocks use launch flag --enable_pruning");
std::exit (1);
}
auto reps = wallets.reps ();
if (reps.half_principal)
{
logger.info (nano::log::type::node, "Found {} local representatives in wallets", reps.accounts.size ());
for (auto const & account : reps.accounts)
{
logger.info (nano::log::type::node, "Local representative: {}", account.to_account ());
}
}
if (flags.enable_voting)
{
config.enable_voting = true;
}
if (config.enable_voting)
{
logger.info (nano::log::type::node, "Voting is enabled, more system resources will be used, local representatives: {}", reps.accounts.size ());
if (reps.accounts.size () > 1)
{
logger.warn (nano::log::type::node, "Voting with more than one representative can limit performance");
}
}
else if (reps.half_principal)
{
logger.warn (nano::log::type::node, "Found local representatives in wallets, but voting is disabled. To enable voting, set `[node] enable_voting=true` in the `config-node.toml` file or use `--enable_voting` command line argument");
}
if ((network_params.network.is_live_network () || network_params.network.is_beta_network ()) && !flags.inactive_node)
{
auto const bootstrap_weights = get_bootstrap_weights ();
ledger.bootstrap_weight_max_blocks = bootstrap_weights.first;
ledger.bootstrap_weights = bootstrap_weights.second;
logger.info (nano::log::type::node, "Initial bootstrap height: {:>10}", ledger.bootstrap_weight_max_blocks);
logger.info (nano::log::type::node, "Current ledger height: {:>10}", ledger.block_count ());
// Use bootstrap weights if initial bootstrap is not completed
const bool use_bootstrap_weight = !ledger.bootstrap_height_reached ();
if (use_bootstrap_weight)
{
logger.info (nano::log::type::node, "Using predefined representative weights, since block count is less than bootstrap threshold");
logger.info (nano::log::type::node, "******************************************** Bootstrap weights ********************************************");
// Sort the weights
std::vector<std::pair<nano::account, nano::uint128_t>> sorted_weights (ledger.bootstrap_weights.begin (), ledger.bootstrap_weights.end ());
std::sort (sorted_weights.begin (), sorted_weights.end (), [] (auto const & entry1, auto const & entry2) {
return entry1.second > entry2.second;
});
for (auto const & rep : sorted_weights)
{
logger.info (nano::log::type::node, "Using bootstrap rep weight: {} -> {}",
rep.first.to_account (),
nano::uint128_union (rep.second).format_balance (nano_ratio, 0, true));
}
logger.info (nano::log::type::node, "******************************************** ================= ********************************************");
}
}
ledger.pruning = flags.enable_pruning || store.pruned.count (store.tx_begin_read ()) > 0;
if (ledger.pruning)
{
if (config.enable_voting && !flags.inactive_node)
{
logger.critical (nano::log::type::node, "Incompatibility detected between config node.enable_voting and existing pruned blocks");
std::exit (1);
}
if (!flags.enable_pruning && !flags.inactive_node)
{
logger.critical (nano::log::type::node, "To start node with existing pruned blocks use launch flag --enable_pruning");
std::exit (1);
}
logger.warn (nano::log::type::node, "WARNING: Ledger pruning is enabled. This feature is experimental and may result in node instability! Please see release notes for more information.");
}
cementing_set.cemented_observers.add ([this] (auto const & block) {
// TODO: Is it neccessary to call this for all blocks?
if (block->is_send ())
{
wallet_workers.post ([this, hash = block->hash (), destination = block->destination ()] () {
wallets.receive_confirmed (hash, destination);
});
}
});
}
else
{
logger.error (nano::log::type::node, "Failed to initialize node");
logger.warn (nano::log::type::node, "WARNING: Ledger pruning is enabled. This feature is experimental and may result in node instability! Please see release notes for more information.");
}
cementing_set.cemented_observers.add ([this] (auto const & block) {
// TODO: Is it neccessary to call this for all blocks?
if (block->is_send ())
{
wallet_workers.post ([this, hash = block->hash (), destination = block->destination ()] () {
wallets.receive_confirmed (hash, destination);
});
}
});
node_initialized_latch.count_down ();
}
@ -883,11 +877,6 @@ int nano::node::store_version ()
return store.version.get (transaction);
}
bool nano::node::init_error () const
{
return store.init_error () || wallets_store.init_error ();
}
std::pair<uint64_t, std::unordered_map<nano::account, nano::uint128_t>> nano::node::get_bootstrap_weights () const
{
std::vector<std::pair<std::string, std::string>> preconfigured_weights = network_params.network.is_live_network () ? nano::weights::preconfigured_weights_live : nano::weights::preconfigured_weights_beta;

View file

@ -81,7 +81,6 @@ public:
uint64_t cemented_count () const;
bool online () const;
bool init_error () const;
std::pair<uint64_t, std::unordered_map<nano::account, nano::uint128_t>> get_bootstrap_weights () const;
/*
* Attempts to bootstrap block. This is the best effort, there is no guarantee that the block will be bootstrapped.

View file

@ -1920,15 +1920,10 @@ auto nano::wallet_store::end (store::transaction const & transaction_a) -> itera
}
nano::mdb_wallets_store::mdb_wallets_store (std::filesystem::path const & path_a, nano::lmdb_config const & lmdb_config_a) :
environment (error, path_a, nano::store::lmdb::env::options::make ().set_config (lmdb_config_a).override_config_sync (nano::lmdb_config::sync_strategy::always).override_config_map_size (1ULL * 1024 * 1024 * 1024))
environment (path_a, nano::store::lmdb::env::options::make ().set_config (lmdb_config_a).override_config_sync (nano::lmdb_config::sync_strategy::always).override_config_map_size (1ULL * 1024 * 1024 * 1024))
{
}
bool nano::mdb_wallets_store::init_error () const
{
return error;
}
nano::container_info nano::wallets::container_info () const
{
nano::lock_guard<nano::mutex> guard{ mutex };

View file

@ -264,7 +264,6 @@ class wallets_store
{
public:
virtual ~wallets_store () = default;
virtual bool init_error () const = 0;
};
class mdb_wallets_store final : public wallets_store
@ -272,7 +271,6 @@ class mdb_wallets_store final : public wallets_store
public:
mdb_wallets_store (std::filesystem::path const &, nano::lmdb_config const & lmdb_config_a = nano::lmdb_config{});
nano::store::lmdb::env environment;
bool init_error () const override;
bool error{ false };
};
}

View file

@ -520,7 +520,6 @@ TEST (history, short_text)
nano::logger logger;
nano::stats stats{ logger };
auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
ASSERT_TRUE (!store->init_error ());
nano::ledger ledger (*store, nano::dev::constants, stats, logger);
{
auto transaction (ledger.tx_begin_write ());
@ -558,7 +557,6 @@ TEST (history, pruned_source)
nano::logger logger;
nano::stats stats{ logger };
auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
ASSERT_TRUE (!store->init_error ());
nano::ledger ledger (*store, nano::dev::constants, stats, logger);
ledger.pruning = true;
nano::block_hash next_pruning;

View file

@ -42,16 +42,7 @@ nano::ledger::ledger (nano::store::component & store_a, nano::ledger_constants &
any{ *any_impl },
confirmed{ *confirmed_impl }
{
// TODO: Throw on error
if (!store.init_error ())
{
initialize (generate_cache_flags_a);
}
else
{
logger.error (nano::log::type::ledger, "Ledger initialization failed, store initialization error");
throw std::runtime_error ("Ledger initialization failed, store initialization error");
}
initialize (generate_cache_flags_a);
}
nano::ledger::~ledger ()
@ -841,12 +832,11 @@ bool nano::ledger::migrate_lmdb_to_rocksdb (std::filesystem::path const & data_p
auto error (false);
// Open rocksdb database
nano::node_config node_config;
node_config.database_backend = database_backend::rocksdb;
auto rocksdb_store = nano::make_store (logger, data_path_a, nano::dev::constants, false, true, node_config);
if (!rocksdb_store->init_error ())
try
{
nano::node_config node_config;
node_config.database_backend = database_backend::rocksdb;
auto rocksdb_store = nano::make_store (logger, data_path_a, nano::dev::constants, false, true, node_config);
auto table_size = store.count (store.tx_begin_read (), tables::blocks);
logger.info (nano::log::type::ledger, "Step 1 of 7: Converting {} entries from blocks table", table_size);
std::atomic<std::size_t> count = 0;
@ -1028,7 +1018,7 @@ bool nano::ledger::migrate_lmdb_to_rocksdb (std::filesystem::path const & data_p
logger.info (nano::log::type::ledger, "Migration completed. Make sure to set `database_backend` under [node] to 'rocksdb' in config-node.toml");
logger.info (nano::log::type::ledger, "After confirming correct node operation, the data.ldb file can be deleted if no longer required");
}
else
catch (std::exception const &)
{
error = true;
}

View file

@ -101,7 +101,6 @@ TEST (system, receive_while_synchronizing)
system.generate_mass_activity (count, *system.nodes[0]);
nano::keypair key;
auto node1 (std::make_shared<nano::node> (system.io_ctx, system.get_available_port (), nano::unique_path (), system.work));
ASSERT_FALSE (node1->init_error ());
auto wallet (node1->wallets.create (1));
wallet->insert_adhoc (nano::dev::genesis_key.prv); // For voting
ASSERT_EQ (key.pub, wallet->insert_adhoc (key.prv));
@ -130,7 +129,6 @@ TEST (ledger, deep_account_compute)
{
nano::logger logger;
auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
ASSERT_FALSE (store->init_error ());
nano::stats stats{ logger };
nano::ledger ledger (*store, nano::dev::constants, stats, logger);
auto transaction = ledger.tx_begin_write ();
@ -554,7 +552,7 @@ TEST (store, pruned_load)
boost::unordered_set<nano::block_hash> hashes;
{
auto store = nano::make_store (logger, path, nano::dev::constants);
ASSERT_FALSE (store->init_error ());
for (auto i (0); i < num_pruned / batch_size; ++i)
{
{
@ -585,7 +583,7 @@ TEST (store, pruned_load)
// Reinitialize store
{
auto store = nano::make_store (logger, path, nano::dev::constants);
ASSERT_FALSE (store->init_error ());
ASSERT_EQ (expected_result, manually_count_pruned_blocks (*store));
}
}
@ -1131,7 +1129,7 @@ TEST (confirmation_height, many_accounts_send_receive_self_no_elections)
nano::logger logger;
auto path (nano::unique_path ());
auto store = nano::make_store (logger, path, nano::dev::constants);
ASSERT_TRUE (!store->init_error ());
nano::stats stats{ logger };
nano::ledger ledger (*store, nano::dev::constants, stats, logger);
nano::store::write_queue write_database_queue;

View file

@ -34,7 +34,6 @@ namespace store
class component
{
friend class rocksdb_block_store_tombstone_count_Test;
friend class mdb_block_store_upgrade_v21_v22_Test;
public:
explicit component (
@ -88,8 +87,6 @@ namespace store
virtual void serialize_mdb_tracker (::boost::property_tree::ptree &, std::chrono::milliseconds, std::chrono::milliseconds){};
virtual void serialize_memory_stats (::boost::property_tree::ptree &) = 0;
virtual bool init_error () const = 0;
/** Start read-write transaction */
virtual write_transaction tx_begin_write () = 0;

View file

@ -15,6 +15,7 @@
#include <boost/property_tree/json_parser.hpp>
#include <queue>
#include <stdexcept>
template class nano::store::typed_iterator<nano::account, nano::account_info_v22>;
@ -46,96 +47,77 @@ nano::store::lmdb::component::component (nano::logger & logger_a, std::filesyste
database_path{ path_a },
mode{ mode_a },
logger{ logger_a },
env (error, path_a, nano::store::lmdb::env::options::make ().set_config (lmdb_config_a).set_use_no_mem_init (true).set_read_only (mode_a == nano::store::open_mode::read_only)),
env (path_a, nano::store::lmdb::env::options::make ().set_config (lmdb_config_a).set_use_no_mem_init (true).set_read_only (mode_a == nano::store::open_mode::read_only)),
mdb_txn_tracker (logger_a, txn_tracking_config_a, block_processor_batch_max_time_a),
txn_tracking_enabled (txn_tracking_config_a.enable)
{
if (!error)
logger.info (nano::log::type::lmdb, "Initializing ledger store: {}", database_path.string ());
debug_assert (path_a.filename () == "data.ldb");
auto is_fully_upgraded (false);
auto is_fresh_db (false);
{
logger.info (nano::log::type::lmdb, "Initializing ledger store: {}", database_path.string ());
debug_assert (path_a.filename () == "data.ldb");
auto is_fully_upgraded (false);
auto is_fresh_db (false);
auto transaction (tx_begin_read ());
auto err = mdb_dbi_open (env.tx (transaction), "meta", 0, &version_store.meta_handle);
is_fresh_db = err != MDB_SUCCESS;
if (err == MDB_SUCCESS)
{
auto transaction (tx_begin_read ());
auto err = mdb_dbi_open (env.tx (transaction), "meta", 0, &version_store.meta_handle);
is_fresh_db = err != MDB_SUCCESS;
if (err == MDB_SUCCESS)
{
is_fully_upgraded = (version.get (transaction) == version_current);
mdb_dbi_close (env, version_store.meta_handle);
}
is_fully_upgraded = (version.get (transaction) == version_current);
mdb_dbi_close (env, version_store.meta_handle);
}
}
// Only open a write lock when upgrades are needed. This is because CLI commands
// open inactive nodes which can otherwise be locked here if there is a long write
// (can be a few minutes with the --fast_bootstrap flag for instance)
if (!is_fully_upgraded)
{
if (mode == nano::store::open_mode::read_only)
{
// Either following cases cannot run in read-only mode:
// a) there is no database yet, the access needs to be in write mode for it to be created;
// b) it will upgrade, and it is not possible to do it in read-only mode.
throw std::runtime_error ("Database requires upgrade but was opened in read-only mode");
}
// Only open a write lock when upgrades are needed. This is because CLI commands
// open inactive nodes which can otherwise be locked here if there is a long write
// (can be a few minutes with the --fast_bootstrap flag for instance)
if (!is_fully_upgraded)
if (!is_fresh_db)
{
if (mode == nano::store::open_mode::read_only)
{
// Either following cases cannot run in read-only mode:
// a) there is no database yet, the access needs to be in write mode for it to be created;
// b) it will upgrade, and it is not possible to do it in read-only mode.
error = true;
return;
}
logger.info (nano::log::type::lmdb, "Upgrade in progress...");
if (!is_fresh_db)
if (backup_before_upgrade_a)
{
logger.info (nano::log::type::lmdb, "Upgrade in progress...");
if (backup_before_upgrade_a)
{
create_backup_file (env, path_a, logger);
}
}
auto needs_vacuuming = false;
{
auto transaction (tx_begin_write ());
open_databases (error, transaction, MDB_CREATE);
if (!error)
{
error |= do_upgrades (transaction, constants, needs_vacuuming);
if (error)
{
logger.error (nano::log::type::lmdb, "Failed to upgrade database: {}", database_path.string ());
return;
}
else
{
logger.info (nano::log::type::lmdb, "Database upgraded successfully to version {}", version_current);
}
}
}
if (needs_vacuuming)
{
logger.info (nano::log::type::lmdb, "Ledger vacuum in progress...");
auto vacuum_success = vacuum_after_upgrade (path_a, lmdb_config_a);
if (vacuum_success)
{
logger.info (nano::log::type::lmdb, "Ledger vacuum completed");
}
else
{
logger.error (nano::log::type::lmdb, "Ledger vacuum failed");
logger.error (nano::log::type::lmdb, "(Optional) Please ensure enough disk space is available for a copy of the database and try to vacuum after shutting down the node");
}
create_backup_file (env, path_a, logger);
}
}
else
auto needs_vacuuming = false;
{
auto transaction (tx_begin_read ());
open_databases (error, transaction, 0);
auto transaction (tx_begin_write ());
open_databases (transaction, MDB_CREATE);
do_upgrades (transaction, constants, needs_vacuuming);
logger.info (nano::log::type::lmdb, "Database upgraded successfully to version {}", version_current);
}
if (needs_vacuuming)
{
logger.info (nano::log::type::lmdb, "Ledger vacuum in progress...");
auto vacuum_success = vacuum_after_upgrade (path_a, lmdb_config_a);
if (vacuum_success)
{
logger.info (nano::log::type::lmdb, "Ledger vacuum completed");
}
else
{
logger.error (nano::log::type::lmdb, "Ledger vacuum failed");
logger.error (nano::log::type::lmdb, "(Optional) Please ensure enough disk space is available for a copy of the database and try to vacuum after shutting down the node");
}
}
}
else
{
logger.critical (nano::log::type::lmdb, "Failed to initialize database environment: {}", database_path.string ());
auto transaction (tx_begin_read ());
open_databases (transaction, 0);
}
}
@ -159,12 +141,9 @@ bool nano::store::lmdb::component::vacuum_after_upgrade (std::filesystem::path c
auto options = nano::store::lmdb::env::options::make ()
.set_config (lmdb_config_a)
.set_use_no_mem_init (true);
env.init (error, path_a, options);
if (!error)
{
auto transaction (tx_begin_read ());
open_databases (error, transaction, 0);
}
env.init (path_a, options);
auto transaction (tx_begin_read ());
open_databases (transaction, 0);
}
else
{
@ -232,30 +211,38 @@ nano::store::lmdb::txn_callbacks nano::store::lmdb::component::create_txn_callba
return mdb_txn_callbacks;
}
void nano::store::lmdb::component::open_databases (bool & error_a, store::transaction const & transaction_a, unsigned flags)
void nano::store::lmdb::component::open_table (store::transaction const & transaction_a, char const * name, unsigned flags, MDB_dbi & handle)
{
error_a |= mdb_dbi_open (env.tx (transaction_a), "online_weight", flags, &online_weight_store.online_weight_handle) != 0;
error_a |= mdb_dbi_open (env.tx (transaction_a), "meta", flags, &version_store.meta_handle) != 0;
error_a |= mdb_dbi_open (env.tx (transaction_a), "peers", flags, &peer_store.peers_handle) != 0;
error_a |= mdb_dbi_open (env.tx (transaction_a), "pruned", flags, &pruned_store.pruned_handle) != 0;
error_a |= mdb_dbi_open (env.tx (transaction_a), "confirmation_height", flags, &confirmation_height_store.confirmation_height_handle) != 0;
error_a |= mdb_dbi_open (env.tx (transaction_a), "accounts", flags, &account_store.accounts_v0_handle) != 0;
account_store.accounts_handle = account_store.accounts_v0_handle;
error_a |= mdb_dbi_open (env.tx (transaction_a), "pending", flags, &pending_store.pending_v0_handle) != 0;
pending_store.pending_handle = pending_store.pending_v0_handle;
error_a |= mdb_dbi_open (env.tx (transaction_a), "final_votes", flags, &final_vote_store.final_votes_handle) != 0;
error_a |= mdb_dbi_open (env.tx (transaction_a), "blocks", MDB_CREATE, &block_store.blocks_handle) != 0;
error_a |= mdb_dbi_open (env.tx (transaction_a), "rep_weights", flags, &rep_weight_store.rep_weights_handle) != 0;
auto status = mdb_dbi_open (env.tx (transaction_a), name, flags, &handle);
if (status != 0)
{
throw std::runtime_error ("Failed to open " + std::string (name) + " database: " + error_string (status));
}
}
bool nano::store::lmdb::component::do_upgrades (store::write_transaction & transaction, nano::ledger_constants & constants, bool & needs_vacuuming)
void nano::store::lmdb::component::open_databases (store::transaction const & transaction_a, unsigned flags)
{
open_table (transaction_a, "online_weight", flags, online_weight_store.online_weight_handle);
open_table (transaction_a, "meta", flags, version_store.meta_handle);
open_table (transaction_a, "peers", flags, peer_store.peers_handle);
open_table (transaction_a, "pruned", flags, pruned_store.pruned_handle);
open_table (transaction_a, "confirmation_height", flags, confirmation_height_store.confirmation_height_handle);
open_table (transaction_a, "accounts", flags, account_store.accounts_v0_handle);
account_store.accounts_handle = account_store.accounts_v0_handle;
open_table (transaction_a, "pending", flags, pending_store.pending_v0_handle);
pending_store.pending_handle = pending_store.pending_v0_handle;
open_table (transaction_a, "final_votes", flags, final_vote_store.final_votes_handle);
open_table (transaction_a, "blocks", MDB_CREATE, block_store.blocks_handle);
open_table (transaction_a, "rep_weights", flags, rep_weight_store.rep_weights_handle);
}
void nano::store::lmdb::component::do_upgrades (store::write_transaction & transaction, nano::ledger_constants & constants, bool & needs_vacuuming)
{
auto error (false);
auto version_l = version.get (transaction);
if (version_l < version_minimum)
{
logger.critical (nano::log::type::lmdb, "The version of the ledger ({}) is lower than the minimum ({}) which is supported for upgrades. Either upgrade a node first or delete the ledger.", version_l, version_minimum);
return true;
throw std::runtime_error ("Ledger version " + std::to_string (version_l) + " is lower than minimum supported version " + std::to_string (version_minimum));
}
switch (version_l)
{
@ -272,10 +259,8 @@ bool nano::store::lmdb::component::do_upgrades (store::write_transaction & trans
break;
default:
logger.critical (nano::log::type::lmdb, "The version of the ledger ({}) is too high for this node", version_l);
error = true;
break;
throw std::runtime_error ("Ledger version " + std::to_string (version_l) + " is too high for this node");
}
return error;
}
void nano::store::lmdb::component::upgrade_v21_to_v22 (store::write_transaction & transaction)
@ -567,11 +552,6 @@ void nano::store::lmdb::component::rebuild_db (store::write_transaction const &
}
}
bool nano::store::lmdb::component::init_error () const
{
return error;
}
nano::store::lmdb::component::upgrade_counters::upgrade_counters (uint64_t count_before_v0, uint64_t count_before_v1) :
before_v0 (count_before_v0),
before_v1 (count_before_v1)

View file

@ -92,19 +92,18 @@ public:
bool copy_db (std::filesystem::path const & destination_file) override;
void rebuild_db (store::write_transaction const & transaction_a) override;
bool init_error () const override;
uint64_t count (store::transaction const &, MDB_dbi) const;
std::string error_string (int status) const override;
private:
bool do_upgrades (store::write_transaction &, nano::ledger_constants & constants, bool &);
void do_upgrades (store::write_transaction &, nano::ledger_constants & constants, bool &);
void upgrade_v21_to_v22 (store::write_transaction &);
void upgrade_v22_to_v23 (store::write_transaction &);
void upgrade_v23_to_v24 (store::write_transaction &);
void open_databases (bool &, store::transaction const &, unsigned);
void open_databases (store::transaction const &, unsigned);
void open_table (store::transaction const &, char const * name, unsigned flags, MDB_dbi & handle);
int drop (store::write_transaction const & transaction_a, tables table_a) override;
int clear (store::write_transaction const & transaction_a, MDB_dbi handle_a);
@ -137,10 +136,6 @@ private:
uint64_t after_v0{ 0 };
uint64_t after_v1{ 0 };
};
friend class mdb_block_store_supported_version_upgrades_Test;
friend class mdb_block_store_upgrade_v21_v22_Test;
friend class block_store_DISABLED_change_dupsort_Test;
};
bool success (int status);

View file

@ -5,13 +5,13 @@
#include <boost/system/error_code.hpp>
nano::store::lmdb::env::env (bool & error_a, std::filesystem::path const & path_a, nano::store::lmdb::env::options options_a) :
nano::store::lmdb::env::env (std::filesystem::path const & path_a, nano::store::lmdb::env::options options_a) :
database_path{ path_a }
{
init (error_a, path_a, options_a);
init (path_a, options_a);
}
void nano::store::lmdb::env::init (bool & error_a, std::filesystem::path const & path_a, nano::store::lmdb::env::options options_a)
void nano::store::lmdb::env::init (std::filesystem::path const & path_a, nano::store::lmdb::env::options options_a)
{
debug_assert (path_a.extension () == ".ldb", "invalid filename extension for lmdb database file");
@ -74,16 +74,15 @@ void nano::store::lmdb::env::init (bool & error_a, std::filesystem::path const &
throw std::runtime_error (message);
}
release_assert (success (status4), error_string (status4));
error_a = !success (status4);
}
else
{
error_a = true;
throw std::runtime_error ("Could not create database directory: " + error_mkdir.message ());
}
}
else
{
error_a = true;
throw std::runtime_error ("Invalid database path: path must have parent directory");
}
}

View file

@ -62,8 +62,8 @@ public:
nano::lmdb_config config;
};
env (bool &, std::filesystem::path const &, env::options options_a = env::options::make ());
void init (bool &, std::filesystem::path const &, env::options options_a = env::options::make ());
env (std::filesystem::path const &, env::options options_a = env::options::make ());
void init (std::filesystem::path const &, env::options options_a = env::options::make ());
~env ();
operator MDB_env * () const;
store::read_transaction tx_begin_read (txn_callbacks callbacks = txn_callbacks{}) const;

View file

@ -12,6 +12,8 @@
#include <boost/polymorphic_cast.hpp>
#include <boost/property_tree/ptree.hpp>
#include <stdexcept>
#include <rocksdb/merge_operator.h>
#include <rocksdb/slice.h>
#include <rocksdb/slice_transform.h>
@ -74,12 +76,11 @@ nano::store::rocksdb::component::component (nano::logger & logger_a, std::filesy
boost::system::error_code error_mkdir, error_chmod;
std::filesystem::create_directories (path_a, error_mkdir);
nano::set_secure_perm_directory (path_a, error_chmod);
error = static_cast<bool> (error_mkdir);
if (error)
if (error_mkdir)
{
logger.critical (nano::log::type::rocksdb, "Failed to create database directory: {}", path_a.string ());
return;
throw std::runtime_error ("Failed to create database directory: " + path_a.string ());
}
logger.info (nano::log::type::rocksdb, "Initializing ledger store: {}", database_path.string ());
@ -94,7 +95,14 @@ nano::store::rocksdb::component::component (nano::logger & logger_a, std::filesy
// The only certain column family is "meta" which contains the DB version info.
// RocksDB requires this operation to be in read-only mode.
auto is_fresh_db = false;
open (is_fresh_db, path_a, true, options, get_single_column_family ("meta"));
try
{
open (path_a, true, options, get_single_column_family ("meta"));
}
catch (std::runtime_error const &)
{
is_fresh_db = true;
}
auto is_fully_upgraded = false;
if (!is_fresh_db)
@ -104,16 +112,12 @@ nano::store::rocksdb::component::component (nano::logger & logger_a, std::filesy
if (version_l > version_current)
{
logger.critical (nano::log::type::rocksdb, "The version of the ledger ({}) is too high for this node", version_l);
error = true;
return;
throw std::runtime_error ("Ledger version " + std::to_string (version_l) + " is too high for this node");
}
else if (version_l < version_minimum)
{
logger.critical (nano::log::type::rocksdb, "The version of the ledger ({}) is lower than the minimum ({}) which is supported for upgrades. Either upgrade a node first or delete the ledger.", version_l, version_minimum);
error = true;
return;
throw std::runtime_error ("Ledger version " + std::to_string (version_l) + " is lower than minimum supported version " + std::to_string (version_minimum));
}
is_fully_upgraded = (version_l == version_current);
}
@ -127,7 +131,7 @@ nano::store::rocksdb::component::component (nano::logger & logger_a, std::filesy
if (is_fully_upgraded)
{
open (error, path_a, (mode == nano::store::open_mode::read_only), options, create_column_families ());
open (path_a, (mode == nano::store::open_mode::read_only), options, create_column_families ());
return;
}
@ -136,29 +140,22 @@ nano::store::rocksdb::component::component (nano::logger & logger_a, std::filesy
// Either following cases cannot run in read-only mode:
// a) there is no database yet, the access needs to be in write mode for it to be created;
// b) it will upgrade, and it is not possible to do it in read-only mode.
error = true;
return;
throw std::runtime_error ("Database requires upgrade but was opened in read-only mode");
}
if (is_fresh_db)
{
open (error, path_a, (mode == nano::store::open_mode::read_only), options, create_column_families ());
if (!error)
{
version.put (tx_begin_write (), version_current); // It is fresh, someone needs to tell it its version.
}
open (path_a, (mode == nano::store::open_mode::read_only), options, create_column_families ());
version.put (tx_begin_write (), version_current); // It is fresh, someone needs to tell it its version.
return;
}
// The database is not upgraded, and it may not be compatible with the current column family set.
open (error, path_a, (mode == nano::store::open_mode::read_only), options, get_current_column_families (path_a.string (), options));
if (!error)
{
logger.info (nano::log::type::rocksdb, "Upgrade in progress...");
open (path_a, (mode == nano::store::open_mode::read_only), options, get_current_column_families (path_a.string (), options));
logger.info (nano::log::type::rocksdb, "Upgrade in progress...");
auto transaction = tx_begin_write ();
error |= do_upgrades (transaction);
}
auto transaction = tx_begin_write ();
do_upgrades (transaction);
}
std::unordered_map<char const *, nano::tables> nano::store::rocksdb::component::create_cf_name_table_map () const
@ -180,7 +177,7 @@ std::unordered_map<char const *, nano::tables> nano::store::rocksdb::component::
return map;
}
void nano::store::rocksdb::component::open (bool & error_a, std::filesystem::path const & path_a, bool open_read_only_a, ::rocksdb::Options const & options_a, std::vector<::rocksdb::ColumnFamilyDescriptor> column_families)
void nano::store::rocksdb::component::open (std::filesystem::path const & path_a, bool open_read_only_a, ::rocksdb::Options const & options_a, std::vector<::rocksdb::ColumnFamilyDescriptor> column_families)
{
// auto options = get_db_options ();
::rocksdb::Status s;
@ -207,18 +204,20 @@ void nano::store::rocksdb::component::open (bool & error_a, std::filesystem::pat
handles[i].reset (handles_l[i]);
}
// Assign handles to supplied
error_a |= !s.ok ();
// Check for errors
if (!s.ok ())
{
throw std::runtime_error ("Failed to open RocksDB: " + s.ToString ());
}
}
bool nano::store::rocksdb::component::do_upgrades (store::write_transaction & transaction)
void nano::store::rocksdb::component::do_upgrades (store::write_transaction & transaction)
{
auto error (false);
auto version_l = version.get (transaction);
if (version_l < version_minimum)
{
logger.critical (nano::log::type::rocksdb, "The version of the ledger ({}) is lower than the minimum ({}) which is supported for upgrades. Either upgrade a node first or delete the ledger.", version_l, version_minimum);
return true;
throw std::runtime_error ("Ledger version " + std::to_string (version_l) + " is lower than minimum supported version " + std::to_string (version_minimum));
}
switch (version_l)
{
@ -235,10 +234,8 @@ bool nano::store::rocksdb::component::do_upgrades (store::write_transaction & tr
break;
default:
logger.critical (nano::log::type::rocksdb, "The version of the ledger ({}) is too high for this node", version_l);
error = true;
break;
throw std::runtime_error ("Ledger version " + std::to_string (version_l) + " is too high for this node");
}
return error;
}
void nano::store::rocksdb::component::upgrade_v21_to_v22 (store::write_transaction & transaction)
@ -877,8 +874,15 @@ bool nano::store::rocksdb::component::copy_db (std::filesystem::path const & des
// Open it so that it flushes all WAL files
if (status.ok ())
{
nano::store::rocksdb::component rocksdb_store{ logger, destination_path.string (), constants, rocksdb_config };
return !rocksdb_store.init_error ();
try
{
nano::store::rocksdb::component rocksdb_store{ logger, destination_path.string (), constants, rocksdb_config };
return true;
}
catch (std::exception const &)
{
return false;
}
}
return false;
}
@ -888,11 +892,6 @@ void nano::store::rocksdb::component::rebuild_db (store::write_transaction const
// Not available for RocksDB
}
bool nano::store::rocksdb::component::init_error () const
{
return error;
}
void nano::store::rocksdb::component::serialize_memory_stats (boost::property_tree::ptree & json)
{
uint64_t val;

View file

@ -86,12 +86,9 @@ public:
unsigned max_block_write_batch_num () const override;
bool init_error () const override;
std::string error_string (int status) const override;
private:
bool error{ false };
std::filesystem::path const database_path;
nano::store::open_mode const mode;
nano::logger & logger;
@ -131,9 +128,9 @@ private:
::rocksdb::ColumnFamilyHandle * table_to_column_family (tables table_a) const;
int clear (::rocksdb::ColumnFamilyHandle * column_family);
void open (bool & error_a, std::filesystem::path const & path_a, bool open_read_only_a, ::rocksdb::Options const & options_a, std::vector<::rocksdb::ColumnFamilyDescriptor> column_families);
void open (std::filesystem::path const & path_a, bool open_read_only_a, ::rocksdb::Options const & options_a, std::vector<::rocksdb::ColumnFamilyDescriptor> column_families);
bool do_upgrades (store::write_transaction &);
void do_upgrades (store::write_transaction &);
void upgrade_v21_to_v22 (store::write_transaction &);
void upgrade_v22_to_v23 (store::write_transaction &);
void upgrade_v23_to_v24 (store::write_transaction &);

View file

@ -9,7 +9,6 @@ nano::test::ledger_context::ledger_context (std::deque<std::shared_ptr<nano::blo
blocks_m{ blocks },
pool_m{ nano::dev::network_params.network, 1 }
{
debug_assert (!store_m->init_error ());
auto tx = ledger_m.tx_begin_write ();
for (auto const & i : blocks_m)
{

View file

@ -120,7 +120,6 @@ std::shared_ptr<nano::node> nano::test::system::add_node (nano::node_flags node_
std::shared_ptr<nano::node> nano::test::system::add_node (nano::node_config const & node_config_a, nano::node_flags node_flags_a, nano::transport::transport_type type_a, std::optional<nano::keypair> const & rep)
{
auto node (std::make_shared<nano::node> (io_ctx, nano::unique_path (), node_config_a, work, node_flags_a, node_sequence++));
debug_assert (!node->init_error ());
setup_node (*node);
auto wallet = node->wallets.create (nano::random_wallet_id ());
if (rep)
@ -165,7 +164,6 @@ std::shared_ptr<nano::node> nano::test::system::make_disconnected_node (std::opt
{
nano::node_config node_config = opt_node_config.has_value () ? *opt_node_config : default_config ();
auto node = std::make_shared<nano::node> (io_ctx, nano::unique_path (), node_config, work, flags);
debug_assert (!node->init_error ());
setup_node (*node);
node->start ();