From ca5bd29a04d8a90224ac7a3c524354b9171a599c Mon Sep 17 00:00:00 2001 From: liwei Date: Sun, 23 Jul 2023 00:30:45 +0800 Subject: [PATCH] fix: torrent file real time completed bytes --- file.go | 65 +++++++++++++++++++++++++++++++++++++--------------- file_test.go | 4 +++- 2 files changed, 49 insertions(+), 20 deletions(-) diff --git a/file.go b/file.go index ed2f5da9..bea4b136 100644 --- a/file.go +++ b/file.go @@ -62,31 +62,58 @@ func fileBytesLeft( fileTorrentOffset int64, fileLength int64, torrentCompletedPieces *roaring.Bitmap, + pieceSizeCompletedFn func(pieceIndex int) int64, ) (left int64) { - numPiecesSpanned := fileEndPieceIndex - fileFirstPieceIndex - switch numPiecesSpanned { - case 0: - case 1: - if !torrentCompletedPieces.Contains(bitmap.BitIndex(fileFirstPieceIndex)) { - left += fileLength - } - default: - if !torrentCompletedPieces.Contains(bitmap.BitIndex(fileFirstPieceIndex)) { - left += torrentUsualPieceSize - (fileTorrentOffset % torrentUsualPieceSize) - } - if !torrentCompletedPieces.Contains(bitmap.BitIndex(fileEndPieceIndex - 1)) { - left += fileTorrentOffset + fileLength - int64(fileEndPieceIndex-1)*torrentUsualPieceSize - } - completedMiddlePieces := torrentCompletedPieces.Clone() - completedMiddlePieces.RemoveRange(0, bitmap.BitRange(fileFirstPieceIndex+1)) - completedMiddlePieces.RemoveRange(bitmap.BitRange(fileEndPieceIndex-1), bitmap.ToEnd) - left += int64(numPiecesSpanned-2-pieceIndex(completedMiddlePieces.GetCardinality())) * torrentUsualPieceSize + if fileLength == 0 { + return } + + noCompletedMiddlePieces := roaring.New() + noCompletedMiddlePieces.AddRange(bitmap.BitRange(fileFirstPieceIndex), bitmap.BitRange(fileEndPieceIndex)) + noCompletedMiddlePieces.AndNot(torrentCompletedPieces) + noCompletedMiddlePieces.Iterate(func(pieceIndex uint32) bool { + i := int(pieceIndex) + pieceSizeCompleted := pieceSizeCompletedFn(i) + if i == fileFirstPieceIndex { + beginOffset := fileTorrentOffset % torrentUsualPieceSize + beginSize := torrentUsualPieceSize - beginOffset + beginDownLoaded := pieceSizeCompleted - beginOffset + if beginDownLoaded < 0 { + beginDownLoaded = 0 + } + left += beginSize - beginDownLoaded + } else if i == fileEndPieceIndex-1 { + endSize := (fileTorrentOffset + fileLength) % torrentUsualPieceSize + if endSize == 0 { + endSize = torrentUsualPieceSize + } + endDownloaded := pieceSizeCompleted + if endDownloaded > endSize { + endDownloaded = endSize + } + left += endSize - endDownloaded + } else { + left += torrentUsualPieceSize - pieceSizeCompleted + } + return true + }) + + if left > fileLength { + left = fileLength + } + // + //numPiecesSpanned := f.EndPieceIndex() - f.BeginPieceIndex() + //completedMiddlePieces := f.t._completedPieces.Clone() + //completedMiddlePieces.RemoveRange(0, bitmap.BitRange(f.BeginPieceIndex()+1)) + //completedMiddlePieces.RemoveRange(bitmap.BitRange(f.EndPieceIndex()-1), bitmap.ToEnd) + //left += int64(numPiecesSpanned-2-pieceIndex(completedMiddlePieces.GetCardinality())) * torrentUsualPieceSize return } func (f *File) bytesLeft() (left int64) { - return fileBytesLeft(int64(f.t.usualPieceSize()), f.BeginPieceIndex(), f.EndPieceIndex(), f.offset, f.length, &f.t._completedPieces) + return fileBytesLeft(int64(f.t.usualPieceSize()), f.BeginPieceIndex(), f.EndPieceIndex(), f.offset, f.length, &f.t._completedPieces, func(pieceIndex int) int64 { + return int64(f.t.piece(pieceIndex).numDirtyBytes()) + }) } // The relative file path for a multi-file torrent, and the torrent name for a diff --git a/file_test.go b/file_test.go index e0df62b4..2f57bcf4 100644 --- a/file_test.go +++ b/file_test.go @@ -35,7 +35,9 @@ type testFileBytesLeft struct { func (me testFileBytesLeft) Run(t *testing.T) { t.Run(me.name, func(t *testing.T) { - assert.EqualValues(t, me.expected, fileBytesLeft(me.usualPieceSize, me.firstPieceIndex, me.endPieceIndex, me.fileOffset, me.fileLength, &me.completedPieces)) + assert.EqualValues(t, me.expected, fileBytesLeft(me.usualPieceSize, me.firstPieceIndex, me.endPieceIndex, me.fileOffset, me.fileLength, &me.completedPieces, func(pieceIndex int) int64 { + return 0 + })) }) }