104 lines
3.1 KiB
C++
104 lines
3.1 KiB
C++
#include <nano/node/distributed_work.hpp>
|
|
#include <nano/node/distributed_work_factory.hpp>
|
|
#include <nano/node/node.hpp>
|
|
|
|
nano::distributed_work_factory::distributed_work_factory (nano::node & node_a) :
|
|
node (node_a)
|
|
{
|
|
}
|
|
|
|
nano::distributed_work_factory::~distributed_work_factory ()
|
|
{
|
|
stop ();
|
|
}
|
|
|
|
bool nano::distributed_work_factory::make (nano::work_version const version_a, nano::root const & root_a, std::vector<std::pair<std::string, uint16_t>> const & peers_a, uint64_t difficulty_a, std::function<void (boost::optional<uint64_t>)> const & callback_a, boost::optional<nano::account> const & account_a)
|
|
{
|
|
return make (std::chrono::seconds (1), nano::work_request{ version_a, root_a, difficulty_a, account_a, callback_a, peers_a });
|
|
}
|
|
|
|
bool nano::distributed_work_factory::make (std::chrono::seconds const & backoff_a, nano::work_request const & request_a)
|
|
{
|
|
bool error_l{ true };
|
|
if (!stopped)
|
|
{
|
|
cleanup_finished ();
|
|
if (node.work_generation_enabled (request_a.peers))
|
|
{
|
|
auto distributed (std::make_shared<nano::distributed_work> (node, request_a, backoff_a));
|
|
{
|
|
nano::lock_guard<nano::mutex> guard (mutex);
|
|
items.emplace (request_a.root, distributed);
|
|
}
|
|
distributed->start ();
|
|
error_l = false;
|
|
}
|
|
}
|
|
return error_l;
|
|
}
|
|
|
|
void nano::distributed_work_factory::cancel (nano::root const & root_a)
|
|
{
|
|
nano::lock_guard<nano::mutex> guard_l (mutex);
|
|
auto root_items_l = items.equal_range (root_a);
|
|
std::for_each (root_items_l.first, root_items_l.second, [] (auto item_l) {
|
|
if (auto distributed_l = item_l.second.lock ())
|
|
{
|
|
// Send work_cancel to work peers and stop local work generation
|
|
distributed_l->cancel ();
|
|
}
|
|
});
|
|
items.erase (root_items_l.first, root_items_l.second);
|
|
}
|
|
|
|
void nano::distributed_work_factory::cleanup_finished ()
|
|
{
|
|
nano::lock_guard<nano::mutex> guard (mutex);
|
|
// std::erase_if in c++20
|
|
auto erase_if = [] (decltype (items) & container, auto pred) {
|
|
for (auto it = container.begin (), end = container.end (); it != end;)
|
|
{
|
|
if (pred (*it))
|
|
{
|
|
it = container.erase (it);
|
|
}
|
|
else
|
|
{
|
|
++it;
|
|
}
|
|
}
|
|
};
|
|
erase_if (items, [] (decltype (items)::value_type item) { return item.second.expired (); });
|
|
}
|
|
|
|
void nano::distributed_work_factory::stop ()
|
|
{
|
|
if (!stopped.exchange (true))
|
|
{
|
|
// Cancel any ongoing work
|
|
nano::lock_guard<nano::mutex> guard (mutex);
|
|
for (auto & item_l : items)
|
|
{
|
|
if (auto distributed_l = item_l.second.lock ())
|
|
{
|
|
distributed_l->cancel ();
|
|
}
|
|
}
|
|
items.clear ();
|
|
}
|
|
}
|
|
|
|
size_t nano::distributed_work_factory::size () const
|
|
{
|
|
nano::lock_guard<nano::mutex> guard_l (mutex);
|
|
return items.size ();
|
|
}
|
|
|
|
std::unique_ptr<nano::container_info_component> nano::collect_container_info (distributed_work_factory & distributed_work, std::string const & name)
|
|
{
|
|
auto item_count = distributed_work.size ();
|
|
auto sizeof_item_element = sizeof (decltype (nano::distributed_work_factory::items)::value_type);
|
|
auto composite = std::make_unique<container_info_composite> (name);
|
|
composite->add_component (std::make_unique<container_info_leaf> (container_info{ "items", item_count, sizeof_item_element }));
|
|
return composite;
|
|
}
|