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.
This commit is contained in:
Mark Travis
2022-02-09 10:53:57 -08:00
committed by Nik Bougalis
parent 8f82b62e0d
commit c0cb389b20
3 changed files with 48 additions and 29 deletions

View File

@@ -774,7 +774,7 @@ Ledger::walkLedger(beast::Journal j, bool parallel) const
else else
{ {
if (parallel) if (parallel)
stateMap_->walkMapParallel(missingNodes1, 32); return stateMap_->walkMapParallel(missingNodes1, 32);
else else
stateMap_->walkMap(missingNodes1, 32); stateMap_->walkMap(missingNodes1, 32);
} }

View File

@@ -328,7 +328,7 @@ public:
void void
walkMap(std::vector<SHAMapMissingNode>& missingNodes, int maxMissing) const; walkMap(std::vector<SHAMapMissingNode>& missingNodes, int maxMissing) const;
void bool
walkMapParallel( walkMapParallel(
std::vector<SHAMapMissingNode>& missingNodes, std::vector<SHAMapMissingNode>& missingNodes,
int maxMissing) const; int maxMissing) const;

View File

@@ -290,13 +290,13 @@ SHAMap::walkMap(std::vector<SHAMapMissingNode>& missingNodes, int maxMissing)
} }
} }
void bool
SHAMap::walkMapParallel( SHAMap::walkMapParallel(
std::vector<SHAMapMissingNode>& missingNodes, std::vector<SHAMapMissingNode>& missingNodes,
int maxMissing) const int maxMissing) const
{ {
if (!root_->isInner()) // root_ is only node, and we have it if (!root_->isInner()) // root_ is only node, and we have it
return; return false;
using StackEntry = std::shared_ptr<SHAMapInnerNode>; using StackEntry = std::shared_ptr<SHAMapInnerNode>;
std::array<std::shared_ptr<SHAMapTreeNode>, 16> topChildren; std::array<std::shared_ptr<SHAMapTreeNode>, 16> topChildren;
@@ -311,6 +311,8 @@ SHAMap::walkMapParallel(
} }
std::vector<std::thread> workers; std::vector<std::thread> workers;
workers.reserve(16); workers.reserve(16);
std::vector<SHAMapMissingNode> exceptions;
exceptions.reserve(16);
std::array<std::stack<StackEntry, std::vector<StackEntry>>, 16> nodeStacks; std::array<std::stack<StackEntry, std::vector<StackEntry>>, 16> nodeStacks;
@@ -329,45 +331,62 @@ SHAMap::walkMapParallel(
JLOG(journal_.debug()) << "starting worker " << rootChildIndex; JLOG(journal_.debug()) << "starting worker " << rootChildIndex;
workers.push_back(std::thread( workers.push_back(std::thread(
[&m, &missingNodes, &maxMissing, this]( [&m, &missingNodes, &maxMissing, &exceptions, this](
std::stack<StackEntry, std::vector<StackEntry>> nodeStack) { std::stack<StackEntry, std::vector<StackEntry>> nodeStack) {
while (!nodeStack.empty()) try
{ {
std::shared_ptr<SHAMapInnerNode> node = while (!nodeStack.empty())
std::move(nodeStack.top());
assert(node);
nodeStack.pop();
for (int i = 0; i < 16; ++i)
{ {
if (node->isEmptyBranch(i)) std::shared_ptr<SHAMapInnerNode> node =
continue; std::move(nodeStack.top());
std::shared_ptr<SHAMapTreeNode> nextNode = assert(node);
descendNoStore(node, i); nodeStack.pop();
if (nextNode) for (int i = 0; i < 16; ++i)
{ {
if (nextNode->isInner()) if (node->isEmptyBranch(i))
nodeStack.push( continue;
std::static_pointer_cast<SHAMapInnerNode>( std::shared_ptr<SHAMapTreeNode> nextNode =
nextNode)); descendNoStore(node, i);
}
else if (nextNode)
{ {
std::lock_guard l{m}; if (nextNode->isInner())
missingNodes.emplace_back( nodeStack.push(std::static_pointer_cast<
type_, node->getChildHash(i)); SHAMapInnerNode>(nextNode));
if (--maxMissing <= 0) }
return; 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]))); std::move(nodeStacks[rootChildIndex])));
} }
for (std::thread& worker : workers) for (std::thread& worker : workers)
worker.join(); 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 } // namespace ripple