20 #include <ripple/basics/contract.h>
21 #include <ripple/shamap/SHAMap.h>
22 #include <ripple/shamap/SHAMapAccountStateLeafNode.h>
23 #include <ripple/shamap/SHAMapNodeID.h>
24 #include <ripple/shamap/SHAMapSyncFilter.h>
25 #include <ripple/shamap/SHAMapTxLeafNode.h>
26 #include <ripple/shamap/SHAMapTxPlusMetaLeafNode.h>
33 boost::intrusive_ptr<SHAMapItem const> item,
37 return std::make_shared<SHAMapTxLeafNode>(std::move(item), owner);
40 return std::make_shared<SHAMapTxPlusMetaLeafNode>(
41 std::move(item), owner);
44 return std::make_shared<SHAMapAccountStateLeafNode>(
45 std::move(item), owner);
48 "Attempt to create leaf node of unknown type " +
71 , journal_(other.f_.journal())
72 , cowid_(other.cowid_ + 1)
73 , ledgerSeq_(other.ledgerSeq_)
77 , backed_(other.backed_)
90 return std::make_shared<SHAMap>(*
this, isMutable);
107 assert(child && (child->cowid() ==
cowid_));
109 while (!stack.
empty())
112 std::dynamic_pointer_cast<SHAMapInnerNode>(stack.
top().
first);
115 assert(node !=
nullptr);
121 node->setChild(branch, std::move(child));
123 child = std::move(node);
130 assert(stack ==
nullptr || stack->
empty());
134 while (inNode->isInner())
136 if (stack !=
nullptr)
137 stack->
push({inNode, nodeID});
139 auto const inner = std::static_pointer_cast<SHAMapInnerNode>(inNode);
141 if (inner->isEmptyBranch(branch))
148 if (stack !=
nullptr)
149 stack->
push({inNode, nodeID});
157 if (leaf && leaf->
peekItem()->key() !=
id)
202 <<
"finishFetch exception: unknonw exception: " << hash;
212 if (
auto nodeData = filter->
getNode(hash))
224 std::move(*nodeData),
234 <<
"Invalid node/data, hash=" << hash <<
": " << x.
what();
283 Throw<SHAMapMissingNode>(
type_, hash);
305 if (!ret && !parent->isEmptyBranch(branch))
306 Throw<SHAMapMissingNode>(
type_, parent->getChildHash(branch));
335 node =
fetchNode(parent->getChildHash(branch));
339 node = parent->canonicalizeChild(branch, std::move(node));
352 ret =
fetchNode(parent->getChildHash(branch));
378 child = childNode.
get();
412 [
this, hash, cb{std::move(callback)}](
414 auto node = finishFetch(hash, object);
428 template <
class Node>
433 assert(node->cowid() <=
cowid_);
434 if (node->cowid() !=
cowid_)
438 node = std::static_pointer_cast<Node>(node->clone(
cowid_));
453 auto& [init, cmp, incr] = loopParams;
456 auto n = std::static_pointer_cast<SHAMapLeafNode>(node);
460 auto inner = std::static_pointer_cast<SHAMapInnerNode>(node);
464 stack.
push({inner, stack.
top().second.getChildNodeID(branch)});
465 for (
int i = init; cmp(i);)
467 if (!inner->isEmptyBranch(i))
470 assert(!stack.
empty());
473 auto n = std::static_pointer_cast<SHAMapLeafNode>(node);
477 inner = std::static_pointer_cast<SHAMapInnerNode>(node);
478 stack.
push({inner, stack.
top().second.getChildNodeID(branch)});
493 auto cmp = [](
int i) {
return i >= 0; };
494 auto incr = [](
int& i) { --i; };
496 return belowHelper(node, stack, branch, {init, cmp, incr});
506 auto incr = [](
int& i) { ++i; };
508 return belowHelper(node, stack, branch, {init, cmp, incr});
510 static const boost::intrusive_ptr<SHAMapItem const>
no_item;
512 boost::intrusive_ptr<SHAMapItem const>
const&
523 if (!inner->isEmptyBranch(i))
544 assert(leaf->peekItem() || (leaf ==
root_.get()));
545 return leaf->peekItem();
551 assert(stack.
empty());
555 while (!stack.
empty())
565 assert(!stack.
empty());
566 assert(stack.
top().
first->isLeaf());
568 while (!stack.
empty())
570 auto [node, nodeID] = stack.
top();
571 assert(!node->isLeaf());
572 auto inner = std::static_pointer_cast<SHAMapInnerNode>(node);
575 if (!inner->isEmptyBranch(i))
580 Throw<SHAMapMissingNode>(
type_,
id);
581 assert(leaf->isLeaf());
591 boost::intrusive_ptr<SHAMapItem const>
const&
602 boost::intrusive_ptr<SHAMapItem const>
const&
619 while (!stack.
empty())
621 auto [node, nodeID] = stack.
top();
625 if (leaf->peekItem()->key() > id)
627 this, leaf->peekItem().get(), std::move(stack));
631 auto inner = std::static_pointer_cast<SHAMapInnerNode>(node);
636 if (!inner->isEmptyBranch(branch))
641 Throw<SHAMapMissingNode>(
type_,
id);
643 this, leaf->peekItem().get(), std::move(stack));
656 while (!stack.
empty())
658 auto [node, nodeID] = stack.
top();
662 if (leaf->peekItem()->key() < id)
664 this, leaf->peekItem().get(), std::move(stack));
668 auto inner = std::static_pointer_cast<SHAMapInnerNode>(node);
669 for (
int branch =
selectBranch(nodeID,
id) - 1; branch >= 0;
672 if (!inner->isEmptyBranch(branch))
675 auto leaf =
lastBelow(node, stack, branch);
677 Throw<SHAMapMissingNode>(
type_,
id);
679 this, leaf->peekItem().get(), std::move(stack));
692 return (
findKey(
id) !=
nullptr);
705 Throw<SHAMapMissingNode>(
type_,
id);
707 auto leaf = std::dynamic_pointer_cast<SHAMapLeafNode>(stack.
top().
first);
710 if (!leaf || (leaf->peekItem()->key() !=
id))
719 while (!stack.
empty())
722 std::static_pointer_cast<SHAMapInnerNode>(stack.
top().
first);
727 node->setChild(
selectBranch(nodeID,
id), std::move(prevNode));
733 const int bc = node->getBranchCount();
748 if (!node->isEmptyBranch(i))
750 node->setChild(i,
nullptr);
759 prevNode = std::move(node);
765 prevNode = std::move(node);
776 boost::intrusive_ptr<SHAMapItem const> item)
788 Throw<SHAMapMissingNode>(
type_, tag);
790 auto [node, nodeID] = stack.
top();
795 auto leaf = std::static_pointer_cast<SHAMapLeafNode>(node);
796 if (leaf->peekItem()->key() == tag)
803 auto inner = std::static_pointer_cast<SHAMapInnerNode>(node);
805 assert(inner->isEmptyBranch(branch));
812 auto leaf = std::static_pointer_cast<SHAMapLeafNode>(node);
813 auto otherItem = leaf->peekItem();
814 assert(otherItem && (tag != otherItem->key()));
816 node = std::make_shared<SHAMapInnerNode>(node->cowid());
823 stack.
push({node, nodeID});
827 nodeID = nodeID.getChildNodeID(b1);
828 node = std::make_shared<SHAMapInnerNode>(
cowid_);
832 assert(node->isInner());
846 boost::intrusive_ptr<SHAMapItem const> item)
854 auto hash =
root_->getHash();
858 hash =
root_->getHash();
866 boost::intrusive_ptr<SHAMapItem const> item)
877 Throw<SHAMapMissingNode>(
type_, tag);
879 auto node = std::dynamic_pointer_cast<SHAMapLeafNode>(stack.
top().
first);
883 if (!node || (node->peekItem()->key() != tag))
889 if (node->getType() != type)
891 JLOG(
journal_.
fatal()) <<
"SHAMap::updateGiveItem: cross-type change!";
897 if (node->setItem(item))
906 if (hash ==
root_->getHash())
913 stream <<
"Fetch root TXN node " << hash;
917 stream <<
"Fetch root STATE node " << hash;
921 stream <<
"Fetch root SHAMap node " << hash;
930 assert(
root_->getHash() == hash);
952 assert(node->cowid() == 0);
958 node->serializeWithPrefix(s);
967 template <
class Node>
973 assert(node->cowid() != 0);
975 if (node->cowid() !=
cowid_)
979 node = std::static_pointer_cast<Node>(node->clone(
cowid_));
1008 if (
root_->isLeaf())
1011 root_->updateHash();
1020 auto node = std::static_pointer_cast<SHAMapInnerNode>(
root_);
1022 if (node->isEmpty())
1024 root_ = std::make_shared<SHAMapInnerNode>(0);
1042 if (node->isEmptyBranch(pos))
1051 auto child = node->getChild(pos++);
1053 if (child && (child->cowid() != 0))
1059 if (child->isInner())
1063 stack.
emplace(std::move(node), branch);
1067 node = std::static_pointer_cast<SHAMapInnerNode>(
1076 assert(node->cowid() ==
cowid_);
1077 child->updateHash();
1083 node->shareChild(branch, child);
1090 node->updateHashDeep();
1096 node = std::static_pointer_cast<SHAMapInnerNode>(
1104 auto parent = std::move(stack.
top().first);
1105 pos = stack.
top().second;
1109 assert(parent->cowid() ==
cowid_);
1110 parent->shareChild(pos, node);
1113 node = std::move(parent);
1118 root_ = std::move(node);
1134 auto [node, nodeID] = stack.
top();
1143 if (node->isInner())
1148 if (!inner->isEmptyBranch(i))
1150 auto child = inner->getChildPointer(i);
1153 assert(child->getHash() == inner->getChildHash(i));
1154 stack.
push({child, nodeID.getChildNodeID(i)});
1161 }
while (!stack.
empty());
1163 JLOG(
journal_.
info()) << leafCount <<
" resident leaves";
1170 assert(!ret || !ret->cowid());
1180 assert(node->cowid() == 0);
1181 assert(node->getHash() == hash);
1184 ->canonicalize_replace_client(hash.
as_uint256(), node);
1191 auto node =
root_.get();
1192 assert(node !=
nullptr);
1193 assert(!node->isLeaf());
1198 node->invariants(
true);