20 #include <ripple/basics/contract.h>
21 #include <ripple/shamap/SHAMap.h>
40 boost::intrusive_ptr<SHAMapItem const>
const& otherMapItem,
50 bool emptyBranch = !otherMapItem;
52 while (!nodeStack.
empty())
54 node = nodeStack.
top();
61 for (
int i = 0; i < 16; ++i)
62 if (!inner->isEmptyBranch(i))
70 if (emptyBranch || (item->key() != otherMapItem->key()))
83 else if (item->slice() != otherMapItem->slice())
88 item->key(),
DeltaRef(item, otherMapItem)));
91 item->key(),
DeltaRef(otherMapItem, item)));
111 otherMapItem->key(), DeltaRef(
nullptr, otherMapItem)));
114 otherMapItem->key(), DeltaRef(otherMapItem,
nullptr)));
124 SHAMap::compare(
SHAMap const& otherMap,
Delta& differences,
int maxCount)
const
131 assert(isValid() && otherMap.
isValid());
133 if (getHash() == otherMap.
getHash())
140 nodeStack.
push({root_.get(), otherMap.
root_.get()});
141 while (!nodeStack.
empty())
143 auto [ourNode, otherNode] = nodeStack.
top();
146 if (!ourNode || !otherNode)
149 Throw<SHAMapMissingNode>(type_,
uint256());
152 if (ourNode->isLeaf() && otherNode->isLeaf())
157 if (ours->peekItem()->key() == other->peekItem()->key())
159 if (ours->peekItem()->slice() != other->peekItem()->slice())
162 ours->peekItem()->key(),
163 DeltaRef(ours->peekItem(), other->peekItem())));
171 ours->peekItem()->key(),
172 DeltaRef(ours->peekItem(),
nullptr)));
177 other->peekItem()->key(),
178 DeltaRef(
nullptr, other->peekItem())));
183 else if (ourNode->isInner() && otherNode->isLeaf())
188 ours, other->peekItem(),
true, differences, maxCount))
191 else if (ourNode->isLeaf() && otherNode->isInner())
196 other, ours->peekItem(),
false, differences, maxCount))
199 else if (ourNode->isInner() && otherNode->isInner())
203 for (
int i = 0; i < 16; ++i)
204 if (ours->getChildHash(i) != other->getChildHash(i))
206 if (other->isEmptyBranch(i))
211 iNode,
nullptr,
true, differences, maxCount))
214 else if (ours->isEmptyBranch(i))
219 iNode,
nullptr,
false, differences, maxCount))
224 {descendThrow(ours, i),
239 if (!root_->isInner())
245 nodeStack.
push(std::static_pointer_cast<SHAMapInnerNode>(root_));
247 while (!nodeStack.
empty())
252 for (
int i = 0; i < 16; ++i)
254 if (!node->isEmptyBranch(i))
257 descendNoStore(node, i);
261 if (nextNode->isInner())
263 std::static_pointer_cast<SHAMapInnerNode>(
268 missingNodes.
emplace_back(type_, node->getChildHash(i));
269 if (--maxMissing <= 0)
278 SHAMap::walkMapParallel(
280 int maxMissing)
const
282 if (!root_->isInner())
288 auto const& innerRoot =
289 std::static_pointer_cast<SHAMapInnerNode>(root_);
290 for (
int i = 0; i < 16; ++i)
292 if (!innerRoot->isEmptyBranch(i))
293 topChildren[i] = descendNoStore(innerRoot, i);
307 for (
int rootChildIndex = 0; rootChildIndex < 16; ++rootChildIndex)
309 auto const& child = topChildren[rootChildIndex];
310 if (!child || !child->isInner())
313 nodeStacks[rootChildIndex].push(
314 std::static_pointer_cast<SHAMapInnerNode>(child));
316 JLOG(journal_.debug()) <<
"starting worker " << rootChildIndex;
318 [&m, &missingNodes, &maxMissing, &exceptions,
this](
322 while (!nodeStack.empty())
324 std::shared_ptr<SHAMapInnerNode> node =
325 std::move(nodeStack.top());
329 for (int i = 0; i < 16; ++i)
331 if (node->isEmptyBranch(i))
333 std::shared_ptr<SHAMapTreeNode> nextNode =
334 descendNoStore(node, i);
338 if (nextNode->isInner())
339 nodeStack.push(std::static_pointer_cast<
340 SHAMapInnerNode>(nextNode));
344 std::lock_guard l{m};
345 missingNodes.emplace_back(
346 type_, node->getChildHash(i));
347 if (--maxMissing <= 0)
359 std::move(nodeStacks[rootChildIndex])));
366 if (exceptions.empty())
369 ss <<
"Exception(s) in ledger load: ";
370 for (
auto const& e : exceptions)
371 ss << e.what() <<
", ";
372 JLOG(journal_.error()) << ss.
str();