"math/rand"
"sync"
+ "github.com/anacrolix/missinggo/bitmap"
"github.com/bradfitz/iter"
pp "github.com/anacrolix/torrent/peer_protocol"
Hash pieceSum
// Chunks we've written to since the last check. The chunk offset and
// length can be determined by the request chunkSize in use.
- DirtyChunks []bool
+ DirtyChunks bitmap.Bitmap
Hashing bool
QueuedForHash bool
EverHashed bool
noPendingWrites sync.Cond
}
+func (p *piece) pendingChunkIndex(chunkIndex int) bool {
+ return !p.DirtyChunks.Contains(chunkIndex)
+}
+
func (p *piece) pendingChunk(cs chunkSpec, chunkSize pp.Integer) bool {
- ci := chunkIndex(cs, chunkSize)
- if ci >= len(p.DirtyChunks) {
- return true
- }
- return !p.DirtyChunks[ci]
+ return p.pendingChunkIndex(chunkIndex(cs, chunkSize))
}
func (p *piece) hasDirtyChunks() bool {
- for _, dirty := range p.DirtyChunks {
- if dirty {
- return true
- }
- }
- return false
+ return p.DirtyChunks.Len() != 0
}
func (p *piece) numDirtyChunks() (ret int) {
- for _, dirty := range p.DirtyChunks {
- if dirty {
- ret++
- }
- }
- return
+ return p.DirtyChunks.Len()
}
func (p *piece) unpendChunkIndex(i int) {
- for i >= len(p.DirtyChunks) {
- p.DirtyChunks = append(p.DirtyChunks, false)
- }
- p.DirtyChunks[i] = true
+ p.DirtyChunks.Add(i)
}
func (p *piece) pendChunkIndex(i int) {
- if i >= len(p.DirtyChunks) {
- return
- }
- p.DirtyChunks[i] = false
+ p.DirtyChunks.Remove(i)
}
func chunkIndexSpec(index int, pieceLength, chunkSize pp.Integer) chunkSpec {
}
css = make([]chunkSpec, 0, numPending)
for ci := range iter.N(t.pieceNumChunks(piece)) {
- if ci >= len(p.DirtyChunks) || !p.DirtyChunks[ci] {
+ if !p.DirtyChunks.Contains(ci) {
css = append(css, t.chunkIndexSpec(ci, piece))
}
}
if !piece.EverHashed {
return
}
- for i, dirty := range piece.DirtyChunks {
- if dirty {
- count -= t.chunkIndexSpec(i, index).Length
- }
+ regularDirty := piece.numDirtyChunks()
+ lastChunkIndex := t.pieceNumChunks(index) - 1
+ if piece.pendingChunkIndex(lastChunkIndex) {
+ regularDirty--
+ count -= t.chunkIndexSpec(lastChunkIndex, index).Length
}
+ count -= pp.Integer(regularDirty) * t.chunkSize
return
}
}
func (t *torrent) pendAllChunkSpecs(pieceIndex int) {
- t.Pieces[pieceIndex].DirtyChunks = nil
+ t.Pieces[pieceIndex].DirtyChunks.Clear()
}
type Peer struct {
}
func (t *torrent) pieceAllDirty(piece int) bool {
- p := &t.Pieces[piece]
- if len(p.DirtyChunks) != t.pieceNumChunks(piece) {
- return false
- }
- for _, dirty := range p.DirtyChunks {
- if !dirty {
- return false
- }
- }
- return true
+ return t.Pieces[piece].DirtyChunks.Len() == t.pieceNumChunks(piece)
}
func (t *torrent) forUrgentPieces(f func(piece int) (again bool)) (all bool) {