From 162643c8a2288e7f2ddf52e267f1156dd600748b Mon Sep 17 00:00:00 2001 From: Colin LeMahieu Date: Thu, 31 Aug 2023 20:19:31 +0100 Subject: [PATCH] Revert "This change reorganizes the names of some classes related to the scheduler. (#4270)" This reverts commit 7b540db780ce3452516067e1ed534987d0ba65e3. --- nano/core_test/CMakeLists.txt | 2 +- nano/core_test/active_transactions.cpp | 28 +-- nano/core_test/buckets.cpp | 253 ------------------------- nano/core_test/conflicts.cpp | 8 +- nano/core_test/election.cpp | 4 +- nano/core_test/election_scheduler.cpp | 20 +- nano/core_test/ledger.cpp | 6 +- nano/core_test/network.cpp | 6 +- nano/core_test/node.cpp | 8 +- nano/core_test/prioritization.cpp | 253 +++++++++++++++++++++++++ nano/node/CMakeLists.txt | 4 +- nano/node/active_transactions.cpp | 6 +- nano/node/node.cpp | 18 +- nano/node/prioritization.cpp | 170 +++++++++++++++++ nano/node/prioritization.hpp | 70 +++++++ nano/node/process_live_dispatcher.cpp | 4 +- nano/node/process_live_dispatcher.hpp | 6 +- nano/node/scheduler/buckets.cpp | 230 +++++++++++----------- nano/node/scheduler/buckets.hpp | 106 +++++------ nano/node/scheduler/component.cpp | 6 +- nano/node/scheduler/component.hpp | 11 +- nano/node/scheduler/hinted.hpp | 1 - nano/node/scheduler/priority.cpp | 174 ----------------- nano/node/scheduler/priority.hpp | 65 ------- nano/rpc_test/rpc.cpp | 10 +- nano/slow_test/node.cpp | 12 +- nano/test_common/testutil.cpp | 6 +- 27 files changed, 736 insertions(+), 751 deletions(-) delete mode 100644 nano/core_test/buckets.cpp create mode 100644 nano/core_test/prioritization.cpp create mode 100644 nano/node/prioritization.cpp create mode 100644 nano/node/prioritization.hpp delete mode 100644 nano/node/scheduler/priority.cpp delete mode 100644 nano/node/scheduler/priority.hpp diff --git a/nano/core_test/CMakeLists.txt b/nano/core_test/CMakeLists.txt index d9192a28a8..f2aae4d263 100644 --- a/nano/core_test/CMakeLists.txt +++ b/nano/core_test/CMakeLists.txt @@ -11,7 +11,6 @@ add_executable( bootstrap.cpp bootstrap_ascending.cpp bootstrap_server.cpp - buckets.cpp cli.cpp confirmation_height.cpp confirmation_solicitor.cpp @@ -39,6 +38,7 @@ add_executable( processing_queue.cpp processor_service.cpp peer_container.cpp + prioritization.cpp request_aggregator.cpp signal_manager.cpp signing.cpp diff --git a/nano/core_test/active_transactions.cpp b/nano/core_test/active_transactions.cpp index 99f3abd228..6da1b28580 100644 --- a/nano/core_test/active_transactions.cpp +++ b/nano/core_test/active_transactions.cpp @@ -1,7 +1,7 @@ #include #include +#include #include -#include #include #include #include @@ -418,7 +418,7 @@ TEST (active_transactions, inactive_votes_cache_multiple_votes) ASSERT_TIMELY (5s, node.inactive_vote_cache.find (send1->hash ())); ASSERT_TIMELY (5s, node.inactive_vote_cache.find (send1->hash ())->voters.size () == 2); ASSERT_EQ (1, node.inactive_vote_cache.cache_size ()); - node.scheduler.priority.activate (nano::dev::genesis_key.pub, node.store.tx_begin_read ()); + node.scheduler.buckets.activate (nano::dev::genesis_key.pub, node.store.tx_begin_read ()); std::shared_ptr election; ASSERT_TIMELY (5s, election = node.active.election (send1->qualified_root ())); ASSERT_EQ (3, election->votes ().size ()); // 2 votes and 1 default not_an_acount @@ -996,7 +996,7 @@ TEST (active_transactions, confirmation_consistency) system.deadline_set (5s); while (!node.ledger.block_confirmed (node.store.tx_begin_read (), block->hash ())) { - node.scheduler.priority.activate (nano::dev::genesis_key.pub, node.store.tx_begin_read ()); + node.scheduler.buckets.activate (nano::dev::genesis_key.pub, node.store.tx_begin_read ()); ASSERT_NO_ERROR (system.poll (5ms)); } ASSERT_NO_ERROR (system.poll_until_true (1s, [&node, &block, i] { @@ -1140,19 +1140,19 @@ TEST (active_transactions, activate_account_chain) ASSERT_EQ (nano::process_result::progress, node.process (*open).code); ASSERT_EQ (nano::process_result::progress, node.process (*receive).code); - node.scheduler.priority.activate (nano::dev::genesis_key.pub, node.store.tx_begin_read ()); + node.scheduler.buckets.activate (nano::dev::genesis_key.pub, node.store.tx_begin_read ()); ASSERT_TIMELY (5s, node.active.election (send->qualified_root ())); auto election1 = node.active.election (send->qualified_root ()); ASSERT_EQ (1, node.active.size ()); ASSERT_EQ (1, election1->blocks ().count (send->hash ())); - node.scheduler.priority.activate (nano::dev::genesis_key.pub, node.store.tx_begin_read ()); + node.scheduler.buckets.activate (nano::dev::genesis_key.pub, node.store.tx_begin_read ()); auto election2 = node.active.election (send->qualified_root ()); ASSERT_EQ (election2, election1); election1->force_confirm (); ASSERT_TIMELY (3s, node.block_confirmed (send->hash ())); // On cementing, the next election is started ASSERT_TIMELY (3s, node.active.active (send2->qualified_root ())); - node.scheduler.priority.activate (nano::dev::genesis_key.pub, node.store.tx_begin_read ()); + node.scheduler.buckets.activate (nano::dev::genesis_key.pub, node.store.tx_begin_read ()); auto election3 = node.active.election (send2->qualified_root ()); ASSERT_NE (nullptr, election3); ASSERT_EQ (1, election3->blocks ().count (send2->hash ())); @@ -1161,11 +1161,11 @@ TEST (active_transactions, activate_account_chain) // On cementing, the next election is started ASSERT_TIMELY (3s, node.active.active (open->qualified_root ())); ASSERT_TIMELY (3s, node.active.active (send3->qualified_root ())); - node.scheduler.priority.activate (nano::dev::genesis_key.pub, node.store.tx_begin_read ()); + node.scheduler.buckets.activate (nano::dev::genesis_key.pub, node.store.tx_begin_read ()); auto election4 = node.active.election (send3->qualified_root ()); ASSERT_NE (nullptr, election4); ASSERT_EQ (1, election4->blocks ().count (send3->hash ())); - node.scheduler.priority.activate (key.pub, node.store.tx_begin_read ()); + node.scheduler.buckets.activate (key.pub, node.store.tx_begin_read ()); auto election5 = node.active.election (open->qualified_root ()); ASSERT_NE (nullptr, election5); ASSERT_EQ (1, election5->blocks ().count (open->hash ())); @@ -1173,7 +1173,7 @@ TEST (active_transactions, activate_account_chain) ASSERT_TIMELY (3s, node.block_confirmed (open->hash ())); // Until send3 is also confirmed, the receive block should not activate std::this_thread::sleep_for (200ms); - node.scheduler.priority.activate (key.pub, node.store.tx_begin_read ()); + node.scheduler.buckets.activate (key.pub, node.store.tx_begin_read ()); election4->force_confirm (); ASSERT_TIMELY (3s, node.block_confirmed (send3->hash ())); ASSERT_TIMELY (3s, node.active.active (receive->qualified_root ())); @@ -1314,7 +1314,7 @@ TEST (active_transactions, vacancy) ASSERT_EQ (nano::process_result::progress, node.process (*send).code); ASSERT_EQ (1, node.active.vacancy ()); ASSERT_EQ (0, node.active.size ()); - node.scheduler.priority.activate (nano::dev::genesis_key.pub, node.store.tx_begin_read ()); + node.scheduler.buckets.activate (nano::dev::genesis_key.pub, node.store.tx_begin_read ()); ASSERT_TIMELY (1s, updated); updated = false; ASSERT_EQ (0, node.active.vacancy ()); @@ -1393,11 +1393,11 @@ TEST (active_transactions, fifo) ASSERT_EQ (nano::process_result::progress, node.process (*receive2).code); // Ensure first transaction becomes active - node.scheduler.priority.manual (receive1); + node.scheduler.buckets.manual (receive1); ASSERT_TIMELY (5s, node.active.election (receive1->qualified_root ()) != nullptr); // Ensure second transaction becomes active - node.scheduler.priority.manual (receive2); + node.scheduler.buckets.manual (receive2); ASSERT_TIMELY (5s, node.active.election (receive2->qualified_root ()) != nullptr); // Ensure excess transactions get trimmed @@ -1503,7 +1503,7 @@ TEST (active_transactions, allow_limited_overflow) // Insert the first part of the blocks into normal election scheduler for (auto const & block : blocks1) { - node.scheduler.priority.activate (block->account (), node.store.tx_begin_read ()); + node.scheduler.buckets.activate (block->account (), node.store.tx_begin_read ()); } // Ensure number of active elections reaches AEC limit and there is no overfill @@ -1565,7 +1565,7 @@ TEST (active_transactions, allow_limited_overflow_adapt) // Insert the first part of the blocks into normal election scheduler for (auto const & block : blocks1) { - node.scheduler.priority.activate (block->account (), node.store.tx_begin_read ()); + node.scheduler.buckets.activate (block->account (), node.store.tx_begin_read ()); } // Ensure number of active elections reaches AEC limit and there is no overfill diff --git a/nano/core_test/buckets.cpp b/nano/core_test/buckets.cpp deleted file mode 100644 index c4c00a3185..0000000000 --- a/nano/core_test/buckets.cpp +++ /dev/null @@ -1,253 +0,0 @@ -#include -#include - -#include - -#include - -nano::keypair & keyzero () -{ - static nano::keypair result; - return result; -} -nano::keypair & key0 () -{ - static nano::keypair result; - return result; -} -nano::keypair & key1 () -{ - static nano::keypair result; - return result; -} -nano::keypair & key2 () -{ - static nano::keypair result; - return result; -} -nano::keypair & key3 () -{ - static nano::keypair result; - return result; -} -std::shared_ptr & blockzero () -{ - nano::block_builder builder; - static auto result = builder - .state () - .account (keyzero ().pub) - .previous (0) - .representative (keyzero ().pub) - .balance (0) - .link (0) - .sign (keyzero ().prv, keyzero ().pub) - .work (0) - .build_shared (); - return result; -} -std::shared_ptr & block0 () -{ - nano::block_builder builder; - static auto result = builder - .state () - .account (key0 ().pub) - .previous (0) - .representative (key0 ().pub) - .balance (nano::Gxrb_ratio) - .link (0) - .sign (key0 ().prv, key0 ().pub) - .work (0) - .build_shared (); - return result; -} -std::shared_ptr & block1 () -{ - nano::block_builder builder; - static auto result = builder - .state () - .account (key1 ().pub) - .previous (0) - .representative (key1 ().pub) - .balance (nano::Mxrb_ratio) - .link (0) - .sign (key1 ().prv, key1 ().pub) - .work (0) - .build_shared (); - return result; -} -std::shared_ptr & block2 () -{ - nano::block_builder builder; - static auto result = builder - .state () - .account (key2 ().pub) - .previous (0) - .representative (key2 ().pub) - .balance (nano::Gxrb_ratio) - .link (0) - .sign (key2 ().prv, key2 ().pub) - .work (0) - .build_shared (); - return result; -} -std::shared_ptr & block3 () -{ - nano::block_builder builder; - static auto result = builder - .state () - .account (key3 ().pub) - .previous (0) - .representative (key3 ().pub) - .balance (nano::Mxrb_ratio) - .link (0) - .sign (key3 ().prv, key3 ().pub) - .work (0) - .build_shared (); - return result; -} - -TEST (scheduler_buckets, construction) -{ - nano::scheduler::buckets buckets; - ASSERT_EQ (0, buckets.size ()); - ASSERT_TRUE (buckets.empty ()); - ASSERT_EQ (62, buckets.bucket_count ()); -} - -TEST (scheduler_buckets, index_min) -{ - nano::scheduler::buckets buckets; - ASSERT_EQ (0, buckets.index (std::numeric_limits::min ())); -} - -TEST (scheduler_buckets, index_max) -{ - nano::scheduler::buckets buckets; - ASSERT_EQ (buckets.bucket_count () - 1, buckets.index (std::numeric_limits::max ())); -} - -TEST (scheduler_buckets, insert_Gxrb) -{ - nano::scheduler::buckets buckets; - buckets.push (1000, block0 (), nano::Gxrb_ratio); - ASSERT_EQ (1, buckets.size ()); - ASSERT_EQ (1, buckets.bucket_size (48)); -} - -TEST (scheduler_buckets, insert_Mxrb) -{ - nano::scheduler::buckets buckets; - buckets.push (1000, block1 (), nano::Mxrb_ratio); - ASSERT_EQ (1, buckets.size ()); - ASSERT_EQ (1, buckets.bucket_size (13)); -} - -// Test two blocks with the same priority -TEST (scheduler_buckets, insert_same_priority) -{ - nano::scheduler::buckets buckets; - buckets.push (1000, block0 (), nano::Gxrb_ratio); - buckets.push (1000, block2 (), nano::Gxrb_ratio); - ASSERT_EQ (2, buckets.size ()); - ASSERT_EQ (2, buckets.bucket_size (48)); -} - -// Test the same block inserted multiple times -TEST (scheduler_buckets, insert_duplicate) -{ - nano::scheduler::buckets buckets; - buckets.push (1000, block0 (), nano::Gxrb_ratio); - buckets.push (1000, block0 (), nano::Gxrb_ratio); - ASSERT_EQ (1, buckets.size ()); - ASSERT_EQ (1, buckets.bucket_size (48)); -} - -TEST (scheduler_buckets, insert_older) -{ - nano::scheduler::buckets buckets; - buckets.push (1000, block0 (), nano::Gxrb_ratio); - buckets.push (1100, block2 (), nano::Gxrb_ratio); - ASSERT_EQ (block0 (), buckets.top ()); - buckets.pop (); - ASSERT_EQ (block2 (), buckets.top ()); - buckets.pop (); -} - -TEST (scheduler_buckets, pop) -{ - nano::scheduler::buckets buckets; - ASSERT_TRUE (buckets.empty ()); - buckets.push (1000, block0 (), nano::Gxrb_ratio); - ASSERT_FALSE (buckets.empty ()); - buckets.pop (); - ASSERT_TRUE (buckets.empty ()); -} - -TEST (scheduler_buckets, top_one) -{ - nano::scheduler::buckets buckets; - buckets.push (1000, block0 (), nano::Gxrb_ratio); - ASSERT_EQ (block0 (), buckets.top ()); -} - -TEST (scheduler_buckets, top_two) -{ - nano::scheduler::buckets buckets; - buckets.push (1000, block0 (), nano::Gxrb_ratio); - buckets.push (1, block1 (), nano::Mxrb_ratio); - ASSERT_EQ (block0 (), buckets.top ()); - buckets.pop (); - ASSERT_EQ (block1 (), buckets.top ()); - buckets.pop (); - ASSERT_TRUE (buckets.empty ()); -} - -TEST (scheduler_buckets, top_round_robin) -{ - nano::scheduler::buckets buckets; - buckets.push (1000, blockzero (), 0); - ASSERT_EQ (blockzero (), buckets.top ()); - buckets.push (1000, block0 (), nano::Gxrb_ratio); - buckets.push (1000, block1 (), nano::Mxrb_ratio); - buckets.push (1100, block3 (), nano::Mxrb_ratio); - buckets.pop (); // blockzero - EXPECT_EQ (block1 (), buckets.top ()); - buckets.pop (); - EXPECT_EQ (block0 (), buckets.top ()); - buckets.pop (); - EXPECT_EQ (block3 (), buckets.top ()); - buckets.pop (); - EXPECT_TRUE (buckets.empty ()); -} - -TEST (scheduler_buckets, trim_normal) -{ - nano::scheduler::buckets buckets{ 1 }; - buckets.push (1000, block0 (), nano::Gxrb_ratio); - buckets.push (1100, block2 (), nano::Gxrb_ratio); - ASSERT_EQ (1, buckets.size ()); - ASSERT_EQ (block0 (), buckets.top ()); -} - -TEST (scheduler_buckets, trim_reverse) -{ - nano::scheduler::buckets buckets{ 1 }; - buckets.push (1100, block2 (), nano::Gxrb_ratio); - buckets.push (1000, block0 (), nano::Gxrb_ratio); - ASSERT_EQ (1, buckets.size ()); - ASSERT_EQ (block0 (), buckets.top ()); -} - -TEST (scheduler_buckets, trim_even) -{ - nano::scheduler::buckets buckets{ 2 }; - buckets.push (1000, block0 (), nano::Gxrb_ratio); - buckets.push (1100, block2 (), nano::Gxrb_ratio); - ASSERT_EQ (1, buckets.size ()); - ASSERT_EQ (block0 (), buckets.top ()); - buckets.push (1000, block1 (), nano::Mxrb_ratio); - ASSERT_EQ (2, buckets.size ()); - ASSERT_EQ (block0 (), buckets.top ()); - buckets.pop (); - ASSERT_EQ (block1 (), buckets.top ()); -} diff --git a/nano/core_test/conflicts.cpp b/nano/core_test/conflicts.cpp index b37bd9560b..95ab8213a4 100644 --- a/nano/core_test/conflicts.cpp +++ b/nano/core_test/conflicts.cpp @@ -1,6 +1,6 @@ #include +#include #include -#include #include #include @@ -27,7 +27,7 @@ TEST (conflicts, start_stop) node1.work_generate_blocking (*send1); ASSERT_EQ (nano::process_result::progress, node1.process (*send1).code); ASSERT_EQ (0, node1.active.size ()); - node1.scheduler.priority.activate (nano::dev::genesis_key.pub, node1.store.tx_begin_read ()); + node1.scheduler.buckets.activate (nano::dev::genesis_key.pub, node1.store.tx_begin_read ()); ASSERT_TIMELY (5s, node1.active.election (send1->qualified_root ())); auto election1 = node1.active.election (send1->qualified_root ()); ASSERT_EQ (1, node1.active.size ()); @@ -60,7 +60,7 @@ TEST (conflicts, add_existing) ASSERT_TIMELY (5s, node1.block (send1->hash ())); // instruct the election scheduler to trigger an election for send1 - node1.scheduler.priority.activate (nano::dev::genesis_key.pub, node1.store.tx_begin_read ()); + node1.scheduler.buckets.activate (nano::dev::genesis_key.pub, node1.store.tx_begin_read ()); // wait for election to be started before processing send2 ASSERT_TIMELY (5s, node1.active.active (*send1)); @@ -167,7 +167,7 @@ TEST (conflicts, add_two) // activate elections for the previous two send blocks (to account3) that we did not forcefully confirm // - node->scheduler.priority.activate (account3.pub, node->store.tx_begin_read ()); + node->scheduler.buckets.activate (account3.pub, node->store.tx_begin_read ()); ASSERT_TIMELY (5s, node->active.election ((*send3)->qualified_root ()) != nullptr); ASSERT_TIMELY (5s, node->active.election ((*send4)->qualified_root ()) != nullptr); diff --git a/nano/core_test/election.cpp b/nano/core_test/election.cpp index db86268819..569c1b056a 100644 --- a/nano/core_test/election.cpp +++ b/nano/core_test/election.cpp @@ -1,6 +1,6 @@ #include +#include #include -#include #include #include #include @@ -150,7 +150,7 @@ TEST (election, quorum_minimum_confirm_success) .build_shared (); node1.work_generate_blocking (*send1); node1.process_active (send1); - node1.scheduler.priority.activate (nano::dev::genesis_key.pub, node1.store.tx_begin_read ()); + node1.scheduler.buckets.activate (nano::dev::genesis_key.pub, node1.store.tx_begin_read ()); ASSERT_TIMELY (5s, node1.active.election (send1->qualified_root ())); auto election = node1.active.election (send1->qualified_root ()); ASSERT_NE (nullptr, election); diff --git a/nano/core_test/election_scheduler.cpp b/nano/core_test/election_scheduler.cpp index 3ed8e93a12..cf69b56fa0 100644 --- a/nano/core_test/election_scheduler.cpp +++ b/nano/core_test/election_scheduler.cpp @@ -1,5 +1,5 @@ +#include #include -#include #include #include @@ -28,7 +28,7 @@ TEST (election_scheduler, activate_one_timely) .work (*system.work.generate (nano::dev::genesis->hash ())) .build_shared (); system.nodes[0]->ledger.process (system.nodes[0]->store.tx_begin_write (), *send1); - system.nodes[0]->scheduler.priority.activate (nano::dev::genesis_key.pub, system.nodes[0]->store.tx_begin_read ()); + system.nodes[0]->scheduler.buckets.activate (nano::dev::genesis_key.pub, system.nodes[0]->store.tx_begin_read ()); ASSERT_TIMELY (5s, system.nodes[0]->active.election (send1->qualified_root ())); } @@ -46,7 +46,7 @@ TEST (election_scheduler, activate_one_flush) .work (*system.work.generate (nano::dev::genesis->hash ())) .build_shared (); system.nodes[0]->ledger.process (system.nodes[0]->store.tx_begin_write (), *send1); - system.nodes[0]->scheduler.priority.activate (nano::dev::genesis_key.pub, system.nodes[0]->store.tx_begin_read ()); + system.nodes[0]->scheduler.buckets.activate (nano::dev::genesis_key.pub, system.nodes[0]->store.tx_begin_read ()); ASSERT_TIMELY (5s, system.nodes[0]->active.election (send1->qualified_root ())); } @@ -115,7 +115,7 @@ TEST (election_scheduler, no_vacancy) ASSERT_EQ (nano::process_result::progress, node.process (*block1).code); // There is vacancy so it should be inserted - node.scheduler.priority.activate (nano::dev::genesis_key.pub, node.store.tx_begin_read ()); + node.scheduler.buckets.activate (nano::dev::genesis_key.pub, node.store.tx_begin_read ()); std::shared_ptr election{}; ASSERT_TIMELY (5s, (election = node.active.election (block1->qualified_root ())) != nullptr); @@ -131,14 +131,14 @@ TEST (election_scheduler, no_vacancy) ASSERT_EQ (nano::process_result::progress, node.process (*block2).code); // There is no vacancy so it should stay queued - node.scheduler.priority.activate (key.pub, node.store.tx_begin_read ()); - ASSERT_TIMELY (5s, node.scheduler.priority.size () == 1); + node.scheduler.buckets.activate (key.pub, node.store.tx_begin_read ()); + ASSERT_TIMELY (5s, node.scheduler.buckets.size () == 1); ASSERT_TRUE (node.active.election (block2->qualified_root ()) == nullptr); // Election confirmed, next in queue should begin election->force_confirm (); ASSERT_TIMELY (5s, node.active.election (block2->qualified_root ()) != nullptr); - ASSERT_TRUE (node.scheduler.priority.empty ()); + ASSERT_TRUE (node.scheduler.buckets.empty ()); } // Ensure that election_scheduler::flush terminates even if no elections can currently be queued e.g. shutdown or no active_transactions vacancy @@ -162,9 +162,9 @@ TEST (election_scheduler, flush_vacancy) .work (*system.work.generate (nano::dev::genesis->hash ())) .build_shared (); ASSERT_EQ (nano::process_result::progress, node.process (*send).code); - node.scheduler.priority.activate (nano::dev::genesis_key.pub, node.store.tx_begin_read ()); + node.scheduler.buckets.activate (nano::dev::genesis_key.pub, node.store.tx_begin_read ()); // Ensure this call does not block, even though no elections can be activated. - node.scheduler.priority.flush (); + node.scheduler.buckets.flush (); ASSERT_EQ (0, node.active.size ()); - ASSERT_EQ (1, node.scheduler.priority.size ()); + ASSERT_EQ (1, node.scheduler.buckets.size ()); } diff --git a/nano/core_test/ledger.cpp b/nano/core_test/ledger.cpp index 43fe65c314..b2c043a2ae 100644 --- a/nano/core_test/ledger.cpp +++ b/nano/core_test/ledger.cpp @@ -2,8 +2,8 @@ #include #include #include +#include #include -#include #include #include #include @@ -913,7 +913,7 @@ TEST (votes, check_signature) auto transaction (node1.store.tx_begin_write ()); ASSERT_EQ (nano::process_result::progress, node1.ledger.process (transaction, *send1).code); } - node1.scheduler.priority.activate (nano::dev::genesis_key.pub, node1.store.tx_begin_read ()); + node1.scheduler.buckets.activate (nano::dev::genesis_key.pub, node1.store.tx_begin_read ()); ASSERT_TIMELY (5s, node1.active.election (send1->qualified_root ())); auto election1 = node1.active.election (send1->qualified_root ()); ASSERT_EQ (1, election1->votes ().size ()); @@ -984,7 +984,7 @@ TEST (votes, add_existing) .build (); node1.work_generate_blocking (*send1); ASSERT_EQ (nano::process_result::progress, node1.ledger.process (node1.store.tx_begin_write (), *send1).code); - node1.scheduler.priority.activate (nano::dev::genesis_key.pub, node1.store.tx_begin_read ()); + node1.scheduler.buckets.activate (nano::dev::genesis_key.pub, node1.store.tx_begin_read ()); ASSERT_TIMELY (5s, node1.active.election (send1->qualified_root ())); auto election1 = node1.active.election (send1->qualified_root ()); auto vote1 (std::make_shared (nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, nano::vote::timestamp_min * 1, 0, std::vector{ send1->hash () })); diff --git a/nano/core_test/network.cpp b/nano/core_test/network.cpp index c9ebbcd90f..55efe9355b 100644 --- a/nano/core_test/network.cpp +++ b/nano/core_test/network.cpp @@ -1,7 +1,7 @@ #include #include +#include #include -#include #include #include #include @@ -366,7 +366,7 @@ TEST (receivable_processor, confirm_insufficient_pos) .build_shared (); node1.work_generate_blocking (*block1); ASSERT_EQ (nano::process_result::progress, node1.process (*block1).code); - node1.scheduler.priority.activate (nano::dev::genesis_key.pub, node1.store.tx_begin_read ()); + node1.scheduler.buckets.activate (nano::dev::genesis_key.pub, node1.store.tx_begin_read ()); nano::keypair key1; auto vote (std::make_shared (key1.pub, key1.prv, 0, 0, std::vector{ block1->hash () })); nano::confirm_ack con1{ nano::dev::network_params.network, vote }; @@ -389,7 +389,7 @@ TEST (receivable_processor, confirm_sufficient_pos) .build_shared (); node1.work_generate_blocking (*block1); ASSERT_EQ (nano::process_result::progress, node1.process (*block1).code); - node1.scheduler.priority.activate (nano::dev::genesis_key.pub, node1.store.tx_begin_read ()); + node1.scheduler.buckets.activate (nano::dev::genesis_key.pub, node1.store.tx_begin_read ()); auto vote (std::make_shared (nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, 0, 0, std::vector{ block1->hash () })); nano::confirm_ack con1{ nano::dev::network_params.network, vote }; auto channel1 = std::make_shared (node1, node1); diff --git a/nano/core_test/node.cpp b/nano/core_test/node.cpp index 20f5ae3188..270c0f99a2 100644 --- a/nano/core_test/node.cpp +++ b/nano/core_test/node.cpp @@ -1,7 +1,7 @@ #include #include +#include #include -#include #include #include #include @@ -987,7 +987,7 @@ TEST (node, fork_open_flip) // give block open1 to node1, manually trigger an election for open1 and ensure it is in the ledger node1.process_active (open1); ASSERT_TIMELY (5s, node1.block (open1->hash ()) != nullptr); - node1.scheduler.priority.manual (open1); + node1.scheduler.buckets.manual (open1); ASSERT_TIMELY (5s, (election = node1.active.election (open1->qualified_root ())) != nullptr); election->transition_active (); @@ -1000,7 +1000,7 @@ TEST (node, fork_open_flip) // ensure open2 is in node2 ledger (and therefore has sideband) and manually trigger an election for open2 ASSERT_TIMELY (5s, node2.block (open2->hash ()) != nullptr); - node2.scheduler.priority.manual (open2); + node2.scheduler.buckets.manual (open2); ASSERT_TIMELY (5s, (election = node2.active.election (open2->qualified_root ())) != nullptr); election->transition_active (); @@ -1415,7 +1415,7 @@ TEST (node, rep_self_vote) ASSERT_EQ (nano::process_result::progress, node0->process (*block0).code); auto & active = node0->active; auto & scheduler = node0->scheduler; - scheduler.priority.activate (nano::dev::genesis_key.pub, node0->store.tx_begin_read ()); + scheduler.buckets.activate (nano::dev::genesis_key.pub, node0->store.tx_begin_read ()); ASSERT_TIMELY (5s, active.election (block0->qualified_root ())); auto election1 = active.election (block0->qualified_root ()); ASSERT_NE (nullptr, election1); diff --git a/nano/core_test/prioritization.cpp b/nano/core_test/prioritization.cpp new file mode 100644 index 0000000000..b2cc897d72 --- /dev/null +++ b/nano/core_test/prioritization.cpp @@ -0,0 +1,253 @@ +#include +#include + +#include + +#include + +nano::keypair & keyzero () +{ + static nano::keypair result; + return result; +} +nano::keypair & key0 () +{ + static nano::keypair result; + return result; +} +nano::keypair & key1 () +{ + static nano::keypair result; + return result; +} +nano::keypair & key2 () +{ + static nano::keypair result; + return result; +} +nano::keypair & key3 () +{ + static nano::keypair result; + return result; +} +std::shared_ptr & blockzero () +{ + nano::block_builder builder; + static auto result = builder + .state () + .account (keyzero ().pub) + .previous (0) + .representative (keyzero ().pub) + .balance (0) + .link (0) + .sign (keyzero ().prv, keyzero ().pub) + .work (0) + .build_shared (); + return result; +} +std::shared_ptr & block0 () +{ + nano::block_builder builder; + static auto result = builder + .state () + .account (key0 ().pub) + .previous (0) + .representative (key0 ().pub) + .balance (nano::Gxrb_ratio) + .link (0) + .sign (key0 ().prv, key0 ().pub) + .work (0) + .build_shared (); + return result; +} +std::shared_ptr & block1 () +{ + nano::block_builder builder; + static auto result = builder + .state () + .account (key1 ().pub) + .previous (0) + .representative (key1 ().pub) + .balance (nano::Mxrb_ratio) + .link (0) + .sign (key1 ().prv, key1 ().pub) + .work (0) + .build_shared (); + return result; +} +std::shared_ptr & block2 () +{ + nano::block_builder builder; + static auto result = builder + .state () + .account (key2 ().pub) + .previous (0) + .representative (key2 ().pub) + .balance (nano::Gxrb_ratio) + .link (0) + .sign (key2 ().prv, key2 ().pub) + .work (0) + .build_shared (); + return result; +} +std::shared_ptr & block3 () +{ + nano::block_builder builder; + static auto result = builder + .state () + .account (key3 ().pub) + .previous (0) + .representative (key3 ().pub) + .balance (nano::Mxrb_ratio) + .link (0) + .sign (key3 ().prv, key3 ().pub) + .work (0) + .build_shared (); + return result; +} + +TEST (prioritization, construction) +{ + nano::prioritization prioritization; + ASSERT_EQ (0, prioritization.size ()); + ASSERT_TRUE (prioritization.empty ()); + ASSERT_EQ (62, prioritization.bucket_count ()); +} + +TEST (prioritization, index_min) +{ + nano::prioritization prioritization; + ASSERT_EQ (0, prioritization.index (std::numeric_limits::min ())); +} + +TEST (prioritization, index_max) +{ + nano::prioritization prioritization; + ASSERT_EQ (prioritization.bucket_count () - 1, prioritization.index (std::numeric_limits::max ())); +} + +TEST (prioritization, insert_Gxrb) +{ + nano::prioritization prioritization; + prioritization.push (1000, block0 (), nano::Gxrb_ratio); + ASSERT_EQ (1, prioritization.size ()); + ASSERT_EQ (1, prioritization.bucket_size (48)); +} + +TEST (prioritization, insert_Mxrb) +{ + nano::prioritization prioritization; + prioritization.push (1000, block1 (), nano::Mxrb_ratio); + ASSERT_EQ (1, prioritization.size ()); + ASSERT_EQ (1, prioritization.bucket_size (13)); +} + +// Test two blocks with the same priority +TEST (prioritization, insert_same_priority) +{ + nano::prioritization prioritization; + prioritization.push (1000, block0 (), nano::Gxrb_ratio); + prioritization.push (1000, block2 (), nano::Gxrb_ratio); + ASSERT_EQ (2, prioritization.size ()); + ASSERT_EQ (2, prioritization.bucket_size (48)); +} + +// Test the same block inserted multiple times +TEST (prioritization, insert_duplicate) +{ + nano::prioritization prioritization; + prioritization.push (1000, block0 (), nano::Gxrb_ratio); + prioritization.push (1000, block0 (), nano::Gxrb_ratio); + ASSERT_EQ (1, prioritization.size ()); + ASSERT_EQ (1, prioritization.bucket_size (48)); +} + +TEST (prioritization, insert_older) +{ + nano::prioritization prioritization; + prioritization.push (1000, block0 (), nano::Gxrb_ratio); + prioritization.push (1100, block2 (), nano::Gxrb_ratio); + ASSERT_EQ (block0 (), prioritization.top ()); + prioritization.pop (); + ASSERT_EQ (block2 (), prioritization.top ()); + prioritization.pop (); +} + +TEST (prioritization, pop) +{ + nano::prioritization prioritization; + ASSERT_TRUE (prioritization.empty ()); + prioritization.push (1000, block0 (), nano::Gxrb_ratio); + ASSERT_FALSE (prioritization.empty ()); + prioritization.pop (); + ASSERT_TRUE (prioritization.empty ()); +} + +TEST (prioritization, top_one) +{ + nano::prioritization prioritization; + prioritization.push (1000, block0 (), nano::Gxrb_ratio); + ASSERT_EQ (block0 (), prioritization.top ()); +} + +TEST (prioritization, top_two) +{ + nano::prioritization prioritization; + prioritization.push (1000, block0 (), nano::Gxrb_ratio); + prioritization.push (1, block1 (), nano::Mxrb_ratio); + ASSERT_EQ (block0 (), prioritization.top ()); + prioritization.pop (); + ASSERT_EQ (block1 (), prioritization.top ()); + prioritization.pop (); + ASSERT_TRUE (prioritization.empty ()); +} + +TEST (prioritization, top_round_robin) +{ + nano::prioritization prioritization; + prioritization.push (1000, blockzero (), 0); + ASSERT_EQ (blockzero (), prioritization.top ()); + prioritization.push (1000, block0 (), nano::Gxrb_ratio); + prioritization.push (1000, block1 (), nano::Mxrb_ratio); + prioritization.push (1100, block3 (), nano::Mxrb_ratio); + prioritization.pop (); // blockzero + EXPECT_EQ (block1 (), prioritization.top ()); + prioritization.pop (); + EXPECT_EQ (block0 (), prioritization.top ()); + prioritization.pop (); + EXPECT_EQ (block3 (), prioritization.top ()); + prioritization.pop (); + EXPECT_TRUE (prioritization.empty ()); +} + +TEST (prioritization, trim_normal) +{ + nano::prioritization prioritization{ 1 }; + prioritization.push (1000, block0 (), nano::Gxrb_ratio); + prioritization.push (1100, block2 (), nano::Gxrb_ratio); + ASSERT_EQ (1, prioritization.size ()); + ASSERT_EQ (block0 (), prioritization.top ()); +} + +TEST (prioritization, trim_reverse) +{ + nano::prioritization prioritization{ 1 }; + prioritization.push (1100, block2 (), nano::Gxrb_ratio); + prioritization.push (1000, block0 (), nano::Gxrb_ratio); + ASSERT_EQ (1, prioritization.size ()); + ASSERT_EQ (block0 (), prioritization.top ()); +} + +TEST (prioritization, trim_even) +{ + nano::prioritization prioritization{ 2 }; + prioritization.push (1000, block0 (), nano::Gxrb_ratio); + prioritization.push (1100, block2 (), nano::Gxrb_ratio); + ASSERT_EQ (1, prioritization.size ()); + ASSERT_EQ (block0 (), prioritization.top ()); + prioritization.push (1000, block1 (), nano::Mxrb_ratio); + ASSERT_EQ (2, prioritization.size ()); + ASSERT_EQ (block0 (), prioritization.top ()); + prioritization.pop (); + ASSERT_EQ (block1 (), prioritization.top ()); +} diff --git a/nano/node/CMakeLists.txt b/nano/node/CMakeLists.txt index 2349e8b050..d31b63aabf 100644 --- a/nano/node/CMakeLists.txt +++ b/nano/node/CMakeLists.txt @@ -163,6 +163,8 @@ add_library( peer_exclusion.cpp portmapping.hpp portmapping.cpp + prioritization.cpp + prioritization.hpp process_live_dispatcher.cpp process_live_dispatcher.hpp repcrawler.hpp @@ -202,8 +204,6 @@ add_library( scheduler/hinted.cpp scheduler/optimistic.hpp scheduler/optimistic.cpp - scheduler/priority.cpp - scheduler/priority.hpp signatures.hpp signatures.cpp state_block_signature_verification.hpp diff --git a/nano/node/active_transactions.cpp b/nano/node/active_transactions.cpp index 6511aa8247..34e1141ac3 100644 --- a/nano/node/active_transactions.cpp +++ b/nano/node/active_transactions.cpp @@ -5,8 +5,8 @@ #include #include #include +#include #include -#include #include #include @@ -151,13 +151,13 @@ void nano::active_transactions::block_cemented_callback (std::shared_ptr #include #include +#include #include #include #include -#include #include #include #include @@ -205,7 +205,7 @@ nano::node::node (boost::asio::io_context & io_ctx_a, boost::filesystem::path co block_broadcast{ network, block_arrival, !flags.disable_block_processor_republishing }, block_publisher{ active }, gap_tracker{ gap_cache }, - process_live_dispatcher{ ledger, scheduler.priority, inactive_vote_cache, websocket } + process_live_dispatcher{ ledger, scheduler.buckets, inactive_vote_cache, websocket } { block_broadcast.connect (block_processor); block_publisher.connect (block_processor); @@ -220,7 +220,7 @@ nano::node::node (boost::asio::io_context & io_ctx_a, boost::filesystem::path co }; backlog.activate_callback.add ([this] (nano::transaction const & transaction, nano::account const & account, nano::account_info const & account_info, nano::confirmation_height_info const & conf_info) { - scheduler.priority.activate (account, transaction); + scheduler.buckets.activate (account, transaction); scheduler.optimistic.activate (account, account_info, conf_info); }); @@ -228,7 +228,7 @@ nano::node::node (boost::asio::io_context & io_ctx_a, boost::filesystem::path co { // Notify election schedulers when AEC frees election slot active.vacancy_update = [this] () { - scheduler.priority.notify (); + scheduler.buckets.notify (); scheduler.hinted.notify (); scheduler.optimistic.notify (); }; @@ -576,7 +576,7 @@ std::unique_ptr nano::collect_container_info (no composite->add_component (collect_container_info (node.confirmation_height_processor, "confirmation_height_processor")); composite->add_component (collect_container_info (node.distributed_work, "distributed_work")); composite->add_component (collect_container_info (node.aggregator, "request_aggregator")); - composite->add_component (node.scheduler.priority.collect_container_info ("election_scheduler")); + composite->add_component (node.scheduler.buckets.collect_container_info ("election_scheduler")); composite->add_component (node.inactive_vote_cache.collect_container_info ("inactive_vote_cache")); composite->add_component (collect_container_info (node.generator, "vote_generator")); composite->add_component (collect_container_info (node.final_generator, "vote_generator_final")); @@ -689,7 +689,7 @@ void nano::node::start () generator.start (); final_generator.start (); scheduler.optimistic.start (); - scheduler.priority.start (); + scheduler.buckets.start (); backlog.start (); scheduler.hinted.start (); bootstrap_server.start (); @@ -723,7 +723,7 @@ void nano::node::stop () block_processor.stop (); aggregator.stop (); vote_processor.stop (); - scheduler.priority.stop (); + scheduler.buckets.stop (); scheduler.optimistic.stop (); scheduler.hinted.stop (); active.stop (); @@ -1265,8 +1265,8 @@ void nano::node::add_initial_peers () std::shared_ptr nano::node::block_confirm (std::shared_ptr const & block_a) { - scheduler.priority.manual (block_a); - scheduler.priority.flush (); + scheduler.buckets.manual (block_a); + scheduler.buckets.flush (); auto election = active.election (block_a->qualified_root ()); if (election != nullptr) { diff --git a/nano/node/prioritization.cpp b/nano/node/prioritization.cpp new file mode 100644 index 0000000000..fe755ae595 --- /dev/null +++ b/nano/node/prioritization.cpp @@ -0,0 +1,170 @@ +#include +#include +#include + +#include + +bool nano::prioritization::value_type::operator< (value_type const & other_a) const +{ + return time < other_a.time || (time == other_a.time && block->hash () < other_a.block->hash ()); +} + +bool nano::prioritization::value_type::operator== (value_type const & other_a) const +{ + return time == other_a.time && block->hash () == other_a.block->hash (); +} + +/** Moves the bucket pointer to the next bucket */ +void nano::prioritization::next () +{ + ++current; + if (current == schedule.end ()) + { + current = schedule.begin (); + } +} + +/** Seek to the next non-empty bucket, if one exists */ +void nano::prioritization::seek () +{ + next (); + for (std::size_t i = 0, n = schedule.size (); buckets[*current].empty () && i < n; ++i) + { + next (); + } +} + +/** Initialise the schedule vector */ +void nano::prioritization::populate_schedule () +{ + for (auto i = 0; i < buckets.size (); ++i) + { + schedule.push_back (i); + } +} + +/** + * Prioritization constructor, construct a container containing approximately 'maximum' number of blocks. + * @param maximum number of blocks that this container can hold, this is a soft and approximate limit. + */ +nano::prioritization::prioritization (uint64_t maximum) : + maximum{ maximum } +{ + auto build_region = [this] (uint128_t const & begin, uint128_t const & end, size_t count) { + auto width = (end - begin) / count; + for (auto i = 0; i < count; ++i) + { + minimums.push_back (begin + i * width); + } + }; + minimums.push_back (uint128_t{ 0 }); + build_region (uint128_t{ 1 } << 88, uint128_t{ 1 } << 92, 2); + build_region (uint128_t{ 1 } << 92, uint128_t{ 1 } << 96, 4); + build_region (uint128_t{ 1 } << 96, uint128_t{ 1 } << 100, 8); + build_region (uint128_t{ 1 } << 100, uint128_t{ 1 } << 104, 16); + build_region (uint128_t{ 1 } << 104, uint128_t{ 1 } << 108, 16); + build_region (uint128_t{ 1 } << 108, uint128_t{ 1 } << 112, 8); + build_region (uint128_t{ 1 } << 112, uint128_t{ 1 } << 116, 4); + build_region (uint128_t{ 1 } << 116, uint128_t{ 1 } << 120, 2); + minimums.push_back (uint128_t{ 1 } << 120); + buckets.resize (minimums.size ()); + populate_schedule (); + current = schedule.begin (); +} + +std::size_t nano::prioritization::index (nano::uint128_t const & balance) const +{ + auto index = std::upper_bound (minimums.begin (), minimums.end (), balance) - minimums.begin () - 1; + return index; +} + +/** + * Push a block and its associated time into the prioritization container. + * The time is given here because sideband might not exist in the case of state blocks. + */ +void nano::prioritization::push (uint64_t time, std::shared_ptr block, nano::amount const & priority) +{ + auto was_empty = empty (); + auto & bucket = buckets[index (priority.number ())]; + bucket.emplace (value_type{ time, block }); + if (bucket.size () > std::max (decltype (maximum){ 1 }, maximum / buckets.size ())) + { + bucket.erase (--bucket.end ()); + } + if (was_empty) + { + seek (); + } +} + +/** Return the highest priority block of the current bucket */ +std::shared_ptr nano::prioritization::top () const +{ + debug_assert (!empty ()); + debug_assert (!buckets[*current].empty ()); + auto result = buckets[*current].begin ()->block; + return result; +} + +/** Pop the current block from the container and seek to the next block, if it exists */ +void nano::prioritization::pop () +{ + debug_assert (!empty ()); + debug_assert (!buckets[*current].empty ()); + auto & bucket = buckets[*current]; + bucket.erase (bucket.begin ()); + seek (); +} + +/** Returns the total number of blocks in buckets */ +std::size_t nano::prioritization::size () const +{ + std::size_t result{ 0 }; + for (auto const & queue : buckets) + { + result += queue.size (); + } + return result; +} + +/** Returns number of buckets, 62 by default */ +std::size_t nano::prioritization::bucket_count () const +{ + return buckets.size (); +} + +/** Returns number of items in bucket with index 'index' */ +std::size_t nano::prioritization::bucket_size (std::size_t index) const +{ + return buckets[index].size (); +} + +/** Returns true if all buckets are empty */ +bool nano::prioritization::empty () const +{ + return std::all_of (buckets.begin (), buckets.end (), [] (priority const & bucket_a) { return bucket_a.empty (); }); +} + +/** Print the state of the class in stderr */ +void nano::prioritization::dump () const +{ + for (auto const & i : buckets) + { + for (auto const & j : i) + { + std::cerr << j.time << ' ' << j.block->hash ().to_string () << '\n'; + } + } + std::cerr << "current: " << std::to_string (*current) << '\n'; +} + +std::unique_ptr nano::prioritization::collect_container_info (std::string const & name) +{ + auto composite = std::make_unique (name); + for (auto i = 0; i < buckets.size (); ++i) + { + auto const & bucket = buckets[i]; + composite->add_component (std::make_unique (container_info{ std::to_string (i), bucket.size (), 0 })); + } + return composite; +} diff --git a/nano/node/prioritization.hpp b/nano/node/prioritization.hpp new file mode 100644 index 0000000000..9fa4f5c6b2 --- /dev/null +++ b/nano/node/prioritization.hpp @@ -0,0 +1,70 @@ +#pragma once +#include +#include + +#include +#include +#include + +namespace nano +{ +class block; + +/** A container for holding blocks and their arrival/creation time. + * + * The container consists of a number of buckets. Each bucket holds an ordered set of 'value_type' items. + * The buckets are accessed in a round robin fashion. The index 'current' holds the index of the bucket to access next. + * When a block is inserted, the bucket to go into is determined by the account balance and the priority inside that + * bucket is determined by its creation/arrival time. + * + * The arrival/creation time is only an approximation and it could even be wildly wrong, + * for example, in the event of bootstrapped blocks. + */ +class prioritization final +{ + class value_type + { + public: + uint64_t time; + std::shared_ptr block; + bool operator< (value_type const & other_a) const; + bool operator== (value_type const & other_a) const; + }; + + using priority = std::set; + + /** container for the buckets to be read in round robin fashion */ + std::vector buckets; + + /** thresholds that define the bands for each bucket, the minimum balance an account must have to enter a bucket, + * the container writes a block to the lowest indexed bucket that has balance larger than the bucket's minimum value */ + std::vector minimums; + + /** Contains bucket indicies to iterate over when making the next scheduling decision */ + std::vector schedule; + + /** index of bucket to read next */ + decltype (schedule)::const_iterator current; + + /** maximum number of blocks in whole container, each bucket's maximum is maximum / bucket_number */ + uint64_t const maximum; + + void next (); + void seek (); + void populate_schedule (); + +public: + prioritization (uint64_t maximum = 250000u); + void push (uint64_t time, std::shared_ptr block, nano::amount const & priority); + std::shared_ptr top () const; + void pop (); + std::size_t size () const; + std::size_t bucket_count () const; + std::size_t bucket_size (std::size_t index) const; + bool empty () const; + void dump () const; + std::size_t index (nano::uint128_t const & balance) const; + + std::unique_ptr collect_container_info (std::string const &); +}; +} diff --git a/nano/node/process_live_dispatcher.cpp b/nano/node/process_live_dispatcher.cpp index 2b231a5258..8a18e3b1ee 100644 --- a/nano/node/process_live_dispatcher.cpp +++ b/nano/node/process_live_dispatcher.cpp @@ -1,14 +1,14 @@ #include #include #include -#include +#include #include #include #include #include #include -nano::process_live_dispatcher::process_live_dispatcher (nano::ledger & ledger, nano::scheduler::priority & scheduler, nano::vote_cache & inactive_vote_cache, nano::websocket_server & websocket) : +nano::process_live_dispatcher::process_live_dispatcher (nano::ledger & ledger, nano::scheduler::buckets & scheduler, nano::vote_cache & inactive_vote_cache, nano::websocket_server & websocket) : ledger{ ledger }, scheduler{ scheduler }, inactive_vote_cache{ inactive_vote_cache }, diff --git a/nano/node/process_live_dispatcher.hpp b/nano/node/process_live_dispatcher.hpp index 23206544d1..2255d8065d 100644 --- a/nano/node/process_live_dispatcher.hpp +++ b/nano/node/process_live_dispatcher.hpp @@ -12,14 +12,14 @@ class transaction; namespace scheduler { - class priority; + class buckets; } // Observes confirmed blocks and dispatches the process_live function. class process_live_dispatcher { public: - process_live_dispatcher (nano::ledger & ledger, nano::scheduler::priority & scheduler, nano::vote_cache & inactive_vote_cache, nano::websocket_server & websocket); + process_live_dispatcher (nano::ledger & ledger, nano::scheduler::buckets & scheduler, nano::vote_cache & inactive_vote_cache, nano::websocket_server & websocket); void connect (nano::block_processor & block_processor); private: @@ -28,7 +28,7 @@ class process_live_dispatcher void process_live (nano::block const & block, nano::transaction const & transaction); nano::ledger & ledger; - nano::scheduler::priority & scheduler; + nano::scheduler::buckets & scheduler; nano::vote_cache & inactive_vote_cache; nano::websocket_server & websocket; }; diff --git a/nano/node/scheduler/buckets.cpp b/nano/node/scheduler/buckets.cpp index 0301ace7f2..bcb13e4f37 100644 --- a/nano/node/scheduler/buckets.cpp +++ b/nano/node/scheduler/buckets.cpp @@ -1,170 +1,172 @@ -#include -#include +#include #include -#include - -bool nano::scheduler::buckets::value_type::operator< (value_type const & other_a) const +nano::scheduler::buckets::buckets (nano::node & node_a, nano::stats & stats_a) : + node{ node_a }, + stats{ stats_a } { - return time < other_a.time || (time == other_a.time && block->hash () < other_a.block->hash ()); } -bool nano::scheduler::buckets::value_type::operator== (value_type const & other_a) const +nano::scheduler::buckets::~buckets () { - return time == other_a.time && block->hash () == other_a.block->hash (); + // Thread must be stopped before destruction + debug_assert (!thread.joinable ()); } -/** Moves the bucket pointer to the next bucket */ -void nano::scheduler::buckets::next () +void nano::scheduler::buckets::start () { - ++current; - if (current == schedule.end ()) - { - current = schedule.begin (); - } + debug_assert (!thread.joinable ()); + + thread = std::thread{ [this] () { + nano::thread_role::set (nano::thread_role::name::election_scheduler); + run (); + } }; } -/** Seek to the next non-empty bucket, if one exists */ -void nano::scheduler::buckets::seek () +void nano::scheduler::buckets::stop () { - next (); - for (std::size_t i = 0, n = schedule.size (); buckets_m[*current].queue.empty () && i < n; ++i) { - next (); + nano::lock_guard lock{ mutex }; + stopped = true; } + notify (); + nano::join_or_pass (thread); } -/** Initialise the schedule vector */ -void nano::scheduler::buckets::populate_schedule () +void nano::scheduler::buckets::manual (std::shared_ptr const & block_a, boost::optional const & previous_balance_a, nano::election_behavior election_behavior_a) { - for (auto i = 0; i < buckets_m.size (); ++i) - { - schedule.push_back (i); - } + nano::lock_guard lock{ mutex }; + manual_queue.push_back (std::make_tuple (block_a, previous_balance_a, election_behavior_a)); + notify (); } -/** - * Prioritization constructor, construct a container containing approximately 'maximum' number of blocks. - * @param maximum number of blocks that this container can hold, this is a soft and approximate limit. - */ -nano::scheduler::buckets::buckets (uint64_t maximum) : - maximum{ maximum } +bool nano::scheduler::buckets::activate (nano::account const & account_a, nano::transaction const & transaction) { - auto build_region = [this] (uint128_t const & begin, uint128_t const & end, size_t count) { - auto width = (end - begin) / count; - for (auto i = 0; i < count; ++i) + debug_assert (!account_a.is_zero ()); + auto info = node.ledger.account_info (transaction, account_a); + if (info) + { + nano::confirmation_height_info conf_info; + node.store.confirmation_height.get (transaction, account_a, conf_info); + if (conf_info.height < info->block_count) { - minimums.push_back (begin + i * width); + debug_assert (conf_info.frontier != info->head); + auto hash = conf_info.height == 0 ? info->open_block : node.store.block.successor (transaction, conf_info.frontier); + auto block = node.store.block.get (transaction, hash); + debug_assert (block != nullptr); + if (node.ledger.dependents_confirmed (transaction, *block)) + { + stats.inc (nano::stat::type::election_scheduler, nano::stat::detail::activated); + auto balance = node.ledger.balance (transaction, hash); + auto previous_balance = node.ledger.balance (transaction, conf_info.frontier); + nano::lock_guard lock{ mutex }; + priority.push (info->modified, block, std::max (balance, previous_balance)); + notify (); + return true; // Activated + } } - }; - minimums.push_back (uint128_t{ 0 }); - build_region (uint128_t{ 1 } << 88, uint128_t{ 1 } << 92, 2); - build_region (uint128_t{ 1 } << 92, uint128_t{ 1 } << 96, 4); - build_region (uint128_t{ 1 } << 96, uint128_t{ 1 } << 100, 8); - build_region (uint128_t{ 1 } << 100, uint128_t{ 1 } << 104, 16); - build_region (uint128_t{ 1 } << 104, uint128_t{ 1 } << 108, 16); - build_region (uint128_t{ 1 } << 108, uint128_t{ 1 } << 112, 8); - build_region (uint128_t{ 1 } << 112, uint128_t{ 1 } << 116, 4); - build_region (uint128_t{ 1 } << 116, uint128_t{ 1 } << 120, 2); - minimums.push_back (uint128_t{ 1 } << 120); - buckets_m.resize (minimums.size ()); - populate_schedule (); - current = schedule.begin (); -} - -std::size_t nano::scheduler::buckets::index (nano::uint128_t const & balance) const -{ - auto index = std::upper_bound (minimums.begin (), minimums.end (), balance) - minimums.begin () - 1; - return index; -} - -/** - * Push a block and its associated time into the prioritization container. - * The time is given here because sideband might not exist in the case of state blocks. - */ -void nano::scheduler::buckets::push (uint64_t time, std::shared_ptr block, nano::amount const & priority) -{ - auto was_empty = empty (); - auto & bucket = buckets_m[index (priority.number ())]; - bucket.queue.emplace (value_type{ time, block }); - if (bucket.queue.size () > std::max (decltype (maximum){ 1 }, maximum / buckets_m.size ())) - { - bucket.queue.erase (--bucket.queue.end ()); - } - if (was_empty) - { - seek (); } + return false; // Not activated } -/** Return the highest priority block of the current bucket */ -std::shared_ptr nano::scheduler::buckets::top () const +void nano::scheduler::buckets::flush () { - debug_assert (!empty ()); - debug_assert (!buckets_m[*current].queue.empty ()); - auto result = buckets_m[*current].queue.begin ()->block; - return result; + nano::unique_lock lock{ mutex }; + condition.wait (lock, [this] () { + return stopped || empty_locked () || node.active.vacancy () <= 0; + }); } -/** Pop the current block from the container and seek to the next block, if it exists */ -void nano::scheduler::buckets::pop () +void nano::scheduler::buckets::notify () { - debug_assert (!empty ()); - debug_assert (!buckets_m[*current].queue.empty ()); - auto & bucket = buckets_m[*current]; - bucket.queue.erase (bucket.queue.begin ()); - seek (); + condition.notify_all (); } -/** Returns the total number of blocks in buckets */ std::size_t nano::scheduler::buckets::size () const { - std::size_t result{ 0 }; - for (auto const & bucket : buckets_m) - { - result += bucket.queue.size (); - } - return result; + nano::lock_guard lock{ mutex }; + return priority.size () + manual_queue.size (); } -/** Returns number of buckets, 62 by default */ -std::size_t nano::scheduler::buckets::bucket_count () const +bool nano::scheduler::buckets::empty_locked () const { - return buckets_m.size (); + return priority.empty () && manual_queue.empty (); } -/** Returns number of items in bucket with index 'index' */ -std::size_t nano::scheduler::buckets::bucket_size (std::size_t index) const +bool nano::scheduler::buckets::empty () const { - return buckets_m[index].queue.size (); + nano::lock_guard lock{ mutex }; + return empty_locked (); } -/** Returns true if all buckets are empty */ -bool nano::scheduler::buckets::empty () const +std::size_t nano::scheduler::buckets::priority_queue_size () const +{ + return priority.size (); +} + +bool nano::scheduler::buckets::priority_queue_predicate () const { - return std::all_of (buckets_m.begin (), buckets_m.end (), [] (auto const & bucket_a) { return bucket_a.queue.empty (); }); + return node.active.vacancy () > 0 && !priority.empty (); } -/** Print the state of the class in stderr */ -void nano::scheduler::buckets::dump () const +bool nano::scheduler::buckets::manual_queue_predicate () const { - for (auto const & i : buckets_m) + return !manual_queue.empty (); +} + +void nano::scheduler::buckets::run () +{ + nano::unique_lock lock{ mutex }; + while (!stopped) { - for (auto const & j : i.queue) + condition.wait (lock, [this] () { + return stopped || priority_queue_predicate () || manual_queue_predicate (); + }); + debug_assert ((std::this_thread::yield (), true)); // Introduce some random delay in debug builds + if (!stopped) { - std::cerr << j.time << ' ' << j.block->hash ().to_string () << '\n'; + stats.inc (nano::stat::type::election_scheduler, nano::stat::detail::loop); + + if (manual_queue_predicate ()) + { + auto const [block, previous_balance, election_behavior] = manual_queue.front (); + manual_queue.pop_front (); + lock.unlock (); + stats.inc (nano::stat::type::election_scheduler, nano::stat::detail::insert_manual); + node.active.insert (block, election_behavior); + } + else if (priority_queue_predicate ()) + { + auto block = priority.top (); + priority.pop (); + lock.unlock (); + stats.inc (nano::stat::type::election_scheduler, nano::stat::detail::insert_priority); + auto result = node.active.insert (block); + if (result.inserted) + { + stats.inc (nano::stat::type::election_scheduler, nano::stat::detail::insert_priority_success); + } + if (result.election != nullptr) + { + result.election->transition_active (); + } + } + else + { + lock.unlock (); + } + notify (); + lock.lock (); } } - std::cerr << "current: " << std::to_string (*current) << '\n'; } std::unique_ptr nano::scheduler::buckets::collect_container_info (std::string const & name) { + nano::unique_lock lock{ mutex }; + auto composite = std::make_unique (name); - for (auto i = 0; i < buckets_m.size (); ++i) - { - auto const & bucket = buckets_m[i]; - composite->add_component (std::make_unique (container_info{ std::to_string (i), bucket.queue.size (), 0 })); - } + composite->add_component (std::make_unique (container_info{ "manual_queue", manual_queue.size (), sizeof (decltype (manual_queue)::value_type) })); + composite->add_component (priority.collect_container_info ("priority")); return composite; } diff --git a/nano/node/scheduler/buckets.hpp b/nano/node/scheduler/buckets.hpp index 54e57effbd..9646690766 100644 --- a/nano/node/scheduler/buckets.hpp +++ b/nano/node/scheduler/buckets.hpp @@ -1,79 +1,65 @@ #pragma once + #include -#include +#include +#include + +#include -#include -#include -#include +#include +#include +#include +#include namespace nano { class block; +class node; } + namespace nano::scheduler { -class limiter; - -/** A container for holding blocks and their arrival/creation time. - * - * The container consists of a number of buckets. Each bucket holds an ordered set of 'value_type' items. - * The buckets are accessed in a round robin fashion. The index 'current' holds the index of the bucket to access next. - * When a block is inserted, the bucket to go into is determined by the account balance and the priority inside that - * bucket is determined by its creation/arrival time. - * - * The arrival/creation time is only an approximation and it could even be wildly wrong, - * for example, in the event of bootstrapped blocks. - */ class buckets final { - class value_type - { - public: - uint64_t time; - std::shared_ptr block; - bool operator< (value_type const & other_a) const; - bool operator== (value_type const & other_a) const; - }; - - class bucket - { - public: - std::set queue; - std::shared_ptr limiter; - }; - - /** container for the buckets to be read in round robin fashion */ - std::vector buckets_m; - - /** thresholds that define the bands for each bucket, the minimum balance an account must have to enter a bucket, - * the container writes a block to the lowest indexed bucket that has balance larger than the bucket's minimum value */ - std::vector minimums; +public: + buckets (nano::node &, nano::stats &); + ~buckets (); - /** Contains bucket indicies to iterate over when making the next scheduling decision */ - std::vector schedule; + void start (); + void stop (); - /** index of bucket to read next */ - decltype (schedule)::const_iterator current; + // Manualy start an election for a block + // Call action with confirmed block, may be different than what we started with + void manual (std::shared_ptr const &, boost::optional const & = boost::none, nano::election_behavior = nano::election_behavior::normal); + /** + * Activates the first unconfirmed block of \p account_a + * @return true if account was activated + */ + bool activate (nano::account const &, nano::transaction const &); + // Blocks until no more elections can be activated or there are no more elections to activate + void flush (); + void notify (); + std::size_t size () const; + bool empty () const; + std::size_t priority_queue_size () const; + std::unique_ptr collect_container_info (std::string const &); - /** maximum number of blocks in whole container, each bucket's maximum is maximum / bucket_number */ - uint64_t const maximum; +private: // Dependencies + nano::node & node; + nano::stats & stats; - void next (); - void seek (); - void populate_schedule (); +private: + void run (); + bool empty_locked () const; + bool priority_queue_predicate () const; + bool manual_queue_predicate () const; -public: - buckets (uint64_t maximum = 250000u); - void push (uint64_t time, std::shared_ptr block, nano::amount const & priority); - std::shared_ptr top () const; - void pop (); - std::size_t size () const; - std::size_t bucket_count () const; - std::size_t bucket_size (std::size_t index) const; - bool empty () const; - void dump () const; - std::size_t index (nano::uint128_t const & balance) const; + nano::prioritization priority; - std::unique_ptr collect_container_info (std::string const &); + std::deque, boost::optional, nano::election_behavior>> manual_queue; + bool stopped{ false }; + nano::condition_variable condition; + mutable nano::mutex mutex; + std::thread thread; }; -} // namespace nano::scheduler +} diff --git a/nano/node/scheduler/component.cpp b/nano/node/scheduler/component.cpp index 5303f52fa8..069bdba124 100644 --- a/nano/node/scheduler/component.cpp +++ b/nano/node/scheduler/component.cpp @@ -1,14 +1,14 @@ #include +#include #include #include #include -#include nano::scheduler::component::component (nano::node & node) : optimistic_impl{ std::make_unique (node.config.optimistic_scheduler, node, node.ledger, node.active, node.network_params.network, node.stats) }, - priority_impl{ std::make_unique (node, node.stats) }, + buckets_impl{ std::make_unique (node, node.stats) }, hinted_impl{ std::make_unique (nano::scheduler::hinted::config{ node.config }, node, node.inactive_vote_cache, node.active, node.online_reps, node.stats) }, - priority{ *priority_impl }, + buckets{ *buckets_impl }, hinted{ *hinted_impl }, optimistic{ *optimistic_impl } { diff --git a/nano/node/scheduler/component.hpp b/nano/node/scheduler/component.hpp index c2b03af4b2..3b5fb18919 100644 --- a/nano/node/scheduler/component.hpp +++ b/nano/node/scheduler/component.hpp @@ -2,26 +2,23 @@ #include -namespace nano -{ -class node; -} namespace nano::scheduler { -class priority; +class buckets; class hinted; +class node; class optimistic; class component { std::unique_ptr optimistic_impl; - std::unique_ptr priority_impl; + std::unique_ptr buckets_impl; std::unique_ptr hinted_impl; public: explicit component (nano::node & node); - nano::scheduler::priority & priority; + nano::scheduler::buckets & buckets; nano::scheduler::hinted & hinted; nano::scheduler::optimistic & optimistic; }; diff --git a/nano/node/scheduler/hinted.hpp b/nano/node/scheduler/hinted.hpp index fe82465fe7..a35b6588e6 100644 --- a/nano/node/scheduler/hinted.hpp +++ b/nano/node/scheduler/hinted.hpp @@ -2,7 +2,6 @@ #include #include -#include #include #include diff --git a/nano/node/scheduler/priority.cpp b/nano/node/scheduler/priority.cpp deleted file mode 100644 index 021afffbe2..0000000000 --- a/nano/node/scheduler/priority.cpp +++ /dev/null @@ -1,174 +0,0 @@ -#include -#include -#include - -nano::scheduler::priority::priority (nano::node & node_a, nano::stats & stats_a) : - node{ node_a }, - stats{ stats_a }, - buckets{ std::make_unique () } -{ -} - -nano::scheduler::priority::~priority () -{ - // Thread must be stopped before destruction - debug_assert (!thread.joinable ()); -} - -void nano::scheduler::priority::start () -{ - debug_assert (!thread.joinable ()); - - thread = std::thread{ [this] () { - nano::thread_role::set (nano::thread_role::name::election_scheduler); - run (); - } }; -} - -void nano::scheduler::priority::stop () -{ - { - nano::lock_guard lock{ mutex }; - stopped = true; - } - notify (); - nano::join_or_pass (thread); -} - -void nano::scheduler::priority::manual (std::shared_ptr const & block_a, boost::optional const & previous_balance_a, nano::election_behavior election_behavior_a) -{ - nano::lock_guard lock{ mutex }; - manual_queue.push_back (std::make_tuple (block_a, previous_balance_a, election_behavior_a)); - notify (); -} - -bool nano::scheduler::priority::activate (nano::account const & account_a, nano::transaction const & transaction) -{ - debug_assert (!account_a.is_zero ()); - auto info = node.ledger.account_info (transaction, account_a); - if (info) - { - nano::confirmation_height_info conf_info; - node.store.confirmation_height.get (transaction, account_a, conf_info); - if (conf_info.height < info->block_count) - { - debug_assert (conf_info.frontier != info->head); - auto hash = conf_info.height == 0 ? info->open_block : node.store.block.successor (transaction, conf_info.frontier); - auto block = node.store.block.get (transaction, hash); - debug_assert (block != nullptr); - if (node.ledger.dependents_confirmed (transaction, *block)) - { - stats.inc (nano::stat::type::election_scheduler, nano::stat::detail::activated); - auto balance = node.ledger.balance (transaction, hash); - auto previous_balance = node.ledger.balance (transaction, conf_info.frontier); - nano::lock_guard lock{ mutex }; - buckets->push (info->modified, block, std::max (balance, previous_balance)); - notify (); - return true; // Activated - } - } - } - return false; // Not activated -} - -void nano::scheduler::priority::flush () -{ - nano::unique_lock lock{ mutex }; - condition.wait (lock, [this] () { - return stopped || empty_locked () || node.active.vacancy () <= 0; - }); -} - -void nano::scheduler::priority::notify () -{ - condition.notify_all (); -} - -std::size_t nano::scheduler::priority::size () const -{ - nano::lock_guard lock{ mutex }; - return buckets->size () + manual_queue.size (); -} - -bool nano::scheduler::priority::empty_locked () const -{ - return buckets->empty () && manual_queue.empty (); -} - -bool nano::scheduler::priority::empty () const -{ - nano::lock_guard lock{ mutex }; - return empty_locked (); -} - -std::size_t nano::scheduler::priority::priority_queue_size () const -{ - return buckets->size (); -} - -bool nano::scheduler::priority::priority_queue_predicate () const -{ - return node.active.vacancy () > 0 && !buckets->empty (); -} - -bool nano::scheduler::priority::manual_queue_predicate () const -{ - return !manual_queue.empty (); -} - -void nano::scheduler::priority::run () -{ - nano::unique_lock lock{ mutex }; - while (!stopped) - { - condition.wait (lock, [this] () { - return stopped || priority_queue_predicate () || manual_queue_predicate (); - }); - debug_assert ((std::this_thread::yield (), true)); // Introduce some random delay in debug builds - if (!stopped) - { - stats.inc (nano::stat::type::election_scheduler, nano::stat::detail::loop); - - if (manual_queue_predicate ()) - { - auto const [block, previous_balance, election_behavior] = manual_queue.front (); - manual_queue.pop_front (); - lock.unlock (); - stats.inc (nano::stat::type::election_scheduler, nano::stat::detail::insert_manual); - node.active.insert (block, election_behavior); - } - else if (priority_queue_predicate ()) - { - auto block = buckets->top (); - buckets->pop (); - lock.unlock (); - stats.inc (nano::stat::type::election_scheduler, nano::stat::detail::insert_priority); - auto result = node.active.insert (block); - if (result.inserted) - { - stats.inc (nano::stat::type::election_scheduler, nano::stat::detail::insert_priority_success); - } - if (result.election != nullptr) - { - result.election->transition_active (); - } - } - else - { - lock.unlock (); - } - notify (); - lock.lock (); - } - } -} - -std::unique_ptr nano::scheduler::priority::collect_container_info (std::string const & name) -{ - nano::unique_lock lock{ mutex }; - - auto composite = std::make_unique (name); - composite->add_component (std::make_unique (container_info{ "manual_queue", manual_queue.size (), sizeof (decltype (manual_queue)::value_type) })); - composite->add_component (buckets->collect_container_info ("priority")); - return composite; -} diff --git a/nano/node/scheduler/priority.hpp b/nano/node/scheduler/priority.hpp deleted file mode 100644 index 9adb02f7e0..0000000000 --- a/nano/node/scheduler/priority.hpp +++ /dev/null @@ -1,65 +0,0 @@ -#pragma once - -#include -#include - -#include - -#include -#include -#include -#include - -namespace nano -{ -class block; -class node; -} - -namespace nano::scheduler -{ -class buckets; -class priority final -{ -public: - priority (nano::node &, nano::stats &); - ~priority (); - - void start (); - void stop (); - - // Manualy start an election for a block - // Call action with confirmed block, may be different than what we started with - void manual (std::shared_ptr const &, boost::optional const & = boost::none, nano::election_behavior = nano::election_behavior::normal); - /** - * Activates the first unconfirmed block of \p account_a - * @return true if account was activated - */ - bool activate (nano::account const &, nano::transaction const &); - // Blocks until no more elections can be activated or there are no more elections to activate - void flush (); - void notify (); - std::size_t size () const; - bool empty () const; - std::size_t priority_queue_size () const; - std::unique_ptr collect_container_info (std::string const &); - -private: // Dependencies - nano::node & node; - nano::stats & stats; - -private: - void run (); - bool empty_locked () const; - bool priority_queue_predicate () const; - bool manual_queue_predicate () const; - - std::unique_ptr buckets; - - std::deque, boost::optional, nano::election_behavior>> manual_queue; - bool stopped{ false }; - nano::condition_variable condition; - mutable nano::mutex mutex; - std::thread thread; -}; -} diff --git a/nano/rpc_test/rpc.cpp b/nano/rpc_test/rpc.cpp index 19ad2a5c30..169ee76103 100644 --- a/nano/rpc_test/rpc.cpp +++ b/nano/rpc_test/rpc.cpp @@ -5,8 +5,8 @@ #include #include #include +#include #include -#include #include #include #include @@ -1559,7 +1559,7 @@ TEST (rpc, process_subtype_open) ASSERT_EQ (nano::process_result::progress, node1->process (*send).code); ASSERT_EQ (nano::process_result::progress, node2.process (*send).code); auto const rpc_ctx = add_rpc (system, node1); - node1->scheduler.priority.manual (send); + node1->scheduler.buckets.manual (send); auto open = builder .state () .account (key.pub) @@ -1608,7 +1608,7 @@ TEST (rpc, process_subtype_receive) ASSERT_EQ (nano::process_result::progress, node1->process (*send).code); ASSERT_EQ (nano::process_result::progress, node2.process (*send).code); auto const rpc_ctx = add_rpc (system, node1); - node1->scheduler.priority.manual (send); + node1->scheduler.buckets.manual (send); auto receive = builder .state () .account (nano::dev::genesis_key.pub) @@ -2448,7 +2448,7 @@ TEST (rpc, account_representative_set_epoch_2_insufficient_work) ASSERT_NE (nullptr, system.upgrade_genesis_epoch (*node, nano::epoch::epoch_2)); // speed up the cementing process, otherwise the node waits for frontiers confirmation to notice the unconfirmed epoch blocks, which takes time - node->scheduler.priority.activate (nano::dev::genesis_key.pub, node->store.tx_begin_read ()); + node->scheduler.buckets.activate (nano::dev::genesis_key.pub, node->store.tx_begin_read ()); // wait for the epoch blocks to be cemented ASSERT_TIMELY (5s, node->get_confirmation_height (node->store.tx_begin_read (), nano::dev::genesis_key.pub) == 3); @@ -6964,7 +6964,7 @@ TEST (node, election_scheduler_container_info) // process the block and wait for it to show up in the election scheduler node->process_active (send1); - ASSERT_TIMELY (10s, node->scheduler.priority.size () == 1); + ASSERT_TIMELY (10s, node->scheduler.buckets.size () == 1); // now check the RPC call boost::property_tree::ptree request; diff --git a/nano/slow_test/node.cpp b/nano/slow_test/node.cpp index 280ce6dff1..18ed359e0a 100644 --- a/nano/slow_test/node.cpp +++ b/nano/slow_test/node.cpp @@ -1,8 +1,8 @@ #include #include #include +#include #include -#include #include #include #include @@ -677,7 +677,7 @@ TEST (confirmation_height, many_accounts_single_confirmation) { auto block = node->block (last_open_hash); ASSERT_NE (nullptr, block); - node->scheduler.priority.manual (block); + node->scheduler.buckets.manual (block); std::shared_ptr election; ASSERT_TIMELY (10s, (election = node->active.election (block->qualified_root ())) != nullptr); election->force_confirm (); @@ -760,7 +760,7 @@ TEST (confirmation_height, many_accounts_many_confirmations) // Confirm all of the accounts for (auto & open_block : open_blocks) { - node->scheduler.priority.manual (open_block); + node->scheduler.buckets.manual (open_block); std::shared_ptr election; ASSERT_TIMELY (10s, (election = node->active.election (open_block->qualified_root ())) != nullptr); election->force_confirm (); @@ -900,7 +900,7 @@ TEST (confirmation_height, long_chains) // Call block confirm on the existing receive block on the genesis account which will confirm everything underneath on both accounts { - node->scheduler.priority.manual (receive1); + node->scheduler.buckets.manual (receive1); std::shared_ptr election; ASSERT_TIMELY (10s, (election = node->active.election (receive1->qualified_root ())) != nullptr); election->force_confirm (); @@ -2225,7 +2225,7 @@ TEST (node, wallet_create_block_confirm_conflicts) // Call block confirm on the top level send block which will confirm everything underneath on both accounts. { auto block = node->store.block.get (node->store.tx_begin_read (), latest); - node->scheduler.priority.manual (block); + node->scheduler.buckets.manual (block); std::shared_ptr election; ASSERT_TIMELY (10s, (election = node->active.election (block->qualified_root ())) != nullptr); election->force_confirm (); @@ -2319,7 +2319,7 @@ TEST (system, block_sequence) std::string message; for (auto i : system.nodes) { - message += boost::str (boost::format ("N:%1% b:%2% c:%3% a:%4% s:%5% p:%6%\n") % std::to_string (i->network.port) % std::to_string (i->ledger.cache.block_count) % std::to_string (i->ledger.cache.cemented_count) % std::to_string (i->active.size ()) % std::to_string (i->scheduler.priority.size ()) % std::to_string (i->network.size ())); + message += boost::str (boost::format ("N:%1% b:%2% c:%3% a:%4% s:%5% p:%6%\n") % std::to_string (i->network.port) % std::to_string (i->ledger.cache.block_count) % std::to_string (i->ledger.cache.cemented_count) % std::to_string (i->active.size ()) % std::to_string (i->scheduler.buckets.size ()) % std::to_string (i->network.size ())); nano::lock_guard lock{ i->active.mutex }; for (auto const & j : i->active.roots) { diff --git a/nano/test_common/testutil.cpp b/nano/test_common/testutil.cpp index 0232f61671..0480913c89 100644 --- a/nano/test_common/testutil.cpp +++ b/nano/test_common/testutil.cpp @@ -1,6 +1,6 @@ #include +#include #include -#include #include #include #include @@ -156,7 +156,7 @@ bool nano::test::activate (nano::node & node, std::vector hash // Block does not exist in the ledger yet return false; } - node.scheduler.priority.manual (disk_block); + node.scheduler.buckets.manual (disk_block); } return true; } @@ -237,7 +237,7 @@ std::shared_ptr nano::test::start_election (nano::test::system & block_l = node_a.block (hash_a); } - node_a.scheduler.priority.manual (block_l); + node_a.scheduler.buckets.manual (block_l); // wait for the election to appear std::shared_ptr election = node_a.active.election (block_l->qualified_root ());