]> Sergey Matveev's repositories - btrtrc.git/blobdiff - worse-conns.go
Drop support for go 1.20
[btrtrc.git] / worse-conns.go
index 00a9b906a26b76780c0e6ac512db6de103f27bfa..ef33b97902c4cd82f07b3a76f71f1f631a2ce821 100644 (file)
@@ -3,30 +3,75 @@ package torrent
 import (
        "container/heap"
        "fmt"
+       "time"
        "unsafe"
 
        "github.com/anacrolix/multiless"
+       "github.com/anacrolix/sync"
 )
 
-func worseConn(l, r *Peer) bool {
+type worseConnInput struct {
+       BadDirection        bool
+       Useful              bool
+       LastHelpful         time.Time
+       CompletedHandshake  time.Time
+       GetPeerPriority     func() (peerPriority, error)
+       getPeerPriorityOnce sync.Once
+       peerPriority        peerPriority
+       peerPriorityErr     error
+       Pointer             uintptr
+}
+
+func (me *worseConnInput) doGetPeerPriority() {
+       me.peerPriority, me.peerPriorityErr = me.GetPeerPriority()
+}
+
+func (me *worseConnInput) doGetPeerPriorityOnce() {
+       me.getPeerPriorityOnce.Do(me.doGetPeerPriority)
+}
+
+type worseConnLensOpts struct {
+       incomingIsBad, outgoingIsBad bool
+}
+
+func worseConnInputFromPeer(p *PeerConn, opts worseConnLensOpts) worseConnInput {
+       ret := worseConnInput{
+               Useful:             p.useful(),
+               LastHelpful:        p.lastHelpful(),
+               CompletedHandshake: p.completedHandshake,
+               Pointer:            uintptr(unsafe.Pointer(p)),
+               GetPeerPriority:    p.peerPriority,
+       }
+       if opts.incomingIsBad && !p.outgoing {
+               ret.BadDirection = true
+       } else if opts.outgoingIsBad && p.outgoing {
+               ret.BadDirection = true
+       }
+       return ret
+}
+
+func (l *worseConnInput) Less(r *worseConnInput) bool {
        less, ok := multiless.New().Bool(
-               l.useful(), r.useful()).CmpInt64(
-               l.lastHelpful().Sub(r.lastHelpful()).Nanoseconds()).CmpInt64(
-               l.completedHandshake.Sub(r.completedHandshake).Nanoseconds()).LazySameLess(
+               r.BadDirection, l.BadDirection).Bool(
+               l.Useful, r.Useful).CmpInt64(
+               l.LastHelpful.Sub(r.LastHelpful).Nanoseconds()).CmpInt64(
+               l.CompletedHandshake.Sub(r.CompletedHandshake).Nanoseconds()).LazySameLess(
                func() (same, less bool) {
-                       lpp, err := l.peerPriority()
-                       if err != nil {
+                       l.doGetPeerPriorityOnce()
+                       if l.peerPriorityErr != nil {
                                same = true
                                return
                        }
-                       rpp, err := r.peerPriority()
-                       if err != nil {
+                       r.doGetPeerPriorityOnce()
+                       if r.peerPriorityErr != nil {
                                same = true
                                return
                        }
-                       return lpp == rpp, lpp < rpp
+                       same = l.peerPriority == r.peerPriority
+                       less = l.peerPriority < r.peerPriority
+                       return
                }).Uintptr(
-               uintptr(unsafe.Pointer(l)), uintptr(unsafe.Pointer(r)),
+               l.Pointer, r.Pointer,
        ).LessOk()
        if !ok {
                panic(fmt.Sprintf("cannot differentiate %#v and %#v", l, r))
@@ -36,6 +81,14 @@ func worseConn(l, r *Peer) bool {
 
 type worseConnSlice struct {
        conns []*PeerConn
+       keys  []worseConnInput
+}
+
+func (me *worseConnSlice) initKeys(opts worseConnLensOpts) {
+       me.keys = make([]worseConnInput, len(me.conns))
+       for i, c := range me.conns {
+               me.keys[i] = worseConnInputFromPeer(c, opts)
+       }
 }
 
 var _ heap.Interface = &worseConnSlice{}
@@ -45,7 +98,7 @@ func (me worseConnSlice) Len() int {
 }
 
 func (me worseConnSlice) Less(i, j int) bool {
-       return worseConn(&me.conns[i].Peer, &me.conns[j].Peer)
+       return me.keys[i].Less(&me.keys[j])
 }
 
 func (me *worseConnSlice) Pop() interface{} {
@@ -56,9 +109,10 @@ func (me *worseConnSlice) Pop() interface{} {
 }
 
 func (me *worseConnSlice) Push(x interface{}) {
-       me.conns = append(me.conns, x.(*PeerConn))
+       panic("not implemented")
 }
 
 func (me worseConnSlice) Swap(i, j int) {
        me.conns[i], me.conns[j] = me.conns[j], me.conns[i]
+       me.keys[i], me.keys[j] = me.keys[j], me.keys[i]
 }