From 95d808d3c5f318b8c09c233b021fb8a8f542c415 Mon Sep 17 00:00:00 2001 From: Matt Joiner Date: Thu, 20 May 2021 11:16:54 +1000 Subject: [PATCH] Use rejiggered missinggo bitmap --- client.go | 4 ++-- file.go | 12 ++++++------ peerconn.go | 29 +++++++++++++++-------------- piece.go | 10 +++++----- request-strategy.go | 3 ++- test/transfer_test.go | 3 ++- torrent.go | 22 +++++++++++----------- torrent_test.go | 5 +++-- 8 files changed, 46 insertions(+), 42 deletions(-) diff --git a/client.go b/client.go index 9300b24b..98bf0892 100644 --- a/client.go +++ b/client.go @@ -18,10 +18,10 @@ import ( "github.com/anacrolix/dht/v2" "github.com/anacrolix/dht/v2/krpc" "github.com/anacrolix/log" - "github.com/anacrolix/missinggo/bitmap" "github.com/anacrolix/missinggo/perf" "github.com/anacrolix/missinggo/pubsub" "github.com/anacrolix/missinggo/slices" + "github.com/anacrolix/missinggo/v2/bitmap" "github.com/anacrolix/missinggo/v2/pproffd" "github.com/anacrolix/sync" "github.com/anacrolix/torrent/internal/limiter" @@ -1007,7 +1007,7 @@ func (cl *Client) sendInitialMessages(conn *PeerConn, torrent *Torrent) { if conn.fastEnabled() { if torrent.haveAllPieces() { conn.write(pp.Message{Type: pp.HaveAll}) - conn.sentHaves.AddRange(0, bitmap.BitIndex(conn.t.NumPieces())) + conn.sentHaves.AddRange(0, bitmap.BitRange(conn.t.NumPieces())) return } else if !torrent.haveAnyPieces() { conn.write(pp.Message{Type: pp.HaveNone}) diff --git a/file.go b/file.go index e2ebcf4d..37c185c1 100644 --- a/file.go +++ b/file.go @@ -66,20 +66,20 @@ func fileBytesLeft( switch numPiecesSpanned { case 0: case 1: - if !torrentCompletedPieces.Get(fileFirstPieceIndex) { + if !torrentCompletedPieces.Get(bitmap.BitIndex(fileFirstPieceIndex)) { left += fileLength } default: - if !torrentCompletedPieces.Get(fileFirstPieceIndex) { + if !torrentCompletedPieces.Get(bitmap.BitIndex(fileFirstPieceIndex)) { left += torrentUsualPieceSize - (fileTorrentOffset % torrentUsualPieceSize) } - if !torrentCompletedPieces.Get(fileEndPieceIndex - 1) { + if !torrentCompletedPieces.Get(bitmap.BitIndex(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 + completedMiddlePieces.RemoveRange(0, bitmap.BitRange(fileFirstPieceIndex+1)) + completedMiddlePieces.RemoveRange(bitmap.BitRange(fileEndPieceIndex-1), bitmap.ToEnd) + left += int64(numPiecesSpanned-2-pieceIndex(completedMiddlePieces.Len())) * torrentUsualPieceSize } return } diff --git a/peerconn.go b/peerconn.go index f3680e18..976081ab 100644 --- a/peerconn.go +++ b/peerconn.go @@ -232,7 +232,7 @@ func (cn *Peer) peerHasAllPieces() (all bool, known bool) { if !cn.t.haveInfo() { return false, false } - return bitmap.Flip(cn._peerPieces, 0, bitmap.BitIndex(cn.t.numPieces())).IsEmpty(), true + return bitmap.Flip(cn._peerPieces, 0, bitmap.BitRange(cn.t.numPieces())).IsEmpty(), true } func (cn *PeerConn) locker() *lockWithDeferreds { @@ -267,7 +267,7 @@ func (cn *PeerConn) onGotInfo(info *metainfo.Info) { // Correct the PeerPieces slice length. Return false if the existing slice is invalid, such as by // receiving badly sized BITFIELD, or invalid HAVE messages. func (cn *PeerConn) setNumPieces(num pieceIndex) { - cn._peerPieces.RemoveRange(bitmap.BitIndex(num), bitmap.ToEnd) + cn._peerPieces.RemoveRange(bitmap.BitRange(num), bitmap.ToEnd) cn.peerPiecesChanged() } @@ -730,10 +730,10 @@ func iterBitmapsDistinct(skip *bitmap.Bitmap, bms ...bitmap.Bitmap) iter.Func { if !iter.All( func(_i interface{}) bool { i := _i.(int) - if skip.Contains(i) { + if skip.Contains(bitmap.BitIndex(i)) { return true } - skip.Add(i) + skip.Add(bitmap.BitIndex(i)) return cb(i) }, bm.Iter, @@ -746,7 +746,7 @@ func iterBitmapsDistinct(skip *bitmap.Bitmap, bms ...bitmap.Bitmap) iter.Func { // check callers updaterequests func (cn *Peer) stopRequestingPiece(piece pieceIndex) bool { - return cn._pieceRequestOrder.Remove(bitmap.BitIndex(piece)) + return cn._pieceRequestOrder.Remove(piece) } // This is distinct from Torrent piece priority, which is the user's @@ -762,7 +762,7 @@ func (cn *Peer) updatePiecePriority(piece pieceIndex) bool { return cn.stopRequestingPiece(piece) } prio := cn.getPieceInclination()[piece] - return cn._pieceRequestOrder.Set(bitmap.BitIndex(piece), prio) + return cn._pieceRequestOrder.Set(piece, prio) } func (cn *Peer) getPieceInclination() []int { @@ -835,15 +835,15 @@ func (cn *PeerConn) peerSentBitfield(bf []bool) error { for i, have := range bf { if have { cn.raisePeerMinPieces(pieceIndex(i) + 1) - if !pp.Contains(i) { + if !pp.Contains(bitmap.BitIndex(i)) { cn.t.incPieceAvailability(i) } } else { - if pp.Contains(i) { + if pp.Contains(bitmap.BitIndex(i)) { cn.t.decPieceAvailability(i) } } - cn._peerPieces.Set(i, have) + cn._peerPieces.Set(bitmap.BitIndex(i), have) } cn.peerPiecesChanged() return nil @@ -854,7 +854,7 @@ func (cn *Peer) onPeerHasAllPieces() { if t.haveInfo() { pp := cn.newPeerPieces() for i := range iter.N(t.numPieces()) { - if !pp.Contains(i) { + if !pp.Contains(bitmap.BitIndex(i)) { t.incPieceAvailability(i) } } @@ -1198,7 +1198,7 @@ func (c *PeerConn) mainReadLoop() (err error) { case pp.AllowedFast: torrent.Add("allowed fasts received", 1) log.Fmsg("peer allowed fast: %d", msg.Index).AddValues(c).SetLevel(log.Debug).Log(c.t.logger) - c.peerAllowedFast.Add(int(msg.Index)) + c.peerAllowedFast.Add(bitmap.BitIndex(msg.Index)) c.updateRequests() case pp.Extended: err = c.onReadExtendedMsg(msg.ExtendedID, msg.ExtendedPayload) @@ -1326,7 +1326,7 @@ func (c *Peer) receiveChunk(msg *pp.Message) error { } c.decExpectedChunkReceive(req) - if c.peerChoking && c.peerAllowedFast.Get(int(req.Index)) { + if c.peerChoking && c.peerAllowedFast.Get(bitmap.BitIndex(req.Index)) { chunksReceived.Add("due to allowed fast", 1) } @@ -1658,11 +1658,12 @@ func (cn *PeerConn) PeerPieces() bitmap.Bitmap { return cn.newPeerPieces() } -// Returns a new Bitmap that includes bits for all pieces we have. +// Returns a new Bitmap that includes bits for all pieces the peer claims to have. func (cn *Peer) newPeerPieces() bitmap.Bitmap { ret := cn._peerPieces.Copy() if cn.peerSentHaveAll { - ret.AddRange(0, cn.t.numPieces()) + + ret.AddRange(0, bitmap.BitRange(cn.t.numPieces())) } return ret } diff --git a/piece.go b/piece.go index 3ee648d3..45b37c0a 100644 --- a/piece.go +++ b/piece.go @@ -53,7 +53,7 @@ func (p *Piece) Storage() storage.Piece { } func (p *Piece) pendingChunkIndex(chunkIndex int) bool { - return !p._dirtyChunks.Contains(chunkIndex) + return !p._dirtyChunks.Contains(bitmap.BitIndex(chunkIndex)) } func (p *Piece) pendingChunk(cs ChunkSpec, chunkSize pp.Integer) bool { @@ -69,12 +69,12 @@ func (p *Piece) numDirtyChunks() pp.Integer { } func (p *Piece) unpendChunkIndex(i int) { - p._dirtyChunks.Add(i) + p._dirtyChunks.Add(bitmap.BitIndex(i)) p.t.tickleReaders() } func (p *Piece) pendChunkIndex(i int) { - p._dirtyChunks.Remove(i) + p._dirtyChunks.Remove(bitmap.BitIndex(i)) } func (p *Piece) numChunks() pp.Integer { @@ -199,7 +199,7 @@ func (p *Piece) purePriority() (ret piecePriority) { for _, f := range p.files { ret.Raise(f.prio) } - if p.t.readerNowPieces().Contains(int(p.index)) { + if p.t.readerNowPieces().Contains(bitmap.BitIndex(p.index)) { ret.Raise(PiecePriorityNow) } // if t._readerNowPieces.Contains(piece - 1) { @@ -234,7 +234,7 @@ func (p *Piece) completion() (ret storage.Completion) { } func (p *Piece) allChunksDirty() bool { - return p._dirtyChunks.Len() == int(p.numChunks()) + return p._dirtyChunks.Len() == bitmap.BitRange(p.numChunks()) } func (p *Piece) dirtyChunks() bitmap.Bitmap { diff --git a/request-strategy.go b/request-strategy.go index f0470007..72f7f3d4 100644 --- a/request-strategy.go +++ b/request-strategy.go @@ -4,6 +4,7 @@ import ( "time" "unsafe" + "github.com/anacrolix/missinggo/v2/bitmap" request_strategy "github.com/anacrolix/torrent/request-strategy" "github.com/anacrolix/torrent/types" ) @@ -66,7 +67,7 @@ func (cl *Client) doRequests() { }, Choking: p.peerChoking, PieceAllowedFast: func(i pieceIndex) bool { - return p.peerAllowedFast.Contains(i) + return p.peerAllowedFast.Contains(bitmap.BitIndex(i)) }, DownloadRate: p.downloadRate(), Age: time.Since(p.completedHandshake), diff --git a/test/transfer_test.go b/test/transfer_test.go index 857cd44f..b3187c0b 100644 --- a/test/transfer_test.go +++ b/test/transfer_test.go @@ -12,6 +12,7 @@ import ( "testing/iotest" "time" + "github.com/anacrolix/missinggo/v2/bitmap" "github.com/anacrolix/missinggo/v2/filecache" "github.com/anacrolix/torrent" "github.com/anacrolix/torrent/internal/testutil" @@ -168,7 +169,7 @@ func testClientTransfer(t *testing.T, ps testClientTransferParams) { for _, pc := range leecherPeerConns { completed := pc.PeerPieces().Len() t.Logf("peer conn %v has %v completed pieces", pc, completed) - if completed == leecherTorrent.Info().NumPieces() { + if completed == bitmap.BitRange(leecherTorrent.Info().NumPieces()) { foundSeeder = true } } diff --git a/torrent.go b/torrent.go index da71ba93..5190b65e 100644 --- a/torrent.go +++ b/torrent.go @@ -759,7 +759,7 @@ func (t *Torrent) bytesMissingLocked() int64 { } func (t *Torrent) bytesLeft() (left int64) { - bitmap.Flip(t._completedPieces, 0, bitmap.BitIndex(t.numPieces())).IterTyped(func(piece int) bool { + bitmap.Flip(t._completedPieces, 0, bitmap.BitRange(t.numPieces())).IterTyped(func(piece int) bool { p := &t.pieces[piece] left += int64(p.length() - p.numDirtyBytes()) return true @@ -794,8 +794,8 @@ func (t *Torrent) numPieces() pieceIndex { return pieceIndex(t.info.NumPieces()) } -func (t *Torrent) numPiecesCompleted() (num int) { - return t._completedPieces.Len() +func (t *Torrent) numPiecesCompleted() (num pieceIndex) { + return pieceIndex(t._completedPieces.Len()) } func (t *Torrent) close() (err error) { @@ -895,7 +895,7 @@ func (t *Torrent) haveAllPieces() bool { if !t.haveInfo() { return false } - return t._completedPieces.Len() == bitmap.BitIndex(t.numPieces()) + return t._completedPieces.Len() == bitmap.BitRange(t.numPieces()) } func (t *Torrent) havePiece(index pieceIndex) bool { @@ -960,7 +960,7 @@ func (t *Torrent) wantPieceIndex(index pieceIndex) bool { if t.pieceComplete(index) { return false } - if t._pendingPieces.Contains(bitmap.BitIndex(index)) { + if t._pendingPieces.Contains(int(index)) { return true } // t.logger.Printf("piece %d not pending", index) @@ -1019,7 +1019,7 @@ func (t *Torrent) pieceNumPendingChunks(piece pieceIndex) pp.Integer { } func (t *Torrent) pieceAllDirty(piece pieceIndex) bool { - return t.pieces[piece]._dirtyChunks.Len() == int(t.pieceNumChunks(piece)) + return t.pieces[piece]._dirtyChunks.Len() == bitmap.BitRange(t.pieceNumChunks(piece)) } func (t *Torrent) readersChanged() { @@ -1078,11 +1078,11 @@ func (t *Torrent) updatePiecePriority(piece pieceIndex) { newPrio := p.uncachedPriority() // t.logger.Printf("torrent %p: piece %d: uncached priority: %v", t, piece, newPrio) if newPrio == PiecePriorityNone { - if !t._pendingPieces.Remove(bitmap.BitIndex(piece)) { + if !t._pendingPieces.Remove(int(piece)) { return } } else { - if !t._pendingPieces.Set(bitmap.BitIndex(piece), newPrio.BitmapPriority()) { + if !t._pendingPieces.Set(int(piece), newPrio.BitmapPriority()) { return } } @@ -1138,7 +1138,7 @@ func (t *Torrent) forReaderOffsetPieces(f func(begin, end pieceIndex) (more bool } func (t *Torrent) piecePriority(piece pieceIndex) piecePriority { - prio, ok := t._pendingPieces.GetPriority(bitmap.BitIndex(piece)) + prio, ok := t._pendingPieces.GetPriority(piece) if !ok { return PiecePriorityNone } @@ -1286,7 +1286,7 @@ func (t *Torrent) readerPiecePriorities() (now, readahead bitmap.Bitmap) { t.forReaderOffsetPieces(func(begin, end pieceIndex) bool { if end > begin { now.Add(bitmap.BitIndex(begin)) - readahead.AddRange(bitmap.BitIndex(begin)+1, bitmap.BitIndex(end)) + readahead.AddRange(bitmap.BitRange(begin)+1, bitmap.BitRange(end)) } return true }) @@ -1966,7 +1966,7 @@ func (t *Torrent) tryCreatePieceHasher() bool { return false } p := t.piece(pi) - t.piecesQueuedForHash.Remove(pi) + t.piecesQueuedForHash.Remove(bitmap.BitIndex(pi)) p.hashing = true t.publishPieceChange(pi) t.updatePiecePriority(pi) diff --git a/torrent_test.go b/torrent_test.go index d53aa693..ceff1fee 100644 --- a/torrent_test.go +++ b/torrent_test.go @@ -9,6 +9,7 @@ import ( "testing" "github.com/anacrolix/missinggo" + "github.com/anacrolix/missinggo/v2/bitmap" "github.com/bradfitz/iter" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -96,8 +97,8 @@ func BenchmarkUpdatePiecePriorities(b *testing.B) { r.Seek(3500000, io.SeekStart) } assert.Len(b, t.readers, 7) - for i := 0; i < int(t.numPieces()); i += 3 { - t._completedPieces.Set(i, true) + for i := 0; i < t.numPieces(); i += 3 { + t._completedPieces.Set(bitmap.BitIndex(i), true) } t.DownloadPieces(0, t.numPieces()) for range iter.N(b.N) { -- 2.44.0