mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
yield value nodes pre-order
This commit is contained in:
parent
18e4da21de
commit
c0ca60b3f4
2 changed files with 41 additions and 15 deletions
|
|
@ -449,7 +449,7 @@ func (it *nodeIterator) findChild(n *fullNode, index int, ancestor common.Hash)
|
||||||
state *nodeIteratorState
|
state *nodeIteratorState
|
||||||
childPath []byte
|
childPath []byte
|
||||||
)
|
)
|
||||||
for ; index < len(n.Children); index++ {
|
for ; index < len(n.Children); index = nextChildIndex(index) {
|
||||||
if n.Children[index] != nil {
|
if n.Children[index] != nil {
|
||||||
child = n.Children[index]
|
child = n.Children[index]
|
||||||
hash, _ := child.cache()
|
hash, _ := child.cache()
|
||||||
|
|
@ -471,8 +471,8 @@ func (it *nodeIterator) nextChild(parent *nodeIteratorState, ancestor common.Has
|
||||||
switch node := parent.node.(type) {
|
switch node := parent.node.(type) {
|
||||||
case *fullNode:
|
case *fullNode:
|
||||||
// Full node, move to the first non-nil child.
|
// Full node, move to the first non-nil child.
|
||||||
if child, state, path, index := it.findChild(node, parent.index+1, ancestor); child != nil {
|
if child, state, path, index := it.findChild(node, nextChildIndex(parent.index), ancestor); child != nil {
|
||||||
parent.index = index - 1
|
parent.index = prevChildIndex(index)
|
||||||
return state, path, true
|
return state, path, true
|
||||||
}
|
}
|
||||||
case *shortNode:
|
case *shortNode:
|
||||||
|
|
@ -498,23 +498,23 @@ func (it *nodeIterator) nextChildAt(parent *nodeIteratorState, ancestor common.H
|
||||||
switch n := parent.node.(type) {
|
switch n := parent.node.(type) {
|
||||||
case *fullNode:
|
case *fullNode:
|
||||||
// Full node, move to the first non-nil child before the desired key position
|
// Full node, move to the first non-nil child before the desired key position
|
||||||
child, state, path, index := it.findChild(n, parent.index+1, ancestor)
|
child, state, path, index := it.findChild(n, nextChildIndex(parent.index), ancestor)
|
||||||
if child == nil {
|
if child == nil {
|
||||||
// No more children in this fullnode
|
// No more children in this fullnode
|
||||||
return parent, it.path, false
|
return parent, it.path, false
|
||||||
}
|
}
|
||||||
// If the child we found is already past the seek position, just return it.
|
// If the child we found is already past the seek position, just return it.
|
||||||
if bytes.Compare(path, key) >= 0 {
|
if bytes.Compare(path, key) >= 0 {
|
||||||
parent.index = index - 1
|
parent.index = prevChildIndex(index)
|
||||||
return state, path, true
|
return state, path, true
|
||||||
}
|
}
|
||||||
// The child is before the seek position. Try advancing
|
// The child is before the seek position. Try advancing
|
||||||
for {
|
for {
|
||||||
nextChild, nextState, nextPath, nextIndex := it.findChild(n, index+1, ancestor)
|
nextChild, nextState, nextPath, nextIndex := it.findChild(n, nextChildIndex(index), ancestor)
|
||||||
// If we run out of children, or skipped past the target, return the
|
// If we run out of children, or skipped past the target, return the
|
||||||
// previous one
|
// previous one
|
||||||
if nextChild == nil || bytes.Compare(nextPath, key) >= 0 {
|
if nextChild == nil || bytes.Compare(nextPath, key) >= 0 {
|
||||||
parent.index = index - 1
|
parent.index = prevChildIndex(index)
|
||||||
return state, path, true
|
return state, path, true
|
||||||
}
|
}
|
||||||
// We found a better child closer to the target
|
// We found a better child closer to the target
|
||||||
|
|
@ -541,7 +541,7 @@ func (it *nodeIterator) push(state *nodeIteratorState, parentIndex *int, path []
|
||||||
it.path = path
|
it.path = path
|
||||||
it.stack = append(it.stack, state)
|
it.stack = append(it.stack, state)
|
||||||
if parentIndex != nil {
|
if parentIndex != nil {
|
||||||
*parentIndex++
|
*parentIndex = nextChildIndex(*parentIndex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -563,6 +563,32 @@ func reachedPath(path, target []byte) bool {
|
||||||
return bytes.Compare(path, target) >= 0
|
return bytes.Compare(path, target) >= 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func prevChildIndex(index int) int {
|
||||||
|
switch index {
|
||||||
|
case 0:
|
||||||
|
return 16
|
||||||
|
case 16:
|
||||||
|
return -1
|
||||||
|
case 17:
|
||||||
|
return 15
|
||||||
|
default:
|
||||||
|
return index - 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func nextChildIndex(index int) int {
|
||||||
|
switch index {
|
||||||
|
case -1:
|
||||||
|
return 16
|
||||||
|
case 15:
|
||||||
|
return 17
|
||||||
|
case 16:
|
||||||
|
return 0
|
||||||
|
default:
|
||||||
|
return index + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func compareNodes(a, b NodeIterator) int {
|
func compareNodes(a, b NodeIterator) int {
|
||||||
if cmp := bytes.Compare(a.Path(), b.Path()); cmp != 0 {
|
if cmp := bytes.Compare(a.Path(), b.Path()); cmp != 0 {
|
||||||
return cmp
|
return cmp
|
||||||
|
|
|
||||||
|
|
@ -182,14 +182,14 @@ func testNodeIteratorCoverage(t *testing.T, scheme string) {
|
||||||
type kvs struct{ k, v string }
|
type kvs struct{ k, v string }
|
||||||
|
|
||||||
var testdata1 = []kvs{
|
var testdata1 = []kvs{
|
||||||
|
{"bar", "b"},
|
||||||
{"barb", "ba"},
|
{"barb", "ba"},
|
||||||
{"bard", "bc"},
|
{"bard", "bc"},
|
||||||
{"bars", "bb"},
|
{"bars", "bb"},
|
||||||
{"bar", "b"},
|
|
||||||
{"fab", "z"},
|
{"fab", "z"},
|
||||||
|
{"foo", "a"},
|
||||||
{"food", "ab"},
|
{"food", "ab"},
|
||||||
{"foos", "aa"},
|
{"foos", "aa"},
|
||||||
{"foo", "a"},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var testdata2 = []kvs{
|
var testdata2 = []kvs{
|
||||||
|
|
@ -218,7 +218,7 @@ func TestIteratorSeek(t *testing.T) {
|
||||||
|
|
||||||
// Seek to a non-existent key.
|
// Seek to a non-existent key.
|
||||||
it = NewIterator(trie.MustNodeIterator([]byte("barc")))
|
it = NewIterator(trie.MustNodeIterator([]byte("barc")))
|
||||||
if err := checkIteratorOrder(testdata1[1:], it); err != nil {
|
if err := checkIteratorOrder(testdata1[2:], it); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -230,7 +230,7 @@ func TestIteratorSeek(t *testing.T) {
|
||||||
|
|
||||||
// Seek to a key for which a prefixing key exists.
|
// Seek to a key for which a prefixing key exists.
|
||||||
it = NewIterator(trie.MustNodeIterator([]byte("food")))
|
it = NewIterator(trie.MustNodeIterator([]byte("food")))
|
||||||
if err := checkIteratorOrder(testdata1[5:], it); err != nil {
|
if err := checkIteratorOrder(testdata1[6:], it); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -317,16 +317,16 @@ func TestUnionIterator(t *testing.T) {
|
||||||
|
|
||||||
all := []struct{ k, v string }{
|
all := []struct{ k, v string }{
|
||||||
{"aardvark", "c"},
|
{"aardvark", "c"},
|
||||||
|
{"bar", "b"},
|
||||||
{"barb", "ba"},
|
{"barb", "ba"},
|
||||||
{"barb", "bd"},
|
{"barb", "bd"},
|
||||||
{"bard", "bc"},
|
{"bard", "bc"},
|
||||||
{"bars", "bb"},
|
{"bars", "bb"},
|
||||||
{"bars", "be"},
|
{"bars", "be"},
|
||||||
{"bar", "b"},
|
|
||||||
{"fab", "z"},
|
{"fab", "z"},
|
||||||
|
{"foo", "a"},
|
||||||
{"food", "ab"},
|
{"food", "ab"},
|
||||||
{"foos", "aa"},
|
{"foos", "aa"},
|
||||||
{"foo", "a"},
|
|
||||||
{"jars", "d"},
|
{"jars", "d"},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -517,7 +517,7 @@ func testIteratorContinueAfterSeekError(t *testing.T, memonly bool, scheme strin
|
||||||
rawdb.WriteTrieNode(diskdb, common.Hash{}, barNodePath, barNodeHash, barNodeBlob, triedb.Scheme())
|
rawdb.WriteTrieNode(diskdb, common.Hash{}, barNodePath, barNodeHash, barNodeBlob, triedb.Scheme())
|
||||||
}
|
}
|
||||||
// Check that iteration produces the right set of values.
|
// Check that iteration produces the right set of values.
|
||||||
if err := checkIteratorOrder(testdata1[2:], NewIterator(it)); err != nil {
|
if err := checkIteratorOrder(testdata1[3:], NewIterator(it)); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue