in lib/torrent/scheduler/dispatch/dispatcher.go [392:425]
func (d *Dispatcher) resendFailedPieceRequests() {
failedRequests := d.pieceRequestManager.GetFailedRequests()
if len(failedRequests) > 0 {
d.log().Infof("Resending %d failed piece requests", len(failedRequests))
d.stats.Counter("piece_request_failures").Inc(int64(len(failedRequests)))
}
var sent int
for _, r := range failedRequests {
d.peers.Range(func(k, v interface{}) bool {
p := v.(*peer)
if (r.Status == piecerequest.StatusExpired || r.Status == piecerequest.StatusInvalid) &&
r.PeerID == p.id {
// Do not resend to the same peer for expired or invalid requests.
return true
}
b := d.torrent.Bitfield()
candidates := p.bitfield.Intersection(b.Complement())
if candidates.Test(uint(r.Piece)) {
nb := bitset.New(b.Len()).Set(uint(r.Piece))
if sent, err := d.maybeSendPieceRequests(p, nb); sent && err == nil {
return false
}
}
return true
})
}
unsent := len(failedRequests) - sent
if unsent > 0 {
d.log().Infof("Nowhere to resend %d / %d failed piece requests", unsent, len(failedRequests))
}
}