diff --git a/src/cpp/ripple/LedgerConsensus.cpp b/src/cpp/ripple/LedgerConsensus.cpp index 23744cb1ec..3ed93cbf9b 100644 --- a/src/cpp/ripple/LedgerConsensus.cpp +++ b/src/cpp/ripple/LedgerConsensus.cpp @@ -347,6 +347,18 @@ void LedgerConsensus::takeInitialPosition(Ledger& initialLedger) propose(); } +bool LedgerConsensus::stillNeedTXSet(const uint256& hash) +{ + if (mAcquired.find(hash) != mAcquired.end()) + return false; + BOOST_FOREACH(u160_prop_pair& it, mPeerPositions) + { + if (it.second->getCurrentHash() == hash) + return true; + } + return false; +} + void LedgerConsensus::createDisputes(SHAMap::ref m1, SHAMap::ref m2) { SHAMap::SHAMapDiff differences; diff --git a/src/cpp/ripple/LedgerConsensus.h b/src/cpp/ripple/LedgerConsensus.h index e511ad4a01..d09af5c750 100644 --- a/src/cpp/ripple/LedgerConsensus.h +++ b/src/cpp/ripple/LedgerConsensus.h @@ -170,6 +170,7 @@ public: SHAMap::pointer getTransactionTree(const uint256& hash, bool doAcquire); TransactionAcquire::pointer getAcquiring(const uint256& hash); void mapComplete(const uint256& hash, SHAMap::ref map, bool acquired); + bool stillNeedTXSet(const uint256& hash); void checkLCL(); void handleLCL(const uint256& lclHash); diff --git a/src/cpp/ripple/NetworkOPs.cpp b/src/cpp/ripple/NetworkOPs.cpp index 7415a605b3..769b48c6f9 100644 --- a/src/cpp/ripple/NetworkOPs.cpp +++ b/src/cpp/ripple/NetworkOPs.cpp @@ -996,6 +996,13 @@ bool NetworkOPs::hasTXSet(const boost::shared_ptr& peer, const uint256& se return mConsensus->peerHasSet(peer, set, status); } +bool NetworkOPs::stillNeedTXSet(const uint256& hash) +{ + if (!mConsensus) + return false; + return mConsensus->stillNeedTXSet(hash); +} + void NetworkOPs::mapComplete(const uint256& hash, SHAMap::ref map) { if (haveConsensusObject()) diff --git a/src/cpp/ripple/NetworkOPs.h b/src/cpp/ripple/NetworkOPs.h index ee656a0612..b4aa58c21c 100644 --- a/src/cpp/ripple/NetworkOPs.h +++ b/src/cpp/ripple/NetworkOPs.h @@ -259,6 +259,7 @@ public: SHAMap::pointer getTXMap(const uint256& hash); bool hasTXSet(const boost::shared_ptr& peer, const uint256& set, ripple::TxSetStatus status); void mapComplete(const uint256& hash, SHAMap::ref map); + bool stillNeedTXSet(const uint256& hash); // network state machine void checkState(const boost::system::error_code& result); diff --git a/src/cpp/ripple/TransactionAcquire.cpp b/src/cpp/ripple/TransactionAcquire.cpp index 662acf47d7..f2e1ee548e 100644 --- a/src/cpp/ripple/TransactionAcquire.cpp +++ b/src/cpp/ripple/TransactionAcquire.cpp @@ -29,6 +29,7 @@ TransactionAcquire::TransactionAcquire(const uint256& hash) : PeerSet(hash, TX_A void TransactionAcquire::done() { + boost::recursive_mutex::scoped_lock sl(theApp->getMasterLock()); if (mFailed) { cLog(lsWARNING) << "Failed to acquire TX set " << mHash; @@ -45,14 +46,27 @@ void TransactionAcquire::done() void TransactionAcquire::onTimer(bool progress) { + bool aggressive = false; if (getTimeouts() > 10) { - cLog(lsWARNING) << "Giving up on TX set " << getHash(); - mFailed = true; - done(); - return; + cLog(lsWARNING) << "Ten timeouts on TX set " << getHash(); + { + boost::recursive_mutex::scoped_lock sl(theApp->getMasterLock()); + if (theApp->getOPs().stillNeedTXSet(mHash)) + { + cLog(lsWARNING) << "Still need it"; + mTimeouts = 0; + aggressive = true; + } + } + if (!aggressive) + { + mFailed = true; + done(); + return; + } } - if (!getPeerCount()) + if (aggressive || !getPeerCount()) { // out of peers cLog(lsWARNING) << "Out of peers for TX set " << getHash();