Remove transaction set acquire logic from consensus object

This creates a new InboundTransactions object that handles transaction sets,
removing this responsibility from the consensus object. The main benefit is
that many inbound transaction operations no longer require the master lock.

Improve logic to decide which peers to query, when to add more peers, and
when to re-query existing peers.
This commit is contained in:
David Schwartz
2015-03-09 11:39:52 -07:00
committed by Tom Ritchford
parent 00596f1436
commit 1fedede771
15 changed files with 575 additions and 321 deletions

View File

@@ -31,6 +31,7 @@
#include <ripple/app/misc/NetworkOPs.h>
#include <ripple/app/misc/Validations.h>
#include <ripple/app/tx/TransactionAcquire.h>
#include <ripple/app/tx/InboundTransactions.h>
#include <ripple/basics/CountedObject.h>
#include <ripple/basics/Log.h>
#include <ripple/core/Config.h>
@@ -78,7 +79,6 @@ public:
/**
The result of applying a transaction to a ledger.
@param clock The clock which will be used to measure time.
@param localtx A set of local transactions to apply.
@param prevLCLHash The hash of the Last Closed Ledger (LCL).
@param previousLedger Best guess of what the Last Closed Ledger (LCL)
@@ -86,11 +86,10 @@ public:
@param closeTime Closing time point of the LCL.
@param feeVote Our desired fee levels and voting logic.
*/
LedgerConsensusImp (clock_type& clock, LocalTxs& localtx,
LedgerConsensusImp (LocalTxs& localtx,
LedgerHash const & prevLCLHash, Ledger::ref previousLedger,
std::uint32_t closeTime, FeeVote& feeVote)
: m_clock (clock)
, m_localTX (localtx)
: m_localTX (localtx)
, m_feeVote (feeVote)
, mState (lcsPRE_CLOSE)
, mCloseTime (closeTime)
@@ -112,6 +111,8 @@ public:
mPreviousMSeconds = getApp().getOPs ().getPreviousConvergeTime ();
assert (mPreviousMSeconds);
getApp().getInboundTransactions().newRound (mPreviousLedger->getLedgerSeq());
// Adapt close time resolution to recent network conditions
mCloseResolution = ContinuousLedgerTiming::getNextLedgerTimeResolution (
mPreviousLedger->getCloseResolution (),
@@ -256,16 +257,6 @@ public:
ret["acquired"] = acq;
}
if (!mAcquiring.empty ())
{
Json::Value acq (Json::arrayValue);
for (auto& at : mAcquiring)
{
acq.append (to_string (at.first));
}
ret["acquiring"] = acq;
}
if (!mDisputes.empty ())
{
Json::Value dsj (Json::objectValue);
@@ -310,64 +301,6 @@ public:
return mPrevLedgerHash;
}
/**
Get a transaction tree, fetching it from the network if required and
requested. When the transaction acquire engine successfully acquires
a transaction set, it will call back.
@param hash hash of the requested transaction tree.
@param doAcquire true if we should get this from the network if we don't
already have it.
@return Pointer to the transaction tree if we got it, else
nullptr.
*/
std::shared_ptr<SHAMap>
getTransactionTree (uint256 const& hash, bool doAcquire)
{
auto it = mAcquired.find (hash);
if (it != mAcquired.end ())
return it->second;
if (mState == lcsPRE_CLOSE)
{
std::shared_ptr<SHAMap> currentMap
= getApp().getLedgerMaster ().getCurrentLedger ()
->peekTransactionMap ();
if (currentMap->getHash () == hash)
{
WriteLog (lsDEBUG, LedgerConsensus)
<< "Map " << hash << " is our current";
currentMap = currentMap->snapShot (false);
mapCompleteInternal (hash, currentMap, false);
return currentMap;
}
}
if (doAcquire)
{
TransactionAcquire::pointer& acquiring = mAcquiring[hash];
if (!acquiring)
{
if (hash.isZero ())
{
auto empty = std::make_shared<SHAMap> (
SHAMapType::TRANSACTION, getApp().family(),
deprecatedLogs().journal("SHAMap"));
mapCompleteInternal (hash, empty, false);
return empty;
}
acquiring = std::make_shared<TransactionAcquire> (hash, m_clock);
startAcquiring (acquiring);
}
}
return std::shared_ptr<SHAMap> ();
}
/**
We have a complete transaction set, typically acquired from the network
@@ -401,7 +334,6 @@ public:
{
// this is an invalid/corrupt map
mAcquired[hash] = map;
mAcquiring.erase (hash);
WriteLog (lsWARNING, LedgerConsensus)
<< "A trusted node directed us to acquire an invalid TXN map";
return;
@@ -416,7 +348,6 @@ public:
{
if (it->second)
{
mAcquiring.erase (hash);
return; // we already have this map
}
@@ -426,6 +357,15 @@ public:
// We now have a map that we did not have before
if (!acquired)
{
// Put the map where others can get it
getApp().getInboundTransactions().giveSet (hash, map, false);
}
// Inform directly-connected peers that we have this transaction set
sendHaveTxSet (hash, true);
if (mOurPosition && (!mOurPosition->isBowOut ())
&& (hash != mOurPosition->getCurrentHash ()))
{
@@ -448,7 +388,6 @@ public:
<< "Not ready to create disputes";
mAcquired[hash] = map;
mAcquiring.erase (hash);
// Adjust tracking for each peer that takes this position
std::vector<NodeID> peers;
@@ -469,30 +408,6 @@ public:
<< hash << " no peers were proposing it";
}
// Inform directly-connected peers that we have this transaction set
sendHaveTxSet (hash, true);
}
/**
Determine if we still need to acquire a transaction set from the network.
If a transaction set is popular, we probably have it. If it's unpopular,
we probably don't need it (and the peer that initially made us
retrieve it has probably already changed its position).
@param hash hash of the transaction set.
@return true if we need to acquire it, else false.
*/
bool stillNeedTXSet (uint256 const& hash)
{
if (mAcquired.find (hash) != mAcquired.end ())
return false;
for (auto const& it : mPeerPositions)
{
if (it.second->getCurrentHash () == hash)
return true;
}
return false;
}
/**
@@ -852,6 +767,20 @@ public:
, mPreviousMSeconds, mCurrentMSeconds, forReal, mConsensusFail);
}
std::shared_ptr<SHAMap> getTransactionTree (uint256 const& hash)
{
auto it = mAcquired.find (hash);
if (it != mAcquired.end() && it->second)
return it->second;
auto set = getApp().getInboundTransactions().getSet (hash, true);
if (set)
mAcquired[hash] = set;
return set;
}
/**
A server has taken a new position, adjust our tracking
Called when a peer takes a new postion.
@@ -910,7 +839,7 @@ public:
currentPosition = newPosition;
std::shared_ptr<SHAMap> set
= getTransactionTree (newPosition->getCurrentHash (), true);
= getTransactionTree (newPosition->getCurrentHash ());
if (set)
{
@@ -926,32 +855,6 @@ public:
return true;
}
/**
A peer has sent us some nodes from a transaction set
@param peer The peer which has sent the nodes
@param setHash The transaction set
@param nodeIDs The nodes in the transaction set
@param nodeData The data
@return The status results of adding the nodes.
*/
SHAMapAddNode peerGaveNodes (Peer::ptr const& peer
, uint256 const& setHash, const std::list<SHAMapNodeID>& nodeIDs
, const std::list< Blob >& nodeData)
{
auto acq (mAcquiring.find (setHash));
if (acq == mAcquiring.end ())
{
WriteLog (lsDEBUG, LedgerConsensus)
<< "Got TX data for set no longer acquiring: " << setHash;
return SHAMapAddNode ();
}
// We must keep the set around during the function
TransactionAcquire::pointer set = acq->second;
return set->takeNodes (nodeIDs, nodeData, peer);
}
bool isOurPubKey (const RippleAddress & k)
{
return k == mValPublic;
@@ -1197,36 +1100,6 @@ private:
}
}
/**
Begin acquiring a transaction set
@param acquire The transaction set to acquire.
*/
void startAcquiring (TransactionAcquire::pointer acquire)
{
// FIXME: Randomize and limit the number
struct build_acquire_list
{
typedef void return_type;
TransactionAcquire::pointer const& acquire;
build_acquire_list (TransactionAcquire::pointer const& acq)
: acquire(acq)
{ }
return_type operator() (Peer::ptr const& peer) const
{
if (peer->hasTxSet (acquire->getHash ()))
acquire->peerHas (peer);
}
};
getApp().overlay ().foreach (build_acquire_list (acquire));
acquire->setTimer ();
}
/**
Compare two proposed transaction sets and create disputed
transctions structures for any mismatches
@@ -1883,7 +1756,6 @@ private:
val->setFieldU32(sfLoadFee, fee);
}
private:
clock_type& m_clock;
LocalTxs& m_localTX;
FeeVote& m_feeVote;
@@ -1918,7 +1790,6 @@ private:
// Transaction Sets, indexed by hash of transaction tree
hash_map<uint256, std::shared_ptr<SHAMap>> mAcquired;
hash_map<uint256, TransactionAcquire::pointer> mAcquiring;
// Disputed transactions
hash_map<uint256, DisputedTx::pointer> mDisputes;
@@ -1938,11 +1809,11 @@ LedgerConsensus::~LedgerConsensus ()
}
std::shared_ptr <LedgerConsensus>
make_LedgerConsensus (LedgerConsensus::clock_type& clock, LocalTxs& localtx,
make_LedgerConsensus (LocalTxs& localtx,
LedgerHash const &prevLCLHash, Ledger::ref previousLedger,
std::uint32_t closeTime, FeeVote& feeVote)
{
return std::make_shared <LedgerConsensusImp> (clock, localtx,
return std::make_shared <LedgerConsensusImp> (localtx,
prevLCLHash, previousLedger, closeTime, feeVote);
}