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
}