piece.go | 34 ++++++++++------------------------ torrent.go | 14 ++++++++------ diff --git a/piece.go b/piece.go index 9f22d718b9f918ec309ffc835f500aefa25112bf..bcc09546c11f4f34f3cee0ae03e9f1fb04695694 100644 --- a/piece.go +++ b/piece.go @@ -1,11 +1,9 @@ package torrent import ( - "math/rand" "sync" "github.com/anacrolix/missinggo/bitmap" - "github.com/bradfitz/iter" pp "github.com/anacrolix/torrent/peer_protocol" ) @@ -30,7 +28,9 @@ ) type piece struct { // The completed piece SHA1 hash, from the metainfo "pieces" field. - Hash pieceSum + Hash pieceSum + t *torrent + index int // Chunks we've written to since the last check. The chunk offset and // length can be determined by the request chunkSize in use. DirtyChunks bitmap.Bitmap @@ -77,27 +77,13 @@ } return ret } -func (p *piece) shuffledPendingChunkSpecs(t *torrent, piece int) (css []chunkSpec) { - // defer func() { - // log.Println(piece, css) - // }() - numPending := t.pieceNumPendingChunks(piece) - if numPending == 0 { - return - } - css = make([]chunkSpec, 0, numPending) - for ci := range iter.N(t.pieceNumChunks(piece)) { - if !p.DirtyChunks.Contains(ci) { - css = append(css, t.chunkIndexSpec(ci, piece)) - } - } - if len(css) <= 1 { - return - } - for i := range css { - j := rand.Intn(i + 1) - css[i], css[j] = css[j], css[i] - } +func (p *piece) numChunks() int { + return p.t.pieceNumChunks(p.index) +} + +func (p *piece) undirtiedChunkIndices() (ret bitmap.Bitmap) { + ret = p.DirtyChunks.Copy() + ret.FlipRange(0, p.numChunks()) return } diff --git a/torrent.go b/torrent.go index d1764875bc12188dbf6a2af314d6b10292024ff3..5f7807c8c3f4d6226f11b53a3d871c06f2f41085 100644 --- a/torrent.go +++ b/torrent.go @@ -14,6 +14,7 @@ "time" "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" @@ -252,6 +253,8 @@ hashes := infoPieceHashes(md) t.Pieces = make([]piece, len(hashes)) for i, hash := range hashes { piece := &t.Pieces[i] + piece.t = t + piece.index = i piece.noPendingWrites.L = &piece.pendingWritesMutex missinggo.CopyExact(piece.Hash[:], hash) } @@ -997,12 +1000,11 @@ func (t *torrent) connRequestPiecePendingChunks(c *connection, piece int) (more bool) { if !c.PeerHasPiece(piece) { return true } - for _, cs := range t.Pieces[piece].shuffledPendingChunkSpecs(t, piece) { - req := request{pp.Integer(piece), cs} - if !c.Request(req) { - return false - } - } + chunkIndices := t.Pieces[piece].undirtiedChunkIndices().ToSortedSlice() + return itertools.ForPerm(len(chunkIndices), func(i int) bool { + req := request{pp.Integer(piece), t.chunkIndexSpec(chunkIndices[i], piece)} + return c.Request(req) + }) return true }