7 "github.com/anacrolix/missinggo/bitmap"
9 "github.com/anacrolix/torrent/metainfo"
10 pp "github.com/anacrolix/torrent/peer_protocol"
11 "github.com/anacrolix/torrent/storage"
14 // Piece priority describes the importance of obtaining a particular piece.
16 type piecePriority byte
18 func (pp *piecePriority) Raise(maybe piecePriority) {
24 // Priority for use in PriorityBitmap
25 func (me piecePriority) BitmapPriority() int {
30 PiecePriorityNone piecePriority = iota // Not wanted. Must be the zero value.
31 PiecePriorityNormal // Wanted.
32 PiecePriorityHigh // Wanted a lot.
33 PiecePriorityReadahead // May be required soon.
34 // Succeeds a piece where a read occurred. Currently the same as Now,
35 // apparently due to issues with caching.
37 PiecePriorityNow // A Reader is reading in this piece. Highest urgency.
41 // The completed piece SHA1 hash, from the metainfo "pieces" field.
46 // Chunks we've written to since the last check. The chunk offset and
47 // length can be determined by the request chunkSize in use.
48 dirtyChunks bitmap.Bitmap
53 storageCompletionOk bool
55 publicPieceState PieceState
56 priority piecePriority
58 pendingWritesMutex sync.Mutex
60 noPendingWrites sync.Cond
63 func (p *Piece) String() string {
64 return fmt.Sprintf("%s/%d", p.t.infoHash.HexString(), p.index)
67 func (p *Piece) Info() metainfo.Piece {
68 return p.t.info.Piece(p.index)
71 func (p *Piece) Storage() storage.Piece {
72 return p.t.storage.Piece(p.Info())
75 func (p *Piece) pendingChunkIndex(chunkIndex int) bool {
76 return !p.dirtyChunks.Contains(chunkIndex)
79 func (p *Piece) pendingChunk(cs chunkSpec, chunkSize pp.Integer) bool {
80 return p.pendingChunkIndex(chunkIndex(cs, chunkSize))
83 func (p *Piece) hasDirtyChunks() bool {
84 return p.dirtyChunks.Len() != 0
87 func (p *Piece) numDirtyChunks() (ret int) {
88 return p.dirtyChunks.Len()
91 func (p *Piece) unpendChunkIndex(i int) {
95 func (p *Piece) pendChunkIndex(i int) {
96 p.dirtyChunks.Remove(i)
99 func (p *Piece) numChunks() int {
100 return p.t.pieceNumChunks(p.index)
103 func (p *Piece) undirtiedChunkIndices() (ret bitmap.Bitmap) {
104 ret = p.dirtyChunks.Copy()
105 ret.FlipRange(0, p.numChunks())
109 func (p *Piece) incrementPendingWrites() {
110 p.pendingWritesMutex.Lock()
112 p.pendingWritesMutex.Unlock()
115 func (p *Piece) decrementPendingWrites() {
116 p.pendingWritesMutex.Lock()
117 if p.pendingWrites == 0 {
121 if p.pendingWrites == 0 {
122 p.noPendingWrites.Broadcast()
124 p.pendingWritesMutex.Unlock()
127 func (p *Piece) waitNoPendingWrites() {
128 p.pendingWritesMutex.Lock()
129 for p.pendingWrites != 0 {
130 p.noPendingWrites.Wait()
132 p.pendingWritesMutex.Unlock()
135 func (p *Piece) chunkIndexDirty(chunk int) bool {
136 return p.dirtyChunks.Contains(chunk)
139 func (p *Piece) chunkIndexSpec(chunk int) chunkSpec {
140 return chunkIndexSpec(chunk, p.length(), p.chunkSize())
143 func (p *Piece) numDirtyBytes() (ret pp.Integer) {
145 // if ret > p.length() {
146 // panic("too many dirty bytes")
149 numRegularDirtyChunks := p.numDirtyChunks()
150 if p.chunkIndexDirty(p.numChunks() - 1) {
151 numRegularDirtyChunks--
152 ret += p.chunkIndexSpec(p.lastChunkIndex()).Length
154 ret += pp.Integer(numRegularDirtyChunks) * p.chunkSize()
158 func (p *Piece) length() pp.Integer {
159 return p.t.pieceLength(p.index)
162 func (p *Piece) chunkSize() pp.Integer {
166 func (p *Piece) lastChunkIndex() int {
167 return p.numChunks() - 1
170 func (p *Piece) bytesLeft() (ret pp.Integer) {
171 if p.t.pieceComplete(p.index) {
174 return p.length() - p.numDirtyBytes()
177 func (p *Piece) VerifyData() {
179 defer p.t.cl.mu.Unlock()
180 target := p.numVerifies + 1
184 // log.Printf("target: %d", target)
185 p.t.queuePieceCheck(p.index)
186 for p.numVerifies < target {
187 // log.Printf("got %d verifies", p.numVerifies)
193 func (p *Piece) queuedForHash() bool {
194 return p.t.piecesQueuedForHash.Get(p.index)
197 func (p *Piece) torrentBeginOffset() int64 {
198 return int64(p.index) * p.t.info.PieceLength
201 func (p *Piece) torrentEndOffset() int64 {
202 return p.torrentBeginOffset() + int64(p.length())