]> Sergey Matveev's repositories - btrtrc.git/blob - piece.go
Merge pull request #16 from scr4t/master
[btrtrc.git] / piece.go
1 package torrent
2
3 import (
4         "math/rand"
5         "sync"
6
7         pp "github.com/anacrolix/torrent/peer_protocol"
8 )
9
10 type piecePriority byte
11
12 const (
13         piecePriorityNone piecePriority = iota
14         piecePriorityNormal
15         piecePriorityReadahead
16         piecePriorityNext
17         piecePriorityNow
18 )
19
20 type piece struct {
21         Hash pieceSum
22         // Chunks we don't have. The offset and length can be determined by our
23         // request chunkSize in use.
24         PendingChunkSpecs []bool
25         Hashing           bool
26         QueuedForHash     bool
27         EverHashed        bool
28         Event             sync.Cond
29         Priority          piecePriority
30 }
31
32 func (p *piece) pendingChunk(cs chunkSpec) bool {
33         if p.PendingChunkSpecs == nil {
34                 return false
35         }
36         return p.PendingChunkSpecs[chunkIndex(cs)]
37 }
38
39 func (p *piece) numPendingChunks() (ret int) {
40         for _, pending := range p.PendingChunkSpecs {
41                 if pending {
42                         ret++
43                 }
44         }
45         return
46 }
47
48 func (p *piece) unpendChunkIndex(i int) {
49         if p.PendingChunkSpecs == nil {
50                 return
51         }
52         p.PendingChunkSpecs[i] = false
53 }
54
55 func chunkIndexSpec(index int, pieceLength pp.Integer) chunkSpec {
56         ret := chunkSpec{pp.Integer(index) * chunkSize, chunkSize}
57         if ret.Begin+ret.Length > pieceLength {
58                 ret.Length = pieceLength - ret.Begin
59         }
60         return ret
61 }
62
63 func (p *piece) shuffledPendingChunkSpecs(pieceLength pp.Integer) (css []chunkSpec) {
64         if p.numPendingChunks() == 0 {
65                 return
66         }
67         css = make([]chunkSpec, 0, p.numPendingChunks())
68         for i, pending := range p.PendingChunkSpecs {
69                 if pending {
70                         css = append(css, chunkIndexSpec(i, pieceLength))
71                 }
72         }
73         if len(css) <= 1 {
74                 return
75         }
76         for i := range css {
77                 j := rand.Intn(i + 1)
78                 css[i], css[j] = css[j], css[i]
79         }
80         return
81 }