/** * Iterate through the unlinked cache and insert anything that * links to the newly inserted item. This will start a recursive * set of calls performing a depth-first insertion of pending blocks as * _push_next(..) calls _push_block(...) which will in turn call _push_next */ void fork_database::_push_next( const item_ptr& new_item ) { auto& prev_idx = _unlinked_index.get<by_previous>(); auto itr = prev_idx.find( new_item->id ); while( itr != prev_idx.end() ) { auto tmp = *itr; prev_idx.erase( itr ); _push_block( tmp ); itr = prev_idx.find( new_item->id ); } }
/** * Push block "may fail" in which case every partial change is unwound. After * push block is successful the block is appended to the chain database on disk. * * @return true if we switched forks as a result of this push. */ bool database::push_block(const signed_block& new_block, uint32_t skip) { // idump((new_block.block_num())(new_block.id())(new_block.timestamp)(new_block.previous)); bool result; detail::with_skip_flags( *this, skip, [&]() { detail::without_pending_transactions( *this, std::move(_pending_tx), [&]() { result = _push_block(new_block); }); }); return result; }
/** * Pushes the block into the fork database and caches it if it doesn't link * */ shared_ptr<fork_item> fork_database::push_block(const signed_block& b) { auto item = std::make_shared<fork_item>(b); try { _push_block(item); } catch ( const unlinkable_block_exception& e ) { wlog( "Pushing block to fork database that failed to link: ${id}, ${num}", ("id",b.id())("num",b.block_num()) ); wlog( "Head: ${num}, ${id}", ("num",_head->data.block_num())("id",_head->data.id()) ); _unlinked_index.insert( item ); } return _head; }