mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-20 19:15:54 +00:00
"Advance" thread to publish ledgers and fetch history.
This commit is contained in:
@@ -616,11 +616,6 @@ void Ledger::saveValidatedLedger (bool current)
|
|||||||
boost::mutex::scoped_lock sl (sPendingSaveLock);
|
boost::mutex::scoped_lock sl (sPendingSaveLock);
|
||||||
sPendingSaves.erase(getLedgerSeq());
|
sPendingSaves.erase(getLedgerSeq());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getApp().getJobQueue ().getJobCountTotal (jtPUBOLDLEDGER) < 2)
|
|
||||||
getApp().getLedgerMaster ().resumeAcquiring ();
|
|
||||||
else
|
|
||||||
WriteLog (lsTRACE, Ledger) << "no resume, too many pending ledger saves";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NO_SQLITE3_PREPARE
|
#ifndef NO_SQLITE3_PREPARE
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ bool LedgerMaster::isCaughtUp(std::string& reason)
|
|||||||
{
|
{
|
||||||
if (getPublishedLedgerAge() > 180)
|
if (getPublishedLedgerAge() > 180)
|
||||||
{
|
{
|
||||||
reason = "No recently-validated ledger";
|
reason = "No recently-published ledger";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
boost::recursive_mutex::scoped_lock ml (mLock);
|
boost::recursive_mutex::scoped_lock ml (mLock);
|
||||||
@@ -91,6 +91,9 @@ void LedgerMaster::pushLedger (Ledger::pointer newLedger)
|
|||||||
// all candidate transactions must already be applied
|
// all candidate transactions must already be applied
|
||||||
WriteLog (lsINFO, LedgerMaster) << "PushLedger: " << newLedger->getHash ();
|
WriteLog (lsINFO, LedgerMaster) << "PushLedger: " << newLedger->getHash ();
|
||||||
|
|
||||||
|
if (getConfig().RUN_STANDALONE)
|
||||||
|
setFullLedger(newLedger, true, false);
|
||||||
|
|
||||||
boost::recursive_mutex::scoped_lock ml (mLock);
|
boost::recursive_mutex::scoped_lock ml (mLock);
|
||||||
|
|
||||||
if (mClosedLedger)
|
if (mClosedLedger)
|
||||||
@@ -109,14 +112,18 @@ void LedgerMaster::pushLedger (Ledger::pointer newLCL, Ledger::pointer newOL)
|
|||||||
assert (newLCL->isClosed () && newLCL->isAccepted ());
|
assert (newLCL->isClosed () && newLCL->isAccepted ());
|
||||||
assert (!newOL->isClosed () && !newOL->isAccepted ());
|
assert (!newOL->isClosed () && !newOL->isAccepted ());
|
||||||
|
|
||||||
|
if (getConfig().RUN_STANDALONE)
|
||||||
|
setFullLedger(newLCL, true, false);
|
||||||
|
|
||||||
boost::recursive_mutex::scoped_lock ml (mLock);
|
boost::recursive_mutex::scoped_lock ml (mLock);
|
||||||
|
|
||||||
if (newLCL->isAccepted ())
|
if (newLCL->isAccepted ())
|
||||||
{
|
{
|
||||||
assert (newLCL->isClosed ());
|
assert (newLCL->isClosed ());
|
||||||
assert (newLCL->isImmutable ());
|
assert (newLCL->isImmutable ());
|
||||||
mLedgerHistory.addAcceptedLedger (newLCL);
|
|
||||||
WriteLog (lsINFO, LedgerMaster) << "StashAccepted: " << newLCL->getHash ();
|
WriteLog (lsINFO, LedgerMaster) << "StashAccepted: " << newLCL->getHash ();
|
||||||
|
if (getConfig().RUN_STANDALONE)
|
||||||
|
newLCL->setValidated();
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -149,18 +156,19 @@ void LedgerMaster::switchLedgers (Ledger::pointer lastClosed, Ledger::pointer cu
|
|||||||
void LedgerMaster::storeLedger (Ledger::pointer ledger)
|
void LedgerMaster::storeLedger (Ledger::pointer ledger)
|
||||||
{
|
{
|
||||||
mLedgerHistory.addLedger (ledger);
|
mLedgerHistory.addLedger (ledger);
|
||||||
|
|
||||||
if (ledger->isAccepted ())
|
|
||||||
mLedgerHistory.addAcceptedLedger (ledger);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LedgerMaster::forceValid (Ledger::pointer ledger)
|
void LedgerMaster::forceValid (Ledger::pointer ledger)
|
||||||
{
|
{
|
||||||
ledger->setValidated();
|
ledger->setValidated();
|
||||||
|
|
||||||
|
boost::recursive_mutex::scoped_lock sl (mLock);
|
||||||
|
|
||||||
if (!mValidLedger || (mPubLedger->getLedgerSeq() < ledger->getLedgerSeq()))
|
if (!mValidLedger || (mPubLedger->getLedgerSeq() < ledger->getLedgerSeq()))
|
||||||
mValidLedger = ledger;
|
mValidLedger = ledger;
|
||||||
if (!mPubLedger || (mPubLedger->getLedgerSeq() < 2))
|
if (!mPubLedger || (mPubLedger->getLedgerSeq() < 2))
|
||||||
mPubLedger = ledger;
|
mPubLedger = ledger;
|
||||||
|
setFullLedger(ledger, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ledger::pointer LedgerMaster::closeLedger (bool recover)
|
Ledger::pointer LedgerMaster::closeLedger (bool recover)
|
||||||
@@ -238,7 +246,7 @@ bool LedgerMaster::getValidatedRange (uint32& minVal, uint32& maxVal)
|
|||||||
{
|
{
|
||||||
boost::recursive_mutex::scoped_lock sl (mLock);
|
boost::recursive_mutex::scoped_lock sl (mLock);
|
||||||
|
|
||||||
if (!mValidLedger)
|
if (!mPubLedger)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
maxVal = mPubLedger->getLedgerSeq ();
|
maxVal = mPubLedger->getLedgerSeq ();
|
||||||
@@ -287,7 +295,7 @@ bool LedgerMaster::getValidatedRange (uint32& minVal, uint32& maxVal)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LedgerMaster::asyncAccept (Ledger::pointer ledger)
|
void LedgerMaster::tryFill (Ledger::pointer ledger)
|
||||||
{
|
{
|
||||||
uint32 seq = ledger->getLedgerSeq ();
|
uint32 seq = ledger->getLedgerSeq ();
|
||||||
uint256 prevHash = ledger->getParentHash ();
|
uint256 prevHash = ledger->getParentHash ();
|
||||||
@@ -337,147 +345,40 @@ void LedgerMaster::asyncAccept (Ledger::pointer ledger)
|
|||||||
boost::recursive_mutex::scoped_lock ml (mLock);
|
boost::recursive_mutex::scoped_lock ml (mLock);
|
||||||
mCompleteLedgers.setRange (minHas, maxHas);
|
mCompleteLedgers.setRange (minHas, maxHas);
|
||||||
}
|
}
|
||||||
|
|
||||||
resumeAcquiring ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LedgerMaster::acquireMissingLedger (Ledger::ref origLedger, uint256 const& ledgerHash, uint32 ledgerSeq)
|
void LedgerMaster::getFetchPack (Ledger::ref nextLedger)
|
||||||
{
|
{
|
||||||
#if 0
|
uint32 fetchSeq = nextLedger->getLedgerSeq () - 1;
|
||||||
// return: false = already gave up recently
|
|
||||||
Ledger::pointer ledger = mLedgerHistory.getLedgerBySeq (ledgerSeq);
|
|
||||||
|
|
||||||
if (ledger && (Ledger::getHashByIndex (ledgerSeq) == ledgerHash))
|
protocol::TMGetObjectByHash tmBH;
|
||||||
|
tmBH.set_type (protocol::TMGetObjectByHash::otFETCH_PACK);
|
||||||
|
tmBH.set_query (true);
|
||||||
|
tmBH.set_seq (fetchSeq);
|
||||||
|
tmBH.set_ledgerhash (nextLedger->getParentHash().begin (), 32);
|
||||||
|
std::vector<Peer::pointer> peerList = getApp().getPeers ().getPeerVector ();
|
||||||
|
|
||||||
|
Peer::pointer target;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
BOOST_FOREACH (const Peer::pointer & peer, peerList)
|
||||||
{
|
{
|
||||||
WriteLog (lsTRACE, LedgerMaster) << "Ledger hash found in database";
|
if (peer->hasRange (fetchSeq, fetchSeq + 1))
|
||||||
getApp().getJobQueue ().addJob (jtPUBOLDLEDGER, "LedgerMaster::asyncAccept",
|
|
||||||
BIND_TYPE (&LedgerMaster::asyncAccept, this, ledger));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getApp().getInboundLedgers ().isFailure (ledgerHash))
|
|
||||||
{
|
|
||||||
WriteLog (lsTRACE, LedgerMaster) << "Already failed to acquire " << ledgerSeq;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
mMissingLedger = getApp().getInboundLedgers ().findCreate (ledgerHash, ledgerSeq);
|
|
||||||
|
|
||||||
if (mMissingLedger->isComplete ())
|
|
||||||
{
|
|
||||||
Ledger::pointer lgr = mMissingLedger->getLedger ();
|
|
||||||
|
|
||||||
if (lgr && (lgr->getLedgerSeq () == ledgerSeq))
|
|
||||||
missingAcquireComplete (mMissingLedger);
|
|
||||||
|
|
||||||
mMissingLedger.reset ();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (mMissingLedger->isDone ())
|
|
||||||
{
|
|
||||||
mMissingLedger.reset ();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
mMissingSeq = ledgerSeq;
|
|
||||||
|
|
||||||
int fetchMax = getConfig ().getSize (siLedgerFetch);
|
|
||||||
int timeoutCount;
|
|
||||||
int fetchCount = getApp().getInboundLedgers ().getFetchCount (timeoutCount);
|
|
||||||
|
|
||||||
if ((fetchCount < fetchMax) && getApp().getOPs ().isFull ())
|
|
||||||
{
|
|
||||||
if (timeoutCount > 2)
|
|
||||||
{
|
{
|
||||||
WriteLog (lsDEBUG, LedgerMaster) << "Not acquiring due to timeouts";
|
if (count++ == 0)
|
||||||
}
|
target = peer;
|
||||||
else
|
else if ((rand () % count) == 0)
|
||||||
{
|
target = peer;
|
||||||
typedef std::pair<uint32, uint256> u_pair;
|
|
||||||
std::vector<u_pair> vec = origLedger->getLedgerHashes ();
|
|
||||||
BOOST_REVERSE_FOREACH (const u_pair & it, vec)
|
|
||||||
{
|
|
||||||
if ((fetchCount < fetchMax) && (it.first < ledgerSeq) &&
|
|
||||||
!mCompleteLedgers.hasValue (it.first) && !getApp().getInboundLedgers ().find (it.second))
|
|
||||||
{
|
|
||||||
InboundLedger::pointer acq = getApp().getInboundLedgers ().findCreate (it.second, it.first);
|
|
||||||
|
|
||||||
if (acq && acq->isComplete ())
|
|
||||||
{
|
|
||||||
acq->getLedger ()->setAccepted ();
|
|
||||||
setFullLedger (acq->getLedger ());
|
|
||||||
mLedgerHistory.addAcceptedLedger (acq->getLedger (), false);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
++fetchCount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getApp().getOPs ().shouldFetchPack (ledgerSeq) && (ledgerSeq > 40000))
|
if (target)
|
||||||
{
|
{
|
||||||
// refill our fetch pack
|
PackedMessage::pointer packet = boost::make_shared<PackedMessage> (tmBH, protocol::mtGET_OBJECTS);
|
||||||
Ledger::pointer nextLedger = mLedgerHistory.getLedgerBySeq (ledgerSeq + 1);
|
target->sendPacket (packet, false);
|
||||||
|
|
||||||
if (nextLedger)
|
|
||||||
{
|
|
||||||
protocol::TMGetObjectByHash tmBH;
|
|
||||||
tmBH.set_type (protocol::TMGetObjectByHash::otFETCH_PACK);
|
|
||||||
tmBH.set_query (true);
|
|
||||||
tmBH.set_seq (ledgerSeq);
|
|
||||||
tmBH.set_ledgerhash (ledgerHash.begin (), 32);
|
|
||||||
std::vector<Peer::pointer> peerList = getApp().getPeers ().getPeerVector ();
|
|
||||||
|
|
||||||
Peer::pointer target;
|
|
||||||
int count = 0;
|
|
||||||
|
|
||||||
BOOST_FOREACH (const Peer::pointer & peer, peerList)
|
|
||||||
{
|
|
||||||
if (peer->hasRange (ledgerSeq, ledgerSeq + 1))
|
|
||||||
{
|
|
||||||
if (count++ == 0)
|
|
||||||
target = peer;
|
|
||||||
else if ((rand () % ++count) == 0)
|
|
||||||
target = peer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (target)
|
|
||||||
{
|
|
||||||
PackedMessage::pointer packet = boost::make_shared<PackedMessage> (tmBH, protocol::mtGET_OBJECTS);
|
|
||||||
target->sendPacket (packet, false);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
WriteLog (lsTRACE, LedgerMaster) << "No peer for fetch pack";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
return true;
|
WriteLog (lsTRACE, LedgerMaster) << "No peer for fetch pack";
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void LedgerMaster::missingAcquireComplete (InboundLedger::pointer acq)
|
|
||||||
{
|
|
||||||
#if 0
|
|
||||||
boost::recursive_mutex::scoped_lock ml (mLock);
|
|
||||||
|
|
||||||
if (acq->isFailed () && (mMissingSeq != 0))
|
|
||||||
{
|
|
||||||
WriteLog (lsWARNING, LedgerMaster) << "Acquire failed for " << mMissingSeq;
|
|
||||||
}
|
|
||||||
|
|
||||||
mMissingLedger.reset ();
|
|
||||||
mMissingSeq = 0;
|
|
||||||
|
|
||||||
if (acq->isComplete ())
|
|
||||||
{
|
|
||||||
acq->getLedger ()->setAccepted ();
|
|
||||||
setFullLedger (acq->getLedger ());
|
|
||||||
mLedgerHistory.addAcceptedLedger (acq->getLedger (), false);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LedgerMaster::shouldAcquire (uint32 currentLedger, uint32 ledgerHistory, uint32 candidateLedger)
|
bool LedgerMaster::shouldAcquire (uint32 currentLedger, uint32 ledgerHistory, uint32 candidateLedger)
|
||||||
@@ -486,62 +387,17 @@ bool LedgerMaster::shouldAcquire (uint32 currentLedger, uint32 ledgerHistory, ui
|
|||||||
|
|
||||||
if (candidateLedger >= currentLedger)
|
if (candidateLedger >= currentLedger)
|
||||||
ret = true;
|
ret = true;
|
||||||
else ret = (currentLedger - candidateLedger) <= ledgerHistory;
|
else
|
||||||
|
ret = (currentLedger - candidateLedger) <= ledgerHistory;
|
||||||
|
|
||||||
WriteLog (lsTRACE, LedgerMaster) << "Missing ledger " << candidateLedger << (ret ? " should" : " should NOT") << " be acquired";
|
WriteLog (lsTRACE, LedgerMaster) << "Missing ledger " << candidateLedger << (ret ? " should" : " should NOT") << " be acquired";
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LedgerMaster::resumeAcquiring ()
|
|
||||||
{
|
|
||||||
// VFALCO NOTE These returns from the middle are troubling. You might think
|
|
||||||
// that calling a function called "resumeAcquiring" would
|
|
||||||
// actually resume acquiring. But it doesn't always resume acquiring,
|
|
||||||
// based on a myriad of conditions which short circuit the function
|
|
||||||
// in ways that the caller cannot expect or predict.
|
|
||||||
//
|
|
||||||
if (!getApp().getOPs ().isFull ())
|
|
||||||
return;
|
|
||||||
|
|
||||||
boost::recursive_mutex::scoped_lock ml (mLock);
|
|
||||||
|
|
||||||
if (mMissingLedger && mMissingLedger->isDone ())
|
|
||||||
mMissingLedger.reset ();
|
|
||||||
|
|
||||||
if (mMissingLedger || !getConfig ().LEDGER_HISTORY)
|
|
||||||
{
|
|
||||||
CondLog (mMissingLedger, lsDEBUG, LedgerMaster) << "Fetch already in progress, not resuming";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32 prevMissing = mCompleteLedgers.prevMissing (mClosedLedger->getLedgerSeq ());
|
|
||||||
|
|
||||||
if (prevMissing == RangeSet::absent)
|
|
||||||
{
|
|
||||||
WriteLog (lsDEBUG, LedgerMaster) << "no prior missing ledger, not resuming";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shouldAcquire (mCurrentLedger->getLedgerSeq (), getConfig ().LEDGER_HISTORY, prevMissing))
|
|
||||||
{
|
|
||||||
WriteLog (lsTRACE, LedgerMaster) << "Resuming at " << prevMissing;
|
|
||||||
assert (!mCompleteLedgers.hasValue (prevMissing));
|
|
||||||
Ledger::pointer nextLedger = getLedgerBySeq (prevMissing + 1);
|
|
||||||
|
|
||||||
if (nextLedger)
|
|
||||||
acquireMissingLedger (nextLedger, nextLedger->getParentHash (), nextLedger->getLedgerSeq () - 1);
|
|
||||||
else
|
|
||||||
WriteLog (lsINFO, LedgerMaster) << "We have a gap at: " << prevMissing + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void LedgerMaster::fixMismatch (Ledger::ref ledger)
|
void LedgerMaster::fixMismatch (Ledger::ref ledger)
|
||||||
{
|
{
|
||||||
int invalidate = 0;
|
int invalidate = 0;
|
||||||
|
|
||||||
mMissingLedger.reset ();
|
|
||||||
mMissingSeq = 0;
|
|
||||||
|
|
||||||
for (uint32 lSeq = ledger->getLedgerSeq () - 1; lSeq > 0; --lSeq)
|
for (uint32 lSeq = ledger->getLedgerSeq () - 1; lSeq > 0; --lSeq)
|
||||||
if (mCompleteLedgers.hasValue (lSeq))
|
if (mCompleteLedgers.hasValue (lSeq))
|
||||||
{
|
{
|
||||||
@@ -579,8 +435,7 @@ void LedgerMaster::setFullLedger (Ledger::pointer ledger, bool isSynchronous, bo
|
|||||||
|
|
||||||
mCompleteLedgers.setValue (ledger->getLedgerSeq ());
|
mCompleteLedgers.setValue (ledger->getLedgerSeq ());
|
||||||
|
|
||||||
if (Ledger::getHashByIndex (ledger->getLedgerSeq ()) != ledger->getHash ())
|
ledger->pendSaveValidated (isSynchronous, isCurrent);
|
||||||
ledger->pendSaveValidated (isSynchronous, isCurrent);
|
|
||||||
|
|
||||||
if ((ledger->getLedgerSeq () != 0) && mCompleteLedgers.hasValue (ledger->getLedgerSeq () - 1))
|
if ((ledger->getLedgerSeq () != 0) && mCompleteLedgers.hasValue (ledger->getLedgerSeq () - 1))
|
||||||
{
|
{
|
||||||
@@ -594,66 +449,6 @@ void LedgerMaster::setFullLedger (Ledger::pointer ledger, bool isSynchronous, bo
|
|||||||
fixMismatch (ledger);
|
fixMismatch (ledger);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mMissingLedger && mMissingLedger->isDone ())
|
|
||||||
{
|
|
||||||
if (mMissingLedger->isFailed ())
|
|
||||||
getApp().getInboundLedgers ().dropLedger (mMissingLedger->getHash ());
|
|
||||||
|
|
||||||
mMissingLedger.reset ();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mMissingLedger || !getConfig ().LEDGER_HISTORY)
|
|
||||||
{
|
|
||||||
CondLog (mMissingLedger, lsDEBUG, LedgerMaster) << "Fetch already in progress, " << mMissingLedger->getTimeouts () << " timeouts";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getApp().getJobQueue ().getJobCountTotal (jtPUBOLDLEDGER) > 1)
|
|
||||||
{
|
|
||||||
WriteLog (lsDEBUG, LedgerMaster) << "Too many pending ledger saves";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// see if there's a ledger gap we need to fill
|
|
||||||
if (!mCompleteLedgers.hasValue (ledger->getLedgerSeq () - 1))
|
|
||||||
{
|
|
||||||
if (!shouldAcquire (mCurrentLedger->getLedgerSeq (), getConfig ().LEDGER_HISTORY, ledger->getLedgerSeq () - 1))
|
|
||||||
{
|
|
||||||
WriteLog (lsTRACE, LedgerMaster) << "Don't need any ledgers";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
WriteLog (lsDEBUG, LedgerMaster) << "We need the ledger before the ledger we just accepted: " << ledger->getLedgerSeq () - 1;
|
|
||||||
acquireMissingLedger (ledger, ledger->getParentHash (), ledger->getLedgerSeq () - 1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
uint32 prevMissing = mCompleteLedgers.prevMissing (ledger->getLedgerSeq ());
|
|
||||||
|
|
||||||
if (prevMissing == RangeSet::absent)
|
|
||||||
{
|
|
||||||
WriteLog (lsDEBUG, LedgerMaster) << "no prior missing ledger";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shouldAcquire (mCurrentLedger->getLedgerSeq (), getConfig ().LEDGER_HISTORY, prevMissing))
|
|
||||||
{
|
|
||||||
WriteLog (lsDEBUG, LedgerMaster) << "Ledger " << prevMissing << " is needed";
|
|
||||||
assert (!mCompleteLedgers.hasValue (prevMissing));
|
|
||||||
Ledger::pointer nextLedger = getLedgerBySeq (prevMissing + 1);
|
|
||||||
|
|
||||||
if (nextLedger)
|
|
||||||
acquireMissingLedger (ledger, nextLedger->getParentHash (), nextLedger->getLedgerSeq () - 1);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mCompleteLedgers.clearValue (prevMissing);
|
|
||||||
WriteLog (lsWARNING, LedgerMaster) << "We have a gap we can't fix: " << prevMissing + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
WriteLog (lsTRACE, LedgerMaster) << "Shouldn't acquire";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LedgerMaster::checkAccept (uint256 const& hash)
|
void LedgerMaster::checkAccept (uint256 const& hash)
|
||||||
@@ -705,6 +500,12 @@ void LedgerMaster::checkAccept (uint256 const& hash, uint32 seq)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ledger->getLedgerSeq() != seq)
|
||||||
|
{
|
||||||
|
WriteLog (lsWARNING, LedgerMaster) << "Acquired ledger " << hash.GetHex() << "didn't have expected seq " << seq;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ledger->setValidated();
|
ledger->setValidated();
|
||||||
mValidLedger = ledger;
|
mValidLedger = ledger;
|
||||||
|
|
||||||
@@ -718,25 +519,89 @@ void LedgerMaster::checkAccept (uint256 const& hash, uint32 seq)
|
|||||||
else
|
else
|
||||||
getApp().getFeeTrack().setRemoteFee(((fee * count) + (fee2 * count2)) / (count + count2));
|
getApp().getFeeTrack().setRemoteFee(((fee * count) + (fee2 * count2)) / (count + count2));
|
||||||
|
|
||||||
tryPublish ();
|
tryAdvance ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LedgerMaster::tryPublish ()
|
// Try to publish ledgers, acquire missing ledgers
|
||||||
|
void LedgerMaster::advanceThread()
|
||||||
{
|
{
|
||||||
boost::recursive_mutex::scoped_lock ml (mLock);
|
boost::recursive_mutex::scoped_lock sl (mLock);
|
||||||
assert (mValidLedger);
|
assert (mValidLedger);
|
||||||
|
|
||||||
if (!mPubLedger)
|
bool progress;
|
||||||
|
|
||||||
|
do
|
||||||
{
|
{
|
||||||
mPubLedger = mValidLedger;
|
progress = false;
|
||||||
mPubLedgers.push_back (mValidLedger);
|
|
||||||
}
|
std::list<Ledger::pointer> pubLedgers = findNewLedgersToPublish();
|
||||||
|
if (pubLedgers.empty())
|
||||||
|
{
|
||||||
|
if (!getConfig().RUN_STANDALONE && (mValidLedger->getLedgerSeq() == mPubLedger->getLedgerSeq()))
|
||||||
|
{ // We are in sync, so can acquire
|
||||||
|
uint32 missing = mCompleteLedgers.prevMissing(mPubLedger->getLedgerSeq());
|
||||||
|
|
||||||
|
if (shouldAcquire(mValidLedger->getLedgerSeq(), getConfig().LEDGER_HISTORY, missing))
|
||||||
|
{
|
||||||
|
Ledger::pointer nextLedger = mLedgerHistory.getLedgerBySeq(missing + 1);
|
||||||
|
if (nextLedger)
|
||||||
|
{
|
||||||
|
Ledger::pointer ledger = getLedgerByHash(nextLedger->getParentHash());
|
||||||
|
if (!ledger)
|
||||||
|
{
|
||||||
|
if (getApp().getOPs().shouldFetchPack(missing) && (missing > 40000))
|
||||||
|
getFetchPack(nextLedger);
|
||||||
|
if (!getApp().getInboundLedgers().isFailure(nextLedger->getParentHash()))
|
||||||
|
{
|
||||||
|
InboundLedger::pointer acq =
|
||||||
|
getApp().getInboundLedgers().findCreate(nextLedger->getParentHash(),
|
||||||
|
nextLedger->getLedgerSeq() - 1);
|
||||||
|
if (acq && acq->isComplete())
|
||||||
|
ledger = acq->getLedger();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ledger)
|
||||||
|
{
|
||||||
|
sl.unlock();
|
||||||
|
setFullLedger(ledger, false, false);
|
||||||
|
tryFill(ledger);
|
||||||
|
sl.lock();
|
||||||
|
progress = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BOOST_FOREACH(Ledger::ref ledger, pubLedgers)
|
||||||
|
{
|
||||||
|
sl.unlock();
|
||||||
|
|
||||||
|
setFullLedger(ledger, true, true);
|
||||||
|
getApp().getOPs().pubLedger(ledger);
|
||||||
|
|
||||||
|
sl.lock();
|
||||||
|
mPubLedger = ledger;
|
||||||
|
progress = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (progress);
|
||||||
|
|
||||||
|
mAdvanceThread = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::list<Ledger::pointer> LedgerMaster::findNewLedgersToPublish()
|
||||||
|
{ // Call with a lock
|
||||||
|
std::list<Ledger::pointer> ret;
|
||||||
|
|
||||||
|
if (!mPubLedger)
|
||||||
|
ret.push_back (mValidLedger);
|
||||||
else if (mValidLedger->getLedgerSeq () > (mPubLedger->getLedgerSeq () + MAX_LEDGER_GAP))
|
else if (mValidLedger->getLedgerSeq () > (mPubLedger->getLedgerSeq () + MAX_LEDGER_GAP))
|
||||||
{
|
{
|
||||||
WriteLog (lsWARNING, LedgerMaster) << "Gap in validated ledger stream " << mPubLedger->getLedgerSeq () << " - " <<
|
WriteLog (lsWARNING, LedgerMaster) << "Gap in validated ledger stream " << mPubLedger->getLedgerSeq () << " - " <<
|
||||||
mValidLedger->getLedgerSeq () - 1;
|
mValidLedger->getLedgerSeq () - 1;
|
||||||
mPubLedger = mValidLedger;
|
ret.push_back (mValidLedger);
|
||||||
mPubLedgers.push_back (mValidLedger);
|
|
||||||
}
|
}
|
||||||
else if (mValidLedger->getLedgerSeq () > mPubLedger->getLedgerSeq ())
|
else if (mValidLedger->getLedgerSeq () > mPubLedger->getLedgerSeq ())
|
||||||
{
|
{
|
||||||
@@ -793,23 +658,16 @@ void LedgerMaster::tryPublish ()
|
|||||||
if (ledger && (ledger->getLedgerSeq() == (mPubLedger->getLedgerSeq() + 1)))
|
if (ledger && (ledger->getLedgerSeq() == (mPubLedger->getLedgerSeq() + 1)))
|
||||||
{ // We acquired the next ledger we need to publish
|
{ // We acquired the next ledger we need to publish
|
||||||
ledger->setValidated();
|
ledger->setValidated();
|
||||||
mPubLedger = ledger;
|
ret.push_back (mPubLedger);
|
||||||
mPubLedgers.push_back (mPubLedger);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mPubLedgers.empty ())
|
if (!ret.empty ())
|
||||||
{
|
{
|
||||||
getApp().getOPs ().clearNeedNetworkLedger ();
|
getApp().getOPs ().clearNeedNetworkLedger ();
|
||||||
|
|
||||||
if (!mPubThread)
|
|
||||||
{
|
|
||||||
mPubThread = true;
|
|
||||||
getApp().getJobQueue ().addJob (jtPUBLEDGER, "Ledger::pubThread",
|
|
||||||
BIND_TYPE (&LedgerMaster::pubThread, this));
|
|
||||||
}
|
|
||||||
mPathFindNewLedger = true;
|
mPathFindNewLedger = true;
|
||||||
|
|
||||||
if (!mPathFindThread)
|
if (!mPathFindThread)
|
||||||
@@ -819,6 +677,20 @@ void LedgerMaster::tryPublish ()
|
|||||||
BIND_TYPE (&LedgerMaster::updatePaths, this));
|
BIND_TYPE (&LedgerMaster::updatePaths, this));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LedgerMaster::tryAdvance()
|
||||||
|
{
|
||||||
|
boost::recursive_mutex::scoped_lock ml (mLock);
|
||||||
|
|
||||||
|
if (!mAdvanceThread)
|
||||||
|
{
|
||||||
|
mAdvanceThread = true;
|
||||||
|
getApp().getJobQueue ().addJob (jtPUBLEDGER, "Ledger::advanceThread",
|
||||||
|
BIND_TYPE (&LedgerMaster::advanceThread, this));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint256 LedgerMaster::getLedgerHash(uint32 desiredSeq, Ledger::ref knownGoodLedger)
|
uint256 LedgerMaster::getLedgerHash(uint32 desiredSeq, Ledger::ref knownGoodLedger)
|
||||||
@@ -851,44 +723,6 @@ uint256 LedgerMaster::getLedgerHash(uint32 desiredSeq, Ledger::ref knownGoodLedg
|
|||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LedgerMaster::pubThread ()
|
|
||||||
{
|
|
||||||
std::list<Ledger::pointer> ledgers;
|
|
||||||
bool published = false;
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
ledgers.clear ();
|
|
||||||
|
|
||||||
{
|
|
||||||
boost::recursive_mutex::scoped_lock ml (mLock);
|
|
||||||
mPubLedgers.swap (ledgers);
|
|
||||||
|
|
||||||
if (ledgers.empty ())
|
|
||||||
{
|
|
||||||
mPubThread = false;
|
|
||||||
|
|
||||||
if (published && !mPathFindThread)
|
|
||||||
{
|
|
||||||
mPathFindThread = true;
|
|
||||||
getApp().getJobQueue ().addJob (jtUPDATE_PF, "updatePaths",
|
|
||||||
BIND_TYPE (&LedgerMaster::updatePaths, this));
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_FOREACH (Ledger::ref l, ledgers)
|
|
||||||
{
|
|
||||||
WriteLog (lsDEBUG, LedgerMaster) << "Publishing ledger " << l->getLedgerSeq ();
|
|
||||||
setFullLedger (l, true, true);
|
|
||||||
getApp().getOPs ().pubLedger (l);
|
|
||||||
published = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void LedgerMaster::updatePaths ()
|
void LedgerMaster::updatePaths ()
|
||||||
{
|
{
|
||||||
Ledger::pointer lastLedger;
|
Ledger::pointer lastLedger;
|
||||||
|
|||||||
@@ -22,10 +22,9 @@ public:
|
|||||||
public:
|
public:
|
||||||
LedgerMaster ()
|
LedgerMaster ()
|
||||||
: mHeldTransactions (uint256 ())
|
: mHeldTransactions (uint256 ())
|
||||||
, mMissingSeq (0)
|
|
||||||
, mMinValidations (0)
|
, mMinValidations (0)
|
||||||
, mLastValidateSeq (0)
|
, mLastValidateSeq (0)
|
||||||
, mPubThread (false)
|
, mAdvanceThread (false)
|
||||||
, mPathFindThread (false)
|
, mPathFindThread (false)
|
||||||
, mPathFindNewLedger (false)
|
, mPathFindNewLedger (false)
|
||||||
, mPathFindNewRequest (false)
|
, mPathFindNewRequest (false)
|
||||||
@@ -159,8 +158,6 @@ public:
|
|||||||
bool haveLedger (uint32 seq);
|
bool haveLedger (uint32 seq);
|
||||||
bool getValidatedRange (uint32& minVal, uint32& maxVal);
|
bool getValidatedRange (uint32& minVal, uint32& maxVal);
|
||||||
|
|
||||||
void resumeAcquiring ();
|
|
||||||
|
|
||||||
void tune (int size, int age)
|
void tune (int size, int age)
|
||||||
{
|
{
|
||||||
mLedgerHistory.tune (size, age);
|
mLedgerHistory.tune (size, age);
|
||||||
@@ -181,7 +178,8 @@ public:
|
|||||||
|
|
||||||
void checkAccept (uint256 const& hash);
|
void checkAccept (uint256 const& hash);
|
||||||
void checkAccept (uint256 const& hash, uint32 seq);
|
void checkAccept (uint256 const& hash, uint32 seq);
|
||||||
void tryPublish ();
|
std::list<Ledger::pointer> findNewLedgersToPublish();
|
||||||
|
void tryAdvance ();
|
||||||
void newPathRequest ();
|
void newPathRequest ();
|
||||||
|
|
||||||
static bool shouldAcquire (uint32 currentLedgerID, uint32 ledgerHistory, uint32 targetLedger);
|
static bool shouldAcquire (uint32 currentLedgerID, uint32 ledgerHistory, uint32 targetLedger);
|
||||||
@@ -191,10 +189,9 @@ private:
|
|||||||
bool isValidTransaction (Transaction::ref trans);
|
bool isValidTransaction (Transaction::ref trans);
|
||||||
bool isTransactionOnFutureList (Transaction::ref trans);
|
bool isTransactionOnFutureList (Transaction::ref trans);
|
||||||
|
|
||||||
void acquireMissingLedger (Ledger::ref from, uint256 const& ledgerHash, uint32 ledgerSeq);
|
void getFetchPack (Ledger::ref have);
|
||||||
void asyncAccept (Ledger::pointer);
|
void tryFill (Ledger::pointer);
|
||||||
void missingAcquireComplete (InboundLedger::pointer);
|
void advanceThread ();
|
||||||
void pubThread ();
|
|
||||||
void updatePaths ();
|
void updatePaths ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -213,8 +210,6 @@ private:
|
|||||||
CanonicalTXSet mHeldTransactions;
|
CanonicalTXSet mHeldTransactions;
|
||||||
|
|
||||||
RangeSet mCompleteLedgers;
|
RangeSet mCompleteLedgers;
|
||||||
InboundLedger::pointer mMissingLedger;
|
|
||||||
uint32 mMissingSeq;
|
|
||||||
|
|
||||||
int mMinValidations; // The minimum validations to publish a ledger
|
int mMinValidations; // The minimum validations to publish a ledger
|
||||||
uint256 mLastValidateHash;
|
uint256 mLastValidateHash;
|
||||||
@@ -222,7 +217,7 @@ private:
|
|||||||
std::list<callback> mOnValidate; // Called when a ledger has enough validations
|
std::list<callback> mOnValidate; // Called when a ledger has enough validations
|
||||||
|
|
||||||
std::list<Ledger::pointer> mPubLedgers; // List of ledgers to publish
|
std::list<Ledger::pointer> mPubLedgers; // List of ledgers to publish
|
||||||
bool mPubThread; // Publish thread is running
|
bool mAdvanceThread; // Publish thread is running
|
||||||
|
|
||||||
bool mPathFindThread; // Pathfind thread is running
|
bool mPathFindThread; // Pathfind thread is running
|
||||||
bool mPathFindNewLedger;
|
bool mPathFindNewLedger;
|
||||||
|
|||||||
@@ -235,9 +235,6 @@ static void LADispatch (
|
|||||||
InboundLedger::pointer la,
|
InboundLedger::pointer la,
|
||||||
std::vector< FUNCTION_TYPE<void (InboundLedger::pointer)> > trig)
|
std::vector< FUNCTION_TYPE<void (InboundLedger::pointer)> > trig)
|
||||||
{
|
{
|
||||||
Ledger::ref ledger = la->getLedger();
|
|
||||||
if (ledger)
|
|
||||||
getApp().getLedgerMaster().checkAccept (ledger->getHash(), ledger->getLedgerSeq());
|
|
||||||
for (unsigned int i = 0; i < trig.size (); ++i)
|
for (unsigned int i = 0; i < trig.size (); ++i)
|
||||||
trig[i] (la);
|
trig[i] (la);
|
||||||
}
|
}
|
||||||
@@ -272,8 +269,10 @@ void InboundLedger::done ()
|
|||||||
getApp().getInboundLedgers ().logFailure (mHash);
|
getApp().getInboundLedgers ().logFailure (mHash);
|
||||||
|
|
||||||
// We hold the PeerSet lock, so must dispatch
|
// We hold the PeerSet lock, so must dispatch
|
||||||
getApp().getJobQueue ().addJob (jtLEDGER_DATA, "triggers",
|
if (!triggers.empty())
|
||||||
BIND_TYPE (LADispatch, P_1, shared_from_this (), triggers));
|
getApp().getJobQueue ().addJob (jtLEDGER_DATA, "triggers",
|
||||||
|
BIND_TYPE (LADispatch, P_1, shared_from_this (), triggers));
|
||||||
|
getApp().getLedgerMaster().tryAdvance();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InboundLedger::addOnComplete (FUNCTION_TYPE<void (InboundLedger::pointer)> trigger)
|
bool InboundLedger::addOnComplete (FUNCTION_TYPE<void (InboundLedger::pointer)> trigger)
|
||||||
|
|||||||
@@ -261,6 +261,8 @@ void InboundLedgers::gotFetchPack (Job&)
|
|||||||
{
|
{
|
||||||
acquire->checkLocal ();
|
acquire->checkLocal ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getApp().getLedgerMaster().tryAdvance();
|
||||||
}
|
}
|
||||||
|
|
||||||
void InboundLedgers::clearFailures ()
|
void InboundLedgers::clearFailures ()
|
||||||
|
|||||||
@@ -23,20 +23,19 @@ LedgerHistory::LedgerHistory () : mLedgersByHash ("LedgerCache", CACHED_LEDGER_N
|
|||||||
|
|
||||||
void LedgerHistory::addLedger (Ledger::pointer ledger)
|
void LedgerHistory::addLedger (Ledger::pointer ledger)
|
||||||
{
|
{
|
||||||
assert (ledger->isImmutable ());
|
assert (ledger && ledger->isImmutable ());
|
||||||
mLedgersByHash.canonicalize (ledger->getHash (), ledger, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LedgerHistory::addAcceptedLedger (Ledger::pointer ledger)
|
|
||||||
{
|
|
||||||
assert (ledger && ledger->isAccepted () && ledger->isImmutable ());
|
|
||||||
assert (ledger->peekAccountStateMap ()->getHash ().isNonZero ());
|
assert (ledger->peekAccountStateMap ()->getHash ().isNonZero ());
|
||||||
|
|
||||||
|
bool v = ledger->isValidated();
|
||||||
|
|
||||||
uint256 h (ledger->getHash ());
|
uint256 h (ledger->getHash ());
|
||||||
boost::recursive_mutex::scoped_lock sl (mLedgersByHash.peekMutex ());
|
boost::recursive_mutex::scoped_lock sl (mLedgersByHash.peekMutex ());
|
||||||
mLedgersByHash.canonicalize (h, ledger, true);
|
mLedgersByHash.canonicalize (h, ledger, true);
|
||||||
assert (ledger);
|
if (v || ledger->isValidated())
|
||||||
assert (ledger->isAccepted ());
|
{
|
||||||
assert (ledger->isImmutable ());
|
ledger->setValidated();
|
||||||
|
mLedgersByIndex[ledger->getLedgerSeq()] = h;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint256 LedgerHistory::getLedgerHash (uint32 index)
|
uint256 LedgerHistory::getLedgerHash (uint32 index)
|
||||||
@@ -123,7 +122,7 @@ Ledger::pointer LedgerHistory::canonicalizeLedger (Ledger::pointer ledger, bool
|
|||||||
boost::recursive_mutex::scoped_lock sl (mLedgersByHash.peekMutex ());
|
boost::recursive_mutex::scoped_lock sl (mLedgersByHash.peekMutex ());
|
||||||
mLedgersByHash.canonicalize (h, ledger);
|
mLedgersByHash.canonicalize (h, ledger);
|
||||||
|
|
||||||
if (ledger->isAccepted ())
|
if (ledger->isValidated ())
|
||||||
mLedgersByIndex[ledger->getLedgerSeq ()] = ledger->getHash ();
|
mLedgersByIndex[ledger->getLedgerSeq ()] = ledger->getHash ();
|
||||||
|
|
||||||
return ledger;
|
return ledger;
|
||||||
|
|||||||
@@ -15,8 +15,6 @@ public:
|
|||||||
|
|
||||||
void addLedger (Ledger::pointer ledger);
|
void addLedger (Ledger::pointer ledger);
|
||||||
|
|
||||||
void addAcceptedLedger (Ledger::pointer ledger);
|
|
||||||
|
|
||||||
float getCacheHitRate ()
|
float getCacheHitRate ()
|
||||||
{
|
{
|
||||||
return mLedgersByHash.getHitRate ();
|
return mLedgersByHash.getHitRate ();
|
||||||
@@ -42,7 +40,7 @@ private:
|
|||||||
TaggedCache <LedgerHash, Ledger, UptimeTimerAdapter> mLedgersByHash;
|
TaggedCache <LedgerHash, Ledger, UptimeTimerAdapter> mLedgersByHash;
|
||||||
|
|
||||||
// Maps ledger indexes to the corresponding hash.
|
// Maps ledger indexes to the corresponding hash.
|
||||||
std::map <LedgerIndex, LedgerHash> mLedgersByIndex; // accepted ledgers
|
std::map <LedgerIndex, LedgerHash> mLedgersByIndex; // validated ledgers
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user