dncurrency/nano/node/ledger_walker.cpp
theohax 3cfc81f8a7
Disable compilation/usage of diskhash on Windows (#3372)
* Disable compilation/usage of diskhash on Windows

* Fix formatting

* Fix CMake formatting

* Take out ledger_walker header from the Windows compilation as well

* Prevent diskhash library from being referenced on Windows
2021-07-08 16:21:47 +03:00

180 lines
4.9 KiB
C++

// TODO: keep this until diskhash builds fine on Windows
#ifndef _WIN32
#include <nano/lib/blocks.hpp>
#include <nano/lib/errors.hpp>
#include <nano/node/ledger_walker.hpp>
#include <nano/secure/ledger.hpp>
#include <nano/secure/store.hpp>
#include <nano/secure/utility.hpp>
#include <algorithm>
#include <limits>
#include <utility>
nano::ledger_walker::ledger_walker (nano::ledger const & ledger_a) :
ledger{ ledger_a },
use_in_memory_walked_blocks{ true },
walked_blocks{},
walked_blocks_disk{},
blocks_to_walk{}
{
debug_assert (!ledger.store.init_error ());
}
void nano::ledger_walker::walk_backward (nano::block_hash const & start_block_hash_a, should_visit_callback const & should_visit_callback_a, visitor_callback const & visitor_callback_a)
{
const auto transaction = ledger.store.tx_begin_read ();
enqueue_block (start_block_hash_a);
while (!blocks_to_walk.empty ())
{
const auto block = dequeue_block (transaction);
if (!should_visit_callback_a (block))
{
continue;
}
visitor_callback_a (block);
for (const auto & hash : ledger.dependent_blocks (transaction, *block))
{
if (!hash.is_zero ())
{
const auto dependent_block = ledger.store.block.get (transaction, hash);
if (dependent_block)
{
enqueue_block (dependent_block);
}
}
}
}
clear_queue ();
}
void nano::ledger_walker::walk (nano::block_hash const & end_block_hash_a, should_visit_callback const & should_visit_callback_a, visitor_callback const & visitor_callback_a)
{
std::uint64_t last_walked_block_order_index = 0;
dht::DiskHash<nano::block_hash> walked_blocks_order{ nano::unique_path ().c_str (), static_cast<int> (std::to_string (std::numeric_limits<std::uint64_t>::max ()).size ()) + 1, dht::DHOpenRW };
walk_backward (end_block_hash_a,
should_visit_callback_a,
[&] (const auto & block) {
walked_blocks_order.insert (std::to_string (++last_walked_block_order_index).c_str (), block->hash ());
});
const auto transaction = ledger.store.tx_begin_read ();
for (auto walked_block_order_index = last_walked_block_order_index; walked_block_order_index != 0; --walked_block_order_index)
{
const auto * block_hash = walked_blocks_order.lookup (std::to_string (walked_block_order_index).c_str ());
if (!block_hash)
{
debug_assert (false);
continue;
}
const auto block = ledger.store.block.get (transaction, *block_hash);
if (!block)
{
debug_assert (false);
continue;
}
visitor_callback_a (block);
}
}
void nano::ledger_walker::walk_backward (nano::block_hash const & start_block_hash_a, visitor_callback const & visitor_callback_a)
{
walk_backward (
start_block_hash_a,
[&] (const auto & /* block */) {
return true;
},
visitor_callback_a);
}
void nano::ledger_walker::walk (nano::block_hash const & end_block_hash_a, visitor_callback const & visitor_callback_a)
{
walk (
end_block_hash_a,
[&] (const auto & /* block */) {
return true;
},
visitor_callback_a);
}
void nano::ledger_walker::enqueue_block (nano::block_hash block_hash_a)
{
if (add_to_walked_blocks (block_hash_a))
{
blocks_to_walk.emplace (std::move (block_hash_a));
}
}
void nano::ledger_walker::enqueue_block (std::shared_ptr<nano::block> const & block_a)
{
debug_assert (block_a);
enqueue_block (block_a->hash ());
}
bool nano::ledger_walker::add_to_walked_blocks (nano::block_hash const & block_hash_a)
{
if (use_in_memory_walked_blocks)
{
if (walked_blocks.size () < in_memory_block_count)
{
return walked_blocks.emplace (block_hash_a).second;
}
use_in_memory_walked_blocks = false;
debug_assert (!walked_blocks_disk.has_value ());
walked_blocks_disk.emplace (nano::unique_path ().c_str (), sizeof (nano::block_hash::bytes) + 1, dht::DHOpenRW);
for (const auto & walked_block_hash : walked_blocks)
{
if (!add_to_walked_blocks_disk (walked_block_hash))
{
debug_assert (false);
}
}
decltype (walked_blocks){}.swap (walked_blocks);
}
return add_to_walked_blocks_disk (block_hash_a);
}
bool nano::ledger_walker::add_to_walked_blocks_disk (nano::block_hash const & block_hash_a)
{
debug_assert (!use_in_memory_walked_blocks);
debug_assert (walked_blocks_disk.has_value ());
std::array<decltype (nano::block_hash::chars)::value_type, sizeof (nano::block_hash::bytes) + 1> block_hash_key{};
std::copy (block_hash_a.chars.cbegin (),
block_hash_a.chars.cend (),
block_hash_key.begin ());
return walked_blocks_disk->insert (block_hash_key.data (), true);
}
void nano::ledger_walker::clear_queue ()
{
use_in_memory_walked_blocks = true;
decltype (walked_blocks){}.swap (walked_blocks);
walked_blocks_disk.reset ();
decltype (blocks_to_walk){}.swap (blocks_to_walk);
}
std::shared_ptr<nano::block> nano::ledger_walker::dequeue_block (nano::transaction const & transaction_a)
{
auto block = ledger.store.block.get (transaction_a, blocks_to_walk.top ());
blocks_to_walk.pop ();
return block;
}
#endif // _WIN32 -- TODO: keep this until diskhash builds fine on Windows