diff --git a/src/cpp/ripple/HashedObject.cpp b/src/cpp/ripple/HashedObject.cpp index d70cce347..d82e002f3 100644 --- a/src/cpp/ripple/HashedObject.cpp +++ b/src/cpp/ripple/HashedObject.cpp @@ -37,7 +37,7 @@ bool HashedObjectStore::store(HashedObjectType type, uint32 index, { // return: false = already in cache, true = added to cache if (!theApp->getHashNodeDB()) { - cLog(lsTRACE) << "HOS: no db"; + cLog(lsWARNING) << "HOS: no db"; return true; } if (mCache.touch(hash)) @@ -50,7 +50,7 @@ bool HashedObjectStore::store(HashedObjectType type, uint32 index, HashedObject::pointer object = boost::make_shared(type, index, data, hash); if (!mCache.canonicalize(hash, object)) { - Serializer s(1 + (32 / 8) + (32 / 8) + data.size()); + Serializer s(9 + data.size()); s.add8(static_cast(type)); s.add32(index); s.add32(index); @@ -63,6 +63,8 @@ bool HashedObjectStore::store(HashedObjectType type, uint32 index, assert(false); } } + else + cLog(lsDEBUG) << "HOS: store race"; return true; } @@ -77,12 +79,18 @@ HashedObject::pointer HashedObjectStore::retrieve(const uint256& hash) return obj; if (!theApp || !theApp->getHashNodeDB()) + { + cLog(lsWARNING) << "HOS: no db"; return obj; + } std::string sData; leveldb::Status st = theApp->getHashNodeDB()->Get(leveldb::ReadOptions(), hash.GetHex(), &sData); if (!st.ok()) + { + assert(st.IsNotFound()); return obj; + } Serializer s(sData); diff --git a/src/cpp/ripple/LedgerAcquire.cpp b/src/cpp/ripple/LedgerAcquire.cpp index d4ca0027a..fb4697fc5 100644 --- a/src/cpp/ripple/LedgerAcquire.cpp +++ b/src/cpp/ripple/LedgerAcquire.cpp @@ -960,7 +960,10 @@ void LedgerAcquireMaster::gotLedgerData(Job&, uint256 hash, cLog(lsWARNING) << "Included TXbase invalid"; } if (!san.isInvalid()) + { + ledger->progress(); ledger->trigger(peer); + } else cLog(lsDEBUG) << "Peer sends invalid base data"; return; @@ -996,7 +999,10 @@ void LedgerAcquireMaster::gotLedgerData(Job&, uint256 hash, else ledger->takeAsNode(nodeIDs, nodeData, ret); if (!ret.isInvalid()) - ledger->trigger(peer); + { + ledger->progress(); + ledger->trigger(peer); + } else cLog(lsDEBUG) << "Peer sends invalid node data"; return; diff --git a/src/cpp/ripple/LedgerConsensus.cpp b/src/cpp/ripple/LedgerConsensus.cpp index 305321818..c0f0c9b43 100644 --- a/src/cpp/ripple/LedgerConsensus.cpp +++ b/src/cpp/ripple/LedgerConsensus.cpp @@ -267,6 +267,7 @@ void LedgerConsensus::checkLCL() void LedgerConsensus::handleLCL(const uint256& lclHash) { + assert((lclHash != mPrevLedgerHash) || (mPreviousLedger->getHash() != lclHash)); if (mPrevLedgerHash != lclHash) { // first time switching to this ledger mPrevLedgerHash = lclHash; @@ -286,30 +287,35 @@ void LedgerConsensus::handleLCL(const uint256& lclHash) playbackProposals(); } - if (mPreviousLedger->getHash() != mPrevLedgerHash) - { // we need to switch the ledger we're working from - Ledger::pointer newLCL = theApp->getLedgerMaster().getLedgerByHash(lclHash); - if (newLCL) - { - mPreviousLedger = newLCL; - mPrevLedgerHash = newLCL->getHash(); - } - else if (!mAcquiringLedger || (mAcquiringLedger->getHash() != mPrevLedgerHash)) - { // need to start acquiring the correct consensus LCL - cLog(lsWARNING) << "Need consensus ledger " << mPrevLedgerHash; + if (mPreviousLedger->getHash() == mPrevLedgerHash) + return; - mAcquiringLedger = theApp->getMasterLedgerAcquire().findCreate(mPrevLedgerHash, 0); - mHaveCorrectLCL = false; - return; - } + // we need to switch the ledger we're working from + Ledger::pointer newLCL = theApp->getLedgerMaster().getLedgerByHash(lclHash); + if (newLCL) + { + assert(newLCL->isClosed()); + assert(newLCL->isImmutable()); + assert(newLCL->getHash() == lclHash); + mPreviousLedger = newLCL; + mPrevLedgerHash = lclHash; + } + else if (!mAcquiringLedger || (mAcquiringLedger->getHash() != mPrevLedgerHash)) + { // need to start acquiring the correct consensus LCL + cLog(lsWARNING) << "Need consensus ledger " << mPrevLedgerHash; + if (mAcquiringLedger) + theApp->getMasterLedgerAcquire().dropLedger(mAcquiringLedger->getHash()); + mAcquiringLedger = theApp->getMasterLedgerAcquire().findCreate(mPrevLedgerHash, 0); + mHaveCorrectLCL = false; + return; } cLog(lsINFO) << "Have the consensus ledger " << mPrevLedgerHash; mHaveCorrectLCL = true; -#if 0 // FIXME: can trigger early + if (mAcquiringLedger && mAcquiringLedger->isComplete()) theApp->getOPs().clearNeedNetworkLedger(); -#endif + mCloseResolution = ContinuousLedgerTiming::getNextLedgerTimeResolution( mPreviousLedger->getCloseResolution(), mPreviousLedger->getCloseAgree(), mPreviousLedger->getLedgerSeq() + 1); diff --git a/src/cpp/ripple/SHAMap.cpp b/src/cpp/ripple/SHAMap.cpp index 2eb19e1a7..d4d4648e7 100644 --- a/src/cpp/ripple/SHAMap.cpp +++ b/src/cpp/ripple/SHAMap.cpp @@ -236,6 +236,31 @@ SHAMapTreeNode* SHAMap::getNodePointer(const SHAMapNode& id, const uint256& hash return fetchNodeExternal(id, hash).get(); } +SHAMapTreeNode* SHAMap::getNodePointer(const SHAMapNode& id, const uint256& hash, SHAMapSyncFilter* filter) +{ + try + { + return getNodePointer(id, hash); + } + catch (SHAMapMissingNode) + { + if (filter) + { + std::vector nodeData; + if (filter->haveNode(id, hash, nodeData)) + { + SHAMapTreeNode::pointer node = boost::make_shared( + boost::cref(id), boost::cref(nodeData), mSeq - 1, snfPREFIX, boost::cref(hash), true); + mTNByID[id] = node; + filter->gotNode(true, id, hash, nodeData, node->getType()); + return node.get(); + } + } + throw; + } +} + + void SHAMap::returnNode(SHAMapTreeNode::pointer& node, bool modify) { // make sure the node is suitable for the intended operation (copy on write) assert(node->isValid()); diff --git a/src/cpp/ripple/SHAMap.h b/src/cpp/ripple/SHAMap.h index adf0a76cb..789c13f71 100644 --- a/src/cpp/ripple/SHAMap.h +++ b/src/cpp/ripple/SHAMap.h @@ -369,6 +369,7 @@ protected: SHAMapTreeNode::pointer getNode(const SHAMapNode& id); SHAMapTreeNode::pointer getNode(const SHAMapNode& id, const uint256& hash, bool modify); SHAMapTreeNode* getNodePointer(const SHAMapNode& id, const uint256& hash); + SHAMapTreeNode* getNodePointer(const SHAMapNode& id, const uint256& hash, SHAMapSyncFilter* filter); SHAMapTreeNode* firstBelow(SHAMapTreeNode*); SHAMapTreeNode* lastBelow(SHAMapTreeNode*); diff --git a/src/cpp/ripple/SHAMapSync.cpp b/src/cpp/ripple/SHAMapSync.cpp index feb655f27..daf97f138 100644 --- a/src/cpp/ripple/SHAMapSync.cpp +++ b/src/cpp/ripple/SHAMapSync.cpp @@ -58,38 +58,21 @@ void SHAMap::getMissingNodes(std::vector& nodeIDs, std::vectorisInner() && !d->isFullBelow()) + { + have_all = false; + stack.push(d); + } } catch (SHAMapMissingNode&) { // node is not in the map - if (filter != NULL) - { - std::vector nodeData; - if (filter->haveNode(childID, childHash, nodeData)) - { - assert(mSeq >= 1); - SHAMapTreeNode::pointer ptr = - boost::make_shared(childID, nodeData, mSeq - 1, - snfPREFIX, childHash, true); - mTNByID[*ptr] = ptr; - d = ptr.get(); - filter->gotNode(true, childID, childHash, nodeData, ptr->getType()); - } - } - } - if (!d) - { // we need this node nodeIDs.push_back(childID); hashes.push_back(childHash); if (--max <= 0) return; have_all = false; } - else if (d->isInner() && !d->isFullBelow()) // we might need children of this node - { - have_all = false; - stack.push(d); - } } } } @@ -142,32 +125,15 @@ std::vector SHAMap::getNeededHashes(int max, SHAMapSyncFilter* filter) SHAMapTreeNode* d = NULL; try { - d = getNodePointer(childID, childHash); - assert(d); - } - catch (SHAMapMissingNode&) - { // node is not in the map - std::vector nodeData; - if (filter && filter->haveNode(childID, childHash, nodeData)) - { - SHAMapTreeNode::pointer ptr = - boost::make_shared(childID, nodeData, mSeq -1, - snfPREFIX, childHash, true); - mTNByID[*ptr] = ptr; - d = ptr.get(); - filter->gotNode(true, childID, childHash, nodeData, ptr->getType()); - } - } - if (d) - { + d = getNodePointer(childID, childHash, filter); if (d->isInner() && !d->isFullBelow()) { have_all = false; stack.push(d); } } - else - { + catch (SHAMapMissingNode&) + { // node is not in the map have_all = false; ret.push_back(childHash); if (--max <= 0) @@ -340,11 +306,8 @@ SMAddNode SHAMap::addKnownNode(const SHAMapNode& node, const std::vectorisLeaf() && !iNode->isFullBelow()) + while (!iNode->isLeaf() && !iNode->isFullBelow() && (iNode->getDepth() < node.getDepth())) { - if (iNode->isLeaf() || iNode->isFullBelow() || (iNode->getDepth() >= node.getDepth())) - return SMAddNode::okay(); - int branch = iNode->selectBranch(node.getNodeID()); assert(branch >= 0); @@ -358,7 +321,7 @@ SMAddNode SHAMap::addKnownNode(const SHAMapNode& node, const std::vectorgetChildNodeID(branch), iNode->getChildHash(branch)); + iNode = getNodePointer(iNode->getChildNodeID(branch), iNode->getChildHash(branch), filter); } catch (SHAMapMissingNode) { @@ -374,6 +337,7 @@ SMAddNode SHAMap::addKnownNode(const SHAMapNode& node, const std::vector(node, rawNode, mSeq - 1, snfWIRE, uZero, false); if (iNode->getChildHash(branch) != newNode->getNodeHash()) { + cLog(lsWARNING) << "Corrupt node recevied"; return SMAddNode::invalid(); } @@ -384,41 +348,11 @@ SMAddNode SHAMap::addKnownNode(const SHAMapNode& node, const std::vectorgotNode(false, node, iNode->getChildHash(branch), s.peekData(), newNode->getType()); } mTNByID[node] = newNode; - - if (!newNode->isLeaf()) // only a leaf can fill an inner node - return SMAddNode::useful(); - - try - { - for (int i = 0; i < 16; ++i) - { // does the parent still need more nodes - if (!iNode->isEmptyBranch(i) && !fullBelowCache.isPresent(iNode->getChildHash(i))) - { - SHAMapTreeNode* d = getNodePointer(iNode->getChildNodeID(i), iNode->getChildHash(i)); - if (d->isInner() && !d->isFullBelow()) // unfilled inner node - return SMAddNode::useful(); - } - } - } - catch (SHAMapMissingNode) - { // still missing something - return SMAddNode::useful(); - } - - // received leaf fills its parent - iNode->setFullBelow(); - if (mType == smtSTATE) - { - fullBelowCache.add(iNode->getNodeHash()); - dropBelow(iNode); - } - if (root->isFullBelow()) - clearSynching(); return SMAddNode::useful(); } } - cLog(lsTRACE) << "got inner node, already had it (late)"; + cLog(lsTRACE) << "got node, already had it (late)"; return SMAddNode::okay(); }