@ -455,24 +455,31 @@ func (tab *Table) ping(id NodeID, addr *net.UDPAddr) error {
func ( tab * Table ) add ( new * Node ) {
func ( tab * Table ) add ( new * Node ) {
b := tab . buckets [ logdist ( tab . self . sha , new . sha ) ]
b := tab . buckets [ logdist ( tab . self . sha , new . sha ) ]
tab . mutex . Lock ( )
tab . mutex . Lock ( )
defer tab . mutex . Unlock ( )
if b . bump ( new ) {
if b . bump ( new ) {
tab . mutex . Unlock ( )
return
return
}
}
var oldest * Node
var oldest * Node
if len ( b . entries ) == bucketSize {
if len ( b . entries ) == bucketSize {
oldest = b . entries [ bucketSize - 1 ]
oldest = b . entries [ bucketSize - 1 ]
if oldest . contested {
// The node is already being replaced, don't attempt
// to replace it.
return
}
oldest . contested = true
// Let go of the mutex so other goroutines can access
// Let go of the mutex so other goroutines can access
// the table while we ping the least recently active node.
// the table while we ping the least recently active node.
tab . mutex . Unlock ( )
tab . mutex . Unlock ( )
if err := tab . ping ( oldest . ID , oldest . addr ( ) ) ; err == nil {
err := tab . ping ( oldest . ID , oldest . addr ( ) )
tab . mutex . Lock ( )
oldest . contested = false
if err == nil {
// The node responded, don't replace it.
// The node responded, don't replace it.
return
return
}
}
tab . mutex . Lock ( )
}
}
added := b . replace ( new , oldest )
added := b . replace ( new , oldest )
tab . mutex . Unlock ( )
if added && tab . nodeAddedHook != nil {
if added && tab . nodeAddedHook != nil {
tab . nodeAddedHook ( new )
tab . nodeAddedHook ( new )
}
}