func()

in lib/torrent/scheduler/dispatch/dispatcher.go [343:397]


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, ok := v.(*peer)
		if !ok {
			panic(fmt.Sprintf("dispatcher: stored value is not *peer: %T", v))
		}
		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.
			if err := p.messages.Send(conn.NewCompleteMessage()); err != nil {
				d.log("peer", p).Errorf("Error sending complete message: %s", err)
			}
		}
		return true
	})

	var piecesRequestedTotal int
	summaries := make(torrentlog.SeederSummaries, 0)
	d.peerStats.Range(func(k, v interface{}) bool {
		peerID, ok := k.(core.PeerID)
		if !ok {
			panic(fmt.Sprintf("dispatcher: stored key is not core.PeerID: %T", k))
		}
		pstats, ok := v.(*peerStats)
		if !ok {
			panic(fmt.Sprintf("dispatcher: stored value is not *peerStats: %T", v))
		}
		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)
		}
	}
}