130 lines
		
	
	
	
		
			3.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			130 lines
		
	
	
	
		
			3.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #pragma once
 | |
| 
 | |
| #include <nano/lib/numbers.hpp>
 | |
| #include <nano/lib/numbers_templ.hpp>
 | |
| #include <nano/lib/observer_set.hpp>
 | |
| #include <nano/lib/thread_pool.hpp>
 | |
| #include <nano/node/fwd.hpp>
 | |
| #include <nano/secure/common.hpp>
 | |
| #include <nano/secure/fwd.hpp>
 | |
| 
 | |
| #include <boost/multi_index/hashed_index.hpp>
 | |
| #include <boost/multi_index/member.hpp>
 | |
| #include <boost/multi_index/ordered_index.hpp>
 | |
| #include <boost/multi_index/sequenced_index.hpp>
 | |
| #include <boost/multi_index_container.hpp>
 | |
| 
 | |
| #include <condition_variable>
 | |
| #include <deque>
 | |
| #include <mutex>
 | |
| #include <thread>
 | |
| #include <unordered_set>
 | |
| 
 | |
| namespace mi = boost::multi_index;
 | |
| 
 | |
| namespace nano
 | |
| {
 | |
| class confirming_set_config final
 | |
| {
 | |
| public:
 | |
| 	// TODO: Serialization & deserialization
 | |
| 
 | |
| public:
 | |
| 	bool enable{ true };
 | |
| 	size_t batch_size{ 256 };
 | |
| 
 | |
| 	/** Maximum number of dependent blocks to be stored in memory during processing */
 | |
| 	size_t max_blocks{ 128 * 1024 };
 | |
| 	size_t max_queued_notifications{ 8 };
 | |
| 
 | |
| 	/** Maximum number of failed blocks to wait for requeuing */
 | |
| 	size_t max_deferred{ 16 * 1024 };
 | |
| 	/** Max age of deferred blocks before they are dropped */
 | |
| 	std::chrono::seconds deferred_age_cutoff{ 15min };
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * Set of blocks to be durably confirmed
 | |
|  */
 | |
| class confirming_set final
 | |
| {
 | |
| 	friend class confirmation_heightDeathTest_missing_block_Test;
 | |
| 	friend class confirmation_height_pruned_source_Test;
 | |
| 
 | |
| public:
 | |
| 	confirming_set (confirming_set_config const &, nano::ledger &, nano::block_processor &, nano::stats &, nano::logger &);
 | |
| 	~confirming_set ();
 | |
| 
 | |
| 	void start ();
 | |
| 	void stop ();
 | |
| 
 | |
| 	// Adds a block to the set of blocks to be confirmed
 | |
| 	void add (nano::block_hash const & hash, std::shared_ptr<nano::election> const & election = nullptr);
 | |
| 	// Added blocks will remain in this set until after ledger has them marked as confirmed.
 | |
| 	bool contains (nano::block_hash const & hash) const;
 | |
| 	std::size_t size () const;
 | |
| 
 | |
| 	nano::container_info container_info () const;
 | |
| 
 | |
| public: // Events
 | |
| 	struct context
 | |
| 	{
 | |
| 		std::shared_ptr<nano::block> block;
 | |
| 		nano::block_hash confirmation_root;
 | |
| 		std::shared_ptr<nano::election> election;
 | |
| 	};
 | |
| 
 | |
| 	nano::observer_set<std::deque<context> const &> batch_cemented;
 | |
| 	nano::observer_set<std::deque<nano::block_hash> const &> already_cemented;
 | |
| 	nano::observer_set<nano::block_hash> cementing_failed;
 | |
| 
 | |
| 	nano::observer_set<std::shared_ptr<nano::block>> cemented_observers;
 | |
| 
 | |
| private: // Dependencies
 | |
| 	confirming_set_config const & config;
 | |
| 	nano::ledger & ledger;
 | |
| 	nano::block_processor & block_processor;
 | |
| 	nano::stats & stats;
 | |
| 	nano::logger & logger;
 | |
| 
 | |
| private:
 | |
| 	struct entry
 | |
| 	{
 | |
| 		nano::block_hash hash;
 | |
| 		std::shared_ptr<nano::election> election;
 | |
| 		std::chrono::steady_clock::time_point timestamp{ std::chrono::steady_clock::now () };
 | |
| 	};
 | |
| 
 | |
| 	void run ();
 | |
| 	void run_batch (std::unique_lock<std::mutex> &);
 | |
| 	std::deque<entry> next_batch (size_t max_count);
 | |
| 	void cleanup (std::unique_lock<std::mutex> &);
 | |
| 
 | |
| private:
 | |
| 	// clang-format off
 | |
| 	class tag_hash {};
 | |
| 	class tag_sequenced {};
 | |
| 
 | |
| 	using ordered_entries = boost::multi_index_container<entry,
 | |
| 	mi::indexed_by<
 | |
| 		mi::sequenced<mi::tag<tag_sequenced>>,
 | |
| 		mi::hashed_unique<mi::tag<tag_hash>,
 | |
| 			mi::member<entry, nano::block_hash, &entry::hash>>
 | |
| 	>>;
 | |
| 	// clang-format on
 | |
| 
 | |
| 	// Blocks that are ready to be cemented
 | |
| 	ordered_entries set;
 | |
| 	// Blocks that could not be cemented immediately (e.g. waiting for rollbacks to complete)
 | |
| 	ordered_entries deferred;
 | |
| 	// Blocks that are being cemented in the current batch
 | |
| 	std::unordered_set<nano::block_hash> current;
 | |
| 
 | |
| 	std::atomic<bool> stopped{ false };
 | |
| 	mutable std::mutex mutex;
 | |
| 	std::condition_variable condition;
 | |
| 	std::thread thread;
 | |
| 
 | |
| 	nano::thread_pool workers;
 | |
| };
 | |
| }
 | 
