7 "github.com/anacrolix/log"
8 "github.com/anacrolix/multiless"
9 pp "github.com/anacrolix/torrent/peer_protocol"
10 "github.com/bradfitz/iter"
13 type clientPieceRequestOrder struct {
14 pieces []pieceRequestOrderPiece
17 type pieceRequestOrderPiece struct {
25 func (me *clientPieceRequestOrder) addPieces(t *Torrent, numPieces pieceIndex) {
26 for i := range iter.N(numPieces) {
27 me.pieces = append(me.pieces, pieceRequestOrderPiece{
34 func (me *clientPieceRequestOrder) removePieces(t *Torrent) {
35 newPieces := make([]pieceRequestOrderPiece, 0, len(me.pieces)-t.numPieces())
36 for _, p := range me.pieces {
38 newPieces = append(newPieces, p)
44 func (me clientPieceRequestOrder) sort() {
45 sort.SliceStable(me.pieces, me.less)
48 func (me clientPieceRequestOrder) update() {
49 for i := range me.pieces {
51 p.prio = p.t.piece(p.index).uncachedPriority()
52 p.partial = p.t.piecePartiallyDownloaded(p.index)
53 p.availability = p.t.pieceAvailability(p.index)
57 func (me clientPieceRequestOrder) less(_i, _j int) bool {
61 ml.Int(int(j.prio), int(i.prio))
62 ml.Bool(j.partial, i.partial)
63 ml.Int(i.availability, j.availability)
67 func (cl *Client) requester() {
75 case <-cl.closed.LockedChan(cl.locker()):
77 case <-time.After(10 * time.Millisecond):
82 func (cl *Client) doRequests() {
83 requestOrder := clientPieceRequestOrder{}
84 allPeers := make(map[*Torrent][]*Peer)
85 storageCapacity := make(map[*Torrent]*int64)
86 for _, t := range cl.torrents {
87 // TODO: We could do metainfo requests here.
89 value := int64(t.usualPieceSize())
90 storageCapacity[t] = &value
91 requestOrder.addPieces(t, t.numPieces())
94 t.iterPeers(func(p *Peer) {
95 peers = append(peers, p)
101 for _, p := range requestOrder.pieces {
102 if p.t.ignorePieceForRequests(p.index) {
105 peers := allPeers[p.t]
106 torrentPiece := p.t.piece(p.index)
107 if left := storageCapacity[p.t]; left != nil {
108 if *left < int64(torrentPiece.length()) {
111 *left -= int64(torrentPiece.length())
113 p.t.piece(p.index).iterUndirtiedChunks(func(chunk ChunkSpec) bool {
114 for _, peer := range peers {
115 req := Request{pp.Integer(p.index), chunk}
116 _, err := peer.request(req)
118 log.Printf("requested %v", req)
125 for _, t := range cl.torrents {
126 t.iterPeers(func(p *Peer) {
127 if !p.peerChoking && p.numLocalRequests() == 0 && !p.writeBufferFull() {
128 p.setInterested(false)
134 //func (requestStrategyDefaults) iterUndirtiedChunks(p requestStrategyPiece, f func(ChunkSpec) bool) bool {
135 // chunkIndices := p.dirtyChunks().Copy()
136 // chunkIndices.FlipRange(0, bitmap.BitIndex(p.numChunks()))
137 // return iter.ForPerm(chunkIndices.Len(), func(i int) bool {
138 // ci, err := chunkIndices.RB.Select(uint32(i))
142 // return f(p.chunkIndexRequest(pp.Integer(ci)).ChunkSpec)
147 //func iterUnbiasedPieceRequestOrder(
148 // cn requestStrategyConnection,
149 // f func(piece pieceIndex) bool,
150 // pieceRequestOrder []pieceIndex,
152 // cn.torrent().sortPieceRequestOrder(pieceRequestOrder)
153 // for _, i := range pieceRequestOrder {
154 // if !cn.peerHasPiece(i) || cn.torrent().ignorePieceForRequests(i) {