7 "github.com/anacrolix/missinggo/v2/bitmap"
9 "github.com/anacrolix/chansync"
10 request_strategy "github.com/anacrolix/torrent/request-strategy"
13 func (cl *Client) requester() {
15 update := func() chansync.Signaled {
19 return cl.updateRequests.Signaled()
21 minWait := time.After(100 * time.Millisecond)
22 maxWait := time.After(1000 * time.Millisecond)
24 case <-cl.closed.Done():
30 case <-cl.closed.Done():
38 func (cl *Client) tickleRequester() {
39 cl.updateRequests.Broadcast()
42 func (cl *Client) getRequestStrategyInput() request_strategy.Input {
43 ts := make([]request_strategy.Torrent, 0, len(cl.torrents))
44 for _, t := range cl.torrents {
45 rst := request_strategy.Torrent{
46 StableId: uintptr(unsafe.Pointer(t)),
49 rst.Capacity = t.storage.Capacity
51 rst.Pieces = make([]request_strategy.Piece, 0, len(t.pieces))
52 for i := range t.pieces {
54 rst.Pieces = append(rst.Pieces, request_strategy.Piece{
55 Request: !t.ignorePieceForRequests(i),
56 Priority: p.purePriority(),
57 Partial: t.piecePartiallyDownloaded(i),
58 Availability: p.availability,
59 Length: int64(p.length()),
60 NumPendingChunks: int(t.pieceNumPendingChunks(i)),
61 IterPendingChunks: p.iterUndirtiedChunks,
64 t.iterPeers(func(p *Peer) {
68 if p.piecesReceivedSinceLastRequestUpdate > p.maxPiecesReceivedBetweenRequestUpdates {
69 p.maxPiecesReceivedBetweenRequestUpdates = p.piecesReceivedSinceLastRequestUpdate
71 p.piecesReceivedSinceLastRequestUpdate = 0
72 rst.Peers = append(rst.Peers, request_strategy.Peer{
73 HasPiece: p.peerHasPiece,
74 MaxRequests: p.nominalMaxRequests(),
75 HasExistingRequest: func(r request_strategy.Request) bool {
76 _, ok := p.actualRequestState.Requests[r]
79 Choking: p.peerChoking,
80 PieceAllowedFast: func(i pieceIndex) bool {
81 return p.peerAllowedFast.Contains(bitmap.BitIndex(i))
83 DownloadRate: p.downloadRate(),
84 Age: time.Since(p.completedHandshake),
87 ptr: uintptr(unsafe.Pointer(p)),
93 return request_strategy.Input{
95 MaxUnverifiedBytes: cl.config.MaxUnverifiedBytes,
99 func (cl *Client) doRequests() {
100 nextPeerStates := request_strategy.Run(cl.getRequestStrategyInput())
101 for p, state := range nextPeerStates {
102 setPeerNextRequestState(p, state)
111 func (p peerId) Uintptr() uintptr {
115 func setPeerNextRequestState(_p request_strategy.PeerId, rp request_strategy.PeerNextRequestState) {
116 p := _p.(peerId).Peer
117 p.nextRequestState = rp
118 p.onNextRequestStateChanged()
121 func (p *Peer) applyNextRequestState() bool {
122 next := p.nextRequestState
123 current := p.actualRequestState
124 if !p.setInterested(next.Interested) {
127 for req := range current.Requests {
128 if _, ok := next.Requests[req]; !ok {
134 for req := range next.Requests {
135 more, err := p.request(req)