trie: link nodes into memory on get

This commit is contained in:
Felix Lange 2016-09-26 21:50:04 +02:00
parent e7394723e2
commit 2beb71af8f

View file

@ -117,32 +117,50 @@ func (t *Trie) Get(key []byte) []byte {
// If a node was not found in the database, a MissingNodeError is returned.
func (t *Trie) TryGet(key []byte) ([]byte, error) {
key = compactHexDecode(key)
pos := 0
tn := t.root
for pos < len(key) {
switch n := tn.(type) {
value, newroot, didResolve, err := t.tryGet(t.root, key, 0)
if err == nil && didResolve {
t.root = newroot
}
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:
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:
tn = n.Children[key[pos]]
pos++
case nil:
return nil, nil
child := n.Children[key[pos]]
value, newnode, didResolve, err = t.tryGet(child, key, pos+1)
if err == nil && didResolve {
n.Children[key[pos]] = newnode
return value, n, didResolve, err
} else {
return value, origNode, didResolve, err
}
case hashNode:
var err error
tn, err = t.resolveHash(n, key[:pos], key[pos:])
child, err := t.resolveHash(n, key[:pos], key[pos:])
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:
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