lib/modulo.go (58 lines of code) (raw):
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package dhcplb
import (
"errors"
"github.com/golang/glog"
"hash/fnv"
"sync"
"sync/atomic"
)
type modulo struct {
lock sync.RWMutex
stable []*DHCPServer
rc []*DHCPServer
rcRatio uint32
}
func (m *modulo) Name() string {
return "xid"
}
func (m *modulo) getHash(token []byte) uint32 {
hasher := fnv.New32a()
hasher.Write(token)
hash := hasher.Sum32()
return hash
}
func (m *modulo) SetRCRatio(ratio uint32) {
atomic.StoreUint32(&m.rcRatio, ratio)
}
func (m *modulo) SelectServerFromList(list []*DHCPServer, message *DHCPMessage) (*DHCPServer, error) {
hash := m.getHash(message.ClientID)
if len(list) == 0 {
return nil, errors.New("Server list is empty")
}
return list[hash%uint32(len(list))], nil
}
func (m *modulo) SelectRatioBasedDhcpServer(message *DHCPMessage) (*DHCPServer, error) {
m.lock.RLock()
defer m.lock.RUnlock()
hash := m.getHash(message.ClientID)
// convert to a number 0-100 and then see if it should be RC
if hash%100 < m.rcRatio {
return m.SelectServerFromList(m.rc, message)
}
// otherwise go to stable
return m.SelectServerFromList(m.stable, message)
}
func (m *modulo) UpdateServerList(name string, list []*DHCPServer, ptr *[]*DHCPServer) error {
m.lock.Lock()
defer m.lock.Unlock()
*ptr = list
glog.Infof("List of available %s servers:", name)
for _, server := range *ptr {
glog.Infof("%s", server)
}
return nil
}
func (m *modulo) UpdateStableServerList(list []*DHCPServer) error {
return m.UpdateServerList("stable", list, &m.stable)
}
func (m *modulo) UpdateRCServerList(list []*DHCPServer) error {
return m.UpdateServerList("rc", list, &m.rc)
}