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) numDirtyChunks() (ret int) {
56 for _, dirty := range p.DirtyChunks {
64 func (p *piece) unpendChunkIndex(i int) {
65 for i >= len(p.DirtyChunks) {
66 p.DirtyChunks = append(p.DirtyChunks, false)
68 p.DirtyChunks[i] = true
71 func (p *piece) pendChunkIndex(i int) {
72 if i >= len(p.DirtyChunks) {
75 p.DirtyChunks[i] = false
78 func chunkIndexSpec(index int, pieceLength, chunkSize pp.Integer) chunkSpec {
79 ret := chunkSpec{pp.Integer(index) * chunkSize, chunkSize}
80 if ret.Begin+ret.Length > pieceLength {
81 ret.Length = pieceLength - ret.Begin
86 func (p *piece) shuffledPendingChunkSpecs(t *torrent, piece int) (css []chunkSpec) {
88 // log.Println(piece, css)
90 numPending := t.pieceNumPendingChunks(piece)
94 css = make([]chunkSpec, 0, numPending)
95 for ci := range iter.N(t.pieceNumChunks(piece)) {
96 if ci >= len(p.DirtyChunks) || !p.DirtyChunks[ci] {
97 css = append(css, t.chunkIndexSpec(ci, piece))
104 j := rand.Intn(i + 1)
105 css[i], css[j] = css[j], css[i]
110 func (p *piece) incrementPendingWrites() {
111 p.pendingWritesMutex.Lock()
113 p.pendingWritesMutex.Unlock()
116 func (p *piece) decrementPendingWrites() {
117 p.pendingWritesMutex.Lock()
118 if p.pendingWrites == 0 {
122 if p.pendingWrites == 0 {
123 p.noPendingWrites.Broadcast()
125 p.pendingWritesMutex.Unlock()
128 func (p *piece) waitNoPendingWrites() {
129 p.pendingWritesMutex.Lock()
130 for p.pendingWrites != 0 {
131 p.noPendingWrites.Wait()
133 p.pendingWritesMutex.Unlock()