 3cfc81f8a7
			
		
	
	
	
	
	3cfc81f8a7* 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
		
			
				
	
	
		
			180 lines
		
	
	
	
		
			4.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			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
 |