lib/rr.go (72 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" "hash/fnv" "sync" "sync/atomic" "github.com/golang/glog" ) type roundRobin struct { lock sync.RWMutex stable []*DHCPServer rc []*DHCPServer rcRatio uint32 iterStable int iterRC int iterList int // iterator used by SelectServerFromList, can be used in stable/rc or passing list manually } func (rr *roundRobin) Name() string { return "rr" } func (rr *roundRobin) getHash(token []byte) uint32 { hasher := fnv.New32a() hasher.Write(token) hash := hasher.Sum32() return hash } func (rr *roundRobin) SetRCRatio(ratio uint32) { atomic.StoreUint32(&rr.rcRatio, ratio) } func (rr *roundRobin) SelectServerFromList(list []*DHCPServer, message *DHCPMessage) (*DHCPServer, error) { rr.lock.RLock() defer rr.lock.RUnlock() if len(list) == 0 { return nil, errors.New("Server list is empty") } // no guarantee that lists are the same size, so modulo before incrementing rr.iterList = rr.iterList % len(list) server := list[rr.iterList] rr.iterList++ return server, nil } func (rr *roundRobin) SelectRatioBasedDhcpServer(message *DHCPMessage) (server *DHCPServer, err error) { // hash the clientid to see if it should be RC/Stable hash := rr.getHash(message.ClientID) rr.lock.Lock() if hash%100 < rr.rcRatio { rr.iterList = rr.iterRC rr.iterRC++ rr.lock.Unlock() return rr.SelectServerFromList(rr.rc, message) } //otherwise go stable rr.iterList = rr.iterStable rr.iterStable++ rr.lock.Unlock() return rr.SelectServerFromList(rr.stable, message) } func (rr *roundRobin) UpdateServerList(name string, list []*DHCPServer, ptr *[]*DHCPServer) error { rr.lock.Lock() defer rr.lock.Unlock() *ptr = list rr.iterStable = 0 rr.iterRC = 0 glog.Infof("List of available %s servers:", name) for _, server := range *ptr { glog.Infof("%s", server) } return nil } func (rr *roundRobin) UpdateStableServerList(list []*DHCPServer) error { return rr.UpdateServerList("stable", list, &rr.stable) } func (rr *roundRobin) UpdateRCServerList(list []*DHCPServer) error { return rr.UpdateServerList("rc", list, &rr.rc) }