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 // Describes the importance of obtaining a particular piece.
15 type piecePriority byte
17 func (pp *piecePriority) Raise(maybe piecePriority) {
23 // Priority for use in PriorityBitmap
24 func (me piecePriority) BitmapPriority() int {
29 PiecePriorityNone piecePriority = iota // Not wanted. Must be the zero value.
30 PiecePriorityNormal // Wanted.
31 PiecePriorityHigh // Wanted a lot.
32 PiecePriorityReadahead // May be required soon.
33 // Succeeds a piece where a read occurred. Currently the same as Now,
34 // apparently due to issues with caching.
36 PiecePriorityNow // A Reader is reading in this piece. Highest urgency.
40 // The completed piece SHA1 hash, from the metainfo "pieces" field.
45 // Chunks we've written to since the last check. The chunk offset and
46 // length can be determined by the request chunkSize in use.
47 dirtyChunks bitmap.Bitmap
52 storageCompletionOk bool
54 publicPieceState PieceState
55 priority piecePriority
57 pendingWritesMutex sync.Mutex
59 noPendingWrites sync.Cond
62 func (p *Piece) String() string {
63 return fmt.Sprintf("%s/%d", p.t.infoHash.HexString(), p.index)
66 func (p *Piece) Info() metainfo.Piece {
67 return p.t.info.Piece(p.index)
70 func (p *Piece) Storage() storage.Piece {
71 return p.t.storage.Piece(p.Info())
74 func (p *Piece) pendingChunkIndex(chunkIndex int) bool {
75 return !p.dirtyChunks.Contains(chunkIndex)
78 func (p *Piece) pendingChunk(cs chunkSpec, chunkSize pp.Integer) bool {
79 return p.pendingChunkIndex(chunkIndex(cs, chunkSize))
82 func (p *Piece) hasDirtyChunks() bool {
83 return p.dirtyChunks.Len() != 0
86 func (p *Piece) numDirtyChunks() (ret int) {
87 return p.dirtyChunks.Len()
90 func (p *Piece) unpendChunkIndex(i int) {
94 func (p *Piece) pendChunkIndex(i int) {
95 p.dirtyChunks.Remove(i)
98 func (p *Piece) numChunks() int {
99 return p.t.pieceNumChunks(p.index)
102 func (p *Piece) undirtiedChunkIndices() (ret bitmap.Bitmap) {
103 ret = p.dirtyChunks.Copy()
104 ret.FlipRange(0, p.numChunks())
108 func (p *Piece) incrementPendingWrites() {
109 p.pendingWritesMutex.Lock()
111 p.pendingWritesMutex.Unlock()
114 func (p *Piece) decrementPendingWrites() {
115 p.pendingWritesMutex.Lock()
116 if p.pendingWrites == 0 {
120 if p.pendingWrites == 0 {
121 p.noPendingWrites.Broadcast()
123 p.pendingWritesMutex.Unlock()
126 func (p *Piece) waitNoPendingWrites() {
127 p.pendingWritesMutex.Lock()
128 for p.pendingWrites != 0 {
129 p.noPendingWrites.Wait()
131 p.pendingWritesMutex.Unlock()
134 func (p *Piece) chunkIndexDirty(chunk int) bool {
135 return p.dirtyChunks.Contains(chunk)
138 func (p *Piece) chunkIndexSpec(chunk int) chunkSpec {
139 return chunkIndexSpec(chunk, p.length(), p.chunkSize())
142 func (p *Piece) numDirtyBytes() (ret pp.Integer) {
144 // if ret > p.length() {
145 // panic("too many dirty bytes")
148 numRegularDirtyChunks := p.numDirtyChunks()
149 if p.chunkIndexDirty(p.numChunks() - 1) {
150 numRegularDirtyChunks--
151 ret += p.chunkIndexSpec(p.lastChunkIndex()).Length
153 ret += pp.Integer(numRegularDirtyChunks) * p.chunkSize()
157 func (p *Piece) length() pp.Integer {
158 return p.t.pieceLength(p.index)
161 func (p *Piece) chunkSize() pp.Integer {
165 func (p *Piece) lastChunkIndex() int {
166 return p.numChunks() - 1
169 func (p *Piece) bytesLeft() (ret pp.Integer) {
170 if p.t.pieceComplete(p.index) {
173 return p.length() - p.numDirtyBytes()
176 func (p *Piece) VerifyData() {
178 defer p.t.cl.mu.Unlock()
179 target := p.numVerifies + 1
183 // log.Printf("target: %d", target)
184 p.t.queuePieceCheck(p.index)
185 for p.numVerifies < target {
186 // log.Printf("got %d verifies", p.numVerifies)
192 func (p *Piece) queuedForHash() bool {
193 return p.t.piecesQueuedForHash.Get(p.index)
196 func (p *Piece) torrentBeginOffset() int64 {
197 return int64(p.index) * p.t.info.PieceLength
200 func (p *Piece) torrentEndOffset() int64 {
201 return p.torrentBeginOffset() + int64(p.length())