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 (p *piece) pendChunkIndex(i int) {
65 if i >= len(p.DirtyChunks) {
68 p.DirtyChunks[i] = false
71 func chunkIndexSpec(index int, pieceLength, chunkSize pp.Integer) chunkSpec {
72 ret := chunkSpec{pp.Integer(index) * chunkSize, chunkSize}
73 if ret.Begin+ret.Length > pieceLength {
74 ret.Length = pieceLength - ret.Begin
79 func (p *piece) shuffledPendingChunkSpecs(t *torrent, piece int) (css []chunkSpec) {
81 // log.Println(piece, css)
83 numPending := t.pieceNumPendingChunks(piece)
87 css = make([]chunkSpec, 0, numPending)
88 for ci := range iter.N(t.pieceNumChunks(piece)) {
89 if ci >= len(p.DirtyChunks) || !p.DirtyChunks[ci] {
90 css = append(css, t.chunkIndexSpec(ci, piece))
98 css[i], css[j] = css[j], css[i]
103 func (p *piece) incrementPendingWrites() {
104 p.pendingWritesMutex.Lock()
106 p.pendingWritesMutex.Unlock()
109 func (p *piece) decrementPendingWrites() {
110 p.pendingWritesMutex.Lock()
111 if p.pendingWrites == 0 {
115 if p.pendingWrites == 0 {
116 p.noPendingWrites.Broadcast()
118 p.pendingWritesMutex.Unlock()
121 func (p *piece) waitNoPendingWrites() {
122 p.pendingWritesMutex.Lock()
123 for p.pendingWrites != 0 {
124 p.noPendingWrites.Wait()
126 p.pendingWritesMutex.Unlock()