diff --git a/reader.go b/reader.go index 3f22c6c6..b3b6fd9b 100644 --- a/reader.go +++ b/reader.go @@ -202,7 +202,7 @@ func (r *Reader) readOnceAt(b []byte, pos int64, ctxErr *error) (n int, err erro 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 @@ func (r *Reader) Close() error { } 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 138770ea..b17226be 100644 --- a/t.go +++ b/t.go @@ -132,7 +132,7 @@ func (t *Torrent) addReader(r *Reader) { 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 c8514654..d53efb0a 100644 --- a/torrent.go +++ b/torrent.go @@ -835,8 +835,36 @@ func (t *Torrent) forUrgentPieces(f func(piece int) (again bool)) (all bool) { } 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 @@ func (t *Torrent) updatePiecePriority(piece int) { 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 0cf213ad..a0d0857c 100644 --- a/torrent_test.go +++ b/torrent_test.go @@ -92,7 +92,7 @@ func BenchmarkUpdatePiecePriorities(b *testing.B) { t.completedPieces.Set(i, true) } for range iter.N(b.N) { - t.updatePiecePriorities() + t.updateAllPiecePriorities() } }