20 #include <ripple/basics/contract.h>
21 #include <ripple/shamap/SHAMap.h>
29 , journal_(f.journal())
34 root_ = std::make_shared<SHAMapInnerNode>(
seq_);
42 , journal_(f.journal())
47 root_ = std::make_shared<SHAMapInnerNode>(
seq_);
58 auto ret = std::make_shared<SHAMap> (
type_,
f_);
89 assert (child && (child->getSeq() ==
seq_));
91 while (!stack.
empty ())
93 auto node = std::dynamic_pointer_cast<SHAMapInnerNode>(stack.
top ().
first);
96 assert (node !=
nullptr);
102 node->setChild (branch, child);
104 child = std::move (node);
111 assert(stack ==
nullptr || stack->
empty());
115 while (inNode->isInner())
117 if (stack !=
nullptr)
118 stack->
push({inNode, nodeID});
120 auto const inner = std::static_pointer_cast<SHAMapInnerNode>(inNode);
122 if (inner->isEmptyBranch (branch))
129 if (stack !=
nullptr)
130 stack->
push({inNode, nodeID});
138 if (leaf && leaf->
peekItem()->key() !=
id)
162 "Invalid DB node " << hash;
169 const_cast<bool&
>(
full_) =
false;
182 if (
auto nodeData = filter->
getNode (hash))
189 std::move(*nodeData), node->getType ());
239 Throw<SHAMapMissingNode> (
type_, hash);
259 if (! ret && ! parent->isEmptyBranch (branch))
260 Throw<SHAMapMissingNode> (
type_, parent->getChildHash (branch));
286 node =
fetchNode (parent->getChildHash (branch));
290 node = parent->canonicalizeChild (branch, std::move(node));
301 ret =
fetchNode (parent->getChildHash (branch));
310 assert ((branch >= 0) && (branch < 16));
323 child = childNode.
get ();
372 template <
class Node>
377 assert (node->isValid ());
378 assert (node->getSeq () <=
seq_);
379 if (node->getSeq () !=
seq_)
383 node = std::static_pointer_cast<Node>(node->clone(
seq_));
384 assert (node->isValid ());
398 auto n = std::static_pointer_cast<SHAMapTreeNode>(node);
399 stack.
push({node, {64, n->peekItem()->key()}});
402 auto inner = std::static_pointer_cast<SHAMapInnerNode>(node);
406 stack.
push({inner, stack.
top().second.getChildNodeID(branch)});
407 for (
int i = 0; i < 16;)
409 if (!inner->isEmptyBranch(i))
412 assert(!stack.
empty());
415 auto n = std::static_pointer_cast<SHAMapTreeNode>(node);
416 stack.
push({n, {64, n->peekItem()->key()}});
419 inner = std::static_pointer_cast<SHAMapInnerNode>(node);
420 stack.
push({inner, stack.
top().second.getChildNodeID(branch)});
440 for (
int i = 0; i < 16; ++i)
442 if (!inner->isEmptyBranch (i))
463 assert (leaf->hasItem () || (leaf ==
root_.get ()));
465 return leaf->peekItem ();
474 assert(stack.
empty());
478 while (!stack.
empty())
488 assert(!stack.
empty());
489 assert(stack.
top().
first->isLeaf());
491 while (!stack.
empty())
493 auto [node, nodeID] = stack.
top();
494 assert(!node->isLeaf());
495 auto inner = std::static_pointer_cast<SHAMapInnerNode>(node);
496 for (
auto i = nodeID.selectBranch(
id) + 1; i < 16; ++i)
498 if (!inner->isEmptyBranch(i))
503 Throw<SHAMapMissingNode> (
type_,
id);
504 assert(leaf->isLeaf());
556 while (!stack.
empty())
558 auto [node, nodeID] = stack.
top();
562 if (leaf->peekItem()->key() > id)
563 return const_iterator(
this, leaf->peekItem().get(), std::move(stack));
567 auto inner = std::static_pointer_cast<SHAMapInnerNode>(node);
568 for (
auto branch = nodeID.selectBranch(
id) + 1; branch < 16; ++branch)
570 if (!inner->isEmptyBranch(branch))
575 Throw<SHAMapMissingNode> (
type_,
id);
590 return (leaf !=
nullptr);
602 Throw<SHAMapMissingNode> (
type_,
id);
604 auto leaf = std::dynamic_pointer_cast<SHAMapTreeNode>(stack.
top ().
first);
607 if (!leaf || (leaf->peekItem ()->key() !=
id))
616 while (!stack.
empty ())
618 auto node = std::static_pointer_cast<SHAMapInnerNode>(stack.
top().
first);
629 const int bc = node->getBranchCount();
642 for (
int i = 0; i < 16; ++i)
644 if (!node->isEmptyBranch (i))
646 node->setChild (i,
nullptr);
650 prevNode = std::make_shared<SHAMapTreeNode>(item, type, node->getSeq());
654 prevNode = std::move (node);
660 prevNode = std::move (node);
670 bool isTransaction,
bool hasMeta)
683 Throw<SHAMapMissingNode> (
type_, tag);
685 auto [node, nodeID] = stack.
top();
690 auto leaf = std::static_pointer_cast<SHAMapTreeNode>(node);
691 if (leaf->peekItem()->key() == tag)
695 if (node->isInner ())
698 auto inner = std::static_pointer_cast<SHAMapInnerNode>(node);
699 int branch = nodeID.selectBranch (tag);
700 assert (inner->isEmptyBranch (branch));
701 auto newNode = std::make_shared<SHAMapTreeNode> (item, type,
seq_);
702 inner->setChild (branch, newNode);
707 auto leaf = std::static_pointer_cast<SHAMapTreeNode>(node);
709 assert (otherItem && (tag != otherItem->key()));
711 node = std::make_shared<SHAMapInnerNode>(node->getSeq());
715 while ((b1 = nodeID.selectBranch (tag)) ==
716 (b2 = nodeID.selectBranch (otherItem->key())))
718 stack.
push ({node, nodeID});
721 nodeID = nodeID.getChildNodeID (b1);
722 node = std::make_shared<SHAMapInnerNode> (
seq_);
726 assert (node->isInner ());
729 std::make_shared<SHAMapTreeNode> (item, type,
seq_);
730 assert (newNode->isValid () && newNode->isLeaf ());
731 auto inner = std::static_pointer_cast<SHAMapInnerNode>(node);
732 inner->setChild (b1, newNode);
734 newNode = std::make_shared<SHAMapTreeNode> (otherItem, type,
seq_);
735 assert (newNode->isValid () && newNode->isLeaf ());
736 inner->setChild (b2, newNode);
746 return addGiveItem(std::make_shared<SHAMapItem const>(std::move(i)),
747 isTransaction, hasMetaData);
753 auto hash =
root_->getNodeHash();
757 hash =
root_->getNodeHash();
764 bool isTransaction,
bool hasMeta)
775 Throw<SHAMapMissingNode> (
type_, tag);
777 auto node = std::dynamic_pointer_cast<SHAMapTreeNode>(stack.
top().
first);
781 if (!node || (node->peekItem ()->key() != tag))
793 "SHAMap setItem, no change";
803 if (hash ==
root_->getNodeHash ())
811 <<
"Fetch root TXN node " << hash;
816 "Fetch root STATE node " << hash;
821 "Fetch root SHAMap node " << hash;
830 assert (
root_->getNodeHash () == hash);
851 assert (node->getSeq() ==
seq_);
860 node->getNodeHash ().as_uint256(),
ledgerSeq_);
867 template <
class Node>
873 assert (node->getSeq() != 0);
875 if (node->getSeq() !=
seq_)
879 node = std::static_pointer_cast<Node>(node->clone(
seq_));
917 auto node = std::static_pointer_cast<SHAMapInnerNode>(
root_);
919 if (node->isEmpty ())
921 root_ = std::make_shared<SHAMapInnerNode>(0);
939 if (node->isEmptyBranch (pos))
948 auto child = node->getChild(pos++);
950 if (child && (child->getSeq() != 0))
956 if (child->isInner ())
960 stack.
emplace (std::move (node), branch);
962 node = std::static_pointer_cast<SHAMapInnerNode>(std::move(child));
970 assert (node->getSeq() ==
seq_);
974 child =
writeNode(t, seq, std::move(child));
978 node->shareChild (branch, child);
985 node->updateHashDeep();
989 node = std::static_pointer_cast<SHAMapInnerNode>(
writeNode(t, seq,
999 auto parent = std::move (stack.
top().first);
1000 pos = stack.
top().second;
1004 assert (parent->getSeq() ==
seq_);
1005 parent->shareChild (pos, node);
1008 node = std::move (parent);
1013 root_ = std::move (node);
1028 auto [node, nodeID] = stack.
top();
1034 JLOG(
journal_.
info()) <<
"Hash: " << node->getNodeHash();
1037 if (node->isInner ())
1040 for (
int i = 0; i < 16; ++i)
1042 if (!inner->isEmptyBranch (i))
1044 auto child = inner->getChildPointer (i);
1047 assert (child->getNodeHash() == inner->getChildHash (i));
1048 stack.
push ({child, nodeID.getChildNodeID (i)});
1056 while (!stack.
empty ());
1058 JLOG(
journal_.
info()) << leafCount <<
" resident leaves";
1064 assert (!ret || !ret->getSeq());
1072 assert (node->getSeq() == 0);
1073 assert (node->getNodeHash() == hash);
1082 auto node =
root_.get();
1083 assert(node !=
nullptr);
1084 assert(!node->isLeaf());
1089 node->invariants(
true);