| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 |
- package torrent
- import (
- "container/heap"
- "fmt"
- "time"
- "unsafe"
- "github.com/anacrolix/multiless"
- "github.com/anacrolix/sync"
- )
- 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(
- 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) {
- l.doGetPeerPriorityOnce()
- if l.peerPriorityErr != nil {
- same = true
- return
- }
- r.doGetPeerPriorityOnce()
- if r.peerPriorityErr != nil {
- same = true
- return
- }
- same = l.peerPriority == r.peerPriority
- less = l.peerPriority < r.peerPriority
- return
- }).Uintptr(
- l.Pointer, r.Pointer,
- ).LessOk()
- if !ok {
- panic(fmt.Sprintf("cannot differentiate %#v and %#v", l, r))
- }
- return less
- }
- 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)(nil)
- func (me *worseConnSlice) Len() int {
- return len(me.conns)
- }
- func (me *worseConnSlice) Less(i, j int) bool {
- return me.keys[i].Less(me.keys[j])
- }
- func (me *worseConnSlice) Pop() interface{} {
- i := len(me.conns) - 1
- ret := me.conns[i]
- me.conns = me.conns[:i]
- return ret
- }
- func (me *worseConnSlice) Push(x interface{}) {
- 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]
- }
|