Change 'shouldClose' to return a bool.

Clear structures on LCL view change during consensus window.
Cleaner calculation of 'rounded' close times.
Maintain close time offset.
This commit is contained in:
JoelKatz
2012-09-03 05:16:32 -07:00
parent 8eb33f6bb5
commit 4f598af582
4 changed files with 36 additions and 26 deletions

View File

@@ -302,6 +302,9 @@ void LedgerConsensus::handleLCL(const uint256& lclHash)
mHaveCorrectLCL = false;
mProposing = false;
mValidating = false;
mCloseTimes.clear();
mPeerPositions.clear();
mDisputes.clear();
return;
}
@@ -318,6 +321,7 @@ void LedgerConsensus::takeInitialPosition(Ledger& initialLedger)
{
SHAMap::pointer initialSet = initialLedger.peekTransactionMap()->snapShot(false);
uint256 txSet = initialSet->getHash();
Log(lsINFO) << "initial position " << txSet;
// if any peers have taken a contrary position, process disputes
boost::unordered_set<uint256> found;
@@ -454,25 +458,24 @@ void LedgerConsensus::statePreClose()
// This ledger is open. This computes how long since the last ledger closed
int sinceClose;
int ledgerInterval = 0;
int idleInterval = 0;
if (mHaveCorrectLCL && mPreviousLedger->getCloseAgree())
{ // we can use consensus timing
sinceClose = 1000 * (theApp->getOPs().getCloseTimeNC() - mPreviousLedger->getCloseTimeNC());
ledgerInterval = 2 * mPreviousLedger->getCloseResolution();
if (ledgerInterval < LEDGER_IDLE_INTERVAL)
ledgerInterval = LEDGER_IDLE_INTERVAL;
idleInterval = 2 * mPreviousLedger->getCloseResolution();
if (idleInterval < LEDGER_IDLE_INTERVAL)
idleInterval = LEDGER_IDLE_INTERVAL;
}
else
{
sinceClose = theApp->getOPs().getLastCloseTime();
ledgerInterval = LEDGER_IDLE_INTERVAL;
idleInterval = LEDGER_IDLE_INTERVAL;
}
if (sinceClose >= ContinuousLedgerTiming::shouldClose(anyTransactions, mPreviousProposers, proposersClosed,
mPreviousMSeconds, sinceClose, ledgerInterval))
if (ContinuousLedgerTiming::shouldClose(anyTransactions, mPreviousProposers, proposersClosed,
mPreviousMSeconds, sinceClose, idleInterval))
{ // it is time to close the ledger
Log(lsINFO) << "CLC: closing ledger";
mState = lcsESTABLISH;
mConsensusStartTime = boost::posix_time::microsec_clock::universal_time();
mCloseTime = theApp->getOPs().getCloseTimeNC();
@@ -496,7 +499,7 @@ void LedgerConsensus::stateEstablish()
}
if (haveConsensus())
{
Log(lsINFO) << "Converge cutoff";
Log(lsINFO) << "Converge cutoff (" << mPeerPositions.size() << " participants)";
mState = lcsFINISHED;
beginAccept();
}
@@ -524,7 +527,7 @@ void LedgerConsensus::timerEntry()
switch (mState)
{
case lcsPRE_CLOSE: statePreClose(); if (mState != lcsESTABLISH) return; fallthru();
case lcsPRE_CLOSE: statePreClose(); return;
case lcsESTABLISH: stateEstablish(); if (mState != lcsFINISHED) return; fallthru();
case lcsFINISHED: stateFinished(); if (mState != lcsACCEPTED) return; fallthru();
case lcsACCEPTED: stateAccepted(); return;
@@ -558,7 +561,7 @@ void LedgerConsensus::updateOurPositions()
}
else
{ // proposal is still fresh
++closeTimes[it->second->getCloseTime() - (it->second->getCloseTime() % mCloseResolution)];
++closeTimes[roundCloseTime(it->second->getCloseTime())];
++it;
}
}
@@ -600,13 +603,13 @@ void LedgerConsensus::updateOurPositions()
if (thresh == 0)
{ // no other times
mHaveCloseTimeConsensus = true;
closeTime = mOurPosition->getCloseTime() - (mOurPosition->getCloseTime() % mCloseResolution);
closeTime = roundCloseTime(mOurPosition->getCloseTime());
}
else
{
if (mProposing)
{
++closeTimes[mOurPosition->getCloseTime() - (mOurPosition->getCloseTime() % mCloseResolution)];
++closeTimes[roundCloseTime(mOurPosition->getCloseTime())];
++thresh;
}
thresh = thresh * neededWeight / 100;
@@ -627,7 +630,7 @@ void LedgerConsensus::updateOurPositions()
}
if ((!changes) &&
((closeTime != (mOurPosition->getCloseTime() - (mOurPosition->getCloseTime() % mCloseResolution))) ||
((closeTime != (roundCloseTime(mOurPosition->getCloseTime()))) ||
(mOurPosition->isStale(ourCutoff))))
{ // close time changed or our position is stale
ourPosition = mComplete[mOurPosition->getCurrentHash()]->snapShot(true);
@@ -957,11 +960,16 @@ void LedgerConsensus::applyTransactions(const SHAMap::pointer& set, Ledger::ref
} while (successes > 0);
}
uint32 LedgerConsensus::roundCloseTime(uint32 closeTime)
{
return closeTime - (closeTime % mCloseResolution);
}
void LedgerConsensus::accept(const SHAMap::pointer& set)
{
assert(set->getHash() == mOurPosition->getCurrentHash());
uint32 closeTime = mOurPosition->getCloseTime() - (mOurPosition->getCloseTime() & mCloseResolution);
uint32 closeTime = roundCloseTime(mOurPosition->getCloseTime());
Log(lsINFO) << "Computing new LCL based on network consensus";
if (mHaveCorrectLCL)
@@ -1035,14 +1043,13 @@ void LedgerConsensus::accept(const SHAMap::pointer& set)
mState = lcsACCEPTED;
sl.unlock();
if (mValidating && mOurPosition->getCurrentHash().isNonZero())
if (mValidating)
{ // see how close our close time is to other node's close time reports
Log(lsINFO) << "We closed at " << boost::lexical_cast<std::string>(mCloseTime);
uint64 closeTotal = mCloseTime;
int closeCount = 1;
for (std::map<uint32, int>::iterator it = mCloseTimes.begin(), end =
mCloseTimes.end(); it != end; ++it)
{
for (std::map<uint32, int>::iterator it = mCloseTimes.begin(), end = mCloseTimes.end(); it != end; ++it)
{ // FIXME: Use median, not average
Log(lsINFO) << boost::lexical_cast<std::string>(it->second) << " time votes for "
<< boost::lexical_cast<std::string>(it->first);
closeCount += it->second;
@@ -1052,6 +1059,7 @@ void LedgerConsensus::accept(const SHAMap::pointer& set)
closeTotal /= closeCount;
int offset = static_cast<int>(closeTotal) - static_cast<int>(mCloseTime);
Log(lsINFO) << "Our close offset is estimated at " << offset << " (" << closeCount << ")";
theApp->getOPs().closeTimeOffset(offset);
}
#ifdef DEBUG

View File

@@ -136,12 +136,15 @@ protected:
void applyTransaction(TransactionEngine& engine, const SerializedTransaction::pointer& txn,
Ledger::ref targetLedger, CanonicalTXSet& failedTransactions, bool openLgr);
uint32 roundCloseTime(uint32 closeTime);
// manipulating our own position
void statusChange(newcoin::NodeEvent, Ledger& ledger);
void takeInitialPosition(Ledger& initialLedger);
void updateOurPositions();
void playbackProposals();
int getThreshold();
void beginAccept();
void endConsensus();

View File

@@ -12,7 +12,7 @@ int ContinuousLedgerTiming::LedgerTimeResolution[] = { 10, 10, 20, 30, 60, 90, 1
// Called when a ledger is open and no close is in progress -- when a transaction is received and no close
// is in process, or when a close completes. Returns the number of seconds the ledger should be be open.
int ContinuousLedgerTiming::shouldClose(
bool ContinuousLedgerTiming::shouldClose(
bool anyTransactions,
int previousProposers, // proposers in the last closing
int proposersClosed, // proposers who have currently closed this ledgers
@@ -27,7 +27,7 @@ int ContinuousLedgerTiming::shouldClose(
boost::str(boost::format("CLC::shouldClose range Trans=%s, Prop: %d/%d, Secs: %d (last:%d)")
% (anyTransactions ? "yes" : "no") % previousProposers % proposersClosed
% currentMSeconds % previousMSeconds);
return currentMSeconds;
return true;;
}
if (!anyTransactions)
@@ -36,7 +36,7 @@ int ContinuousLedgerTiming::shouldClose(
{
Log(lsTRACE) << "no transactions, many proposers: now (" << proposersClosed << "closed, "
<< previousProposers << " before)";
return currentMSeconds;
return true;
}
#if 0 // This false triggers on the genesis ledger
if (previousMSeconds > (1000 * (LEDGER_IDLE_INTERVAL + 2))) // the last ledger was very slow to close
@@ -47,11 +47,10 @@ int ContinuousLedgerTiming::shouldClose(
return previousMSeconds - 1000;
}
#endif
return idleInterval * 1000; // normal idle
return currentMSeconds >= (idleInterval * 1000); // normal idle
}
Log(lsTRACE) << "close now";
return currentMSeconds; // this ledger should close now
return true; // this ledger should close now
}
// Returns whether we have a consensus or not. If so, we expect all honest nodes

View File

@@ -52,7 +52,7 @@ public:
// Returns the number of seconds the ledger was or should be open
// Call when a consensus is reached and when any transaction is relayed to be added
static int shouldClose(
static bool shouldClose(
bool anyTransactions,
int previousProposers, int proposersClosed,
int previousSeconds, int currentSeconds,