Add tracker interface and tests #3
22
iterator.go
22
iterator.go
@ -23,16 +23,21 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/trie"
|
"github.com/ethereum/go-ethereum/trie"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PrefixBoundIterator is a NodeIterator constrained by a lower & upper bound (as hex path prefixes)
|
|
||||||
type PrefixBoundIterator struct {
|
|
||||||
trie.NodeIterator
|
|
||||||
EndPath []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
// IteratorConstructor is a constructor returning a NodeIterator, which is used to decouple this
|
// IteratorConstructor is a constructor returning a NodeIterator, which is used to decouple this
|
||||||
// code from the trie implementation.
|
// code from the trie implementation.
|
||||||
type IteratorConstructor = func(startKey []byte) trie.NodeIterator
|
type IteratorConstructor = func(startKey []byte) trie.NodeIterator
|
||||||
|
|
||||||
|
// PrefixBoundIterator is a NodeIterator constrained by a lower & upper bound (as hex path prefixes)
|
||||||
|
type PrefixBoundIterator struct {
|
||||||
|
trie.NodeIterator
|
||||||
|
StartPath, EndPath []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPrefixBoundIterator returns an iterator with an upper bound value (hex path prefix)
|
||||||
|
func NewPrefixBoundIterator(it trie.NodeIterator, to []byte) *PrefixBoundIterator {
|
||||||
|
return &PrefixBoundIterator{NodeIterator: it, StartPath: it.Path(), EndPath: to}
|
||||||
|
}
|
||||||
|
|
||||||
func (it *PrefixBoundIterator) Next(descend bool) bool {
|
func (it *PrefixBoundIterator) Next(descend bool) bool {
|
||||||
if it.EndPath == nil {
|
if it.EndPath == nil {
|
||||||
return it.NodeIterator.Next(descend)
|
return it.NodeIterator.Next(descend)
|
||||||
@ -49,9 +54,8 @@ func (it *PrefixBoundIterator) Next(descend bool) bool {
|
|||||||
return bytes.Compare(it.Path(), it.EndPath) <= 0
|
return bytes.Compare(it.Path(), it.EndPath) <= 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPrefixBoundIterator returns an iterator with an upper bound value (hex path prefix)
|
func (it *PrefixBoundIterator) Bounds() ([]byte, []byte) {
|
||||||
func NewPrefixBoundIterator(it trie.NodeIterator, to []byte) *PrefixBoundIterator {
|
return it.StartPath, it.EndPath
|
||||||
return &PrefixBoundIterator{NodeIterator: it, EndPath: to}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// generates nibble slice prefixes at uniform intervals
|
// generates nibble slice prefixes at uniform intervals
|
||||||
|
@ -69,11 +69,7 @@ func (tr *Tracker) dump() error {
|
|||||||
log.Debug("Dumping recovery state", "to", tr.recoveryFile)
|
log.Debug("Dumping recovery state", "to", tr.recoveryFile)
|
||||||
var rows [][]string
|
var rows [][]string
|
||||||
for it := range tr.started {
|
for it := range tr.started {
|
||||||
var endPath []byte
|
_, endPath := it.Bounds()
|
||||||
if impl, ok := it.NodeIterator.(*iter.PrefixBoundIterator); ok {
|
|
||||||
endPath = impl.EndPath
|
|
||||||
}
|
|
||||||
|
|
||||||
rows = append(rows, []string{
|
rows = append(rows, []string{
|
||||||
fmt.Sprintf("%x", it.Path()),
|
fmt.Sprintf("%x", it.Path()),
|
||||||
fmt.Sprintf("%x", endPath),
|
fmt.Sprintf("%x", endPath),
|
||||||
@ -184,6 +180,13 @@ func (it *Iterator) Next(descend bool) bool {
|
|||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (it *Iterator) Bounds() ([]byte, []byte) {
|
||||||
roysc marked this conversation as resolved
Outdated
|
|||||||
|
if impl, ok := it.NodeIterator.(*iter.PrefixBoundIterator); ok {
|
||||||
|
return impl.Bounds()
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Rewinds to the path of the previous (pre-order) node:
|
// Rewinds to the path of the previous (pre-order) node:
|
||||||
// If the last byte of the path is zero, pops it. Otherwise, decrements it
|
// If the last byte of the path is zero, pops it. Otherwise, decrements it
|
||||||
// and pads with 0xF to 64 bytes (e.g. [1] => [0 f f f ...]).
|
// and pads with 0xF to 64 bytes (e.g. [1] => [0 f f f ...]).
|
||||||
|
Loading…
Reference in New Issue
Block a user
Is it explicit anywhere that you must call CloseAndSave in order to close the channel, set running to false, etc?
What happens if you don't call that, but the iterator completes?
If we need to call it, I think the pattern:
Needs to be documented explicitly somewhere (unless I am just missing something).
If it's not called, it should just be sort of a leak. The channels won't be flushed or saved, but once all its iterators die, the tracker will still be gc'd. No critical consequences that I foresee, but I will document it.