func()

in tracker/peerstore/redis.go [159:199]


func (s *RedisStore) GetPeers(h core.InfoHash, n int) ([]*core.PeerInfo, error) {
	c := s.pool.Get()
	defer c.Close()

	// Try to sample n peers from each window in randomized order until we have
	// collected n distinct peers. This achieves random sampling across multiple
	// windows.
	// TODO(codyg): One limitation of random window sampling is we're no longer
	// guaranteed to include the latest completion bits. A simple way to mitigate
	// this is to decrease the number of windows.
	windows := s.peerSetWindows()
	randutil.ShuffleInt64s(windows)

	// Eliminate duplicates from other windows and collapses complete bits.
	selected := make(map[peerIdentity]bool)

	for i := 0; len(selected) < n && i < len(windows); i++ {
		k := peerSetKey(h, windows[i])
		result, err := redis.Strings(c.Do("SRANDMEMBER", k, n-len(selected)))
		if err == redis.ErrNil {
			continue
		} else if err != nil {
			return nil, err
		}
		for _, s := range result {
			id, complete, err := deserializePeer(s)
			if err != nil {
				log.Errorf("Error deserializing peer %q: %s", s, err)
				continue
			}
			selected[id] = selected[id] || complete
		}
	}

	var peers []*core.PeerInfo
	for id, complete := range selected {
		p := core.NewPeerInfo(id.peerID, id.ip, id.port, false, complete)
		peers = append(peers, p)
	}
	return peers, nil
}