Add unchecked_map stats (#4148)
* Add stats counting to unchecked_map. * Moving several tests related to unchecked_map to the unchecked_map.cpp file.
This commit is contained in:
		
					parent
					
						
							
								430346c0ff
							
						
					
				
			
			
				commit
				
					
						f9e5bbfb47
					
				
			
		
					 7 changed files with 240 additions and 218 deletions
				
			
		| 
						 | 
					@ -412,214 +412,6 @@ TEST (block_store, genesis)
 | 
				
			||||||
	ASSERT_EQ (nano::dev::genesis->account (), nano::dev::genesis_key.pub);
 | 
						ASSERT_EQ (nano::dev::genesis->account (), nano::dev::genesis_key.pub);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// This test checks for basic operations in the unchecked table such as putting a new block, retrieving it, and
 | 
					 | 
				
			||||||
// deleting it from the database
 | 
					 | 
				
			||||||
TEST (unchecked, simple)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	nano::test::system system{};
 | 
					 | 
				
			||||||
	nano::logger_mt logger{};
 | 
					 | 
				
			||||||
	auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
 | 
					 | 
				
			||||||
	nano::unchecked_map unchecked{ *store, false };
 | 
					 | 
				
			||||||
	ASSERT_TRUE (!store->init_error ());
 | 
					 | 
				
			||||||
	nano::block_builder builder;
 | 
					 | 
				
			||||||
	auto block = builder
 | 
					 | 
				
			||||||
				 .send ()
 | 
					 | 
				
			||||||
				 .previous (0)
 | 
					 | 
				
			||||||
				 .destination (1)
 | 
					 | 
				
			||||||
				 .balance (2)
 | 
					 | 
				
			||||||
				 .sign (nano::keypair ().prv, 4)
 | 
					 | 
				
			||||||
				 .work (5)
 | 
					 | 
				
			||||||
				 .build_shared ();
 | 
					 | 
				
			||||||
	// Asserts the block wasn't added yet to the unchecked table
 | 
					 | 
				
			||||||
	auto block_listing1 = unchecked.get (store->tx_begin_read (), block->previous ());
 | 
					 | 
				
			||||||
	ASSERT_TRUE (block_listing1.empty ());
 | 
					 | 
				
			||||||
	// Enqueues a block to be saved on the unchecked table
 | 
					 | 
				
			||||||
	unchecked.put (block->previous (), nano::unchecked_info (block));
 | 
					 | 
				
			||||||
	// Waits for the block to get written in the database
 | 
					 | 
				
			||||||
	auto check_block_is_listed = [&] (nano::transaction const & transaction_a, nano::block_hash const & block_hash_a) {
 | 
					 | 
				
			||||||
		return unchecked.get (transaction_a, block_hash_a).size () > 0;
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	ASSERT_TIMELY (5s, check_block_is_listed (store->tx_begin_read (), block->previous ()));
 | 
					 | 
				
			||||||
	auto transaction = store->tx_begin_write ();
 | 
					 | 
				
			||||||
	// Retrieves the block from the database
 | 
					 | 
				
			||||||
	auto block_listing2 = unchecked.get (transaction, block->previous ());
 | 
					 | 
				
			||||||
	ASSERT_FALSE (block_listing2.empty ());
 | 
					 | 
				
			||||||
	// Asserts the added block is equal to the retrieved one
 | 
					 | 
				
			||||||
	ASSERT_EQ (*block, *(block_listing2[0].block));
 | 
					 | 
				
			||||||
	// Deletes the block from the database
 | 
					 | 
				
			||||||
	unchecked.del (transaction, nano::unchecked_key (block->previous (), block->hash ()));
 | 
					 | 
				
			||||||
	// Asserts the block is deleted
 | 
					 | 
				
			||||||
	auto block_listing3 = unchecked.get (transaction, block->previous ());
 | 
					 | 
				
			||||||
	ASSERT_TRUE (block_listing3.empty ());
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// This test ensures the unchecked table is able to receive more than one block
 | 
					 | 
				
			||||||
TEST (unchecked, multiple)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	nano::test::system system{};
 | 
					 | 
				
			||||||
	if (nano::rocksdb_config::using_rocksdb_in_tests ())
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		// Don't test this in rocksdb mode
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	nano::logger_mt logger{};
 | 
					 | 
				
			||||||
	auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
 | 
					 | 
				
			||||||
	nano::unchecked_map unchecked{ *store, false };
 | 
					 | 
				
			||||||
	ASSERT_TRUE (!store->init_error ());
 | 
					 | 
				
			||||||
	nano::block_builder builder;
 | 
					 | 
				
			||||||
	auto block = builder
 | 
					 | 
				
			||||||
				 .send ()
 | 
					 | 
				
			||||||
				 .previous (4)
 | 
					 | 
				
			||||||
				 .destination (1)
 | 
					 | 
				
			||||||
				 .balance (2)
 | 
					 | 
				
			||||||
				 .sign (nano::keypair ().prv, 4)
 | 
					 | 
				
			||||||
				 .work (5)
 | 
					 | 
				
			||||||
				 .build_shared ();
 | 
					 | 
				
			||||||
	// Asserts the block wasn't added yet to the unchecked table
 | 
					 | 
				
			||||||
	auto block_listing1 = unchecked.get (store->tx_begin_read (), block->previous ());
 | 
					 | 
				
			||||||
	ASSERT_TRUE (block_listing1.empty ());
 | 
					 | 
				
			||||||
	// Enqueues the first block
 | 
					 | 
				
			||||||
	unchecked.put (block->previous (), nano::unchecked_info (block));
 | 
					 | 
				
			||||||
	// Enqueues a second block
 | 
					 | 
				
			||||||
	unchecked.put (block->source (), nano::unchecked_info (block));
 | 
					 | 
				
			||||||
	auto check_block_is_listed = [&] (nano::transaction const & transaction_a, nano::block_hash const & block_hash_a) {
 | 
					 | 
				
			||||||
		return unchecked.get (transaction_a, block_hash_a).size () > 0;
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	// Waits for and asserts the first block gets saved in the database
 | 
					 | 
				
			||||||
	ASSERT_TIMELY (5s, check_block_is_listed (store->tx_begin_read (), block->previous ()));
 | 
					 | 
				
			||||||
	// Waits for and asserts the second block gets saved in the database
 | 
					 | 
				
			||||||
	ASSERT_TIMELY (5s, check_block_is_listed (store->tx_begin_read (), block->source ()));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// This test ensures that a block can't occur twice in the unchecked table.
 | 
					 | 
				
			||||||
TEST (unchecked, double_put)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	nano::test::system system{};
 | 
					 | 
				
			||||||
	nano::logger_mt logger{};
 | 
					 | 
				
			||||||
	auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
 | 
					 | 
				
			||||||
	nano::unchecked_map unchecked{ *store, false };
 | 
					 | 
				
			||||||
	ASSERT_TRUE (!store->init_error ());
 | 
					 | 
				
			||||||
	nano::block_builder builder;
 | 
					 | 
				
			||||||
	auto block = builder
 | 
					 | 
				
			||||||
				 .send ()
 | 
					 | 
				
			||||||
				 .previous (4)
 | 
					 | 
				
			||||||
				 .destination (1)
 | 
					 | 
				
			||||||
				 .balance (2)
 | 
					 | 
				
			||||||
				 .sign (nano::keypair ().prv, 4)
 | 
					 | 
				
			||||||
				 .work (5)
 | 
					 | 
				
			||||||
				 .build_shared ();
 | 
					 | 
				
			||||||
	// Asserts the block wasn't added yet to the unchecked table
 | 
					 | 
				
			||||||
	auto block_listing1 = unchecked.get (store->tx_begin_read (), block->previous ());
 | 
					 | 
				
			||||||
	ASSERT_TRUE (block_listing1.empty ());
 | 
					 | 
				
			||||||
	// Enqueues the block to be saved in the unchecked table
 | 
					 | 
				
			||||||
	unchecked.put (block->previous (), nano::unchecked_info (block));
 | 
					 | 
				
			||||||
	// Enqueues the block again in an attempt to have it there twice
 | 
					 | 
				
			||||||
	unchecked.put (block->previous (), nano::unchecked_info (block));
 | 
					 | 
				
			||||||
	auto check_block_is_listed = [&] (nano::transaction const & transaction_a, nano::block_hash const & block_hash_a) {
 | 
					 | 
				
			||||||
		return unchecked.get (transaction_a, block_hash_a).size () > 0;
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	// Waits for and asserts the block was added at least once
 | 
					 | 
				
			||||||
	ASSERT_TIMELY (5s, check_block_is_listed (store->tx_begin_read (), block->previous ()));
 | 
					 | 
				
			||||||
	// Asserts the block was added at most once -- this is objective of this test.
 | 
					 | 
				
			||||||
	auto block_listing2 = unchecked.get (store->tx_begin_read (), block->previous ());
 | 
					 | 
				
			||||||
	ASSERT_EQ (block_listing2.size (), 1);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Tests that recurrent get calls return the correct values
 | 
					 | 
				
			||||||
TEST (unchecked, multiple_get)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	nano::test::system system{};
 | 
					 | 
				
			||||||
	nano::logger_mt logger{};
 | 
					 | 
				
			||||||
	auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
 | 
					 | 
				
			||||||
	nano::unchecked_map unchecked{ *store, false };
 | 
					 | 
				
			||||||
	ASSERT_TRUE (!store->init_error ());
 | 
					 | 
				
			||||||
	// Instantiates three blocks
 | 
					 | 
				
			||||||
	nano::block_builder builder;
 | 
					 | 
				
			||||||
	auto block1 = builder
 | 
					 | 
				
			||||||
				  .send ()
 | 
					 | 
				
			||||||
				  .previous (4)
 | 
					 | 
				
			||||||
				  .destination (1)
 | 
					 | 
				
			||||||
				  .balance (2)
 | 
					 | 
				
			||||||
				  .sign (nano::keypair ().prv, 4)
 | 
					 | 
				
			||||||
				  .work (5)
 | 
					 | 
				
			||||||
				  .build_shared ();
 | 
					 | 
				
			||||||
	auto block2 = builder
 | 
					 | 
				
			||||||
				  .send ()
 | 
					 | 
				
			||||||
				  .previous (3)
 | 
					 | 
				
			||||||
				  .destination (1)
 | 
					 | 
				
			||||||
				  .balance (2)
 | 
					 | 
				
			||||||
				  .sign (nano::keypair ().prv, 4)
 | 
					 | 
				
			||||||
				  .work (5)
 | 
					 | 
				
			||||||
				  .build_shared ();
 | 
					 | 
				
			||||||
	auto block3 = builder
 | 
					 | 
				
			||||||
				  .send ()
 | 
					 | 
				
			||||||
				  .previous (5)
 | 
					 | 
				
			||||||
				  .destination (1)
 | 
					 | 
				
			||||||
				  .balance (2)
 | 
					 | 
				
			||||||
				  .sign (nano::keypair ().prv, 4)
 | 
					 | 
				
			||||||
				  .work (5)
 | 
					 | 
				
			||||||
				  .build_shared ();
 | 
					 | 
				
			||||||
	// Add the blocks' info to the unchecked table
 | 
					 | 
				
			||||||
	unchecked.put (block1->previous (), nano::unchecked_info (block1)); // unchecked1
 | 
					 | 
				
			||||||
	unchecked.put (block1->hash (), nano::unchecked_info (block1)); // unchecked2
 | 
					 | 
				
			||||||
	unchecked.put (block2->previous (), nano::unchecked_info (block2)); // unchecked3
 | 
					 | 
				
			||||||
	unchecked.put (block1->previous (), nano::unchecked_info (block2)); // unchecked1
 | 
					 | 
				
			||||||
	unchecked.put (block1->hash (), nano::unchecked_info (block2)); // unchecked2
 | 
					 | 
				
			||||||
	unchecked.put (block3->previous (), nano::unchecked_info (block3));
 | 
					 | 
				
			||||||
	unchecked.put (block3->hash (), nano::unchecked_info (block3)); // unchecked4
 | 
					 | 
				
			||||||
	unchecked.put (block1->previous (), nano::unchecked_info (block3)); // unchecked1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// count the number of blocks in the unchecked table by counting them one by one
 | 
					 | 
				
			||||||
	// we cannot trust the count() method if the backend is rocksdb
 | 
					 | 
				
			||||||
	auto count_unchecked_blocks_one_by_one = [&store, &unchecked] () {
 | 
					 | 
				
			||||||
		size_t count = 0;
 | 
					 | 
				
			||||||
		auto transaction = store->tx_begin_read ();
 | 
					 | 
				
			||||||
		unchecked.for_each (transaction, [&count] (nano::unchecked_key const & key, nano::unchecked_info const & info) {
 | 
					 | 
				
			||||||
			++count;
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
		return count;
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Waits for the blocks to get saved in the database
 | 
					 | 
				
			||||||
	ASSERT_TIMELY (5s, 8 == count_unchecked_blocks_one_by_one ());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	std::vector<nano::block_hash> unchecked1;
 | 
					 | 
				
			||||||
	// Asserts the entries will be found for the provided key
 | 
					 | 
				
			||||||
	auto transaction = store->tx_begin_read ();
 | 
					 | 
				
			||||||
	auto unchecked1_blocks = unchecked.get (transaction, block1->previous ());
 | 
					 | 
				
			||||||
	ASSERT_EQ (unchecked1_blocks.size (), 3);
 | 
					 | 
				
			||||||
	for (auto & i : unchecked1_blocks)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		unchecked1.push_back (i.block->hash ());
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Asserts the payloads where correclty saved
 | 
					 | 
				
			||||||
	ASSERT_TRUE (std::find (unchecked1.begin (), unchecked1.end (), block1->hash ()) != unchecked1.end ());
 | 
					 | 
				
			||||||
	ASSERT_TRUE (std::find (unchecked1.begin (), unchecked1.end (), block2->hash ()) != unchecked1.end ());
 | 
					 | 
				
			||||||
	ASSERT_TRUE (std::find (unchecked1.begin (), unchecked1.end (), block3->hash ()) != unchecked1.end ());
 | 
					 | 
				
			||||||
	std::vector<nano::block_hash> unchecked2;
 | 
					 | 
				
			||||||
	// Asserts the entries will be found for the provided key
 | 
					 | 
				
			||||||
	auto unchecked2_blocks = unchecked.get (transaction, block1->hash ());
 | 
					 | 
				
			||||||
	ASSERT_EQ (unchecked2_blocks.size (), 2);
 | 
					 | 
				
			||||||
	for (auto & i : unchecked2_blocks)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		unchecked2.push_back (i.block->hash ());
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Asserts the payloads where correctly saved
 | 
					 | 
				
			||||||
	ASSERT_TRUE (std::find (unchecked2.begin (), unchecked2.end (), block1->hash ()) != unchecked2.end ());
 | 
					 | 
				
			||||||
	ASSERT_TRUE (std::find (unchecked2.begin (), unchecked2.end (), block2->hash ()) != unchecked2.end ());
 | 
					 | 
				
			||||||
	// Asserts the entry is found by the key and the payload is saved
 | 
					 | 
				
			||||||
	auto unchecked3 = unchecked.get (transaction, block2->previous ());
 | 
					 | 
				
			||||||
	ASSERT_EQ (unchecked3.size (), 1);
 | 
					 | 
				
			||||||
	ASSERT_EQ (unchecked3[0].block->hash (), block2->hash ());
 | 
					 | 
				
			||||||
	// Asserts the entry is found by the key and the payload is saved
 | 
					 | 
				
			||||||
	auto unchecked4 = unchecked.get (transaction, block3->hash ());
 | 
					 | 
				
			||||||
	ASSERT_EQ (unchecked4.size (), 1);
 | 
					 | 
				
			||||||
	ASSERT_EQ (unchecked4[0].block->hash (), block3->hash ());
 | 
					 | 
				
			||||||
	// Asserts no entry is found for a block that wasn't added
 | 
					 | 
				
			||||||
	auto unchecked5 = unchecked.get (transaction, block2->hash ());
 | 
					 | 
				
			||||||
	ASSERT_EQ (unchecked5.size (), 0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TEST (block_store, empty_accounts)
 | 
					TEST (block_store, empty_accounts)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	nano::logger_mt logger;
 | 
						nano::logger_mt logger;
 | 
				
			||||||
| 
						 | 
					@ -653,9 +445,10 @@ TEST (block_store, one_block)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TEST (block_store, empty_bootstrap)
 | 
					TEST (block_store, empty_bootstrap)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						nano::test::system system{};
 | 
				
			||||||
	nano::logger_mt logger;
 | 
						nano::logger_mt logger;
 | 
				
			||||||
	auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
 | 
						auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
 | 
				
			||||||
	nano::unchecked_map unchecked{ *store, false };
 | 
						nano::unchecked_map unchecked{ *store, system.stats, false };
 | 
				
			||||||
	ASSERT_TRUE (!store->init_error ());
 | 
						ASSERT_TRUE (!store->init_error ());
 | 
				
			||||||
	auto transaction (store->tx_begin_read ());
 | 
						auto transaction (store->tx_begin_read ());
 | 
				
			||||||
	size_t count = 0;
 | 
						size_t count = 0;
 | 
				
			||||||
| 
						 | 
					@ -1176,10 +969,11 @@ namespace lmdb
 | 
				
			||||||
	// Databases need to be dropped in order to convert to dupsort compatible
 | 
						// Databases need to be dropped in order to convert to dupsort compatible
 | 
				
			||||||
	TEST (block_store, DISABLED_change_dupsort) // Unchecked is no longer dupsort table
 | 
						TEST (block_store, DISABLED_change_dupsort) // Unchecked is no longer dupsort table
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
 | 
							nano::test::system system{};
 | 
				
			||||||
		auto path (nano::unique_path ());
 | 
							auto path (nano::unique_path ());
 | 
				
			||||||
		nano::logger_mt logger{};
 | 
							nano::logger_mt logger{};
 | 
				
			||||||
		nano::lmdb::store store{ logger, path, nano::dev::constants };
 | 
							nano::lmdb::store store{ logger, path, nano::dev::constants };
 | 
				
			||||||
		nano::unchecked_map unchecked{ store, false };
 | 
							nano::unchecked_map unchecked{ store, system.stats, false };
 | 
				
			||||||
		auto transaction (store.tx_begin_write ());
 | 
							auto transaction (store.tx_begin_write ());
 | 
				
			||||||
		ASSERT_EQ (0, mdb_drop (store.env.tx (transaction), store.unchecked_store.unchecked_handle, 1));
 | 
							ASSERT_EQ (0, mdb_drop (store.env.tx (transaction), store.unchecked_store.unchecked_handle, 1));
 | 
				
			||||||
		ASSERT_EQ (0, mdb_dbi_open (store.env.tx (transaction), "unchecked", MDB_CREATE, &store.unchecked_store.unchecked_handle));
 | 
							ASSERT_EQ (0, mdb_dbi_open (store.env.tx (transaction), "unchecked", MDB_CREATE, &store.unchecked_store.unchecked_handle));
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5535,12 +5535,13 @@ TEST (ledger, hash_root_random)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TEST (ledger, migrate_lmdb_to_rocksdb)
 | 
					TEST (ledger, migrate_lmdb_to_rocksdb)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						nano::test::system system{};
 | 
				
			||||||
	auto path = nano::unique_path ();
 | 
						auto path = nano::unique_path ();
 | 
				
			||||||
	nano::logger_mt logger{};
 | 
						nano::logger_mt logger{};
 | 
				
			||||||
	boost::asio::ip::address_v6 address (boost::asio::ip::make_address_v6 ("::ffff:127.0.0.1"));
 | 
						boost::asio::ip::address_v6 address (boost::asio::ip::make_address_v6 ("::ffff:127.0.0.1"));
 | 
				
			||||||
	uint16_t port = 100;
 | 
						uint16_t port = 100;
 | 
				
			||||||
	nano::lmdb::store store{ logger, path / "data.ldb", nano::dev::constants };
 | 
						nano::lmdb::store store{ logger, path / "data.ldb", nano::dev::constants };
 | 
				
			||||||
	nano::unchecked_map unchecked{ store, false };
 | 
						nano::unchecked_map unchecked{ store, system.stats, false };
 | 
				
			||||||
	nano::stats stats{};
 | 
						nano::stats stats{};
 | 
				
			||||||
	nano::ledger ledger{ store, stats, nano::dev::constants };
 | 
						nano::ledger ledger{ store, stats, nano::dev::constants };
 | 
				
			||||||
	nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits<unsigned>::max () };
 | 
						nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits<unsigned>::max () };
 | 
				
			||||||
| 
						 | 
					@ -5582,7 +5583,7 @@ TEST (ledger, migrate_lmdb_to_rocksdb)
 | 
				
			||||||
	ASSERT_FALSE (error);
 | 
						ASSERT_FALSE (error);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	nano::rocksdb::store rocksdb_store{ logger, path / "rocksdb", nano::dev::constants };
 | 
						nano::rocksdb::store rocksdb_store{ logger, path / "rocksdb", nano::dev::constants };
 | 
				
			||||||
	nano::unchecked_map rocksdb_unchecked{ rocksdb_store, false };
 | 
						nano::unchecked_map rocksdb_unchecked{ rocksdb_store, system.stats, false };
 | 
				
			||||||
	auto rocksdb_transaction (rocksdb_store.tx_begin_read ());
 | 
						auto rocksdb_transaction (rocksdb_store.tx_begin_read ());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	nano::pending_info pending_info{};
 | 
						nano::pending_info pending_info{};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,6 @@
 | 
				
			||||||
#include <nano/lib/blockbuilders.hpp>
 | 
					#include <nano/lib/blockbuilders.hpp>
 | 
				
			||||||
#include <nano/lib/logger_mt.hpp>
 | 
					#include <nano/lib/logger_mt.hpp>
 | 
				
			||||||
 | 
					#include <nano/lib/stats.hpp>
 | 
				
			||||||
#include <nano/node/unchecked_map.hpp>
 | 
					#include <nano/node/unchecked_map.hpp>
 | 
				
			||||||
#include <nano/secure/store.hpp>
 | 
					#include <nano/secure/store.hpp>
 | 
				
			||||||
#include <nano/secure/utility.hpp>
 | 
					#include <nano/secure/utility.hpp>
 | 
				
			||||||
| 
						 | 
					@ -19,10 +20,11 @@ class context
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
	context () :
 | 
						context () :
 | 
				
			||||||
		store{ nano::make_store (logger, nano::unique_path (), nano::dev::constants) },
 | 
							store{ nano::make_store (logger, nano::unique_path (), nano::dev::constants) },
 | 
				
			||||||
		unchecked{ *store, false }
 | 
							unchecked{ *store, stats, false }
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	nano::logger_mt logger;
 | 
						nano::logger_mt logger;
 | 
				
			||||||
 | 
						nano::stats stats;
 | 
				
			||||||
	std::unique_ptr<nano::store> store;
 | 
						std::unique_ptr<nano::store> store;
 | 
				
			||||||
	nano::unchecked_map unchecked;
 | 
						nano::unchecked_map unchecked;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -58,7 +60,7 @@ TEST (block_store, one_bootstrap)
 | 
				
			||||||
	nano::test::system system{};
 | 
						nano::test::system system{};
 | 
				
			||||||
	nano::logger_mt logger{};
 | 
						nano::logger_mt logger{};
 | 
				
			||||||
	auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
 | 
						auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
 | 
				
			||||||
	nano::unchecked_map unchecked{ *store, false };
 | 
						nano::unchecked_map unchecked{ *store, system.stats, false };
 | 
				
			||||||
	ASSERT_TRUE (!store->init_error ());
 | 
						ASSERT_TRUE (!store->init_error ());
 | 
				
			||||||
	nano::block_builder builder;
 | 
						nano::block_builder builder;
 | 
				
			||||||
	auto block1 = builder
 | 
						auto block1 = builder
 | 
				
			||||||
| 
						 | 
					@ -87,3 +89,211 @@ TEST (block_store, one_bootstrap)
 | 
				
			||||||
	auto block2 = blocks[0].block;
 | 
						auto block2 = blocks[0].block;
 | 
				
			||||||
	ASSERT_EQ (*block1, *block2);
 | 
						ASSERT_EQ (*block1, *block2);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// This test checks for basic operations in the unchecked table such as putting a new block, retrieving it, and
 | 
				
			||||||
 | 
					// deleting it from the database
 | 
				
			||||||
 | 
					TEST (unchecked, simple)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						nano::test::system system{};
 | 
				
			||||||
 | 
						nano::logger_mt logger{};
 | 
				
			||||||
 | 
						auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
 | 
				
			||||||
 | 
						nano::unchecked_map unchecked{ *store, system.stats, false };
 | 
				
			||||||
 | 
						ASSERT_TRUE (!store->init_error ());
 | 
				
			||||||
 | 
						nano::block_builder builder;
 | 
				
			||||||
 | 
						auto block = builder
 | 
				
			||||||
 | 
									 .send ()
 | 
				
			||||||
 | 
									 .previous (0)
 | 
				
			||||||
 | 
									 .destination (1)
 | 
				
			||||||
 | 
									 .balance (2)
 | 
				
			||||||
 | 
									 .sign (nano::keypair ().prv, 4)
 | 
				
			||||||
 | 
									 .work (5)
 | 
				
			||||||
 | 
									 .build_shared ();
 | 
				
			||||||
 | 
						// Asserts the block wasn't added yet to the unchecked table
 | 
				
			||||||
 | 
						auto block_listing1 = unchecked.get (store->tx_begin_read (), block->previous ());
 | 
				
			||||||
 | 
						ASSERT_TRUE (block_listing1.empty ());
 | 
				
			||||||
 | 
						// Enqueues a block to be saved on the unchecked table
 | 
				
			||||||
 | 
						unchecked.put (block->previous (), nano::unchecked_info (block));
 | 
				
			||||||
 | 
						// Waits for the block to get written in the database
 | 
				
			||||||
 | 
						auto check_block_is_listed = [&] (nano::transaction const & transaction_a, nano::block_hash const & block_hash_a) {
 | 
				
			||||||
 | 
							return unchecked.get (transaction_a, block_hash_a).size () > 0;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						ASSERT_TIMELY (5s, check_block_is_listed (store->tx_begin_read (), block->previous ()));
 | 
				
			||||||
 | 
						auto transaction = store->tx_begin_write ();
 | 
				
			||||||
 | 
						// Retrieves the block from the database
 | 
				
			||||||
 | 
						auto block_listing2 = unchecked.get (transaction, block->previous ());
 | 
				
			||||||
 | 
						ASSERT_FALSE (block_listing2.empty ());
 | 
				
			||||||
 | 
						// Asserts the added block is equal to the retrieved one
 | 
				
			||||||
 | 
						ASSERT_EQ (*block, *(block_listing2[0].block));
 | 
				
			||||||
 | 
						// Deletes the block from the database
 | 
				
			||||||
 | 
						unchecked.del (transaction, nano::unchecked_key (block->previous (), block->hash ()));
 | 
				
			||||||
 | 
						// Asserts the block is deleted
 | 
				
			||||||
 | 
						auto block_listing3 = unchecked.get (transaction, block->previous ());
 | 
				
			||||||
 | 
						ASSERT_TRUE (block_listing3.empty ());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// This test ensures the unchecked table is able to receive more than one block
 | 
				
			||||||
 | 
					TEST (unchecked, multiple)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						nano::test::system system{};
 | 
				
			||||||
 | 
						if (nano::rocksdb_config::using_rocksdb_in_tests ())
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							// Don't test this in rocksdb mode
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						nano::logger_mt logger{};
 | 
				
			||||||
 | 
						auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
 | 
				
			||||||
 | 
						nano::unchecked_map unchecked{ *store, system.stats, false };
 | 
				
			||||||
 | 
						ASSERT_TRUE (!store->init_error ());
 | 
				
			||||||
 | 
						nano::block_builder builder;
 | 
				
			||||||
 | 
						auto block = builder
 | 
				
			||||||
 | 
									 .send ()
 | 
				
			||||||
 | 
									 .previous (4)
 | 
				
			||||||
 | 
									 .destination (1)
 | 
				
			||||||
 | 
									 .balance (2)
 | 
				
			||||||
 | 
									 .sign (nano::keypair ().prv, 4)
 | 
				
			||||||
 | 
									 .work (5)
 | 
				
			||||||
 | 
									 .build_shared ();
 | 
				
			||||||
 | 
						// Asserts the block wasn't added yet to the unchecked table
 | 
				
			||||||
 | 
						auto block_listing1 = unchecked.get (store->tx_begin_read (), block->previous ());
 | 
				
			||||||
 | 
						ASSERT_TRUE (block_listing1.empty ());
 | 
				
			||||||
 | 
						// Enqueues the first block
 | 
				
			||||||
 | 
						unchecked.put (block->previous (), nano::unchecked_info (block));
 | 
				
			||||||
 | 
						// Enqueues a second block
 | 
				
			||||||
 | 
						unchecked.put (block->source (), nano::unchecked_info (block));
 | 
				
			||||||
 | 
						auto check_block_is_listed = [&] (nano::transaction const & transaction_a, nano::block_hash const & block_hash_a) {
 | 
				
			||||||
 | 
							return unchecked.get (transaction_a, block_hash_a).size () > 0;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						// Waits for and asserts the first block gets saved in the database
 | 
				
			||||||
 | 
						ASSERT_TIMELY (5s, check_block_is_listed (store->tx_begin_read (), block->previous ()));
 | 
				
			||||||
 | 
						// Waits for and asserts the second block gets saved in the database
 | 
				
			||||||
 | 
						ASSERT_TIMELY (5s, check_block_is_listed (store->tx_begin_read (), block->source ()));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// This test ensures that a block can't occur twice in the unchecked table.
 | 
				
			||||||
 | 
					TEST (unchecked, double_put)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						nano::test::system system{};
 | 
				
			||||||
 | 
						nano::logger_mt logger{};
 | 
				
			||||||
 | 
						auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
 | 
				
			||||||
 | 
						nano::unchecked_map unchecked{ *store, system.stats, false };
 | 
				
			||||||
 | 
						ASSERT_TRUE (!store->init_error ());
 | 
				
			||||||
 | 
						nano::block_builder builder;
 | 
				
			||||||
 | 
						auto block = builder
 | 
				
			||||||
 | 
									 .send ()
 | 
				
			||||||
 | 
									 .previous (4)
 | 
				
			||||||
 | 
									 .destination (1)
 | 
				
			||||||
 | 
									 .balance (2)
 | 
				
			||||||
 | 
									 .sign (nano::keypair ().prv, 4)
 | 
				
			||||||
 | 
									 .work (5)
 | 
				
			||||||
 | 
									 .build_shared ();
 | 
				
			||||||
 | 
						// Asserts the block wasn't added yet to the unchecked table
 | 
				
			||||||
 | 
						auto block_listing1 = unchecked.get (store->tx_begin_read (), block->previous ());
 | 
				
			||||||
 | 
						ASSERT_TRUE (block_listing1.empty ());
 | 
				
			||||||
 | 
						// Enqueues the block to be saved in the unchecked table
 | 
				
			||||||
 | 
						unchecked.put (block->previous (), nano::unchecked_info (block));
 | 
				
			||||||
 | 
						// Enqueues the block again in an attempt to have it there twice
 | 
				
			||||||
 | 
						unchecked.put (block->previous (), nano::unchecked_info (block));
 | 
				
			||||||
 | 
						auto check_block_is_listed = [&] (nano::transaction const & transaction_a, nano::block_hash const & block_hash_a) {
 | 
				
			||||||
 | 
							return unchecked.get (transaction_a, block_hash_a).size () > 0;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						// Waits for and asserts the block was added at least once
 | 
				
			||||||
 | 
						ASSERT_TIMELY (5s, check_block_is_listed (store->tx_begin_read (), block->previous ()));
 | 
				
			||||||
 | 
						// Asserts the block was added at most once -- this is objective of this test.
 | 
				
			||||||
 | 
						auto block_listing2 = unchecked.get (store->tx_begin_read (), block->previous ());
 | 
				
			||||||
 | 
						ASSERT_EQ (block_listing2.size (), 1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Tests that recurrent get calls return the correct values
 | 
				
			||||||
 | 
					TEST (unchecked, multiple_get)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						nano::test::system system{};
 | 
				
			||||||
 | 
						nano::logger_mt logger{};
 | 
				
			||||||
 | 
						auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
 | 
				
			||||||
 | 
						nano::unchecked_map unchecked{ *store, system.stats, false };
 | 
				
			||||||
 | 
						ASSERT_TRUE (!store->init_error ());
 | 
				
			||||||
 | 
						// Instantiates three blocks
 | 
				
			||||||
 | 
						nano::block_builder builder;
 | 
				
			||||||
 | 
						auto block1 = builder
 | 
				
			||||||
 | 
									  .send ()
 | 
				
			||||||
 | 
									  .previous (4)
 | 
				
			||||||
 | 
									  .destination (1)
 | 
				
			||||||
 | 
									  .balance (2)
 | 
				
			||||||
 | 
									  .sign (nano::keypair ().prv, 4)
 | 
				
			||||||
 | 
									  .work (5)
 | 
				
			||||||
 | 
									  .build_shared ();
 | 
				
			||||||
 | 
						auto block2 = builder
 | 
				
			||||||
 | 
									  .send ()
 | 
				
			||||||
 | 
									  .previous (3)
 | 
				
			||||||
 | 
									  .destination (1)
 | 
				
			||||||
 | 
									  .balance (2)
 | 
				
			||||||
 | 
									  .sign (nano::keypair ().prv, 4)
 | 
				
			||||||
 | 
									  .work (5)
 | 
				
			||||||
 | 
									  .build_shared ();
 | 
				
			||||||
 | 
						auto block3 = builder
 | 
				
			||||||
 | 
									  .send ()
 | 
				
			||||||
 | 
									  .previous (5)
 | 
				
			||||||
 | 
									  .destination (1)
 | 
				
			||||||
 | 
									  .balance (2)
 | 
				
			||||||
 | 
									  .sign (nano::keypair ().prv, 4)
 | 
				
			||||||
 | 
									  .work (5)
 | 
				
			||||||
 | 
									  .build_shared ();
 | 
				
			||||||
 | 
						// Add the blocks' info to the unchecked table
 | 
				
			||||||
 | 
						unchecked.put (block1->previous (), nano::unchecked_info (block1)); // unchecked1
 | 
				
			||||||
 | 
						unchecked.put (block1->hash (), nano::unchecked_info (block1)); // unchecked2
 | 
				
			||||||
 | 
						unchecked.put (block2->previous (), nano::unchecked_info (block2)); // unchecked3
 | 
				
			||||||
 | 
						unchecked.put (block1->previous (), nano::unchecked_info (block2)); // unchecked1
 | 
				
			||||||
 | 
						unchecked.put (block1->hash (), nano::unchecked_info (block2)); // unchecked2
 | 
				
			||||||
 | 
						unchecked.put (block3->previous (), nano::unchecked_info (block3));
 | 
				
			||||||
 | 
						unchecked.put (block3->hash (), nano::unchecked_info (block3)); // unchecked4
 | 
				
			||||||
 | 
						unchecked.put (block1->previous (), nano::unchecked_info (block3)); // unchecked1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// count the number of blocks in the unchecked table by counting them one by one
 | 
				
			||||||
 | 
						// we cannot trust the count() method if the backend is rocksdb
 | 
				
			||||||
 | 
						auto count_unchecked_blocks_one_by_one = [&store, &unchecked] () {
 | 
				
			||||||
 | 
							size_t count = 0;
 | 
				
			||||||
 | 
							auto transaction = store->tx_begin_read ();
 | 
				
			||||||
 | 
							unchecked.for_each (transaction, [&count] (nano::unchecked_key const & key, nano::unchecked_info const & info) {
 | 
				
			||||||
 | 
								++count;
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
							return count;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Waits for the blocks to get saved in the database
 | 
				
			||||||
 | 
						ASSERT_TIMELY (5s, 8 == count_unchecked_blocks_one_by_one ());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						std::vector<nano::block_hash> unchecked1;
 | 
				
			||||||
 | 
						// Asserts the entries will be found for the provided key
 | 
				
			||||||
 | 
						auto transaction = store->tx_begin_read ();
 | 
				
			||||||
 | 
						auto unchecked1_blocks = unchecked.get (transaction, block1->previous ());
 | 
				
			||||||
 | 
						ASSERT_EQ (unchecked1_blocks.size (), 3);
 | 
				
			||||||
 | 
						for (auto & i : unchecked1_blocks)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							unchecked1.push_back (i.block->hash ());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// Asserts the payloads where correclty saved
 | 
				
			||||||
 | 
						ASSERT_TRUE (std::find (unchecked1.begin (), unchecked1.end (), block1->hash ()) != unchecked1.end ());
 | 
				
			||||||
 | 
						ASSERT_TRUE (std::find (unchecked1.begin (), unchecked1.end (), block2->hash ()) != unchecked1.end ());
 | 
				
			||||||
 | 
						ASSERT_TRUE (std::find (unchecked1.begin (), unchecked1.end (), block3->hash ()) != unchecked1.end ());
 | 
				
			||||||
 | 
						std::vector<nano::block_hash> unchecked2;
 | 
				
			||||||
 | 
						// Asserts the entries will be found for the provided key
 | 
				
			||||||
 | 
						auto unchecked2_blocks = unchecked.get (transaction, block1->hash ());
 | 
				
			||||||
 | 
						ASSERT_EQ (unchecked2_blocks.size (), 2);
 | 
				
			||||||
 | 
						for (auto & i : unchecked2_blocks)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							unchecked2.push_back (i.block->hash ());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// Asserts the payloads where correctly saved
 | 
				
			||||||
 | 
						ASSERT_TRUE (std::find (unchecked2.begin (), unchecked2.end (), block1->hash ()) != unchecked2.end ());
 | 
				
			||||||
 | 
						ASSERT_TRUE (std::find (unchecked2.begin (), unchecked2.end (), block2->hash ()) != unchecked2.end ());
 | 
				
			||||||
 | 
						// Asserts the entry is found by the key and the payload is saved
 | 
				
			||||||
 | 
						auto unchecked3 = unchecked.get (transaction, block2->previous ());
 | 
				
			||||||
 | 
						ASSERT_EQ (unchecked3.size (), 1);
 | 
				
			||||||
 | 
						ASSERT_EQ (unchecked3[0].block->hash (), block2->hash ());
 | 
				
			||||||
 | 
						// Asserts the entry is found by the key and the payload is saved
 | 
				
			||||||
 | 
						auto unchecked4 = unchecked.get (transaction, block3->hash ());
 | 
				
			||||||
 | 
						ASSERT_EQ (unchecked4.size (), 1);
 | 
				
			||||||
 | 
						ASSERT_EQ (unchecked4[0].block->hash (), block3->hash ());
 | 
				
			||||||
 | 
						// Asserts no entry is found for a block that wasn't added
 | 
				
			||||||
 | 
						auto unchecked5 = unchecked.get (transaction, block2->hash ());
 | 
				
			||||||
 | 
						ASSERT_EQ (unchecked5.size (), 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -36,6 +36,7 @@ enum class type : uint8_t
 | 
				
			||||||
	bootstrap_server,
 | 
						bootstrap_server,
 | 
				
			||||||
	active,
 | 
						active,
 | 
				
			||||||
	backlog,
 | 
						backlog,
 | 
				
			||||||
 | 
						unchecked,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_last // Must be the last enum
 | 
						_last // Must be the last enum
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -257,6 +258,11 @@ enum class detail : uint8_t
 | 
				
			||||||
	// backlog
 | 
						// backlog
 | 
				
			||||||
	activated,
 | 
						activated,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// unchecked
 | 
				
			||||||
 | 
						put,
 | 
				
			||||||
 | 
						satisfied,
 | 
				
			||||||
 | 
						trigger,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_last // Must be the last enum
 | 
						_last // Must be the last enum
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -275,4 +281,4 @@ namespace nano
 | 
				
			||||||
std::string_view to_string (stat::type type);
 | 
					std::string_view to_string (stat::type type);
 | 
				
			||||||
std::string_view to_string (stat::detail detail);
 | 
					std::string_view to_string (stat::detail detail);
 | 
				
			||||||
std::string_view to_string (stat::dir dir);
 | 
					std::string_view to_string (stat::dir dir);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -159,7 +159,7 @@ nano::node::node (boost::asio::io_context & io_ctx_a, boost::filesystem::path co
 | 
				
			||||||
	logger (config_a.logging.min_time_between_log_output),
 | 
						logger (config_a.logging.min_time_between_log_output),
 | 
				
			||||||
	store_impl (nano::make_store (logger, application_path_a, network_params.ledger, flags.read_only, true, config_a.rocksdb_config, config_a.diagnostics_config.txn_tracking, config_a.block_processor_batch_max_time, config_a.lmdb_config, config_a.backup_before_upgrade)),
 | 
						store_impl (nano::make_store (logger, application_path_a, network_params.ledger, flags.read_only, true, config_a.rocksdb_config, config_a.diagnostics_config.txn_tracking, config_a.block_processor_batch_max_time, config_a.lmdb_config, config_a.backup_before_upgrade)),
 | 
				
			||||||
	store (*store_impl),
 | 
						store (*store_impl),
 | 
				
			||||||
	unchecked{ store, flags.disable_block_processor_unchecked_deletion },
 | 
						unchecked{ store, stats, flags.disable_block_processor_unchecked_deletion },
 | 
				
			||||||
	wallets_store_impl (std::make_unique<nano::mdb_wallets_store> (application_path_a / "wallets.ldb", config_a.lmdb_config)),
 | 
						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_store (*wallets_store_impl),
 | 
				
			||||||
	gap_cache (*this),
 | 
						gap_cache (*this),
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,11 +1,14 @@
 | 
				
			||||||
#include <nano/lib/locks.hpp>
 | 
					#include <nano/lib/locks.hpp>
 | 
				
			||||||
 | 
					#include <nano/lib/stats.hpp>
 | 
				
			||||||
 | 
					#include <nano/lib/stats_enums.hpp>
 | 
				
			||||||
#include <nano/lib/threading.hpp>
 | 
					#include <nano/lib/threading.hpp>
 | 
				
			||||||
#include <nano/lib/timer.hpp>
 | 
					#include <nano/lib/timer.hpp>
 | 
				
			||||||
#include <nano/node/unchecked_map.hpp>
 | 
					#include <nano/node/unchecked_map.hpp>
 | 
				
			||||||
#include <nano/secure/store.hpp>
 | 
					#include <nano/secure/store.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
nano::unchecked_map::unchecked_map (nano::store & store, bool const & disable_delete) :
 | 
					nano::unchecked_map::unchecked_map (nano::store & store, nano::stats & stats, bool const & disable_delete) :
 | 
				
			||||||
	store{ store },
 | 
						store{ store },
 | 
				
			||||||
 | 
						stats{ stats },
 | 
				
			||||||
	disable_delete{ disable_delete },
 | 
						disable_delete{ disable_delete },
 | 
				
			||||||
	thread{ [this] () { run (); } }
 | 
						thread{ [this] () { run (); } }
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -22,6 +25,7 @@ void nano::unchecked_map::put (nano::hash_or_account const & dependency, nano::u
 | 
				
			||||||
	nano::unique_lock<nano::mutex> lock{ mutex };
 | 
						nano::unique_lock<nano::mutex> lock{ mutex };
 | 
				
			||||||
	buffer.push_back (std::make_pair (dependency, info));
 | 
						buffer.push_back (std::make_pair (dependency, info));
 | 
				
			||||||
	lock.unlock ();
 | 
						lock.unlock ();
 | 
				
			||||||
 | 
						stats.inc (nano::stat::type::unchecked, nano::stat::detail::put);
 | 
				
			||||||
	condition.notify_all (); // Notify run ()
 | 
						condition.notify_all (); // Notify run ()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -151,6 +155,7 @@ void nano::unchecked_map::trigger (nano::hash_or_account const & dependency)
 | 
				
			||||||
	buffer.push_back (dependency);
 | 
						buffer.push_back (dependency);
 | 
				
			||||||
	debug_assert (buffer.back ().which () == 1); // which stands for "query".
 | 
						debug_assert (buffer.back ().which () == 1); // which stands for "query".
 | 
				
			||||||
	lock.unlock ();
 | 
						lock.unlock ();
 | 
				
			||||||
 | 
						stats.inc (nano::stat::type::unchecked, nano::stat::detail::trigger);
 | 
				
			||||||
	condition.notify_all (); // Notify run ()
 | 
						condition.notify_all (); // Notify run ()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -247,6 +252,7 @@ void nano::unchecked_map::query_impl (nano::write_transaction const & transactio
 | 
				
			||||||
	std::deque<nano::unchecked_key> delete_queue;
 | 
						std::deque<nano::unchecked_key> delete_queue;
 | 
				
			||||||
	for_each (transaction, hash, [this, &delete_queue] (nano::unchecked_key const & key, nano::unchecked_info const & info) {
 | 
						for_each (transaction, hash, [this, &delete_queue] (nano::unchecked_key const & key, nano::unchecked_info const & info) {
 | 
				
			||||||
		delete_queue.push_back (key);
 | 
							delete_queue.push_back (key);
 | 
				
			||||||
 | 
							stats.inc (nano::stat::type::unchecked, nano::stat::detail::satisfied);
 | 
				
			||||||
		satisfied (info);
 | 
							satisfied (info);
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
	if (!disable_delete)
 | 
						if (!disable_delete)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,15 +16,17 @@ namespace mi = boost::multi_index;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace nano
 | 
					namespace nano
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					class stats;
 | 
				
			||||||
class store;
 | 
					class store;
 | 
				
			||||||
class transaction;
 | 
					class transaction;
 | 
				
			||||||
class unchecked_info;
 | 
					class unchecked_info;
 | 
				
			||||||
class unchecked_key;
 | 
					class unchecked_key;
 | 
				
			||||||
class write_transaction;
 | 
					class write_transaction;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class unchecked_map
 | 
					class unchecked_map
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
	unchecked_map (nano::store & store, bool const & do_delete);
 | 
						unchecked_map (nano::store &, nano::stats &, bool const & do_delete);
 | 
				
			||||||
	~unchecked_map ();
 | 
						~unchecked_map ();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void put (nano::hash_or_account const & dependency, nano::unchecked_info const & info);
 | 
						void put (nano::hash_or_account const & dependency, nano::unchecked_info const & info);
 | 
				
			||||||
| 
						 | 
					@ -62,6 +64,9 @@ private:
 | 
				
			||||||
	void insert_impl (nano::write_transaction const & transaction, nano::hash_or_account const & dependency, nano::unchecked_info const & info);
 | 
						void insert_impl (nano::write_transaction const & transaction, nano::hash_or_account const & dependency, nano::unchecked_info const & info);
 | 
				
			||||||
	void query_impl (nano::write_transaction const & transaction, nano::block_hash const & hash);
 | 
						void query_impl (nano::write_transaction const & transaction, nano::block_hash const & hash);
 | 
				
			||||||
	nano::store & store;
 | 
						nano::store & store;
 | 
				
			||||||
 | 
						nano::stats & stats;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
	bool const & disable_delete;
 | 
						bool const & disable_delete;
 | 
				
			||||||
	std::deque<boost::variant<insert, query>> buffer;
 | 
						std::deque<boost::variant<insert, query>> buffer;
 | 
				
			||||||
	std::deque<boost::variant<insert, query>> back_buffer;
 | 
						std::deque<boost::variant<insert, query>> back_buffer;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue