9 "github.com/anacrolix/multiless"
10 "github.com/anacrolix/sync"
13 type worseConnInput struct {
17 CompletedHandshake time.Time
18 GetPeerPriority func() (peerPriority, error)
19 getPeerPriorityOnce sync.Once
20 peerPriority peerPriority
25 func (me *worseConnInput) doGetPeerPriority() {
26 me.peerPriority, me.peerPriorityErr = me.GetPeerPriority()
29 func (me *worseConnInput) doGetPeerPriorityOnce() {
30 me.getPeerPriorityOnce.Do(me.doGetPeerPriority)
33 type worseConnLensOpts struct {
34 incomingIsBad, outgoingIsBad bool
37 func worseConnInputFromPeer(p *Peer, opts worseConnLensOpts) worseConnInput {
38 ret := worseConnInput{
40 LastHelpful: p.lastHelpful(),
41 CompletedHandshake: p.completedHandshake,
42 Pointer: uintptr(unsafe.Pointer(p)),
43 GetPeerPriority: p.peerPriority,
45 if opts.incomingIsBad && !p.outgoing {
46 ret.BadDirection = true
47 } else if opts.outgoingIsBad && p.outgoing {
48 ret.BadDirection = true
53 func worseConn(_l, _r *Peer) bool {
54 // TODO: Use generics for ptr to
55 l := worseConnInputFromPeer(_l, worseConnLensOpts{})
56 r := worseConnInputFromPeer(_r, worseConnLensOpts{})
60 func (l *worseConnInput) Less(r *worseConnInput) bool {
61 less, ok := multiless.New().Bool(
62 r.BadDirection, l.BadDirection).Bool(
63 l.Useful, r.Useful).CmpInt64(
64 l.LastHelpful.Sub(r.LastHelpful).Nanoseconds()).CmpInt64(
65 l.CompletedHandshake.Sub(r.CompletedHandshake).Nanoseconds()).LazySameLess(
66 func() (same, less bool) {
67 l.doGetPeerPriorityOnce()
68 if l.peerPriorityErr != nil {
72 r.doGetPeerPriorityOnce()
73 if r.peerPriorityErr != nil {
77 same = l.peerPriority == r.peerPriority
78 less = l.peerPriority < r.peerPriority
84 panic(fmt.Sprintf("cannot differentiate %#v and %#v", l, r))
89 type worseConnSlice struct {
94 func (me *worseConnSlice) initKeys(opts worseConnLensOpts) {
95 me.keys = make([]worseConnInput, len(me.conns))
96 for i, c := range me.conns {
97 me.keys[i] = worseConnInputFromPeer(&c.Peer, opts)
101 var _ heap.Interface = &worseConnSlice{}
103 func (me worseConnSlice) Len() int {
107 func (me worseConnSlice) Less(i, j int) bool {
108 return me.keys[i].Less(&me.keys[j])
111 func (me *worseConnSlice) Pop() interface{} {
112 i := len(me.conns) - 1
114 me.conns = me.conns[:i]
118 func (me *worseConnSlice) Push(x interface{}) {
119 panic("not implemented")
122 func (me worseConnSlice) Swap(i, j int) {
123 me.conns[i], me.conns[j] = me.conns[j], me.conns[i]
124 me.keys[i], me.keys[j] = me.keys[j], me.keys[i]