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())
+}
--- /dev/null
+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)
+ }
+}
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 {
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)
}
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 {
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