-
Notifications
You must be signed in to change notification settings - Fork 72
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
IF: Support load of fork database after instant-finality is enabled #2113
Changes from 1 commit
a0a3528
4f634cd
7ec302e
a0a5573
5cae9d9
1207522
23bee43
7a4b5d5
d31be4f
175af8f
e07d937
9310754
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -11,33 +11,33 @@ namespace eosio::chain { | |||||
struct fork_database_impl; | ||||||
|
||||||
/** | ||||||
* @class fork_database | ||||||
* @class fork_database_t | ||||||
* @brief manages light-weight state for all potential unconfirmed forks | ||||||
* | ||||||
* As new blocks are received, they are pushed into the fork database. The fork | ||||||
* database tracks the longest chain and the last irreversible block number. All | ||||||
* blocks older than the last irreversible block are freed after emitting the | ||||||
* irreversible signal. | ||||||
* | ||||||
* An internal mutex is used to provide thread-safety. | ||||||
* Not thread safe, thread safety provided by fork_database below. | ||||||
*/ | ||||||
template<class bsp> // either block_state_legacy_ptr or block_state_ptr | ||||||
class fork_database { | ||||||
class fork_database_t { | ||||||
public: | ||||||
static constexpr uint32_t legacy_magic_number = 0x30510FDB; | ||||||
static constexpr uint32_t magic_number = 0x4242FDB; | ||||||
linh2931 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
|
||||||
using bs = bsp::element_type; | ||||||
using bhsp = bs::bhsp_t; | ||||||
using bhs = bhsp::element_type; | ||||||
using bsp_t = bsp; | ||||||
using branch_type = deque<bsp>; | ||||||
using branch_type_pair = pair<branch_type, branch_type>; | ||||||
|
||||||
explicit fork_database( const std::filesystem::path& data_dir ); | ||||||
~fork_database(); | ||||||
explicit fork_database_t(uint32_t magic_number = legacy_magic_number); | ||||||
|
||||||
std::filesystem::path get_data_dir() const; | ||||||
|
||||||
void open( validator_t& validator ); | ||||||
void close(); | ||||||
void open( const std::filesystem::path& fork_db_file, validator_t& validator ); | ||||||
void close( const std::filesystem::path& fork_db_file ); | ||||||
|
||||||
bhsp get_block_header( const block_id_type& id ) const; | ||||||
bsp get_block( const block_id_type& id ) const; | ||||||
|
@@ -70,6 +70,9 @@ namespace eosio::chain { | |||||
bsp head() const; | ||||||
bsp pending_head() const; | ||||||
|
||||||
// only accessed by main thread, no mutex protection | ||||||
bsp chain_head; | ||||||
|
||||||
/** | ||||||
* Returns the sequence of block states resulting from trimming the branch from the | ||||||
* root block (exclusive) to the block with an id of `h` (inclusive) by removing any | ||||||
|
@@ -95,15 +98,77 @@ namespace eosio::chain { | |||||
|
||||||
void mark_valid( const bsp& h ); | ||||||
|
||||||
static const uint32_t magic_number; | ||||||
|
||||||
static const uint32_t min_supported_version; | ||||||
static const uint32_t max_supported_version; | ||||||
|
||||||
private: | ||||||
unique_ptr<fork_database_impl<bsp>> my; | ||||||
}; | ||||||
|
||||||
using fork_database_legacy = fork_database<block_state_legacy_ptr>; | ||||||
|
||||||
using fork_database_legacy_t = fork_database_t<block_state_legacy_ptr>; | ||||||
using fork_database_if_t = fork_database_t<block_state_ptr>; | ||||||
|
||||||
/** | ||||||
* Provides thread safety on fork_database_t and provide mechanism for opening the correct type | ||||||
* as well as switching from legacy to instant-finality. | ||||||
*/ | ||||||
class fork_database { | ||||||
mutable std::recursive_mutex m; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not a fan of recursive mutexes. However, currently controller uses nested calls of |
||||||
const std::filesystem::path data_dir; | ||||||
std::variant<fork_database_t<block_state_legacy_ptr>, fork_database_t<block_state_ptr>> v; | ||||||
public: | ||||||
explicit fork_database(const std::filesystem::path& data_dir); | ||||||
~fork_database(); // close on destruction | ||||||
|
||||||
void open( validator_t& validator ); | ||||||
|
||||||
void switch_from_legacy(); | ||||||
|
||||||
// see fork_database_t::fetch_branch(forkdb->head()->id()) | ||||||
std::vector<signed_block_ptr> fetch_branch_from_head(); | ||||||
|
||||||
template <class R, class F> | ||||||
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); | ||||||
else | ||||||
return std::visit([&](auto& forkdb) -> R { return f(forkdb); }, v); | ||||||
} | ||||||
|
||||||
template <class R, class F> | ||||||
R apply_if(const F& f) { | ||||||
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); | ||||||
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); | ||||||
} | ||||||
|
||||||
template <class R, class F> | ||||||
R apply_dpos(const F& f) { | ||||||
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); | ||||||
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); | ||||||
} | ||||||
|
||||||
// if we every support more than one version then need to save min/max in fork_database_t | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Comment doesn't read right. Maybe this
Suggested change
|
||||||
static constexpr uint32_t min_supported_version = 1; | ||||||
static constexpr uint32_t max_supported_version = 1; | ||||||
}; | ||||||
} /// eosio::chain |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now it occurs to me, if we already have an issue, we don't need a warning, because the issue will remind us.