Migrate thread safety to RCLConsensus (RIPD-1389):

Moves thread safety from generic Consensus to RCLConsensus and switch generic
Consensus to adaptor design.
This commit is contained in:
Brad Chase
2017-04-26 11:13:30 -04:00
committed by seelabs
parent 8c155dd875
commit 01b4d5cdd4
23 changed files with 1729 additions and 1135 deletions

View File

@@ -21,7 +21,8 @@
#include <boost/container/flat_map.hpp>
#include <boost/container/flat_set.hpp>
#include <ripple/consensus/Consensus.h>
#include <ripple/consensus/ConsensusProposal.h>
#include <test/csf/Ledger.h>
#include <test/csf/Tx.h>
#include <test/csf/UNL.h>
@@ -115,20 +116,43 @@ public:
directly from the generic types.
*/
using Proposal = ConsensusProposal<PeerID, Ledger::ID, TxSetType>;
class PeerPosition
{
public:
PeerPosition(Proposal const & p)
: proposal_(p)
{
}
struct Traits
Proposal const&
proposal() const
{
return proposal_;
}
Json::Value
getJson() const
{
return proposal_.getJson();
}
private:
Proposal proposal_;
};
/** Represents a single node participating in the consensus process.
It implements the Adaptor requirements of generic Consensus.
*/
struct Peer
{
using Ledger_t = Ledger;
using NodeID_t = PeerID;
using TxSet_t = TxSet;
};
using PeerPosition_t = PeerPosition;
using Result = ConsensusResult<Peer>;
/** Represents a single node participating in the consensus process.
It implements the Callbacks required by Consensus.
*/
struct Peer : public Consensus<Peer, Traits>
{
using Base = Consensus<Peer, Traits>;
Consensus<Peer> consensus;
//! Our unique ID
PeerID id;
@@ -172,12 +196,17 @@ struct Peer : public Consensus<Peer, Traits>
bool validating_ = true;
bool proposing_ = true;
ConsensusParms parms_;
std::size_t prevProposers_ = 0;
std::chrono::milliseconds prevRoundTime_;
//! All peers start from the default constructed ledger
Peer(PeerID i, BasicNetwork<Peer*>& n, UNL const& u, ConsensusParms p)
: Consensus<Peer, Traits>(n.clock(), p, beast::Journal{})
: consensus(n.clock(), *this, beast::Journal{})
, id{i}
, net{n}
, unl(u)
, parms_(p)
{
ledgers[lastClosedLedger.id()] = lastClosedLedger;
}
@@ -210,12 +239,6 @@ struct Peer : public Consensus<Peer, Traits>
return nullptr;
}
auto const&
proposals(Ledger::ID const& ledgerHash)
{
return peerPositions_[ledgerHash];
}
TxSet const*
acquireTxSet(TxSet::ID const& setId)
{
@@ -245,17 +268,17 @@ struct Peer : public Consensus<Peer, Traits>
}
Result
onClose(Ledger const& prevLedger, NetClock::time_point closeTime, Mode mode)
onClose(Ledger const& prevLedger, NetClock::time_point closeTime, ConsensusMode mode)
{
TxSet res{openTxs};
return Result{TxSet{openTxs},
Proposal{prevLedger.id(),
return Result(TxSet{openTxs},
Proposal(prevLedger.id(),
Proposal::seqJoin,
res.id(),
closeTime,
now(),
id}};
id));
}
void
@@ -263,10 +286,17 @@ struct Peer : public Consensus<Peer, Traits>
Result const& result,
Ledger const& prevLedger,
NetClock::duration const& closeResolution,
CloseTimes const& rawCloseTimes,
Mode const& mode)
ConsensusCloseTimes const& rawCloseTimes,
ConsensusMode const& mode,
Json::Value && consensusJson)
{
onAccept(result, prevLedger, closeResolution, rawCloseTimes, mode);
onAccept(
result,
prevLedger,
closeResolution,
rawCloseTimes,
mode,
std::move(consensusJson));
}
void
@@ -274,8 +304,9 @@ struct Peer : public Consensus<Peer, Traits>
Result const& result,
Ledger const& prevLedger,
NetClock::duration const& closeResolution,
CloseTimes const& rawCloseTimes,
Mode const& mode)
ConsensusCloseTimes const& rawCloseTimes,
ConsensusMode const& mode,
Json::Value && consensusJson)
{
auto newLedger = prevLedger.close(
result.set.txs_,
@@ -283,7 +314,8 @@ struct Peer : public Consensus<Peer, Traits>
rawCloseTimes.self,
result.position.closeTime() != NetClock::time_point{});
ledgers[newLedger.id()] = newLedger;
prevProposers_ = result.proposers;
prevRoundTime_ = result.roundTime.read();
lastClosedLedger = newLedger;
auto it =
@@ -304,16 +336,16 @@ struct Peer : public Consensus<Peer, Traits>
// TODO: reconsider this and instead just save LCL generated here?
if (completedLedgers <= targetLedgers)
{
startRound(
consensus.startRound(
now(), lastClosedLedger.id(), lastClosedLedger, proposing_);
}
}
Ledger::ID
getPrevLedger(Ledger::ID const& ledgerID, Ledger const& ledger, Mode mode)
getPrevLedger(Ledger::ID const& ledgerID, Ledger const& ledger, ConsensusMode mode)
{
// TODO: Use generic validation code
if (mode != Mode::wrongLedger && ledgerID.seq > 0 &&
if (mode != ConsensusMode::wrongLedger && ledgerID.seq > 0 &&
ledger.id().seq > 0)
return peerValidations.getBestLCL(ledgerID, ledger.parentID());
return ledgerID;
@@ -323,24 +355,31 @@ struct Peer : public Consensus<Peer, Traits>
propose(Proposal const& pos)
{
if (proposing_)
relay(pos);
relay(PeerPosition(pos));
}
ConsensusParms const &
parms() const
{
return parms_;
}
//-------------------------------------------------------------------------
// non-callback helpers
void
receive(Proposal const& p)
receive(PeerPosition const& peerPos)
{
Proposal const & p = peerPos.proposal();
if (unl.find(p.nodeID()) == unl.end())
return;
// TODO: Be sure this is a new proposal!!!!!
// TODO: Supress repeats more efficiently
auto& dest = peerPositions_[p.prevLedger()];
if (std::find(dest.begin(), dest.end(), p) != dest.end())
return;
dest.push_back(p);
peerProposal(now(), p);
consensus.peerProposal(now(), peerPos);
}
void
@@ -349,7 +388,7 @@ struct Peer : public Consensus<Peer, Traits>
// save and map complete?
auto it = txSets.insert(std::make_pair(txs.id(), txs));
if (it.second)
gotTxSet(now(), txs);
consensus.gotTxSet(now(), txs);
}
void
@@ -392,7 +431,7 @@ struct Peer : public Consensus<Peer, Traits>
void
timerEntry()
{
Base::timerEntry(now());
consensus.timerEntry(now());
// only reschedule if not completed
if (completedLedgers < targetLedgers)
net.timer(parms().ledgerGRANULARITY, [&]() { timerEntry(); });
@@ -406,7 +445,7 @@ struct Peer : public Consensus<Peer, Traits>
// so there is no gaurantee that bestLCL == lastClosedLedger.id()
auto bestLCL = peerValidations.getBestLCL(
lastClosedLedger.id(), lastClosedLedger.parentID());
startRound(now(), bestLCL, lastClosedLedger, proposing_);
consensus.startRound(now(), bestLCL, lastClosedLedger, proposing_);
}
NetClock::time_point
@@ -435,6 +474,28 @@ struct Peer : public Consensus<Peer, Traits>
else
net.timer(when, std::forward<T>(what));
}
Ledger::ID
prevLedgerID()
{
return consensus.prevLedgerID();
}
std::size_t
prevProposers()
{
return prevProposers_;
}
std::chrono::milliseconds
prevRoundTime()
{
return prevRoundTime_;
}
// Not interested in tracking consensus mode
void
onModeChange(ConsensusMode, ConsensusMode) {}
};
} // csf