2
0
mirror of synced 2025-02-24 14:48:27 +00:00
torrent/piece.go
Matt Joiner d01c6221e6 Remove sync.Cond from piece
It's not trivial to ensure that anyone waiting on the piece Cond will wake on events like the torrent being dropped from the client.
2015-11-06 00:40:16 +11:00

89 lines
2.1 KiB
Go

package torrent
import (
"math/rand"
"sync"
pp "github.com/anacrolix/torrent/peer_protocol"
)
// Piece priority describes the importance of obtaining a particular piece.
type piecePriority byte
const (
PiecePriorityNone piecePriority = iota // Not wanted.
PiecePriorityNormal // Wanted.
PiecePriorityReadahead // May be required soon.
PiecePriorityNext // Succeeds a piece where a read occurred.
PiecePriorityNow // A read occurred in this piece.
)
type piece struct {
// The completed piece SHA1 hash, from the metainfo "pieces" field.
Hash pieceSum
// Chunks we don't have. The offset and length can be determined by the
// request chunkSize in use.
PendingChunkSpecs []bool
Hashing bool
QueuedForHash bool
EverHashed bool
Priority piecePriority
PublicPieceState PieceState
pendingWritesMutex sync.Mutex
pendingWrites int
noPendingWrites sync.Cond
}
func (p *piece) pendingChunk(cs chunkSpec, chunkSize pp.Integer) bool {
if p.PendingChunkSpecs == nil {
return false
}
return p.PendingChunkSpecs[chunkIndex(cs, chunkSize)]
}
func (p *piece) numPendingChunks() (ret int) {
for _, pending := range p.PendingChunkSpecs {
if pending {
ret++
}
}
return
}
func (p *piece) unpendChunkIndex(i int) {
if p.PendingChunkSpecs == nil {
return
}
p.PendingChunkSpecs[i] = false
}
func chunkIndexSpec(index int, pieceLength, chunkSize pp.Integer) chunkSpec {
ret := chunkSpec{pp.Integer(index) * chunkSize, chunkSize}
if ret.Begin+ret.Length > pieceLength {
ret.Length = pieceLength - ret.Begin
}
return ret
}
func (p *piece) shuffledPendingChunkSpecs(pieceLength, chunkSize pp.Integer) (css []chunkSpec) {
if p.numPendingChunks() == 0 {
return
}
css = make([]chunkSpec, 0, p.numPendingChunks())
for i, pending := range p.PendingChunkSpecs {
if pending {
css = append(css, chunkIndexSpec(i, pieceLength, chunkSize))
}
}
if len(css) <= 1 {
return
}
for i := range css {
j := rand.Intn(i + 1)
css[i], css[j] = css[j], css[i]
}
return
}