mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-05-14 12:06:40 +00:00
p2p/discover: improve iterator
This commit is contained in:
parent
f4046b0cfb
commit
4ed8f5ee2b
1 changed files with 26 additions and 22 deletions
|
|
@ -49,11 +49,14 @@ func newLookup(ctx context.Context, tab *Table, target enode.ID, q queryFunc) *l
|
||||||
result: nodesByDistance{target: target},
|
result: nodesByDistance{target: target},
|
||||||
replyCh: make(chan []*enode.Node, alpha),
|
replyCh: make(chan []*enode.Node, alpha),
|
||||||
cancelCh: ctx.Done(),
|
cancelCh: ctx.Done(),
|
||||||
queries: -1,
|
|
||||||
}
|
}
|
||||||
// Don't query further if we hit ourself.
|
// Don't query further if we hit ourself.
|
||||||
// Unlikely to happen often in practice.
|
// Unlikely to happen often in practice.
|
||||||
it.asked[tab.self().ID()] = true
|
it.asked[tab.self().ID()] = true
|
||||||
|
|
||||||
|
// Initialize the lookup with nodes from table.
|
||||||
|
closest := it.tab.findnodeByID(it.result.target, bucketSize, false)
|
||||||
|
it.addNodes(closest.entries)
|
||||||
return it
|
return it
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -64,22 +67,18 @@ func (it *lookup) run() []*enode.Node {
|
||||||
return it.result.entries
|
return it.result.entries
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (it *lookup) empty() bool {
|
||||||
|
return len(it.replyBuffer) == 0
|
||||||
|
}
|
||||||
|
|
||||||
// advance advances the lookup until any new nodes have been found.
|
// advance advances the lookup until any new nodes have been found.
|
||||||
// It returns false when the lookup has ended.
|
// It returns false when the lookup has ended.
|
||||||
func (it *lookup) advance() bool {
|
func (it *lookup) advance() bool {
|
||||||
for it.startQueries() {
|
for it.startQueries() {
|
||||||
select {
|
select {
|
||||||
case nodes := <-it.replyCh:
|
case nodes := <-it.replyCh:
|
||||||
it.replyBuffer = it.replyBuffer[:0]
|
|
||||||
for _, n := range nodes {
|
|
||||||
if n != nil && !it.seen[n.ID()] {
|
|
||||||
it.seen[n.ID()] = true
|
|
||||||
it.result.push(n, bucketSize)
|
|
||||||
it.replyBuffer = append(it.replyBuffer, n)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
it.queries--
|
it.queries--
|
||||||
if len(it.replyBuffer) > 0 {
|
if it.addNodes(nodes) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
case <-it.cancelCh:
|
case <-it.cancelCh:
|
||||||
|
|
@ -89,6 +88,18 @@ func (it *lookup) advance() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (it *lookup) addNodes(nodes []*enode.Node) (done bool) {
|
||||||
|
it.replyBuffer = it.replyBuffer[:0]
|
||||||
|
for _, n := range nodes {
|
||||||
|
if n != nil && !it.seen[n.ID()] {
|
||||||
|
it.seen[n.ID()] = true
|
||||||
|
it.result.push(n, bucketSize)
|
||||||
|
it.replyBuffer = append(it.replyBuffer, n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return len(it.replyBuffer) == 0
|
||||||
|
}
|
||||||
|
|
||||||
func (it *lookup) shutdown() {
|
func (it *lookup) shutdown() {
|
||||||
for it.queries > 0 {
|
for it.queries > 0 {
|
||||||
<-it.replyCh
|
<-it.replyCh
|
||||||
|
|
@ -103,17 +114,6 @@ func (it *lookup) startQueries() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// The first query returns nodes from the local table.
|
|
||||||
if it.queries == -1 {
|
|
||||||
closest := it.tab.findnodeByID(it.result.target, bucketSize, false)
|
|
||||||
if len(closest.entries) == 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
it.queries = 1
|
|
||||||
it.replyCh <- closest.entries
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ask the closest nodes that we haven't asked yet.
|
// Ask the closest nodes that we haven't asked yet.
|
||||||
for i := 0; i < len(it.result.entries) && it.queries < alpha; i++ {
|
for i := 0; i < len(it.result.entries) && it.queries < alpha; i++ {
|
||||||
n := it.result.entries[i]
|
n := it.result.entries[i]
|
||||||
|
|
@ -180,10 +180,14 @@ func (it *lookupIterator) Next() bool {
|
||||||
}
|
}
|
||||||
if it.lookup == nil {
|
if it.lookup == nil {
|
||||||
it.lookup = it.nextLookup(it.ctx)
|
it.lookup = it.nextLookup(it.ctx)
|
||||||
|
if it.lookup.empty() {
|
||||||
|
// If the lookup is empty right after creation, it means the local table
|
||||||
|
// is in a degraded state, and we need to wait for it to fill again.
|
||||||
|
it.lookupFailed(it.lookup.tab)
|
||||||
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if !it.lookup.advance() {
|
if !it.lookup.advance() {
|
||||||
it.lookupFailed(it.lookup.tab)
|
|
||||||
it.lookup = nil
|
it.lookup = nil
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue