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
16 func (me *piecePriority) Raise(maybe piecePriority) {
23 PiecePriorityNone piecePriority = iota // Not wanted.
24 PiecePriorityNormal // Wanted.
25 PiecePriorityReadahead // May be required soon.
26 PiecePriorityNext // Succeeds a piece where a read occurred.
27 PiecePriorityNow // A read occurred in this piece.
31 // The completed piece SHA1 hash, from the metainfo "pieces" field.
33 // Chunks we've written to since the last check. The chunk offset and
34 // length can be determined by the request chunkSize in use.
39 PublicPieceState PieceState
40 priority piecePriority
42 pendingWritesMutex sync.Mutex
44 noPendingWrites sync.Cond
47 func (p *piece) pendingChunk(cs chunkSpec, chunkSize pp.Integer) bool {
48 ci := chunkIndex(cs, chunkSize)
49 if ci >= len(p.DirtyChunks) {
52 return !p.DirtyChunks[ci]
55 func (p *piece) hasDirtyChunks() bool {
56 for _, dirty := range p.DirtyChunks {
64 func (p *piece) numDirtyChunks() (ret int) {
65 for _, dirty := range p.DirtyChunks {
73 func (p *piece) unpendChunkIndex(i int) {
74 for i >= len(p.DirtyChunks) {
75 p.DirtyChunks = append(p.DirtyChunks, false)
77 p.DirtyChunks[i] = true
80 func (p *piece) pendChunkIndex(i int) {
81 if i >= len(p.DirtyChunks) {
84 p.DirtyChunks[i] = false
87 func chunkIndexSpec(index int, pieceLength, chunkSize pp.Integer) chunkSpec {
88 ret := chunkSpec{pp.Integer(index) * chunkSize, chunkSize}
89 if ret.Begin+ret.Length > pieceLength {
90 ret.Length = pieceLength - ret.Begin
95 func (p *piece) shuffledPendingChunkSpecs(t *torrent, piece int) (css []chunkSpec) {
97 // log.Println(piece, css)
99 numPending := t.pieceNumPendingChunks(piece)
103 css = make([]chunkSpec, 0, numPending)
104 for ci := range iter.N(t.pieceNumChunks(piece)) {
105 if ci >= len(p.DirtyChunks) || !p.DirtyChunks[ci] {
106 css = append(css, t.chunkIndexSpec(ci, piece))
113 j := rand.Intn(i + 1)
114 css[i], css[j] = css[j], css[i]
119 func (p *piece) incrementPendingWrites() {
120 p.pendingWritesMutex.Lock()
122 p.pendingWritesMutex.Unlock()
125 func (p *piece) decrementPendingWrites() {
126 p.pendingWritesMutex.Lock()
127 if p.pendingWrites == 0 {
131 if p.pendingWrites == 0 {
132 p.noPendingWrites.Broadcast()
134 p.pendingWritesMutex.Unlock()
137 func (p *piece) waitNoPendingWrites() {
138 p.pendingWritesMutex.Lock()
139 for p.pendingWrites != 0 {
140 p.noPendingWrites.Wait()
142 p.pendingWritesMutex.Unlock()