Merge pull request #4925 from pwojcikdev/init-error
Use exceptions for store initialization errors
This commit is contained in:
		
				commit
				
					
						aa281cfaf0
					
				
			
		
					 28 changed files with 453 additions and 604 deletions
				
			
		|  | @ -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; | ||||
|  |  | |||
|  | @ -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 () | ||||
|  |  | |||
|  | @ -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 () }); | ||||
|  |  | |||
|  | @ -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 () }; | ||||
|  |  | |||
|  | @ -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 ()); | ||||
|  |  | |||
|  | @ -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); | ||||
|  |  | |||
|  | @ -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 () }; | ||||
|  |  | |||
|  | @ -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) | ||||
|  |  | |||
|  | @ -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"); | ||||
|  |  | |||
|  | @ -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"); | ||||
|  |  | |||
|  | @ -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); | ||||
| 		} | ||||
|  |  | |||
|  | @ -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); | ||||
| 		} | ||||
|  |  | |||
|  | @ -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; | ||||
|  |  | |||
|  | @ -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. | ||||
|  |  | |||
|  | @ -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 }; | ||||
|  |  | |||
|  | @ -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 }; | ||||
| }; | ||||
| } | ||||
|  |  | |||
|  | @ -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; | ||||
|  |  | |||
|  | @ -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; | ||||
| 	} | ||||
|  |  | |||
|  | @ -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; | ||||
|  |  | |||
|  | @ -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; | ||||
| 
 | ||||
|  |  | |||
|  | @ -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) | ||||
|  |  | |||
|  | @ -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); | ||||
|  |  | |||
|  | @ -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"); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -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; | ||||
|  |  | |||
|  | @ -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; | ||||
|  |  | |||
|  | @ -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 &); | ||||
|  |  | |||
|  | @ -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) | ||||
| 	{ | ||||
|  |  | |||
|  | @ -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 (); | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Piotr Wójcik
				Piotr Wójcik