prioritized-peers.go 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. package torrent
  2. import (
  3. "hash/maphash"
  4. "github.com/anacrolix/multiless"
  5. "github.com/google/btree"
  6. )
  7. // Peers are stored with their priority at insertion. Their priority may
  8. // change if our apparent IP changes, we don't currently handle that.
  9. type prioritizedPeersItem struct {
  10. prio peerPriority
  11. p PeerInfo
  12. }
  13. var hashSeed = maphash.MakeSeed()
  14. func (me prioritizedPeersItem) addrHash() int64 {
  15. var h maphash.Hash
  16. h.SetSeed(hashSeed)
  17. h.WriteString(me.p.Addr.String())
  18. return int64(h.Sum64())
  19. }
  20. func (me prioritizedPeersItem) Less(than btree.Item) bool {
  21. other := than.(prioritizedPeersItem)
  22. return multiless.New().Bool(
  23. me.p.Trusted, other.p.Trusted).Uint32(
  24. me.prio, other.prio).Int64(
  25. me.addrHash(), other.addrHash(),
  26. ).Less()
  27. }
  28. type prioritizedPeers struct {
  29. om *btree.BTree
  30. getPrio func(PeerInfo) peerPriority
  31. }
  32. func (me *prioritizedPeers) Each(f func(PeerInfo)) {
  33. me.om.Ascend(func(i btree.Item) bool {
  34. f(i.(prioritizedPeersItem).p)
  35. return true
  36. })
  37. }
  38. func (me *prioritizedPeers) Len() int {
  39. if me == nil || me.om == nil {
  40. return 0
  41. }
  42. return me.om.Len()
  43. }
  44. // Returns true if a peer is replaced.
  45. func (me *prioritizedPeers) Add(p PeerInfo) bool {
  46. return me.om.ReplaceOrInsert(prioritizedPeersItem{me.getPrio(p), p}) != nil
  47. }
  48. // Returns true if a peer is replaced.
  49. func (me *prioritizedPeers) AddReturningReplacedPeer(p PeerInfo) (ret PeerInfo, ok bool) {
  50. item := me.om.ReplaceOrInsert(prioritizedPeersItem{me.getPrio(p), p})
  51. if item == nil {
  52. return
  53. }
  54. ret = item.(prioritizedPeersItem).p
  55. ok = true
  56. return
  57. }
  58. func (me *prioritizedPeers) DeleteMin() (ret prioritizedPeersItem, ok bool) {
  59. i := me.om.DeleteMin()
  60. if i == nil {
  61. return
  62. }
  63. ret = i.(prioritizedPeersItem)
  64. ok = true
  65. return
  66. }
  67. func (me *prioritizedPeers) PopMax() PeerInfo {
  68. return me.om.DeleteMax().(prioritizedPeersItem).p
  69. }