Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[1.0.4] Fast shutdown in irreversible mode #1061

Merged
merged 3 commits into from
Dec 11, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 28 additions & 15 deletions libraries/chain/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1308,8 +1308,6 @@ struct controller_impl {
// When in IRREVERSIBLE mode fork_db blocks are applied and marked valid when they become irreversible
template<typename ForkDB, typename BSP>
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<block_state_legacy_ptr, std::decay_t<decltype(bsp)>>) {
// before transition to savanna
Expand Down Expand Up @@ -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();
Expand All @@ -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))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't start be reset?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once this returns false, the method exits.

return false;
greg7mdp marked this conversation as resolved.
Show resolved Hide resolved
return true;
}
return bsp->is_valid();
};

std::vector<std::future<std::vector<char>>> 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<char>>;
std::vector<packed_block_future> 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() );
greg7mdp marked this conversation as resolved.
Show resolved Hide resolved

db.commit( (*bitr)->block_num() );
root_id = (*bitr)->id();
Expand All @@ -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;
}
Expand Down Expand Up @@ -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 {
Expand Down
Loading