From c0cb389b2014867d05649052a905b97a05ffd1ce Mon Sep 17 00:00:00 2001 From: Mark Travis Date: Wed, 9 Feb 2022 10:53:57 -0800 Subject: [PATCH] Fallback to normal sync if fast loading is not possible: If fast loading is enabled but the last persisted ledger is not entirely on disk, the server would fail to start without manual intervention by the server operator. This commit allows the server to detect this scenario and attempt to automatically recover. --- src/ripple/app/ledger/Ledger.cpp | 2 +- src/ripple/shamap/SHAMap.h | 2 +- src/ripple/shamap/impl/SHAMapDelta.cpp | 73 ++++++++++++++++---------- 3 files changed, 48 insertions(+), 29 deletions(-) diff --git a/src/ripple/app/ledger/Ledger.cpp b/src/ripple/app/ledger/Ledger.cpp index cac9c40bb..66bea5682 100644 --- a/src/ripple/app/ledger/Ledger.cpp +++ b/src/ripple/app/ledger/Ledger.cpp @@ -774,7 +774,7 @@ Ledger::walkLedger(beast::Journal j, bool parallel) const else { if (parallel) - stateMap_->walkMapParallel(missingNodes1, 32); + return stateMap_->walkMapParallel(missingNodes1, 32); else stateMap_->walkMap(missingNodes1, 32); } diff --git a/src/ripple/shamap/SHAMap.h b/src/ripple/shamap/SHAMap.h index f5a108523..76e27bf1e 100644 --- a/src/ripple/shamap/SHAMap.h +++ b/src/ripple/shamap/SHAMap.h @@ -328,7 +328,7 @@ public: void walkMap(std::vector& missingNodes, int maxMissing) const; - void + bool walkMapParallel( std::vector& missingNodes, int maxMissing) const; diff --git a/src/ripple/shamap/impl/SHAMapDelta.cpp b/src/ripple/shamap/impl/SHAMapDelta.cpp index eb6da19e3..896678ef9 100644 --- a/src/ripple/shamap/impl/SHAMapDelta.cpp +++ b/src/ripple/shamap/impl/SHAMapDelta.cpp @@ -290,13 +290,13 @@ SHAMap::walkMap(std::vector& missingNodes, int maxMissing) } } -void +bool SHAMap::walkMapParallel( std::vector& missingNodes, int maxMissing) const { if (!root_->isInner()) // root_ is only node, and we have it - return; + return false; using StackEntry = std::shared_ptr; std::array, 16> topChildren; @@ -311,6 +311,8 @@ SHAMap::walkMapParallel( } std::vector workers; workers.reserve(16); + std::vector exceptions; + exceptions.reserve(16); std::array>, 16> nodeStacks; @@ -329,45 +331,62 @@ SHAMap::walkMapParallel( JLOG(journal_.debug()) << "starting worker " << rootChildIndex; workers.push_back(std::thread( - [&m, &missingNodes, &maxMissing, this]( + [&m, &missingNodes, &maxMissing, &exceptions, this]( std::stack> nodeStack) { - while (!nodeStack.empty()) + try { - std::shared_ptr node = - std::move(nodeStack.top()); - assert(node); - nodeStack.pop(); - - for (int i = 0; i < 16; ++i) + while (!nodeStack.empty()) { - if (node->isEmptyBranch(i)) - continue; - std::shared_ptr nextNode = - descendNoStore(node, i); + std::shared_ptr node = + std::move(nodeStack.top()); + assert(node); + nodeStack.pop(); - if (nextNode) + for (int i = 0; i < 16; ++i) { - if (nextNode->isInner()) - nodeStack.push( - std::static_pointer_cast( - nextNode)); - } - else - { - std::lock_guard l{m}; - missingNodes.emplace_back( - type_, node->getChildHash(i)); - if (--maxMissing <= 0) - return; + if (node->isEmptyBranch(i)) + continue; + std::shared_ptr nextNode = + descendNoStore(node, i); + + if (nextNode) + { + if (nextNode->isInner()) + nodeStack.push(std::static_pointer_cast< + SHAMapInnerNode>(nextNode)); + } + else + { + std::lock_guard l{m}; + missingNodes.emplace_back( + type_, node->getChildHash(i)); + if (--maxMissing <= 0) + return; + } } } } + catch (SHAMapMissingNode const& e) + { + std::lock_guard l(m); + exceptions.push_back(e); + } }, std::move(nodeStacks[rootChildIndex]))); } for (std::thread& worker : workers) worker.join(); + + std::lock_guard l(m); + if (exceptions.empty()) + return true; + std::stringstream ss; + ss << "Exception(s) in ledger load: "; + for (auto const& e : exceptions) + ss << e.what() << ", "; + JLOG(journal_.error()) << ss.str(); + return false; } } // namespace ripple