in lib/torrent/scheduler/dispatch/dispatcher.go [312:355]
func (d *Dispatcher) complete() {
d.completeOnce.Do(func() { go d.events.DispatcherComplete(d) })
d.pendingPiecesDoneOnce.Do(func() { close(d.pendingPiecesDone) })
d.peers.Range(func(k, v interface{}) bool {
p := v.(*peer)
if p.bitfield.Complete() {
// Close connections to other completed peers since those connections
// are now useless.
d.log("peer", p).Info("Closing connection to completed peer")
p.messages.Close()
} else {
// Notify in-progress peers that we have completed the torrent and
// all pieces are available.
p.messages.Send(conn.NewCompleteMessage())
}
return true
})
var piecesRequestedTotal int
summaries := make(torrentlog.SeederSummaries, 0)
d.peerStats.Range(func(k, v interface{}) bool {
peerID := k.(core.PeerID)
pstats := v.(*peerStats)
requested := pstats.getPieceRequestsSent()
piecesRequestedTotal += requested
summary := torrentlog.SeederSummary{
PeerID: peerID,
RequestsSent: requested,
GoodPiecesReceived: pstats.getGoodPiecesReceived(),
DuplicatePiecesReceived: pstats.getDuplicatePiecesReceived(),
}
summaries = append(summaries, summary)
return true
})
// Only log if we actually requested pieces from others.
if piecesRequestedTotal > 0 {
if err := d.torrentlog.SeederSummaries(
d.torrent.Digest(), d.torrent.InfoHash(), summaries); err != nil {
d.log().Errorf("Error logging outgoing piece request summary: %s", err)
}
}
}