From 63c73e18b3b3ed438fea5666192cff682f4377bc Mon Sep 17 00:00:00 2001 From: Matt Joiner Date: Fri, 5 Feb 2016 01:18:54 +1100 Subject: [PATCH] Add File.Cancel --- file.go | 14 ++++++++++++++ file_test.go | 22 ++++++++++++++++++++++ piece.go | 9 +++++++++ t.go | 10 +++++++--- torrent.go | 42 +++++++++++++++++++++++++++++++++++++++--- 5 files changed, 91 insertions(+), 6 deletions(-) create mode 100644 file_test.go diff --git a/file.go b/file.go index 8e28781b..94d71a1f 100644 --- a/file.go +++ b/file.go @@ -78,3 +78,17 @@ func (f *File) State() (ret []FilePieceState) { func (f *File) Download() { f.t.DownloadPieces(f.t.torrent.byteRegionPieces(f.offset, f.length)) } + +func byteRegionExclusivePieces(off, size, pieceSize int64) (begin, end int) { + begin = int((off + pieceSize - 1) / pieceSize) + end = int((off + size) / pieceSize) + return +} + +func (f *File) exclusivePieces() (begin, end int) { + return byteRegionExclusivePieces(f.offset, f.length, int64(f.t.torrent.usualPieceSize())) +} + +func (f *File) Cancel() { + f.t.CancelPieces(f.exclusivePieces()) +} diff --git a/file_test.go b/file_test.go new file mode 100644 index 00000000..b66d1985 --- /dev/null +++ b/file_test.go @@ -0,0 +1,22 @@ +package torrent + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestFileExclusivePieces(t *testing.T) { + for _, _case := range []struct { + off, size, pieceSize int64 + begin, end int + }{ + {0, 2, 2, 0, 1}, + {1, 2, 2, 1, 1}, + {1, 4, 2, 1, 2}, + } { + begin, end := byteRegionExclusivePieces(_case.off, _case.size, _case.pieceSize) + assert.EqualValues(t, _case.begin, begin) + assert.EqualValues(t, _case.end, end) + } +} diff --git a/piece.go b/piece.go index 16f20653..a56225c1 100644 --- a/piece.go +++ b/piece.go @@ -52,6 +52,15 @@ func (p *piece) pendingChunk(cs chunkSpec, chunkSize pp.Integer) bool { return !p.DirtyChunks[ci] } +func (p *piece) hasDirtyChunks() bool { + for _, dirty := range p.DirtyChunks { + if dirty { + return true + } + } + return false +} + func (p *piece) numDirtyChunks() (ret int) { for _, dirty := range p.DirtyChunks { if dirty { diff --git a/t.go b/t.go index ffb64dd3..6bb10711 100644 --- a/t.go +++ b/t.go @@ -140,7 +140,11 @@ func (t Torrent) deleteReader(r *Reader) { func (t Torrent) DownloadPieces(begin, end int) { t.cl.mu.Lock() defer t.cl.mu.Unlock() - for i := begin; i < end; i++ { - t.torrent.pendPiece(i, t.cl) - } + t.torrent.pendPieceRange(begin, end) +} + +func (t Torrent) CancelPieces(begin, end int) { + t.cl.mu.Lock() + defer t.cl.mu.Unlock() + t.torrent.unpendPieceRange(begin, end) } diff --git a/torrent.go b/torrent.go index fd462e1f..1d465957 100644 --- a/torrent.go +++ b/torrent.go @@ -508,9 +508,14 @@ func (t *torrent) bytesLeft() (left int64) { return } -func (t *torrent) piecePartiallyDownloaded(index int) bool { - pendingBytes := t.pieceNumPendingBytes(index) - return pendingBytes != 0 && pendingBytes != t.pieceLength(index) +func (t *torrent) piecePartiallyDownloaded(piece int) bool { + if t.pieceComplete(piece) { + return false + } + if t.pieceAllDirty(piece) { + return true + } + return t.Pieces[piece].hasDirtyChunks() } func numChunksForPiece(chunkSize int, pieceSize int) int { @@ -976,6 +981,37 @@ func (t *torrent) pendPiece(piece int, cl *Client) { t.piecePriorityChanged(piece) } +func (t *torrent) getCompletedPieces() (ret bitmap.Bitmap) { + for i := range iter.N(t.numPieces()) { + if t.pieceComplete(i) { + ret.Add(i) + } + } + return +} + +func (t *torrent) pendPieces(pend *bitmap.Bitmap) { + t.pendingPieces.Union(pend) + t.updatePiecePriorities() +} + +func (t *torrent) unpendPieces(unpend *bitmap.Bitmap) { + t.pendingPieces.Sub(unpend) + t.updatePiecePriorities() +} + +func (t *torrent) pendPieceRange(begin, end int) { + var bm bitmap.Bitmap + bm.AddRange(begin, end) + t.pendPieces(&bm) +} + +func (t *torrent) unpendPieceRange(begin, end int) { + var bm bitmap.Bitmap + bm.AddRange(begin, end) + t.unpendPieces(&bm) +} + func (t *torrent) connRequestPiecePendingChunks(c *connection, piece int) (more bool) { if !c.PeerHasPiece(piece) { return true