mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-05-21 23:39:26 +00:00
p2p/discover: add waitForNodes
This commit is contained in:
parent
1f7f95d718
commit
46e4f0b5c1
2 changed files with 40 additions and 14 deletions
|
|
@ -19,7 +19,6 @@ package discover
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/p2p/enode"
|
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||||
)
|
)
|
||||||
|
|
@ -106,11 +105,10 @@ func (it *lookup) startQueries() bool {
|
||||||
// The first query returns nodes from the local table.
|
// The first query returns nodes from the local table.
|
||||||
if it.queries == -1 {
|
if it.queries == -1 {
|
||||||
closest := it.tab.findnodeByID(it.result.target, bucketSize, false)
|
closest := it.tab.findnodeByID(it.result.target, bucketSize, false)
|
||||||
// Avoid finishing the lookup too quickly if table is empty. It'd be better to wait
|
// Avoid finishing the lookup too quickly if table is empty.
|
||||||
// for the table to fill in this case, but there is no good mechanism for that
|
// Wait for the table to fill.
|
||||||
// yet.
|
|
||||||
if len(closest.entries) == 0 {
|
if len(closest.entries) == 0 {
|
||||||
it.slowdown()
|
it.tab.waitForNodes(1)
|
||||||
}
|
}
|
||||||
it.queries = 1
|
it.queries = 1
|
||||||
it.replyCh <- closest.entries
|
it.replyCh <- closest.entries
|
||||||
|
|
@ -130,15 +128,6 @@ func (it *lookup) startQueries() bool {
|
||||||
return it.queries > 0
|
return it.queries > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (it *lookup) slowdown() {
|
|
||||||
sleep := time.NewTimer(1 * time.Second)
|
|
||||||
defer sleep.Stop()
|
|
||||||
select {
|
|
||||||
case <-sleep.C:
|
|
||||||
case <-it.tab.closeReq:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (it *lookup) query(n *enode.Node, reply chan<- []*enode.Node) {
|
func (it *lookup) query(n *enode.Node, reply chan<- []*enode.Node) {
|
||||||
r, err := it.queryfunc(n)
|
r, err := it.queryfunc(n)
|
||||||
if !errors.Is(err, errClosed) { // avoid recording failures on shutdown.
|
if !errors.Is(err, errClosed) { // avoid recording failures on shutdown.
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ import (
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/mclock"
|
"github.com/ethereum/go-ethereum/common/mclock"
|
||||||
|
"github.com/ethereum/go-ethereum/event"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/metrics"
|
"github.com/ethereum/go-ethereum/metrics"
|
||||||
"github.com/ethereum/go-ethereum/p2p/enode"
|
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||||
|
|
@ -84,6 +85,7 @@ type Table struct {
|
||||||
closeReq chan struct{}
|
closeReq chan struct{}
|
||||||
closed chan struct{}
|
closed chan struct{}
|
||||||
|
|
||||||
|
nodeFeed event.FeedOf[*enode.Node]
|
||||||
nodeAddedHook func(*bucket, *tableNode)
|
nodeAddedHook func(*bucket, *tableNode)
|
||||||
nodeRemovedHook func(*bucket, *tableNode)
|
nodeRemovedHook func(*bucket, *tableNode)
|
||||||
}
|
}
|
||||||
|
|
@ -567,6 +569,8 @@ func (tab *Table) nodeAdded(b *bucket, n *tableNode) {
|
||||||
}
|
}
|
||||||
n.addedToBucket = time.Now()
|
n.addedToBucket = time.Now()
|
||||||
tab.revalidation.nodeAdded(tab, n)
|
tab.revalidation.nodeAdded(tab, n)
|
||||||
|
|
||||||
|
tab.nodeFeed.Send(n.Node)
|
||||||
if tab.nodeAddedHook != nil {
|
if tab.nodeAddedHook != nil {
|
||||||
tab.nodeAddedHook(b, n)
|
tab.nodeAddedHook(b, n)
|
||||||
}
|
}
|
||||||
|
|
@ -702,3 +706,36 @@ func (tab *Table) deleteNode(n *enode.Node) {
|
||||||
b := tab.bucket(n.ID())
|
b := tab.bucket(n.ID())
|
||||||
tab.deleteInBucket(b, n.ID())
|
tab.deleteInBucket(b, n.ID())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// waitForNodes blocks until the table contains at least n nodes.
|
||||||
|
func (tab *Table) waitForNodes(n int) bool {
|
||||||
|
getlength := func() (count int) {
|
||||||
|
for _, b := range &tab.buckets {
|
||||||
|
count += len(b.entries)
|
||||||
|
}
|
||||||
|
return count
|
||||||
|
}
|
||||||
|
|
||||||
|
var ch chan *enode.Node
|
||||||
|
for {
|
||||||
|
tab.mutex.Lock()
|
||||||
|
if getlength() >= n {
|
||||||
|
tab.mutex.Unlock()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if ch == nil {
|
||||||
|
// Init subscription.
|
||||||
|
ch = make(chan *enode.Node)
|
||||||
|
sub := tab.nodeFeed.Subscribe(ch)
|
||||||
|
defer sub.Unsubscribe()
|
||||||
|
}
|
||||||
|
tab.mutex.Unlock()
|
||||||
|
|
||||||
|
// Wait for a node add event.
|
||||||
|
select {
|
||||||
|
case <-ch:
|
||||||
|
case <-tab.closeReq:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue