]> Sergey Matveev's repositories - btrtrc.git/commitdiff
Rewrite file.bytesLeft
authorMatt Joiner <anacrolix@gmail.com>
Tue, 24 Mar 2020 01:15:35 +0000 (12:15 +1100)
committerMatt Joiner <anacrolix@gmail.com>
Tue, 24 Mar 2020 01:15:35 +0000 (12:15 +1100)
Avoids iteration, and should handle files that are entirely inside a single piece, as well as zero-sized at the beginning of a torrent. Should fix #387.

file.go
file_test.go

diff --git a/file.go b/file.go
index 1c54f20c610d621301c9a826643a455d64cf7a85..f02424000971f46f65583864c7fd1809aac8b841 100644 (file)
--- a/file.go
+++ b/file.go
@@ -62,21 +62,24 @@ func fileBytesLeft(
        fileLength int64,
        torrentCompletedPieces bitmap.Bitmap,
 ) (left int64) {
-       fileEndPieceIndex--
-       bitmap.Flip(torrentCompletedPieces, fileFirstPieceIndex+1, fileEndPieceIndex).IterTyped(func(piece int) bool {
-               if piece >= fileEndPieceIndex {
-                       return false
+       numPiecesSpanned := fileEndPieceIndex - fileFirstPieceIndex
+       switch numPiecesSpanned {
+       case 0:
+       case 1:
+               if !torrentCompletedPieces.Get(fileFirstPieceIndex) {
+                       left += fileLength
                }
-               if piece > fileFirstPieceIndex {
-                       left += torrentUsualPieceSize
+       default:
+               if !torrentCompletedPieces.Get(fileFirstPieceIndex) {
+                       left += torrentUsualPieceSize - (fileTorrentOffset % torrentUsualPieceSize)
                }
-               return true
-       })
-       if !torrentCompletedPieces.Get(fileFirstPieceIndex) {
-               left += torrentUsualPieceSize - (fileTorrentOffset % torrentUsualPieceSize)
-       }
-       if !torrentCompletedPieces.Get(fileEndPieceIndex) {
-               left += (fileTorrentOffset + fileLength) % torrentUsualPieceSize
+               if !torrentCompletedPieces.Get(fileEndPieceIndex - 1) {
+                       left += fileTorrentOffset + fileLength - int64(fileEndPieceIndex-1)*torrentUsualPieceSize
+               }
+               completedMiddlePieces := torrentCompletedPieces.Copy()
+               completedMiddlePieces.RemoveRange(0, fileFirstPieceIndex+1)
+               completedMiddlePieces.RemoveRange(fileEndPieceIndex-1, bitmap.ToEnd)
+               left += int64(numPiecesSpanned-2-completedMiddlePieces.Len()) * torrentUsualPieceSize
        }
        return
 }
index b411126808ba922e8f48a4dcfa65cc59727e613a..0443cf3bd5cc63a9e9766f45a9d4a489f709c43f 100644 (file)
@@ -40,19 +40,31 @@ func (me testFileBytesLeft) Run(t *testing.T) {
 }
 
 func TestFileBytesLeft(t *testing.T) {
+
        testFileBytesLeft{
-               usualPieceSize:  2,
+               usualPieceSize:  3,
                firstPieceIndex: 1,
                endPieceIndex:   1,
                fileOffset:      1,
+               fileLength:      0,
+               expected:        0,
+               name:            "ZeroLengthFile",
+       }.Run(t)
+
+       testFileBytesLeft{
+               usualPieceSize:  2,
+               firstPieceIndex: 1,
+               endPieceIndex:   2,
+               fileOffset:      1,
                fileLength:      1,
                expected:        1,
+               name:            "EndOfSecondPiece",
        }.Run(t)
 
        testFileBytesLeft{
                usualPieceSize:  3,
                firstPieceIndex: 0,
-               endPieceIndex:   0,
+               endPieceIndex:   1,
                fileOffset:      1,
                fileLength:      1,
                expected:        1,
@@ -62,10 +74,44 @@ func TestFileBytesLeft(t *testing.T) {
        testFileBytesLeft{
                usualPieceSize:  3,
                firstPieceIndex: 0,
-               endPieceIndex:   0,
+               endPieceIndex:   1,
                fileOffset:      1,
                fileLength:      1,
                expected:        1,
                name:            "LandLocked",
        }.Run(t)
+
+       testFileBytesLeft{
+               usualPieceSize:  3,
+               firstPieceIndex: 1,
+               endPieceIndex:   3,
+               fileOffset:      4,
+               fileLength:      4,
+               expected:        4,
+               name:            "TwoPieces",
+       }.Run(t)
+
+       testFileBytesLeft{
+               usualPieceSize:  3,
+               firstPieceIndex: 1,
+               endPieceIndex:   4,
+               fileOffset:      5,
+               fileLength:      7,
+               expected:        7,
+               name:            "ThreePieces",
+       }.Run(t)
+
+       testFileBytesLeft{
+               usualPieceSize:  3,
+               firstPieceIndex: 1,
+               endPieceIndex:   4,
+               fileOffset:      5,
+               fileLength:      7,
+               expected:        0,
+               completedPieces: func() (ret bitmap.Bitmap) {
+                       ret.AddRange(0, 5)
+                       return
+               }(),
+               name: "ThreePiecesCompletedAll",
+       }.Run(t)
 }