Fixed rare deadlock condition :(

This commit is contained in:
clemahieu 2016-03-30 19:44:47 -05:00
commit 4680489925
4 changed files with 18 additions and 19 deletions

View file

@ -926,7 +926,7 @@ application_path (application_path_a)
});
observers.add_vote ([this] (rai::vote const & vote_a)
{
rai::transaction transaction (store.environment, nullptr, false);
rai::transaction transaction (store.environment, nullptr, true);
this->gap_cache.vote (transaction, vote_a);
});
if (config.logging.log_to_cerr ())
@ -1031,7 +1031,7 @@ void rai::gap_cache::vote (MDB_txn * transaction_a, rai::vote const & vote_a)
auto existing (blocks.get <2> ().find (hash));
if (existing != blocks.get <2> ().end ())
{
auto changed (existing->votes->vote (node.store, vote_a));
auto changed (existing->votes->vote (transaction_a, node.store, vote_a));
if (changed)
{
auto winner (node.ledger.winner (transaction_a, *existing->votes));
@ -2198,26 +2198,25 @@ void rai::election::confirm_once ()
}
}
bool rai::election::recalculate_winner ()
bool rai::election::recalculate_winner (MDB_txn * transaction_a)
{
auto result (false);
rai::transaction transaction (node.store.environment, nullptr, true);
auto tally_l (node.ledger.tally (transaction, votes));
auto tally_l (node.ledger.tally (transaction_a, votes));
assert (tally_l.size () > 0);
auto quorum_threshold_l (quorum_threshold (transaction, node.ledger));
auto quorum_threshold_l (quorum_threshold (transaction_a, node.ledger));
auto winner (std::move (tally_l.begin ()));
if (!(*winner->second == *last_winner) && (winner->first > quorum_threshold_l))
{
// Replace our block with the winner and roll back any dependent blocks
node.ledger.rollback (transaction, last_winner->hash ());
node.ledger.process (transaction, *winner->second);
node.ledger.rollback (transaction_a, last_winner->hash ());
node.ledger.process (transaction_a, *winner->second);
last_winner = std::move (winner->second);
}
// Check if we can do a fast confirm for the usual case of good actors
if (tally_l.size () == 1)
{
// No forks detected
if (tally_l.begin ()->first > quorum_threshold (transaction, node.ledger))
if (tally_l.begin ()->first > quorum_threshold (transaction_a, node.ledger))
{
// We have vote quarum
result = true;
@ -2226,9 +2225,9 @@ bool rai::election::recalculate_winner ()
return result;
}
void rai::election::confirm_if_quarum ()
void rai::election::confirm_if_quarum (MDB_txn * transaction_a)
{
auto quarum (recalculate_winner ());
auto quarum (recalculate_winner (transaction_a));
if (quarum)
{
confirm_once ();
@ -2242,10 +2241,11 @@ void rai::election::confirm_cutoff ()
void rai::election::vote (rai::vote const & vote_a)
{
auto tally_changed (votes.vote (node.store, vote_a));
rai::transaction transaction (node.store.environment, nullptr, true);
auto tally_changed (votes.vote (transaction, node.store, vote_a));
if (tally_changed)
{
confirm_if_quarum ();
confirm_if_quarum (transaction);
}
}

View file

@ -42,13 +42,13 @@ public:
election (rai::node &, rai::block const &, std::function <void (rai::block &)> const &);
void vote (rai::vote const &);
// Set last_winner based on our current state of the ledger
bool recalculate_winner ();
bool recalculate_winner (MDB_txn *);
// Tell the network our view of the winner
void broadcast_winner ();
// Change our winner to agree with the network
void recompute_winner ();
// Confirmation method 1, uncontested quarum
void confirm_if_quarum ();
void confirm_if_quarum (MDB_txn *);
// Confirmation method 2, settling time
void confirm_cutoff ();
rai::uint128_t quorum_threshold (MDB_txn *, rai::ledger &);

View file

@ -123,15 +123,14 @@ bool rai::unique_ptr_block_hash::operator () (std::unique_ptr <rai::block> const
return *lhs == *rhs;
}
bool rai::votes::vote (rai::block_store & store_a, rai::vote const & vote_a)
bool rai::votes::vote (MDB_txn * transaction_a, rai::block_store & store_a, rai::vote const & vote_a)
{
auto result (false);
// Reject unsigned votes
if (!rai::validate_message (vote_a.account, vote_a.hash (), vote_a.signature))
{
rai::transaction transaction (store_a.environment, nullptr, true);
// Make sure this sequence number is > any we've seen from this account before
if (store_a.sequence_atomic_observe (transaction, vote_a.account, vote_a.sequence) == vote_a.sequence)
if (store_a.sequence_atomic_observe (transaction_a, vote_a.account, vote_a.sequence) == vote_a.sequence)
{
// Check if we're adding a new vote entry or modifying an existing one.
auto existing (rep_votes.find (vote_a.account));

View file

@ -436,7 +436,7 @@ class votes
{
public:
votes (rai::block const &);
bool vote (rai::block_store &, rai::vote const &);
bool vote (MDB_txn *, rai::block_store &, rai::vote const &);
// Root block of fork
rai::block_hash id;
// All votes received by account