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
35 pendingWritesMutex sync.Mutex
37 noPendingWrites sync.Cond
40 func (p *piece) pendingChunk(cs chunkSpec, chunkSize pp.Integer) bool {
41 ci := chunkIndex(cs, chunkSize)
42 if ci >= len(p.DirtyChunks) {
45 return !p.DirtyChunks[ci]
48 func (p *piece) numDirtyChunks() (ret int) {
49 for _, dirty := range p.DirtyChunks {
57 func (p *piece) unpendChunkIndex(i int) {
58 for i >= len(p.DirtyChunks) {
59 p.DirtyChunks = append(p.DirtyChunks, false)
61 p.DirtyChunks[i] = true
64 func chunkIndexSpec(index int, pieceLength, chunkSize pp.Integer) chunkSpec {
65 ret := chunkSpec{pp.Integer(index) * chunkSize, chunkSize}
66 if ret.Begin+ret.Length > pieceLength {
67 ret.Length = pieceLength - ret.Begin
72 func (p *piece) shuffledPendingChunkSpecs(t *torrent, piece int) (css []chunkSpec) {
74 // log.Println(piece, css)
76 numPending := t.pieceNumPendingChunks(piece)
80 css = make([]chunkSpec, 0, numPending)
81 for ci := range iter.N(t.pieceNumChunks(piece)) {
82 if ci >= len(p.DirtyChunks) || !p.DirtyChunks[ci] {
83 css = append(css, t.chunkIndexSpec(ci, piece))
91 css[i], css[j] = css[j], css[i]
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()