mirror of
https://github.com/golang/go
synced 2024-11-22 03:24:41 -07:00
net: sort records returned by LookupSRV
R=golang-dev, rsc CC=golang-dev https://golang.org/cl/4518061
This commit is contained in:
parent
8ef0d181f6
commit
aea17570c0
@ -398,10 +398,49 @@ type SRV struct {
|
|||||||
Weight uint16
|
Weight uint16
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// byPriorityWeight sorts SRV records by ascending priority and weight.
|
||||||
|
type byPriorityWeight []*SRV
|
||||||
|
|
||||||
|
func (s byPriorityWeight) Len() int { return len(s) }
|
||||||
|
|
||||||
|
func (s byPriorityWeight) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||||
|
|
||||||
|
func (s byPriorityWeight) Less(i, j int) bool {
|
||||||
|
return s[i].Priority < s[j].Priority ||
|
||||||
|
(s[i].Priority == s[j].Priority && s[i].Weight < s[j].Weight)
|
||||||
|
}
|
||||||
|
|
||||||
|
// shuffleSRVByWeight shuffles SRV records by weight using the algorithm
|
||||||
|
// described in RFC 2782.
|
||||||
|
func shuffleSRVByWeight(addrs []*SRV) {
|
||||||
|
sum := 0
|
||||||
|
for _, addr := range addrs {
|
||||||
|
sum += int(addr.Weight)
|
||||||
|
}
|
||||||
|
for sum > 0 && len(addrs) > 1 {
|
||||||
|
s := 0
|
||||||
|
n := rand.Intn(sum + 1)
|
||||||
|
for i := range addrs {
|
||||||
|
s += int(addrs[i].Weight)
|
||||||
|
if s >= n {
|
||||||
|
if i > 0 {
|
||||||
|
t := addrs[i]
|
||||||
|
copy(addrs[1:i+1], addrs[0:i])
|
||||||
|
addrs[0] = t
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sum -= int(addrs[0].Weight)
|
||||||
|
addrs = addrs[1:]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// LookupSRV tries to resolve an SRV query of the given service,
|
// LookupSRV tries to resolve an SRV query of the given service,
|
||||||
// protocol, and domain name, as specified in RFC 2782. In most cases
|
// protocol, and domain name, as specified in RFC 2782. In most cases
|
||||||
// the proto argument can be the same as the corresponding
|
// the proto argument can be the same as the corresponding
|
||||||
// Addr.Network().
|
// Addr.Network(). The returned records are sorted by priority
|
||||||
|
// and randomized by weight within a priority.
|
||||||
func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err os.Error) {
|
func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err os.Error) {
|
||||||
target := "_" + service + "._" + proto + "." + name
|
target := "_" + service + "._" + proto + "." + name
|
||||||
var records []dnsRR
|
var records []dnsRR
|
||||||
@ -414,6 +453,15 @@ func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err os.
|
|||||||
r := rr.(*dnsRR_SRV)
|
r := rr.(*dnsRR_SRV)
|
||||||
addrs[i] = &SRV{r.Target, r.Port, r.Priority, r.Weight}
|
addrs[i] = &SRV{r.Target, r.Port, r.Priority, r.Weight}
|
||||||
}
|
}
|
||||||
|
sort.Sort(byPriorityWeight(addrs))
|
||||||
|
i := 0
|
||||||
|
for j := 1; j < len(addrs); j++ {
|
||||||
|
if addrs[i].Priority != addrs[j].Priority {
|
||||||
|
shuffleSRVByWeight(addrs[i:j])
|
||||||
|
i = j
|
||||||
|
}
|
||||||
|
}
|
||||||
|
shuffleSRVByWeight(addrs[i:len(addrs)])
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user