]> Sergey Matveev's repositories - btrtrc.git/blob - request-strategy.go
Extract request strategy stuff into a separate module
[btrtrc.git] / request-strategy.go
1 package torrent
2
3 import (
4         "log"
5         "time"
6         "unsafe"
7
8         request_strategy "github.com/anacrolix/torrent/request-strategy"
9         "github.com/anacrolix/torrent/types"
10 )
11
12 func (cl *Client) requester() {
13         for {
14                 func() {
15                         cl.lock()
16                         defer cl.unlock()
17                         cl.doRequests()
18                 }()
19                 select {
20                 case <-cl.closed.LockedChan(cl.locker()):
21                         return
22                 case <-time.After(100 * time.Millisecond):
23                 }
24         }
25 }
26
27 func (cl *Client) doRequests() {
28         ts := make([]*request_strategy.Torrent, 0, len(cl.torrents))
29         for _, t := range cl.torrents {
30                 rst := &request_strategy.Torrent{}
31                 if t.storage != nil {
32                         rst.Capacity = t.storage.Capacity
33                 }
34                 for i := range t.pieces {
35                         p := &t.pieces[i]
36                         rst.Pieces = append(rst.Pieces, request_strategy.Piece{
37                                 Request:          !t.ignorePieceForRequests(i),
38                                 Priority:         p.purePriority(),
39                                 Partial:          t.piecePartiallyDownloaded(i),
40                                 Availability:     p.availability,
41                                 Length:           int64(p.length()),
42                                 NumPendingChunks: int(t.pieceNumPendingChunks(i)),
43                                 IterPendingChunks: func(f func(types.ChunkSpec)) {
44                                         p.iterUndirtiedChunks(func(cs ChunkSpec) bool {
45                                                 f(cs)
46                                                 return true
47                                         })
48                                 },
49                         })
50                 }
51                 t.iterPeers(func(p *Peer) {
52                         if p.closed.IsSet() {
53                                 return
54                         }
55                         rst.Peers = append(rst.Peers, &request_strategy.Peer{
56                                 HasPiece:    p.peerHasPiece,
57                                 MaxRequests: p.nominalMaxRequests,
58                                 HasExistingRequest: func(r request_strategy.Request) bool {
59                                         _, ok := p.requests[r]
60                                         return ok
61                                 },
62                                 Choking: p.peerChoking,
63                                 PieceAllowedFast: func(i pieceIndex) bool {
64                                         return p.peerAllowedFast.Contains(i)
65                                 },
66                                 DownloadRate: p.downloadRate(),
67                                 Age:          time.Since(p.completedHandshake),
68                                 Id:           unsafe.Pointer(p),
69                         })
70                 })
71                 ts = append(ts, rst)
72         }
73         nextPeerStates := cl.pieceRequestOrder.DoRequests(ts)
74         for p, state := range nextPeerStates {
75                 applyPeerNextRequestState(p, state)
76         }
77 }
78
79 func applyPeerNextRequestState(_p request_strategy.PeerPointer, rp request_strategy.PeerNextRequestState) {
80         p := (*Peer)(_p)
81         p.setInterested(rp.Interested)
82         for req := range p.requests {
83                 if _, ok := rp.Requests[req]; !ok {
84                         p.cancel(req)
85                 }
86         }
87         for req := range rp.Requests {
88                 err := p.request(req)
89                 if err != nil {
90                         panic(err)
91                 } else {
92                         log.Print(req)
93                 }
94         }
95 }