Skip to content

Commit dd54fef

Browse files
committed
p2p/discover: don't attempt to replace nodes that are being replaced
PR #1621 changed Table locking so the mutex is not held while a contested node is being pinged. If multiple nodes ping the local node during this time window, multiple ping packets will be sent to the contested node. The changes in this commit prevent multiple packets by tracking whether the node is being replaced.
1 parent edccc7a commit dd54fef

File tree

2 files changed

+15
-4
lines changed

2 files changed

+15
-4
lines changed

p2p/discover/node.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ type Node struct {
4848
// In those tests, the content of sha will not actually correspond
4949
// with ID.
5050
sha common.Hash
51+
52+
// whether this node is currently being pinged in order to replace
53+
// it in a bucket
54+
contested bool
5155
}
5256

5357
func newNode(id NodeID, ip net.IP, udpPort, tcpPort uint16) *Node {

p2p/discover/table.go

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -455,24 +455,31 @@ func (tab *Table) ping(id NodeID, addr *net.UDPAddr) error {
455455
func (tab *Table) add(new *Node) {
456456
b := tab.buckets[logdist(tab.self.sha, new.sha)]
457457
tab.mutex.Lock()
458+
defer tab.mutex.Unlock()
458459
if b.bump(new) {
459-
tab.mutex.Unlock()
460460
return
461461
}
462462
var oldest *Node
463463
if len(b.entries) == bucketSize {
464464
oldest = b.entries[bucketSize-1]
465+
if oldest.contested {
466+
// The node is already being replaced, don't attempt
467+
// to replace it.
468+
return
469+
}
470+
oldest.contested = true
465471
// Let go of the mutex so other goroutines can access
466472
// the table while we ping the least recently active node.
467473
tab.mutex.Unlock()
468-
if err := tab.ping(oldest.ID, oldest.addr()); err == nil {
474+
err := tab.ping(oldest.ID, oldest.addr())
475+
tab.mutex.Lock()
476+
oldest.contested = false
477+
if err == nil {
469478
// The node responded, don't replace it.
470479
return
471480
}
472-
tab.mutex.Lock()
473481
}
474482
added := b.replace(new, oldest)
475-
tab.mutex.Unlock()
476483
if added && tab.nodeAddedHook != nil {
477484
tab.nodeAddedHook(new)
478485
}

0 commit comments

Comments
 (0)