22 boost::intrusive_ptr<SHAMapItem const>
const& otherMapItem,
32 bool emptyBranch = !otherMapItem;
34 while (!nodeStack.
empty())
36 node = nodeStack.
top();
43 for (
int i = 0; i < 16; ++i)
44 if (!inner->isEmptyBranch(i))
52 if (emptyBranch || (item->key() != otherMapItem->key()))
63 else if (item->slice() != otherMapItem->slice())
88 differences.insert(
std::make_pair(otherMapItem->key(), DeltaRef(
nullptr, otherMapItem)));
90 differences.insert(
std::make_pair(otherMapItem->key(), DeltaRef(otherMapItem,
nullptr)));
100SHAMap::compare(
SHAMap const& otherMap,
Delta& differences,
int maxCount)
const
107 XRPL_ASSERT(isValid() && otherMap.
isValid(),
"xrpl::SHAMap::compare : valid state and valid input");
109 if (getHash() == otherMap.
getHash())
115 nodeStack.
push({root_.get(), otherMap.
root_.get()});
116 while (!nodeStack.
empty())
118 auto [ourNode, otherNode] = nodeStack.
top();
121 if (!ourNode || !otherNode)
124 UNREACHABLE(
"xrpl::SHAMap::compare : missing a node");
125 Throw<SHAMapMissingNode>(type_,
uint256());
129 if (ourNode->isLeaf() && otherNode->isLeaf())
134 if (ours->peekItem()->key() == other->peekItem()->key())
136 if (ours->peekItem()->slice() != other->peekItem()->slice())
155 else if (ourNode->isInner() && otherNode->isLeaf())
159 if (!walkBranch(ours, other->peekItem(),
true, differences, maxCount))
162 else if (ourNode->isLeaf() && otherNode->isInner())
166 if (!otherMap.
walkBranch(other, ours->peekItem(),
false, differences, maxCount))
169 else if (ourNode->isInner() && otherNode->isInner())
173 for (
int i = 0; i < 16; ++i)
174 if (ours->getChildHash(i) != other->getChildHash(i))
176 if (other->isEmptyBranch(i))
180 if (!walkBranch(iNode,
nullptr,
true, differences, maxCount))
183 else if (ours->isEmptyBranch(i))
187 if (!otherMap.
walkBranch(iNode,
nullptr,
false, differences, maxCount))
197 UNREACHABLE(
"xrpl::SHAMap::compare : invalid node");
208 if (!root_->isInner())
214 nodeStack.
push(intr_ptr::static_pointer_cast<SHAMapInnerNode>(root_));
216 while (!nodeStack.
empty())
221 for (
int i = 0; i < 16; ++i)
223 if (!node->isEmptyBranch(i))
229 if (nextNode->isInner())
230 nodeStack.
push(intr_ptr::static_pointer_cast<SHAMapInnerNode>(nextNode));
234 missingNodes.
emplace_back(type_, node->getChildHash(i));
235 if (--maxMissing <= 0)
246 if (!root_->isInner())
252 auto const& innerRoot = intr_ptr::static_pointer_cast<SHAMapInnerNode>(root_);
253 for (
int i = 0; i < 16; ++i)
255 if (!innerRoot->isEmptyBranch(i))
256 topChildren[i] = descendNoStore(*innerRoot, i);
270 for (
int rootChildIndex = 0; rootChildIndex < 16; ++rootChildIndex)
272 auto const& child = topChildren[rootChildIndex];
273 if (!child || !child->isInner())
276 nodeStacks[rootChildIndex].push(intr_ptr::static_pointer_cast<SHAMapInnerNode>(child));
278 JLOG(journal_.debug()) <<
"starting worker " << rootChildIndex;
280 [&m, &missingNodes, &maxMissing, &exceptions,
this](
284 while (!nodeStack.empty())
286 intr_ptr::SharedPtr<SHAMapInnerNode> node = std::move(nodeStack.top());
287 XRPL_ASSERT(node,
"xrpl::SHAMap::walkMapParallel : non-null node");
290 for (int i = 0; i < 16; ++i)
292 if (node->isEmptyBranch(i))
294 intr_ptr::SharedPtr<SHAMapTreeNode> nextNode = descendNoStore(*node, i);
298 if (nextNode->isInner())
299 nodeStack.push(intr_ptr::static_pointer_cast<SHAMapInnerNode>(nextNode));
303 std::lock_guard l{m};
304 missingNodes.emplace_back(type_, node->getChildHash(i));
305 if (--maxMissing <= 0)
317 std::move(nodeStacks[rootChildIndex])));
324 if (exceptions.empty())
327 ss <<
"Exception(s) in ledger load: ";
328 for (
auto const& e : exceptions)
329 ss << e.what() <<
", ";
330 JLOG(journal_.error()) << ss.
str();
bool walkBranch(SHAMapTreeNode *node, boost::intrusive_ptr< SHAMapItem const > const &otherMapItem, bool isFirstMap, Delta &differences, int &maxCount) const