Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add unchecked_map stats #4148

Merged
merged 2 commits into from
Feb 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
214 changes: 4 additions & 210 deletions nano/core_test/block_store.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -412,214 +412,6 @@ TEST (block_store, genesis)
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)
{
nano::logger_mt logger;
Expand Down Expand Up @@ -653,9 +445,10 @@ TEST (block_store, one_block)

TEST (block_store, empty_bootstrap)
{
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 };
nano::unchecked_map unchecked{ *store, system.stats, false };
ASSERT_TRUE (!store->init_error ());
auto transaction (store->tx_begin_read ());
size_t count = 0;
Expand Down Expand Up @@ -1176,10 +969,11 @@ namespace lmdb
// Databases need to be dropped in order to convert to dupsort compatible
TEST (block_store, DISABLED_change_dupsort) // Unchecked is no longer dupsort table
{
nano::test::system system{};
auto path (nano::unique_path ());
nano::logger_mt logger{};
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 ());
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));
Expand Down
5 changes: 3 additions & 2 deletions nano/core_test/ledger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5535,12 +5535,13 @@ TEST (ledger, hash_root_random)

TEST (ledger, migrate_lmdb_to_rocksdb)
{
nano::test::system system{};
auto path = nano::unique_path ();
nano::logger_mt logger{};
boost::asio::ip::address_v6 address (boost::asio::ip::make_address_v6 ("::ffff:127.0.0.1"));
uint16_t port = 100;
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::ledger ledger{ store, stats, nano::dev::constants };
nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits<unsigned>::max () };
Expand Down Expand Up @@ -5582,7 +5583,7 @@ TEST (ledger, migrate_lmdb_to_rocksdb)
ASSERT_FALSE (error);

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 ());

nano::pending_info pending_info{};
Expand Down
Loading