mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-25 14:16:44 +00:00
trie: link nodes into memory on get
This commit is contained in:
parent
e7394723e2
commit
2beb71af8f
1 changed files with 43 additions and 25 deletions
52
trie/trie.go
52
trie/trie.go
|
|
@ -117,33 +117,51 @@ func (t *Trie) Get(key []byte) []byte {
|
||||||
// If a node was not found in the database, a MissingNodeError is returned.
|
// If a node was not found in the database, a MissingNodeError is returned.
|
||||||
func (t *Trie) TryGet(key []byte) ([]byte, error) {
|
func (t *Trie) TryGet(key []byte) ([]byte, error) {
|
||||||
key = compactHexDecode(key)
|
key = compactHexDecode(key)
|
||||||
pos := 0
|
value, newroot, didResolve, err := t.tryGet(t.root, key, 0)
|
||||||
tn := t.root
|
if err == nil && didResolve {
|
||||||
for pos < len(key) {
|
t.root = newroot
|
||||||
switch n := tn.(type) {
|
}
|
||||||
|
return value, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Trie) tryGet(origNode node, key []byte, pos int) (value []byte, newnode node, didResolve bool, err error) {
|
||||||
|
switch n := (origNode).(type) {
|
||||||
|
case nil:
|
||||||
|
return nil, nil, false, nil
|
||||||
|
case valueNode:
|
||||||
|
return n, n, false, nil
|
||||||
case shortNode:
|
case shortNode:
|
||||||
if len(key)-pos < len(n.Key) || !bytes.Equal(n.Key, key[pos:pos+len(n.Key)]) {
|
if len(key)-pos < len(n.Key) || !bytes.Equal(n.Key, key[pos:pos+len(n.Key)]) {
|
||||||
return nil, nil
|
// key not found in trie
|
||||||
|
return nil, n, false, nil
|
||||||
|
}
|
||||||
|
value, newnode, didResolve, err = t.tryGet(n.Val, key, pos+len(n.Key))
|
||||||
|
if err == nil && didResolve {
|
||||||
|
n.Val = newnode
|
||||||
|
return value, n, didResolve, err
|
||||||
|
} else {
|
||||||
|
return value, origNode, didResolve, err
|
||||||
}
|
}
|
||||||
tn = n.Val
|
|
||||||
pos += len(n.Key)
|
|
||||||
case fullNode:
|
case fullNode:
|
||||||
tn = n.Children[key[pos]]
|
child := n.Children[key[pos]]
|
||||||
pos++
|
value, newnode, didResolve, err = t.tryGet(child, key, pos+1)
|
||||||
case nil:
|
if err == nil && didResolve {
|
||||||
return nil, nil
|
n.Children[key[pos]] = newnode
|
||||||
|
return value, n, didResolve, err
|
||||||
|
} else {
|
||||||
|
return value, origNode, didResolve, err
|
||||||
|
}
|
||||||
case hashNode:
|
case hashNode:
|
||||||
var err error
|
child, err := t.resolveHash(n, key[:pos], key[pos:])
|
||||||
tn, err = t.resolveHash(n, key[:pos], key[pos:])
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, n, true, err
|
||||||
}
|
}
|
||||||
|
value, newnode, _, err := t.tryGet(child, key, pos)
|
||||||
|
return value, newnode, true, err
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("%T: invalid node: %v", tn, tn))
|
panic(fmt.Sprintf("%T: invalid node: %v", origNode, origNode))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return tn.(valueNode), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update associates key with value in the trie. Subsequent calls to
|
// Update associates key with value in the trie. Subsequent calls to
|
||||||
// Get will return value. If value has length zero, any existing value
|
// Get will return value. If value has length zero, any existing value
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue