2016-07-24 17:22:46 -04:00
|
|
|
package protocol
|
|
|
|
|
|
|
|
import (
|
|
|
|
"sync"
|
|
|
|
)
|
|
|
|
|
|
|
|
type ServerList struct {
|
|
|
|
sync.RWMutex
|
|
|
|
servers []*ServerSpec
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewServerList() *ServerList {
|
|
|
|
return &ServerList{}
|
|
|
|
}
|
|
|
|
|
2017-04-25 17:40:25 -04:00
|
|
|
func (sl *ServerList) AddServer(server *ServerSpec) {
|
|
|
|
sl.Lock()
|
|
|
|
defer sl.Unlock()
|
2016-07-24 17:22:46 -04:00
|
|
|
|
2017-04-25 17:40:25 -04:00
|
|
|
sl.servers = append(sl.servers, server)
|
2016-07-24 17:22:46 -04:00
|
|
|
}
|
|
|
|
|
2017-04-25 17:40:25 -04:00
|
|
|
func (sl *ServerList) Size() uint32 {
|
|
|
|
sl.RLock()
|
|
|
|
defer sl.RUnlock()
|
2016-07-24 17:22:46 -04:00
|
|
|
|
2017-04-25 17:40:25 -04:00
|
|
|
return uint32(len(sl.servers))
|
2016-07-24 17:22:46 -04:00
|
|
|
}
|
|
|
|
|
2017-04-25 17:40:25 -04:00
|
|
|
func (sl *ServerList) GetServer(idx uint32) *ServerSpec {
|
|
|
|
sl.Lock()
|
|
|
|
defer sl.Unlock()
|
2016-07-24 17:22:46 -04:00
|
|
|
|
|
|
|
for {
|
2017-04-25 17:40:25 -04:00
|
|
|
if idx >= uint32(len(sl.servers)) {
|
2016-07-24 17:22:46 -04:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2017-04-25 17:40:25 -04:00
|
|
|
server := sl.servers[idx]
|
2016-07-24 17:22:46 -04:00
|
|
|
if !server.IsValid() {
|
2017-04-25 17:40:25 -04:00
|
|
|
sl.removeServer(idx)
|
2016-07-24 17:22:46 -04:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
return server
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-25 17:40:25 -04:00
|
|
|
func (sl *ServerList) removeServer(idx uint32) {
|
|
|
|
n := len(sl.servers)
|
|
|
|
sl.servers[idx] = sl.servers[n-1]
|
|
|
|
sl.servers = sl.servers[:n-1]
|
2016-07-24 17:22:46 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
type ServerPicker interface {
|
|
|
|
PickServer() *ServerSpec
|
|
|
|
}
|
|
|
|
|
|
|
|
type RoundRobinServerPicker struct {
|
|
|
|
sync.Mutex
|
|
|
|
serverlist *ServerList
|
|
|
|
nextIndex uint32
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewRoundRobinServerPicker(serverlist *ServerList) *RoundRobinServerPicker {
|
|
|
|
return &RoundRobinServerPicker{
|
|
|
|
serverlist: serverlist,
|
|
|
|
nextIndex: 0,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-25 17:40:25 -04:00
|
|
|
func (p *RoundRobinServerPicker) PickServer() *ServerSpec {
|
|
|
|
p.Lock()
|
|
|
|
defer p.Unlock()
|
2016-07-24 17:22:46 -04:00
|
|
|
|
2017-04-25 17:40:25 -04:00
|
|
|
next := p.nextIndex
|
|
|
|
server := p.serverlist.GetServer(next)
|
2016-07-24 17:22:46 -04:00
|
|
|
if server == nil {
|
|
|
|
next = 0
|
2017-04-25 17:40:25 -04:00
|
|
|
server = p.serverlist.GetServer(0)
|
2016-07-24 17:22:46 -04:00
|
|
|
}
|
|
|
|
next++
|
2017-04-25 17:40:25 -04:00
|
|
|
if next >= p.serverlist.Size() {
|
2016-07-24 17:22:46 -04:00
|
|
|
next = 0
|
|
|
|
}
|
2017-04-25 17:40:25 -04:00
|
|
|
p.nextIndex = next
|
2016-07-24 17:22:46 -04:00
|
|
|
|
|
|
|
return server
|
|
|
|
}
|