diff --git a/nano/node/prioritization.cpp b/nano/node/prioritization.cpp index 3d6efe41..ebe17275 100644 --- a/nano/node/prioritization.cpp +++ b/nano/node/prioritization.cpp @@ -14,6 +14,7 @@ bool nano::prioritization::value_type::operator== (value_type const & other_a) c return time == other_a.time && block->hash () == other_a.block->hash (); } +/** Moves the bucket pointer to the next bucket */ void nano::prioritization::next () { ++current; @@ -23,6 +24,7 @@ void nano::prioritization::next () } } +/** Seek to the next non-empty bucket, if one exists */ void nano::prioritization::seek () { next (); @@ -32,6 +34,7 @@ void nano::prioritization::seek () } } +/** Initialise the schedule vector */ void nano::prioritization::populate_schedule () { for (auto i = 0; i < buckets.size (); ++i) @@ -40,8 +43,11 @@ void nano::prioritization::populate_schedule () } } -nano::prioritization::prioritization (uint64_t maximum, std::function)> const & drop_a) : - drop{ drop_a }, +/** + * 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 } { static std::size_t constexpr bucket_count = 129; @@ -57,6 +63,10 @@ nano::prioritization::prioritization (uint64_t maximum, std::function block) { auto was_empty = empty (); @@ -76,6 +86,7 @@ void nano::prioritization::push (uint64_t time, std::shared_ptr blo } } +/** Return the highest priority block of the current bucket */ std::shared_ptr nano::prioritization::top () const { debug_assert (!empty ()); @@ -84,6 +95,7 @@ std::shared_ptr nano::prioritization::top () const 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 ()); @@ -93,6 +105,7 @@ void nano::prioritization::pop () seek (); } +/** Returns the total number of blocks in buckets */ std::size_t nano::prioritization::size () const { std::size_t result{ 0 }; @@ -103,22 +116,26 @@ std::size_t nano::prioritization::size () const return result; } +/** Returns number of buckets, 129 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 (); }); } -void nano::prioritization::dump () +/** Print the state of the class in stderr */ +void nano::prioritization::dump () const { for (auto const & i : buckets) { diff --git a/nano/node/prioritization.hpp b/nano/node/prioritization.hpp index 56df6dfd..e925b379 100644 --- a/nano/node/prioritization.hpp +++ b/nano/node/prioritization.hpp @@ -9,6 +9,17 @@ 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 @@ -19,19 +30,31 @@ class prioritization final 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 (); - std::function)> drop; - // Contains bucket indicies to iterate over when making the next scheduling decision - std::vector schedule; - decltype (schedule)::const_iterator current; public: - prioritization (uint64_t maximum = 250000u, std::function)> const & drop_a = nullptr); + prioritization (uint64_t maximum = 250000u); void push (uint64_t time, std::shared_ptr block); std::shared_ptr top () const; void pop (); @@ -39,8 +62,7 @@ public: std::size_t bucket_count () const; std::size_t bucket_size (std::size_t index) const; bool empty () const; - void dump (); - uint64_t const maximum; + void dump () const; std::unique_ptr collect_container_info (std::string const &); };