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