6 "github.com/anacrolix/missinggo/bitmap"
8 "github.com/anacrolix/torrent/metainfo"
9 pp "github.com/anacrolix/torrent/peer_protocol"
10 "github.com/anacrolix/torrent/storage"
13 // Piece priority describes the importance of obtaining a particular piece.
15 type piecePriority byte
17 func (pp *piecePriority) Raise(maybe piecePriority) {
24 PiecePriorityNone piecePriority = iota // Not wanted.
25 PiecePriorityNormal // Wanted.
26 PiecePriorityReadahead // May be required soon.
27 // Succeeds a piece where a read occurred. Currently the same as Now, apparently due to issues with caching.
29 PiecePriorityNow // A Reader is reading in this piece.
33 // The completed piece SHA1 hash, from the metainfo "pieces" field.
37 // Chunks we've written to since the last check. The chunk offset and
38 // length can be determined by the request chunkSize in use.
39 DirtyChunks bitmap.Bitmap
46 PublicPieceState PieceState
47 priority piecePriority
49 pendingWritesMutex sync.Mutex
51 noPendingWrites sync.Cond
54 func (p *piece) Info() metainfo.Piece {
55 return p.t.info.Piece(p.index)
58 func (p *piece) Storage() storage.Piece {
59 return p.t.storage.Piece(p.Info())
62 func (p *piece) pendingChunkIndex(chunkIndex int) bool {
63 return !p.DirtyChunks.Contains(chunkIndex)
66 func (p *piece) pendingChunk(cs chunkSpec, chunkSize pp.Integer) bool {
67 return p.pendingChunkIndex(chunkIndex(cs, chunkSize))
70 func (p *piece) hasDirtyChunks() bool {
71 return p.DirtyChunks.Len() != 0
74 func (p *piece) numDirtyChunks() (ret int) {
75 return p.DirtyChunks.Len()
78 func (p *piece) unpendChunkIndex(i int) {
82 func (p *piece) pendChunkIndex(i int) {
83 p.DirtyChunks.Remove(i)
86 func (p *piece) numChunks() int {
87 return p.t.pieceNumChunks(p.index)
90 func (p *piece) undirtiedChunkIndices() (ret bitmap.Bitmap) {
91 ret = p.DirtyChunks.Copy()
92 ret.FlipRange(0, p.numChunks())
96 func (p *piece) incrementPendingWrites() {
97 p.pendingWritesMutex.Lock()
99 p.pendingWritesMutex.Unlock()
102 func (p *piece) decrementPendingWrites() {
103 p.pendingWritesMutex.Lock()
104 if p.pendingWrites == 0 {
108 if p.pendingWrites == 0 {
109 p.noPendingWrites.Broadcast()
111 p.pendingWritesMutex.Unlock()
114 func (p *piece) waitNoPendingWrites() {
115 p.pendingWritesMutex.Lock()
116 for p.pendingWrites != 0 {
117 p.noPendingWrites.Wait()
119 p.pendingWritesMutex.Unlock()
122 func (p *piece) chunkIndexDirty(chunk int) bool {
123 return p.DirtyChunks.Contains(chunk)
126 func (p *piece) chunkIndexSpec(chunk int) chunkSpec {
127 return chunkIndexSpec(chunk, p.length(), p.chunkSize())
130 func (p *piece) numDirtyBytes() (ret pp.Integer) {
132 if ret > p.length() {
133 panic("too many dirty bytes")
136 numRegularDirtyChunks := p.numDirtyChunks()
137 if p.chunkIndexDirty(p.numChunks() - 1) {
138 numRegularDirtyChunks--
139 ret += p.chunkIndexSpec(p.lastChunkIndex()).Length
141 ret += pp.Integer(numRegularDirtyChunks) * p.chunkSize()
145 func (p *piece) length() pp.Integer {
146 return p.t.pieceLength(p.index)
149 func (p *piece) chunkSize() pp.Integer {
153 func (p *piece) lastChunkIndex() int {
154 return p.numChunks() - 1
157 func (p *piece) bytesLeft() (ret pp.Integer) {
158 if p.t.pieceComplete(p.index) {
161 return p.length() - p.numDirtyBytes()
164 func (p *piece) VerifyData() {
166 defer p.t.cl.mu.Unlock()
167 target := p.numVerifies + 1
171 p.t.queuePieceCheck(p.index)
172 for p.numVerifies < target {