VOL-2112 move to voltha-lib-go
Change-Id: Ic1af08003c1d2c698c0cce371e64f47b47b8d875
diff --git a/vendor/gopkg.in/jcmturner/dnsutils.v1/srv.go b/vendor/gopkg.in/jcmturner/dnsutils.v1/srv.go
new file mode 100644
index 0000000..15ea912
--- /dev/null
+++ b/vendor/gopkg.in/jcmturner/dnsutils.v1/srv.go
@@ -0,0 +1,95 @@
+package dnsutils
+
+import (
+ "math/rand"
+ "net"
+ "sort"
+)
+
+// OrderedSRV returns a count of the results and a map keyed on the order they should be used.
+// This based on the records' priority and randomised selection based on their relative weighting.
+// The function's inputs are the same as those for net.LookupSRV
+// To use in the correct order:
+//
+// count, orderedSRV, err := OrderedSRV(service, proto, name)
+// i := 1
+// for i <= count {
+// srv := orderedSRV[i]
+// // Do something such as dial this SRV. If fails move on the the next or break if it succeeds.
+// i += 1
+// }
+func OrderedSRV(service, proto, name string) (int, map[int]*net.SRV, error) {
+ _, addrs, err := net.LookupSRV(service, proto, name)
+ if err != nil {
+ return 0, make(map[int]*net.SRV), err
+ }
+ index, osrv := orderSRV(addrs)
+ return index, osrv, nil
+}
+
+func orderSRV(addrs []*net.SRV) (int, map[int]*net.SRV) {
+ // Initialise the ordered map
+ var o int
+ osrv := make(map[int]*net.SRV)
+
+ prioMap := make(map[int][]*net.SRV, 0)
+ for _, srv := range addrs {
+ prioMap[int(srv.Priority)] = append(prioMap[int(srv.Priority)], srv)
+ }
+
+ priorities := make([]int, 0)
+ for p := range prioMap {
+ priorities = append(priorities, p)
+ }
+
+ var count int
+ sort.Ints(priorities)
+ for _, p := range priorities {
+ tos := weightedOrder(prioMap[p])
+ for i, s := range tos {
+ count += 1
+ osrv[o+i] = s
+ }
+ o += len(tos)
+ }
+ return count, osrv
+}
+
+func weightedOrder(srvs []*net.SRV) map[int]*net.SRV {
+ // Get the total weight
+ var tw int
+ for _, s := range srvs {
+ tw += int(s.Weight)
+ }
+
+ // Initialise the ordered map
+ o := 1
+ osrv := make(map[int]*net.SRV)
+
+ // Whilst there are still entries to be ordered
+ l := len(srvs)
+ for l > 0 {
+ i := rand.Intn(l)
+ s := srvs[i]
+ var rw int
+ if tw > 0 {
+ // Greater the weight the more likely this will be zero or less
+ rw = rand.Intn(tw) - int(s.Weight)
+ }
+ if rw <= 0 {
+ // Put entry in position
+ osrv[o] = s
+ if len(srvs) > 1 {
+ // Remove the entry from the source slice by swapping with the last entry and truncating
+ srvs[len(srvs)-1], srvs[i] = srvs[i], srvs[len(srvs)-1]
+ srvs = srvs[:len(srvs)-1]
+ l = len(srvs)
+ } else {
+ l = 0
+ }
+ o += 1
+ tw = tw - int(s.Weight)
+ }
+ }
+ return osrv
+}