From dc578a8085b4537b1728f4dc4a15a89f6e30f1b6 Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Tue, 25 Dec 2012 18:08:13 -0800 Subject: [PATCH] Push clean up code for bad ripple nodes. --- src/cpp/ripple/LedgerEntrySet.cpp | 45 ++++++++++++++++++++++----- src/cpp/ripple/LedgerEntrySet.h | 3 +- src/cpp/ripple/TrustSetTransactor.cpp | 6 ++-- 3 files changed, 43 insertions(+), 11 deletions(-) diff --git a/src/cpp/ripple/LedgerEntrySet.cpp b/src/cpp/ripple/LedgerEntrySet.cpp index 50183f3e06..9508bf6ba6 100644 --- a/src/cpp/ripple/LedgerEntrySet.cpp +++ b/src/cpp/ripple/LedgerEntrySet.cpp @@ -621,7 +621,8 @@ TER LedgerEntrySet::dirDelete( const uint64& uNodeDir, // --> Node containing entry. const uint256& uRootIndex, // --> The index of the base of the directory. Nodes are based off of this. const uint256& uLedgerIndex, // --> Value to remove from directory. - const bool bStable) // --> True, not to change relative order of entries. + const bool bStable, // --> True, not to change relative order of entries. + const bool bSoft) // --> True, uNodeDir is not hard and fast (pass uNodeDir=0). { uint64 uNodeCur = uNodeDir; SLE::pointer sleNode = entryCache(ltDIR_NODE, uNodeCur ? Ledger::getDirNodeIndex(uRootIndex, uNodeCur) : uRootIndex); @@ -634,8 +635,21 @@ TER LedgerEntrySet::dirDelete( % strHex(uNodeDir) % uLedgerIndex.ToString()); - assert(false); - return tefBAD_LEDGER; + if (!bSoft) + { + assert(false); + return tefBAD_LEDGER; + } + else if (uNodeDir < 20) + { + // Go the extra mile. Even if node doesn't exist, try the next node. + + return dirDelete(bKeepRoot, uNodeDir+1, uRootIndex, uLedgerIndex, bStable, true); + } + else + { + return tefBAD_LEDGER; + } } STVector256 svIndexes = sleNode->getFieldV256(sfIndexes); @@ -647,11 +661,24 @@ TER LedgerEntrySet::dirDelete( assert(vuiIndexes.end() != it); if (vuiIndexes.end() == it) { - assert(false); + if (!bSoft) + { + assert(false); - cLog(lsWARNING) << "dirDelete: no such entry"; + cLog(lsWARNING) << "dirDelete: no such entry"; - return tefBAD_LEDGER; + return tefBAD_LEDGER; + } + else if (uNodeDir < 20) + { + // Go the extra mile. Even if entry not in node, try the next node. + + return dirDelete(bKeepRoot, uNodeDir+1, uRootIndex, uLedgerIndex, bStable, true); + } + else + { + return tefBAD_LEDGER; + } } // Remove the element. @@ -866,8 +893,9 @@ void LedgerEntrySet::ownerCountAdjust(const uint160& uOwnerID, int iAmount, SLE: TER LedgerEntrySet::offerDelete(const SLE::pointer& sleOffer, const uint256& uOfferIndex, const uint160& uOwnerID) { + bool bOwnerNode = sleOffer->isFieldPresent(sfOwnerNode); // Detect legacy dirs. uint64 uOwnerNode = sleOffer->getFieldU64(sfOwnerNode); - TER terResult = dirDelete(false, uOwnerNode, Ledger::getOwnerDirIndex(uOwnerID), uOfferIndex, false); + TER terResult = dirDelete(false, uOwnerNode, Ledger::getOwnerDirIndex(uOwnerID), uOfferIndex, false, !bOwnerNode); if (tesSUCCESS == terResult) { @@ -876,7 +904,8 @@ TER LedgerEntrySet::offerDelete(const SLE::pointer& sleOffer, const uint256& uOf uint256 uDirectory = sleOffer->getFieldH256(sfBookDirectory); uint64 uBookNode = sleOffer->getFieldU64(sfBookNode); - terResult = dirDelete(false, uBookNode, uDirectory, uOfferIndex, true); + // Offer delete is always hard. Always have hints. + terResult = dirDelete(false, uBookNode, uDirectory, uOfferIndex, true, true); } entryDelete(sleOffer); diff --git a/src/cpp/ripple/LedgerEntrySet.h b/src/cpp/ripple/LedgerEntrySet.h index 15747a493b..159ef43747 100644 --- a/src/cpp/ripple/LedgerEntrySet.h +++ b/src/cpp/ripple/LedgerEntrySet.h @@ -97,7 +97,8 @@ public: const uint64& uNodeDir, // Node item is mentioned in. const uint256& uRootIndex, const uint256& uLedgerIndex, // Item being deleted - const bool bStable); + const bool bStable, + const bool bSoft); bool dirFirst(const uint256& uRootIndex, SLE::pointer& sleNode, unsigned int& uDirEntry, uint256& uEntryIndex); bool dirNext(const uint256& uRootIndex, SLE::pointer& sleNode, unsigned int& uDirEntry, uint256& uEntryIndex); diff --git a/src/cpp/ripple/TrustSetTransactor.cpp b/src/cpp/ripple/TrustSetTransactor.cpp index abb6cfbc05..8262eb0630 100644 --- a/src/cpp/ripple/TrustSetTransactor.cpp +++ b/src/cpp/ripple/TrustSetTransactor.cpp @@ -221,16 +221,18 @@ TER TrustSetTransactor::doApply() { // Can delete. + bool bLowNode = sleRippleState->isFieldPresent(sfLowNode); // Detect legacy dirs. + bool bHighNode = sleRippleState->isFieldPresent(sfHighNode); uint64 uLowNode = sleRippleState->getFieldU64(sfLowNode); uint64 uHighNode = sleRippleState->getFieldU64(sfHighNode); cLog(lsTRACE) << "doTrustSet: Deleting ripple line: low"; - terResult = mEngine->getNodes().dirDelete(false, uLowNode, Ledger::getOwnerDirIndex(uLowAccountID), sleRippleState->getIndex(), false); + terResult = mEngine->getNodes().dirDelete(false, uLowNode, Ledger::getOwnerDirIndex(uLowAccountID), sleRippleState->getIndex(), false, !bLowNode); if (tesSUCCESS == terResult) { cLog(lsTRACE) << "doTrustSet: Deleting ripple line: high"; - terResult = mEngine->getNodes().dirDelete(false, uHighNode, Ledger::getOwnerDirIndex(uHighAccountID), sleRippleState->getIndex(), false); + terResult = mEngine->getNodes().dirDelete(false, uHighNode, Ledger::getOwnerDirIndex(uHighAccountID), sleRippleState->getIndex(), false, !bHighNode); } cLog(lsINFO) << "doTrustSet: Deleting ripple line: state";