forked from bradfitz/gomemcache
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathroundrobin_selector.go
More file actions
95 lines (84 loc) · 2.27 KB
/
roundrobin_selector.go
File metadata and controls
95 lines (84 loc) · 2.27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package memcache
import (
"net"
"strings"
"sync"
)
// NewRoundRobin returns a memcache client using the provided server(s)
// with equal weight. If a server is listed multiple times,
// it gets a proportional amount of weight.
func NewRoundRobin(server ...string) *Client {
ss := new(RoundRobinServerList)
err := ss.SetServers(server...)
if err != nil {
return nil
}
return NewFromRoundRobinSelector(ss)
}
// NewFromRoundRobinSelector returns a new Client using the provided RoundRobinServerSelector.
func NewFromRoundRobinSelector(ss *RoundRobinServerList) *Client {
return &Client{
selector: ss,
DisableCAS: false,
}
}
// RoundRobinServerList is a simple ServerSelector. Its zero value is usable.
type RoundRobinServerList struct {
mu sync.Mutex
addrs []net.Addr
next int
}
// SetServers changes a RoundRobinServerList's set of servers at runtime and is
// safe for concurrent use by multiple goroutines.
//
// Each server is given equal weight. A server is given more weight
// if it's listed multiple times.
//
// SetServers returns an error if any of the server names fail to
// resolve. No attempt is made to connect to the server. If any error
// is returned, no changes are made to the RoundRobinServerList.
func (ss *RoundRobinServerList) SetServers(servers ...string) error {
naddr := make([]net.Addr, len(servers))
for i, server := range servers {
if strings.Contains(server, "/") {
addr, err := net.ResolveUnixAddr("unix", server)
if err != nil {
return err
}
naddr[i] = newStaticAddr(addr)
} else {
tcpaddr, err := net.ResolveTCPAddr("tcp", server)
if err != nil {
return err
}
naddr[i] = newStaticAddr(tcpaddr)
}
}
ss.mu.Lock()
defer ss.mu.Unlock()
ss.addrs = naddr
return nil
}
// Each iterates over each server calling the given function
func (ss *RoundRobinServerList) Each(f func(net.Addr) error) error {
ss.mu.Lock()
defer ss.mu.Unlock()
for _, a := range ss.addrs {
if err := f(a); nil != err {
return err
}
}
return nil
}
func (ss *RoundRobinServerList) PickServer(key string) (net.Addr, error) {
ss.mu.Lock()
defer ss.mu.Unlock()
if len(ss.addrs) == 0 {
return nil, ErrNoServers
}
if len(ss.addrs) == 1 {
return ss.addrs[0], nil
}
ss.next = (ss.next + 1) % len(ss.addrs)
return ss.addrs[ss.next], nil
}