Include hashed addr when comparing prioritized peers

In particular, fixes the issue where peers where can't calculate a priority and fallback on 0 clobber each other.
This commit is contained in:
Matt Joiner 2020-04-16 11:59:31 +10:00
parent 5f47e808fb
commit 6a86e9e999
2 changed files with 26 additions and 2 deletions

View File

@ -1,6 +1,8 @@
package torrent package torrent
import ( import (
"hash/maphash"
"github.com/anacrolix/multiless" "github.com/anacrolix/multiless"
"github.com/google/btree" "github.com/google/btree"
) )
@ -12,11 +14,21 @@ type prioritizedPeersItem struct {
p Peer p Peer
} }
var hashSeed = maphash.MakeSeed()
func (me prioritizedPeersItem) addrHash() int64 {
var h maphash.Hash
h.SetSeed(hashSeed)
h.WriteString(me.p.Addr.String())
return int64(h.Sum64())
}
func (me prioritizedPeersItem) Less(than btree.Item) bool { func (me prioritizedPeersItem) Less(than btree.Item) bool {
other := than.(prioritizedPeersItem) other := than.(prioritizedPeersItem)
return multiless.New().Bool( return multiless.New().Bool(
me.p.Trusted, other.p.Trusted).Uint32( me.p.Trusted, other.p.Trusted).Uint32(
me.prio, other.prio, me.prio, other.prio).Int64(
me.addrHash(), other.addrHash(),
).Less() ).Less()
} }
@ -41,6 +53,17 @@ func (me *prioritizedPeers) Add(p Peer) bool {
return me.om.ReplaceOrInsert(prioritizedPeersItem{me.getPrio(p), p}) != nil return me.om.ReplaceOrInsert(prioritizedPeersItem{me.getPrio(p), p}) != nil
} }
// Returns true if a peer is replaced.
func (me *prioritizedPeers) AddReturningReplacedPeer(p Peer) (ret Peer, ok bool) {
item := me.om.ReplaceOrInsert(prioritizedPeersItem{me.getPrio(p), p})
if item == nil {
return
}
ret = item.(prioritizedPeersItem).p
ok = true
return
}
func (me *prioritizedPeers) DeleteMin() (ret prioritizedPeersItem, ok bool) { func (me *prioritizedPeers) DeleteMin() (ret prioritizedPeersItem, ok bool) {
i := me.om.DeleteMin() i := me.om.DeleteMin()
if i == nil { if i == nil {

View File

@ -266,8 +266,9 @@ func (t *Torrent) addPeer(p Peer) {
return return
} }
} }
if t.peers.Add(p) { if replaced, ok := t.peers.AddReturningReplacedPeer(p); ok {
torrent.Add("peers replaced", 1) torrent.Add("peers replaced", 1)
t.logger.Printf("added %v replacing %v", p, replaced)
} }
t.openNewConns() t.openNewConns()
for t.peers.Len() > cl.config.TorrentPeersHighWater { for t.peers.Len() > cl.config.TorrentPeersHighWater {