7 "github.com/anacrolix/missinggo/bitmap"
8 "github.com/bradfitz/iter"
10 pp "github.com/anacrolix/torrent/peer_protocol"
13 // Piece priority describes the importance of obtaining a particular piece.
15 type piecePriority byte
17 func (me *piecePriority) Raise(maybe piecePriority) {
24 PiecePriorityNone piecePriority = iota // Not wanted.
25 PiecePriorityNormal // Wanted.
26 PiecePriorityReadahead // May be required soon.
27 PiecePriorityNext // Succeeds a piece where a read occurred.
28 PiecePriorityNow // A read occurred in this piece.
32 // The completed piece SHA1 hash, from the metainfo "pieces" field.
34 // Chunks we've written to since the last check. The chunk offset and
35 // length can be determined by the request chunkSize in use.
36 DirtyChunks bitmap.Bitmap
40 PublicPieceState PieceState
41 priority piecePriority
43 pendingWritesMutex sync.Mutex
45 noPendingWrites sync.Cond
48 func (p *piece) pendingChunkIndex(chunkIndex int) bool {
49 return !p.DirtyChunks.Contains(chunkIndex)
52 func (p *piece) pendingChunk(cs chunkSpec, chunkSize pp.Integer) bool {
53 return p.pendingChunkIndex(chunkIndex(cs, chunkSize))
56 func (p *piece) hasDirtyChunks() bool {
57 return p.DirtyChunks.Len() != 0
60 func (p *piece) numDirtyChunks() (ret int) {
61 return p.DirtyChunks.Len()
64 func (p *piece) unpendChunkIndex(i int) {
68 func (p *piece) pendChunkIndex(i int) {
69 p.DirtyChunks.Remove(i)
72 func chunkIndexSpec(index int, pieceLength, chunkSize pp.Integer) chunkSpec {
73 ret := chunkSpec{pp.Integer(index) * chunkSize, chunkSize}
74 if ret.Begin+ret.Length > pieceLength {
75 ret.Length = pieceLength - ret.Begin
80 func (p *piece) shuffledPendingChunkSpecs(t *torrent, piece int) (css []chunkSpec) {
82 // log.Println(piece, css)
84 numPending := t.pieceNumPendingChunks(piece)
88 css = make([]chunkSpec, 0, numPending)
89 for ci := range iter.N(t.pieceNumChunks(piece)) {
90 if !p.DirtyChunks.Contains(ci) {
91 css = append(css, t.chunkIndexSpec(ci, piece))
99 css[i], css[j] = css[j], css[i]
104 func (p *piece) incrementPendingWrites() {
105 p.pendingWritesMutex.Lock()
107 p.pendingWritesMutex.Unlock()
110 func (p *piece) decrementPendingWrites() {
111 p.pendingWritesMutex.Lock()
112 if p.pendingWrites == 0 {
116 if p.pendingWrites == 0 {
117 p.noPendingWrites.Broadcast()
119 p.pendingWritesMutex.Unlock()
122 func (p *piece) waitNoPendingWrites() {
123 p.pendingWritesMutex.Lock()
124 for p.pendingWrites != 0 {
125 p.noPendingWrites.Wait()
127 p.pendingWritesMutex.Unlock()