From: Matt Joiner <anacrolix@gmail.com>
Date: Mon, 1 Feb 2016 11:06:13 +0000 (+1100)
Subject: Recalculate all piece priorities more efficiently
X-Git-Tag: v1.0.0~927
X-Git-Url: http://www.git.stargrave.org/?a=commitdiff_plain;h=430f26f726f92bd475044337888067f7d07fa8d1;p=btrtrc.git

Recalculate all piece priorities more efficiently
---

diff --git a/client.go b/client.go
index 2def4f90..8a611bae 100644
--- a/client.go
+++ b/client.go
@@ -1672,8 +1672,9 @@ func (t *torrent) needData() bool {
 	if !t.haveInfo() {
 		return true
 	}
-	for i := t.pendingPieces.Iter(); i.Next(); {
-		if t.wantPiece(i.Value()) {
+	for i := t.pendingPieces.IterTyped(); i.Next(); {
+		if t.wantPiece(i.ValueInt()) {
+			i.Stop()
 			return true
 		}
 	}
diff --git a/piece.go b/piece.go
index 843ddb9e..16f20653 100644
--- a/piece.go
+++ b/piece.go
@@ -13,6 +13,12 @@ import (
 
 type piecePriority byte
 
+func (me *piecePriority) Raise(maybe piecePriority) {
+	if maybe > *me {
+		*me = maybe
+	}
+}
+
 const (
 	PiecePriorityNone      piecePriority = iota // Not wanted.
 	PiecePriorityNormal                         // Wanted.
diff --git a/torrent.go b/torrent.go
index b50db665..48fce3ff 100644
--- a/torrent.go
+++ b/torrent.go
@@ -14,6 +14,7 @@ import (
 
 	"github.com/anacrolix/missinggo"
 	"github.com/anacrolix/missinggo/bitmap"
+	"github.com/anacrolix/missinggo/itertools"
 	"github.com/anacrolix/missinggo/perf"
 	"github.com/anacrolix/missinggo/pubsub"
 	"github.com/bradfitz/iter"
@@ -762,8 +763,9 @@ func (t *torrent) forNeededPieces(f func(piece int) (more bool)) (all bool) {
 }
 
 func (t *torrent) connHasWantedPieces(c *connection) bool {
-	for it := t.pendingPieces.Iter(); it.Next(); {
-		if c.PeerHasPiece(it.Value()) {
+	for it := t.pendingPieces.IterTyped(); it.Next(); {
+		if c.PeerHasPiece(it.ValueInt()) {
+			it.Stop()
 			return true
 		}
 	}
@@ -870,15 +872,26 @@ func (t *torrent) updatePiecePriority(piece int) bool {
 }
 
 func (t *torrent) updatePiecePriorities() {
-	for i := range t.Pieces {
-		if t.updatePiecePriority(i) {
+	newPrios := make([]piecePriority, t.numPieces())
+	itertools.ForIterable(&t.pendingPieces, func(value interface{}) (next bool) {
+		newPrios[value.(int)] = PiecePriorityNormal
+		return true
+	})
+	t.forReaderOffsetPieces(func(begin, end int) (next bool) {
+		if begin < end {
+			newPrios[begin].Raise(PiecePriorityNow)
+		}
+		for i := begin + 1; i < end; i++ {
+			newPrios[begin].Raise(PiecePriorityReadahead)
+		}
+		return true
+	})
+	for i, prio := range newPrios {
+		if prio != t.Pieces[i].priority {
+			t.Pieces[i].priority = prio
 			t.piecePriorityChanged(i)
 		}
 	}
-	for _, c := range t.Conns {
-		c.updateRequests()
-	}
-	t.maybeNewConns()
 }
 
 func (t *torrent) byteRegionPieces(off, size int64) (begin, end int) {
@@ -935,11 +948,7 @@ func (t *torrent) piecePriorityUncached(piece int) (ret piecePriority) {
 	if t.pendingPieces.Contains(piece) {
 		ret = PiecePriorityNormal
 	}
-	raiseRet := func(prio piecePriority) {
-		if prio > ret {
-			ret = prio
-		}
-	}
+	raiseRet := ret.Raise
 	t.forReaderOffsetPieces(func(begin, end int) (again bool) {
 		if piece == begin {
 			raiseRet(PiecePriorityNow)