...
1 package piece
2
3 import (
4 "fmt"
5 "sync"
6
7 "github.com/concurrency-8/parser"
8 )
9
10
11
12 type PieceTracker struct {
13 Torrent parser.TorrentFile
14 Requested [][]bool
15 Received [][]bool
16 lock sync.Mutex
17 }
18
19
20 func NewPieceTracker(torrent parser.TorrentFile) (tracker *PieceTracker) {
21 tracker = new(PieceTracker)
22 tracker.Torrent = torrent
23 numPieces := uint32(len(torrent.Piece) / 20)
24 fmt.Println("numPieces: ", numPieces)
25 for i := uint32(0); i < numPieces; i++ {
26 blocksPerPiece, _ := parser.BlocksPerPiece(torrent, i)
27 tracker.Requested = append(tracker.Requested, make([]bool, blocksPerPiece))
28 tracker.Received = append(tracker.Received, make([]bool, blocksPerPiece))
29 }
30 return
31 }
32
33
34
35 func (tracker *PieceTracker) AddRequested(block parser.PieceBlock) {
36 index := block.Begin / parser.BLOCK_LEN
37 tracker.Requested[block.Index][index] = true
38 }
39
40
41
42 func (tracker *PieceTracker) AddReceived(block parser.PieceBlock) {
43 index := block.Begin / parser.BLOCK_LEN
44 tracker.Received[block.Index][index] = true
45 }
46
47
48
49 func (tracker *PieceTracker) Needed(block parser.PieceBlock) bool {
50
51
52 allRequested := true
53 for _, i := range tracker.Requested {
54 if !allRequested {
55 break
56 }
57 for _, j := range i {
58 allRequested = allRequested && j
59 }
60 }
61
62
63 if allRequested {
64 tracker.lock.Lock()
65 tracker.Requested = clone(tracker.Received)
66 tracker.lock.Unlock()
67 }
68
69 return !tracker.Requested[block.Index][block.Begin/parser.BLOCK_LEN]
70 }
71
72
73 func clone(array [][]bool) (result [][]bool) {
74 for _, i := range array {
75 temp := make([]bool, len(i))
76 for index, j := range i {
77 temp[index] = j
78 }
79 result = append(result, temp)
80 }
81 return
82 }
83
84
85 func (tracker *PieceTracker) PieceIsDone(pieceIndex uint32) (result bool) {
86 result = true
87 for _, i := range tracker.Received[pieceIndex] {
88 result = result && i
89 }
90 return
91 }
92
93
94 func (tracker *PieceTracker) IsDone() (result bool) {
95 result = true
96 for _, i := range tracker.Received {
97 for _, j := range i {
98 result = result && j
99 }
100 }
101 return
102 }
103
104
105 func (tracker *PieceTracker) PrintPercentageDone() {
106 downloaded, total := 0.0, 0
107 for _, i := range tracker.Received {
108 for _, j := range i {
109 total++
110 if j {
111 downloaded++
112 }
113 }
114 }
115 percent := float64(downloaded*100) / float64(total)
116 fmt.Print("progress:", percent, "\r")
117 }
118
119
120 func (tracker *PieceTracker) Reset(index uint32) {
121 tracker.lock.Lock()
122 for i := range tracker.Requested[index] {
123 tracker.Requested[index][i] = false
124 tracker.Received[index][i] = false
125 }
126 tracker.lock.Unlock()
127 }
128
129
130 func (tracker *PieceTracker) Fill(index uint32) {
131 for i := range tracker.Requested[index] {
132 tracker.Requested[index][i] = true
133 tracker.Received[index][i] = true
134 }
135 }
136
View as plain text