torrent.go | 11 ++++++++--- worst_conns.go | 39 +++++++++++++++++++++++++++++---------- diff --git a/torrent.go b/torrent.go index 5d6b66b77190a9831d522bda390d8570241abb61..771933838cf4ceb53d12bd1cb23d82236e37265e 100644 --- a/torrent.go +++ b/torrent.go @@ -70,8 +70,10 @@ metadataHave []bool } func (t *torrent) worstConnsHeap() (wcs *worstConns) { - wcs = new(worstConns) - *wcs = append([]*connection{}, t.Conns...) + wcs = &worstConns{ + c: append([]*connection{}, t.Conns...), + t: t, + } heap.Init(wcs) return } @@ -292,7 +294,10 @@ } fmt.Fprintln(w) fmt.Fprintf(w, "Pending peers: %d\n", len(t.Peers)) fmt.Fprintf(w, "Active peers: %d\n", len(t.Conns)) - sort.Sort(worstConns(t.Conns)) + sort.Sort(&worstConns{ + c: t.Conns, + t: t, + }) for _, c := range t.Conns { c.WriteStatus(w) } diff --git a/worst_conns.go b/worst_conns.go index a1bf326bf8647c85fa14925cba471084adce8f9b..3b26c18f65e04211459795816d947c9a60895994 100644 --- a/worst_conns.go +++ b/worst_conns.go @@ -5,33 +5,52 @@ "time" ) // Implements heap functions such that [0] is the worst connection. -type worstConns []*connection +type worstConns struct { + c []*connection + t *torrent +} -func (me worstConns) Len() int { return len(me) } -func (me worstConns) Swap(i, j int) { me[i], me[j] = me[j], me[i] } +func (me worstConns) Len() int { return len(me.c) } +func (me worstConns) Swap(i, j int) { me.c[i], me.c[j] = me.c[j], me.c[i] } func (me *worstConns) Pop() (ret interface{}) { - old := *me + old := me.c n := len(old) ret = old[n-1] - *me = old[:n-1] + me.c = old[:n-1] return } func (me *worstConns) Push(x interface{}) { - *me = append(*me, x.(*connection)) + me.c = append(me.c, x.(*connection)) +} + +type worstConnsSortKey struct { + level int + age time.Duration +} + +func (me worstConnsSortKey) Less(other worstConnsSortKey) bool { + if me.level != other.level { + return me.level > other.level + } + return me.age > other.age } -func (me worstConns) key(i int) (ret time.Duration) { - c := me[i] - return time.Duration(1+c.UnwantedChunksReceived) * time.Now().Sub(func() time.Time { +func (me worstConns) key(i int) (key worstConnsSortKey) { + c := me.c[i] + if time.Now().Sub(c.completedHandshake) >= 30*time.Second && !me.t.connHasWantedPieces(c) { + key.level = 1 + } + key.age = time.Duration(1+3*c.UnwantedChunksReceived) * time.Now().Sub(func() time.Time { if !c.lastUsefulChunkReceived.IsZero() { return c.lastUsefulChunkReceived } return c.completedHandshake.Add(-time.Minute) }()) / time.Duration(1+c.UsefulChunksReceived) + return } func (me worstConns) Less(i, j int) bool { - return me.key(i) > me.key(j) + return me.key(i).Less(me.key(j)) }