7 "github.com/bradfitz/iter"
9 pp "github.com/anacrolix/torrent/peer_protocol"
12 // Piece priority describes the importance of obtaining a particular piece.
14 type piecePriority byte
17 PiecePriorityNone piecePriority = iota // Not wanted.
18 PiecePriorityNormal // Wanted.
19 PiecePriorityReadahead // May be required soon.
20 PiecePriorityNext // Succeeds a piece where a read occurred.
21 PiecePriorityNow // A read occurred in this piece.
25 // The completed piece SHA1 hash, from the metainfo "pieces" field.
27 // Chunks we've written to since the last check. The chunk offset and
28 // length can be determined by the request chunkSize in use.
33 PublicPieceState PieceState
34 priority piecePriority
36 pendingWritesMutex sync.Mutex
38 noPendingWrites sync.Cond
41 func (p *piece) pendingChunk(cs chunkSpec, chunkSize pp.Integer) bool {
42 ci := chunkIndex(cs, chunkSize)
43 if ci >= len(p.DirtyChunks) {
46 return !p.DirtyChunks[ci]
49 func (p *piece) numDirtyChunks() (ret int) {
50 for _, dirty := range p.DirtyChunks {
58 func (p *piece) unpendChunkIndex(i int) {
59 for i >= len(p.DirtyChunks) {
60 p.DirtyChunks = append(p.DirtyChunks, false)
62 p.DirtyChunks[i] = true
65 func (p *piece) pendChunkIndex(i int) {
66 if i >= len(p.DirtyChunks) {
69 p.DirtyChunks[i] = false
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 ci >= len(p.DirtyChunks) || !p.DirtyChunks[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()