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
{
if (parallel)
stateMap_->walkMapParallel(missingNodes1, 32);
return stateMap_->walkMapParallel(missingNodes1, 32);
else
stateMap_->walkMap(missingNodes1, 32);
}

View File

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

View File

@@ -290,13 +290,13 @@ SHAMap::walkMap(std::vector<SHAMapMissingNode>& missingNodes, int maxMissing)
}
}
void
bool
SHAMap::walkMapParallel(
std::vector<SHAMapMissingNode>& missingNodes,
int maxMissing) const
{
if (!root_->isInner()) // root_ is only node, and we have it
return;
return false;
using StackEntry = std::shared_ptr<SHAMapInnerNode>;
std::array<std::shared_ptr<SHAMapTreeNode>, 16> topChildren;
@@ -311,6 +311,8 @@ SHAMap::walkMapParallel(
}
std::vector<std::thread> workers;
workers.reserve(16);
std::vector<SHAMapMissingNode> exceptions;
exceptions.reserve(16);
std::array<std::stack<StackEntry, std::vector<StackEntry>>, 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<StackEntry, std::vector<StackEntry>> nodeStack) {
while (!nodeStack.empty())
try
{
std::shared_ptr<SHAMapInnerNode> 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<SHAMapTreeNode> nextNode =
descendNoStore(node, i);
std::shared_ptr<SHAMapInnerNode> 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<SHAMapInnerNode>(
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<SHAMapTreeNode> 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