diff --git a/libraries/chain/controller.cpp b/libraries/chain/controller.cpp index 3a7eae907f..00a363d4e2 100644 --- a/libraries/chain/controller.cpp +++ b/libraries/chain/controller.cpp @@ -1308,8 +1308,6 @@ struct controller_impl { // When in IRREVERSIBLE mode fork_db blocks are applied and marked valid when they become irreversible template bool apply_irreversible_block(ForkDB& forkdb, const BSP& bsp) { - if (read_mode != db_read_mode::IRREVERSIBLE) - return true; // ignore controller::block_report br; if constexpr (std::is_same_v>) { // before transition to savanna @@ -1493,6 +1491,8 @@ struct controller_impl { if( new_lib_num <= lib_num ) return; + const fc::time_point start = fc::time_point::now(); + auto mark_branch_irreversible = [&, this](auto& forkdb) { assert(!irreversible_mode() || forkdb.head()); const auto& head_id = irreversible_mode() ? forkdb.head()->id() : chain_head.id(); @@ -1512,27 +1512,39 @@ struct controller_impl { // irreversible. Instead, this moves irreversible as much as possible and allows the next maybe_switch_forks call to apply these // non-validated blocks. After the maybe_switch_forks call (before next produced block or on next received block), irreversible // can then move forward on the then validated blocks. - return read_mode == db_read_mode::IRREVERSIBLE || bsp->is_valid(); + // In irreversible mode, break every ~500ms to allow other tasks (e.g. get_info, SHiP) opportunity to run. There is a post + // for every incoming blocks; enough posted tasks to apply all blocks queued to the fork db. + if (irreversible_mode()) { + if (!replaying && fc::time_point::now() - start > fc::milliseconds(500)) + return false; + return true; + } + return bsp->is_valid(); }; - std::vector>> v; - v.reserve( branch.size() ); - for( auto bitr = branch.rbegin(); bitr != branch.rend() && should_process(*bitr); ++bitr ) { - - v.emplace_back( post_async_task( thread_pool.get_executor(), [b=(*bitr)->block]() { return fc::raw::pack(*b); } ) ); + using packed_block_future = std::future>; + std::vector v; + if (!irreversible_mode()) { + v.reserve( branch.size() ); + for( auto bitr = branch.rbegin(); bitr != branch.rend() && should_process(*bitr); ++bitr ) { + v.emplace_back( post_async_task( thread_pool.get_executor(), [b=(*bitr)->block]() { return fc::raw::pack(*b); } ) ); + } } auto it = v.begin(); for( auto bitr = branch.rbegin(); bitr != branch.rend() && should_process(*bitr); ++bitr ) { - if (!apply_irreversible_block(forkdb, *bitr)) - break; + packed_block_future f; + if (irreversible_mode()) { + f = post_async_task( thread_pool.get_executor(), [b=(*bitr)->block]() { return fc::raw::pack(*b); } ); + if (!apply_irreversible_block(forkdb, *bitr)) + break; + } emit( irreversible_block, std::tie((*bitr)->block, (*bitr)->id()), __FILE__, __LINE__ ); // blog.append could fail due to failures like running out of space. // Do it before commit so that in case it throws, DB can be rolled back. - blog.append( (*bitr)->block, (*bitr)->id(), it->get() ); - ++it; + blog.append( (*bitr)->block, (*bitr)->id(), irreversible_mode() ? f.get() : it++->get() ); db.commit( (*bitr)->block_num() ); root_id = (*bitr)->id(); @@ -1544,13 +1556,14 @@ struct controller_impl { } } catch( const std::exception& e ) { try { + elog("Caught exception while logging irreversible: ${e}", ("e", e.what())); if (root_id != forkdb.root()->id()) { forkdb.advance_root(root_id); } } catch( const fc::exception& e2 ) { - wlog("Caught exception ${e2}, while processing exception ${e}", ("e2", e2.to_detail_string())("e", e.what())); + elog("Caught exception ${e2}, while processing exception ${e}", ("e2", e2.to_detail_string())("e", e.what())); } catch( const std::exception& e2 ) { - wlog("Caught exception ${e2}, while processing exception ${e}", ("e2", e2.what())("e", e.what())); + elog("Caught exception ${e2}, while processing exception ${e}", ("e2", e2.what())("e", e.what())); } throw; } @@ -4985,7 +4998,7 @@ struct controller_impl { } bool should_terminate() const { - return should_terminate(chain_head.block_num()); + return should_terminate(chain_head.block_num()) || check_shutdown(); } bool is_builtin_activated( builtin_protocol_feature_t f )const {