From: i96751414 Date: Tue, 26 Nov 2019 00:54:26 +0000 (+0000) Subject: Add BytesCompleted method for files (#347) X-Git-Tag: v1.10.0~7 X-Git-Url: http://www.git.stargrave.org/?a=commitdiff_plain;h=f22acca80406929d414ef0d16c223da508d405a6;p=btrtrc.git Add BytesCompleted method for files (#347) * Add BytesCompleted method for files * Make sure we check limit pieces correctly * Remove unnecessary info check --- diff --git a/file.go b/file.go index 15f5e239..4775b4ff 100644 --- a/file.go +++ b/file.go @@ -3,7 +3,10 @@ package torrent import ( "strings" + "github.com/anacrolix/missinggo/bitmap" + "github.com/anacrolix/torrent/metainfo" + pp "github.com/anacrolix/torrent/peer_protocol" ) // Provides access to regions of torrent data that correspond to its files. @@ -40,6 +43,46 @@ func (f *File) Length() int64 { return f.length } +// Number of bytes of the entire file we have completed. This is the sum of +// completed pieces, and dirtied chunks of incomplete pieces. +func (f *File) BytesCompleted() int64 { + f.t.cl.rLock() + defer f.t.cl.rUnlock() + return f.bytesCompleted() +} + +func (f *File) bytesCompleted() int64 { + return f.length - f.bytesLeft() +} + +func (f *File) bytesLeft() (left int64) { + firstPieceIndex := f.firstPieceIndex() + endPieceIndex := f.endPieceIndex() + bitmap.Flip(f.t.completedPieces, firstPieceIndex, endPieceIndex+1).IterTyped(func(piece int) bool { + p := &f.t.pieces[piece] + left += int64(p.length() - p.numDirtyBytes()) + return true + }) + startPiece := f.t.piece(firstPieceIndex) + endChunk := int(f.offset%f.t.info.PieceLength) * int(startPiece.numChunks()) / int(startPiece.length()) + bitmap.Flip(startPiece.dirtyChunks, 0, endChunk).IterTyped(func(chunk int) bool { + left -= int64(startPiece.chunkSize()) + return true + }) + endPiece := f.t.piece(endPieceIndex) + startChunk := int((f.offset+f.length)%f.t.info.PieceLength) * int(endPiece.numChunks()) / int(endPiece.length()) + lastChunkIndex := int(endPiece.lastChunkIndex()) + bitmap.Flip(endPiece.dirtyChunks, startChunk, int(endPiece.numChunks())).IterTyped(func(chunk int) bool { + if chunk == lastChunkIndex { + left -= int64(endPiece.chunkIndexSpec(pp.Integer(chunk)).Length) + } else { + left -= int64(endPiece.chunkSize()) + } + return true + }) + return +} + // The relative file path for a multi-file torrent, and the torrent name for a // single-file torrent. func (f *File) DisplayPath() string {