reader.go | 11 ++++++----- t.go | 2 +- torrent.go | 38 +++++++++++++++++++++++++++++++++++--- torrent_test.go | 2 +- diff --git a/reader.go b/reader.go index 3f22c6c656548c0804a2953b7bad8141d7de65ea..b3b6fd9be6ac099640770327fa0e45f9b6a88b0f 100644 --- a/reader.go +++ b/reader.go @@ -202,7 +202,7 @@ } log.Printf("error reading torrent %q piece %d offset %d, %d bytes: %s", r.t, pi, po, len(b1), err) r.t.cl.mu.Lock() r.t.updateAllPieceCompletions() - r.t.updatePiecePriorities() + r.t.updateAllPiecePriorities() r.t.cl.mu.Unlock() } } @@ -214,12 +214,13 @@ return nil } func (r *Reader) posChanged() { - p := r.piecesUncached() - if p == r.pieces { + to := r.piecesUncached() + from := r.pieces + if to == from { return } - r.pieces = p - r.t.readersChanged() + r.pieces = to + r.t.readerPosChanged(from, to) } func (r *Reader) Seek(off int64, whence int) (ret int64, err error) { diff --git a/t.go b/t.go index 138770ea7257566c4b40a191713580a17ac52253..b17226be9b16d7269564f31b1f84b25aa8cb8184 100644 --- a/t.go +++ b/t.go @@ -132,7 +132,7 @@ if t.readers == nil { t.readers = make(map[*Reader]struct{}) } t.readers[r] = struct{}{} - t.readersChanged() + r.posChanged() } func (t *Torrent) deleteReader(r *Reader) { diff --git a/torrent.go b/torrent.go index c8514654c4751f7f00a1aad1fa467f6bb3f416e6..d53efb0acb96ec75fe4ebc17b84e9b53cb755cd2 100644 --- a/torrent.go +++ b/torrent.go @@ -835,8 +835,36 @@ }) } func (t *Torrent) readersChanged() { + t.updateReaderPieces() + t.updateAllPiecePriorities() +} + +func (t *Torrent) updateReaderPieces() { t.readerNowPieces, t.readerReadaheadPieces = t.readerPiecePriorities() - t.updatePiecePriorities() +} + +func (t *Torrent) readerPosChanged(from, to pieceRange) { + if from == to { + return + } + t.updateReaderPieces() + // Order the ranges, high and low. + l, h := from, to + if l.begin > h.begin { + l, h = h, l + } + if l.end < h.begin { + // Two distinct ranges. + t.updatePiecePriorities(l.begin, l.end) + t.updatePiecePriorities(h.begin, h.end) + } else { + // Ranges overlap. + end := l.end + if h.end > end { + end = h.end + } + t.updatePiecePriorities(l.begin, end) + } } func (t *Torrent) maybeNewConns() { @@ -863,10 +891,14 @@ p.priority = newPrio t.piecePriorityChanged(piece) } +func (t *Torrent) updateAllPiecePriorities() { + t.updatePiecePriorities(0, len(t.pieces)) +} + // Update all piece priorities in one hit. This function should have the same // output as updatePiecePriority, but across all pieces. -func (t *Torrent) updatePiecePriorities() { - for i := range t.pieces { +func (t *Torrent) updatePiecePriorities(begin, end int) { + for i := begin; i < end; i++ { t.updatePiecePriority(i) } } diff --git a/torrent_test.go b/torrent_test.go index 0cf213ad20982f530455d746f09737c69f48c5ba..a0d0857c69ce972abd490202bdafa01accb59197 100644 --- a/torrent_test.go +++ b/torrent_test.go @@ -92,7 +92,7 @@ for i := 0; i < t.numPieces(); i += 3 { t.completedPieces.Set(i, true) } for range iter.N(b.N) { - t.updatePiecePriorities() + t.updateAllPiecePriorities() } }