diff --git a/nano/core_test/active_transactions.cpp b/nano/core_test/active_transactions.cpp index 9842f8bf28..7e5ccd46b9 100644 --- a/nano/core_test/active_transactions.cpp +++ b/nano/core_test/active_transactions.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -1520,9 +1521,9 @@ TEST (active_transactions, allow_limited_overflow) } // Ensure active elections overfill AEC only up to normal + hinted limit - ASSERT_TIMELY_EQ (5s, node.active.size (), node.active.limit () + node.active.limit (nano::election_behavior::hinted)); + ASSERT_TIMELY_EQ (5s, node.active.size (), node.active.limit () + node.scheduler.hinted.limit ()); // And it stays that way without increasing - ASSERT_ALWAYS (1s, node.active.size () == node.active.limit () + node.active.limit (nano::election_behavior::hinted)); + ASSERT_ALWAYS (1s, node.active.size () == node.active.limit () + node.scheduler.hinted.limit ()); } /* @@ -1558,9 +1559,9 @@ TEST (active_transactions, allow_limited_overflow_adapt) } // Ensure hinted election amount is bounded by hinted limit - ASSERT_TIMELY_EQ (5s, node.active.size (), node.active.limit (nano::election_behavior::hinted)); + ASSERT_TIMELY_EQ (5s, node.active.size (), node.scheduler.hinted.limit ()); // And it stays that way without increasing - ASSERT_ALWAYS (1s, node.active.size () == node.active.limit (nano::election_behavior::hinted)); + ASSERT_ALWAYS (1s, node.active.size () == node.scheduler.hinted.limit ()); // Insert the first part of the blocks into normal election scheduler for (auto const & block : blocks1) diff --git a/nano/lib/stats_enums.hpp b/nano/lib/stats_enums.hpp index 123b60c7f1..f7e690101a 100644 --- a/nano/lib/stats_enums.hpp +++ b/nano/lib/stats_enums.hpp @@ -159,9 +159,10 @@ enum class detail : uint8_t election_block_conflict, election_restart, election_not_confirmed, - election_hinted_overflow, election_hinted_confirmed, election_hinted_drop, + election_hinted_overflow, + election_hinted_started, generate_vote, generate_vote_normal, generate_vote_final, diff --git a/nano/node/active_transactions.cpp b/nano/node/active_transactions.cpp index 984521b979..a33aa74f45 100644 --- a/nano/node/active_transactions.cpp +++ b/nano/node/active_transactions.cpp @@ -194,13 +194,13 @@ int64_t nano::active_transactions::limit (nano::election_behavior behavior) cons } case nano::election_behavior::hinted: { - const uint64_t limit = node.config.active_elections_hinted_limit_percentage * node.config.active_elections_size / 100; - return static_cast (limit); + debug_assert (false); + return 0; } case nano::election_behavior::optimistic: { - const uint64_t limit = node.config.active_elections_optimistic_limit_percentage * node.config.active_elections_size / 100; - return static_cast (limit); + debug_assert (false); + return 0; } } @@ -450,6 +450,10 @@ nano::election_insertion_result nano::active_transactions::insert_impl (nano::un } trim (); } + if (result.election == nullptr) + { + std::cerr << '\0'; + } return result; } diff --git a/nano/node/scheduler/hinted.cpp b/nano/node/scheduler/hinted.cpp index ba8ec51e10..926d40f8bf 100644 --- a/nano/node/scheduler/hinted.cpp +++ b/nano/node/scheduler/hinted.cpp @@ -1,6 +1,7 @@ #include #include #include +#include nano::scheduler::hinted::config::config (nano::node_config const & config) : vote_cache_check_interval_ms{ config.network_params.network.is_dev_network () ? 100u : 1000u } @@ -11,9 +12,8 @@ nano::scheduler::hinted::hinted (config const & config_a, nano::node & node_a, n config_m{ config_a }, node{ node_a }, inactive_vote_cache{ inactive_vote_cache_a }, - active{ active_a }, - online_reps{ online_reps_a }, - stats{ stats_a } + limiter{ std::make_shared (node.active.insert_fn (), std::max (node.config.active_elections_hinted_limit_percentage * node.config.active_elections_size / 100, 1u), nano::election_behavior::hinted) }, + online_reps{ online_reps_a }, stats{ stats_a } { } @@ -48,10 +48,15 @@ void nano::scheduler::hinted::notify () condition.notify_all (); } +size_t nano::scheduler::hinted::limit () const +{ + return limiter->limit (); +} + bool nano::scheduler::hinted::predicate (nano::uint128_t const & minimum_tally) const { // Check if there is space inside AEC for a new hinted election - if (active.vacancy (nano::election_behavior::hinted) > 0) + if (limiter->available ()) { // Check if there is any vote cache entry surpassing our minimum vote tally threshold if (inactive_vote_cache.peek (minimum_tally)) @@ -59,6 +64,10 @@ bool nano::scheduler::hinted::predicate (nano::uint128_t const & minimum_tally) return true; } } + else + { + std::cerr << '\0'; + } return false; } @@ -77,9 +86,9 @@ bool nano::scheduler::hinted::run_one (nano::uint128_t const & minimum_tally) { // Try to insert it into AEC as hinted election // We check for AEC vacancy inside our predicate - auto result = node.active.insert (block, nano::election_behavior::hinted); + auto result = limiter->activate (block); - stats.inc (nano::stat::type::hinting, result.inserted ? nano::stat::detail::insert : nano::stat::detail::insert_failed); + stats.inc (nano::stat::type::hinting, result.inserted ? nano::stat::detail::hinted : nano::stat::detail::insert_failed); return result.inserted; // Return whether block was inserted } diff --git a/nano/node/scheduler/hinted.hpp b/nano/node/scheduler/hinted.hpp index a35b6588e6..1d1686c093 100644 --- a/nano/node/scheduler/hinted.hpp +++ b/nano/node/scheduler/hinted.hpp @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -12,11 +13,13 @@ namespace nano class node; class node_config; class active_transactions; +class node; class vote_cache; class online_reps; } namespace nano::scheduler { +class limiter; /* * Monitors inactive vote cache and schedules elections with the highest observed vote tally. */ @@ -41,18 +44,20 @@ class hinted final * Notify about changes in AEC vacancy */ void notify (); + size_t limit () const; private: bool predicate (nano::uint128_t const & minimum_tally) const; void run (); bool run_one (nano::uint128_t const & minimum_tally); + nano::election_insertion_result insert_action (std::shared_ptr block); nano::uint128_t tally_threshold () const; private: // Dependencies nano::node & node; nano::vote_cache & inactive_vote_cache; - nano::active_transactions & active; + std::shared_ptr limiter; nano::online_reps & online_reps; nano::stats & stats; diff --git a/nano/node/scheduler/optimistic.cpp b/nano/node/scheduler/optimistic.cpp index beb7d3353a..be6f4dab7f 100644 --- a/nano/node/scheduler/optimistic.cpp +++ b/nano/node/scheduler/optimistic.cpp @@ -1,13 +1,14 @@ #include #include #include +#include #include nano::scheduler::optimistic::optimistic (optimistic_config const & config_a, nano::node & node_a, nano::ledger & ledger_a, nano::active_transactions & active_a, nano::network_constants const & network_constants_a, nano::stats & stats_a) : config{ config_a }, node{ node_a }, ledger{ ledger_a }, - active{ active_a }, + limiter{ std::make_shared (node.active.insert_fn (), std::max (node.config.active_elections_optimistic_limit_percentage * node.config.active_elections_size / 100, 1u), nano::election_behavior::optimistic) }, network_constants{ network_constants_a }, stats{ stats_a } { @@ -100,7 +101,7 @@ bool nano::scheduler::optimistic::predicate () const { debug_assert (!mutex.try_lock ()); - if (active.vacancy (nano::election_behavior::optimistic) <= 0) + if (!limiter->available ()) { return false; } @@ -154,7 +155,7 @@ void nano::scheduler::optimistic::run_one (nano::transaction const & transaction { // Try to insert it into AEC // We check for AEC vacancy inside our predicate - auto result = node.active.insert (block, nano::election_behavior::optimistic); + auto result = limiter->activate (block); stats.inc (nano::stat::type::optimistic_scheduler, result.inserted ? nano::stat::detail::insert : nano::stat::detail::insert_failed); } diff --git a/nano/node/scheduler/optimistic.hpp b/nano/node/scheduler/optimistic.hpp index 2cc802ea43..fd2e22e43f 100644 --- a/nano/node/scheduler/optimistic.hpp +++ b/nano/node/scheduler/optimistic.hpp @@ -22,13 +22,14 @@ namespace mi = boost::multi_index; namespace nano { -class node; -class ledger; class active_transactions; +class ledger; +class node; } namespace nano::scheduler { +class limiter; class optimistic_config final { public: @@ -76,7 +77,7 @@ class optimistic final optimistic_config const & config; nano::node & node; nano::ledger & ledger; - nano::active_transactions & active; + std::shared_ptr limiter; nano::network_constants const & network_constants; nano::stats & stats; diff --git a/nano/node/scheduler/priority.cpp b/nano/node/scheduler/priority.cpp index 9c1b7cc5d0..aeb5b80369 100644 --- a/nano/node/scheduler/priority.cpp +++ b/nano/node/scheduler/priority.cpp @@ -1,5 +1,6 @@ #include #include +#include #include nano::scheduler::priority::priority (nano::node & node_a, nano::stats & stats_a) : @@ -124,30 +125,42 @@ void nano::scheduler::priority::run () 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); auto result = node.active.insert (block, election_behavior); - if (result.election != nullptr) + if (result.election) { - result.election->transition_active (); + manual_queue.pop_front (); } + else + { + std::cerr << '\0'; + } + stats.inc (nano::stat::type::election_scheduler, nano::stat::detail::insert_manual); } 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.first); - if (result.inserted) + if (!buckets->top ().second->available ()) { - stats.inc (nano::stat::type::election_scheduler, nano::stat::detail::insert_priority_success); + buckets->seek (); } + auto [block, limiter] = buckets->top (); + debug_assert (limiter->available ()); + auto result = limiter->activate (block); if (result.election != nullptr) { + buckets->pop (); + lock.unlock (); result.election->transition_active (); + if (result.inserted) + { + stats.inc (nano::stat::type::election_scheduler, nano::stat::detail::insert_priority_success); + } } + else + { + lock.unlock (); + } + stats.inc (nano::stat::type::election_scheduler, nano::stat::detail::insert_priority); } else {