Skip to content

Commit

Permalink
GH-2048 Misc cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
heifner committed Jan 20, 2024
1 parent 7ec302e commit 1207522
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 51 deletions.
35 changes: 18 additions & 17 deletions libraries/chain/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -668,7 +668,7 @@ struct building_block {
// branch from parent
std::optional<qc_data_t> qc_data;
if (!validating) {
// get fork_database so that we can search for the best qc to include in this block.
// get fork_database so that we can search for the best qc to include in this block.
fork_db.apply_if<void>([&](const auto& forkdb) {
auto branch = forkdb.fetch_branch(parent_id());
for( auto it = branch.begin(); it != branch.end(); ++it ) {
Expand Down Expand Up @@ -1245,7 +1245,7 @@ struct controller_impl {
forkdb.chain_head->block = std::make_shared<signed_block>(genheader.header);
};

fork_db.apply_dpos<void>(init_blockchain); // assuming here that genesis_state is always dpos
fork_db.apply_legacy<void>(init_blockchain); // assuming here that genesis_state is always dpos

db.set_revision( head_block_num() );
initialize_database(genesis);
Expand Down Expand Up @@ -1625,7 +1625,7 @@ struct controller_impl {
section.template add_row<block_header_state_legacy>(*forkdb.chain_head, db);
});
};
fork_db.apply_dpos<void>(write_block_state_section);
fork_db.apply_legacy<void>(write_block_state_section);

controller_index_set::walk_indices([this, &snapshot]( auto utils ){
using value_t = typename decltype(utils)::index_t::value_type;
Expand Down Expand Up @@ -1702,7 +1702,7 @@ struct controller_impl {
forkdb.chain_head = std::make_shared<block_state_legacy>();
static_cast<block_header_state_legacy&>(*forkdb.chain_head) = head_header_state;
};
fork_db.apply_dpos<void>(read_block_state_section);
fork_db.apply_legacy<void>(read_block_state_section);

controller_index_set::walk_indices([this, &snapshot, &header]( auto utils ){
using value_t = typename decltype(utils)::index_t::value_type;
Expand Down Expand Up @@ -2470,16 +2470,17 @@ struct controller_impl {
"db revision is not on par with head block",
("db.revision()", db.revision())("controller_head_block", head_block_num())("fork_db_head_block", fork_db_head_block_num()) );

fork_db.apply_dpos<void>([&](auto& forkdb) {
maybe_session session = self.skip_db_sessions(s) ? maybe_session() : maybe_session(db);
pending.emplace(std::move(session), *forkdb.chain_head, when, confirm_block_count, new_protocol_feature_activations);
});
fork_db.apply_if<void>([&](auto& forkdb) {
maybe_session session = self.skip_db_sessions(s) ? maybe_session() : maybe_session(db);
building_block_input bbi{ forkdb.chain_head->id(), when, forkdb.chain_head->get_scheduled_producer(when).producer_name,
new_protocol_feature_activations };
pending.emplace(std::move(session), *forkdb.chain_head, bbi);
});
fork_db.apply<void>(
[&](auto& forkdb) { // legacy
maybe_session session = self.skip_db_sessions(s) ? maybe_session() : maybe_session(db);
pending.emplace(std::move(session), *forkdb.chain_head, when, confirm_block_count, new_protocol_feature_activations);
},
[&](auto& forkdb) { // instant-finality
maybe_session session = self.skip_db_sessions(s) ? maybe_session() : maybe_session(db);
building_block_input bbi{forkdb.chain_head->id(), when, forkdb.chain_head->get_scheduled_producer(when).producer_name,
new_protocol_feature_activations};
pending.emplace(std::move(session), *forkdb.chain_head, bbi);
});

pending->_block_status = s;
pending->_producer_block_id = producer_block_id;
Expand Down Expand Up @@ -2686,7 +2687,7 @@ struct controller_impl {

fork_db.apply<void>(add_completed_block);

fork_db.apply_dpos<void>([this](auto& forkdb) {
fork_db.apply_legacy<void>([this](auto& forkdb) {
#warning todo: support deep_mind_logger even when in IF mode (use apply instead of apply_dpos)
// at block level, no transaction specific logging is possible
if (auto* dm_logger = get_deep_mind_logger(false)) {
Expand Down Expand Up @@ -2714,7 +2715,7 @@ struct controller_impl {
}
return false;
};
if (fork_db.apply_dpos<bool>(transition)) {
if (fork_db.apply_legacy<bool>(transition)) {
fork_db.switch_from_legacy();
}

Expand Down Expand Up @@ -3981,7 +3982,7 @@ const block_header& controller::head_block_header()const {

block_state_legacy_ptr controller::head_block_state_legacy()const {
// returns null after instant finality activated
return my->fork_db.apply_dpos<block_state_legacy_ptr>(
return my->fork_db.apply_legacy<block_state_legacy_ptr>(
[](auto& forkdb) -> block_state_legacy_ptr { return forkdb.chain_head; });
}

Expand Down
19 changes: 13 additions & 6 deletions libraries/chain/fork_database.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ namespace eosio::chain {
using bhsp = bs::bhsp_t;
using bhs = bhsp::element_type;

using fork_db_t = fork_database_t<bsp>;
using fork_db_t = fork_database_t<bsp>;
using branch_type = fork_db_t::branch_type;
using branch_type_pair = fork_db_t::branch_type_pair;

Expand Down Expand Up @@ -565,6 +565,10 @@ namespace eosio::chain {
}

fork_database::~fork_database() {
close();
}

void fork_database::close() {
apply<void>([&](auto& forkdb) { forkdb.close(data_dir / config::forkdb_filename); });
}

Expand Down Expand Up @@ -592,26 +596,29 @@ namespace eosio::chain {
);

if (totem == fork_database_legacy_t::legacy_magic_number) {
apply_dpos<void>([&](auto& forkdb) {
apply_legacy<void>([&](auto& forkdb) {
forkdb.open(fork_db_file, validator);
});
} else {
// file is instant-finality data, so switch to fork_database_if_t
v.emplace<fork_database_if_t>(fork_database_if_t::magic_number);
vforkdb.emplace<fork_database_if_t>(fork_database_if_t::magic_number);
apply_if<void>([&](auto& forkdb) {
forkdb.open(fork_db_file, validator);
});
}
apply<void>([&](auto& forkdb) {
forkdb.open(fork_db_file, validator);
});
} FC_CAPTURE_AND_RETHROW( (fork_db_file) )
}
}

void fork_database::switch_from_legacy() {
std::lock_guard g(m);
// no need to close fork_db because we don't want to write anything out, file is removed on open
block_state_legacy_ptr head = std::get<fork_database_legacy_t>(v).chain_head; // will throw if called after transistion
block_state_legacy_ptr head = std::get<fork_database_legacy_t>(vforkdb).chain_head; // will throw if called after transistion
auto new_head = std::make_shared<block_state>(*head);
std::lock_guard g(m);
v.emplace<fork_database_if_t>(fork_database_if_t::magic_number);
vforkdb.emplace<fork_database_if_t>(fork_database_if_t::magic_number);
apply_if<void>([&](auto& forkdb) {
forkdb.chain_head = new_head;
forkdb.reset(*new_head);
Expand Down
70 changes: 42 additions & 28 deletions libraries/chain/include/eosio/chain/fork_database.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ namespace eosio::chain {
* irreversible signal.
*
* Not thread safe, thread safety provided by fork_database below.
* fork_database should be used instead of fork_database_t directly as it manages
* the different supported types.
*/
template<class bsp> // either block_state_legacy_ptr or block_state_ptr
class fork_database_t {
Expand Down Expand Up @@ -107,17 +109,20 @@ namespace eosio::chain {

/**
* Provides thread safety on fork_database_t and provide mechanism for opening the correct type
* as well as switching from legacy to instant-finality.
* as well as switching from legacy (old dpos) to instant-finality.
*
* All methods assert until open() is closed.
*/
class fork_database {
mutable std::recursive_mutex m;
const std::filesystem::path data_dir;
std::variant<fork_database_t<block_state_legacy_ptr>, fork_database_t<block_state_ptr>> v;
std::variant<fork_database_t<block_state_legacy_ptr>, fork_database_t<block_state_ptr>> vforkdb;
public:
explicit fork_database(const std::filesystem::path& data_dir);
~fork_database(); // close on destruction

void open( validator_t& validator );
void close();

void switch_from_legacy();

Expand All @@ -128,55 +133,64 @@ namespace eosio::chain {
R apply(const F& f) {
std::lock_guard g(m);
if constexpr (std::is_same_v<void, R>)
std::visit([&](auto& forkdb) { f(forkdb); }, v);
std::visit([&](auto& forkdb) { f(forkdb); }, vforkdb);
else
return std::visit([&](auto& forkdb) -> R { return f(forkdb); }, v);
return std::visit([&](auto& forkdb) -> R { return f(forkdb); }, vforkdb);
}

template <class R, class F>
R apply(const F& f) const {
std::lock_guard g(m);
if constexpr (std::is_same_v<void, R>)
std::visit([&](const auto& forkdb) { f(forkdb); }, v);
std::visit([&](const auto& forkdb) { f(forkdb); }, vforkdb);
else
return std::visit([&](const auto& forkdb) -> R { return f(forkdb); }, v);
return std::visit([&](const auto& forkdb) -> R { return f(forkdb); }, vforkdb);
}

/// Apply for when only need lambda executed when in instant-finality mode
template <class R, class F>
R apply_if(const F& f) {
std::lock_guard g(m);
if constexpr (std::is_same_v<void, R>)
std::visit(overloaded{[&](fork_database_legacy_t&) {},
[&](fork_database_if_t& forkdb) {
std::lock_guard g(m);
f(forkdb);
}}, v);
[&](fork_database_if_t& forkdb) { f(forkdb); }},
vforkdb);
else
return std::visit(overloaded{[&](fork_database_legacy_t&) -> R { return {}; },
[&](fork_database_if_t& forkdb) -> R {
std::lock_guard g(m);
return f(forkdb);
}}, v);
[&](fork_database_if_t& forkdb) -> R { return f(forkdb); }},
vforkdb);
}

/// Apply for when only need lambda executed when in legacy mode
template <class R, class F>
R apply_dpos(const F& f) {
R apply_legacy(const F& f) {
std::lock_guard g(m);
if constexpr (std::is_same_v<void, R>)
std::visit(overloaded{[&](fork_database_legacy_t& forkdb) { f(forkdb); },
[&](fork_database_if_t&) {}},
vforkdb);
else
return std::visit(overloaded{[&](fork_database_legacy_t& forkdb) -> R { return f(forkdb); },
[&](fork_database_if_t&) -> R { return {}; }},
vforkdb);
}

/// @param legacy_f the lambda to execute if in legacy mode
/// @param if_f the lambda to execute if in instant-finality mode
template <class R, class LegacyF, class IfF>
R apply(const LegacyF& legacy_f, const IfF& if_f) {
std::lock_guard g(m);
if constexpr (std::is_same_v<void, R>)
std::visit(overloaded{[&](fork_database_legacy_t& forkdb) {
std::lock_guard g(m);
f(forkdb);
},
[&](fork_database_if_t&) {}}, v);
std::visit(overloaded{[&](fork_database_legacy_t& forkdb) { legacy_f(forkdb); },
[&](fork_database_if_t& forkdb) { if_f(forkdb); }},
vforkdb);
else
return std::visit(overloaded{[&](fork_database_legacy_t& forkdb) -> R {
std::lock_guard g(m);
return f(forkdb);
},
[&](fork_database_if_t&) -> R {
return {};
}}, v);
return std::visit(overloaded{[&](fork_database_legacy_t& forkdb) -> R { return legacy_f(forkdb); },
[&](fork_database_if_t& forkdb) -> R { return if_f(forkdb); }},
vforkdb);
}

// if we every support more than one version then need to save min/max in fork_database_t
// if we ever support more than one version then need to save min/max in fork_database_t
static constexpr uint32_t min_supported_version = 1;
static constexpr uint32_t max_supported_version = 1;
};
Expand Down

0 comments on commit 1207522

Please sign in to comment.