lib/server.go (70 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 (
"net"
"sync"
"sync/atomic"
"unsafe"
"github.com/golang/glog"
)
// UDP acceptor
type Server struct {
server bool
conn *net.UDPConn
logger loggerHelper
config *Config
stableServers []*DHCPServer
rcServers []*DHCPServer
bufPool sync.Pool
throttle *Throttle
}
// returns a pointer to the current config struct, so that if it does get changed while being used,
// it shouldn't affect the caller and this copy struct should be GC'ed when it falls out of scope
func (s *Server) GetConfig() *Config {
return s.config
}
// ListenAndServe starts the server
func (s *Server) ListenAndServe() error {
if !s.server {
s.startUpdatingServerList()
}
glog.Infof("Started server, processing DHCP requests...")
for {
s.handleConnection()
}
}
// SetConfig updates the server config
func (s *Server) SetConfig(config *Config) {
glog.Infof("Updating server config")
// update server list because Algorithm instance was recreated
config.Algorithm.UpdateStableServerList(s.stableServers)
config.Algorithm.UpdateRCServerList(s.rcServers)
atomic.SwapPointer((*unsafe.Pointer)(unsafe.Pointer(&s.config)), unsafe.Pointer(config))
// update the throttle rate
s.throttle.setRate(config.Rate)
glog.Infof("Updated server config")
}
// HasServers checks if the list of backend servers is not empty
func (s *Server) HasServers() bool {
return len(s.stableServers) > 0 || len(s.rcServers) > 0
}
// NewServer initialized a Server before returning it.
func NewServer(config *Config, serverMode bool, personalizedLogger PersonalizedLogger) (*Server, error) {
conn, err := net.ListenUDP("udp", config.Addr)
if err != nil {
return nil, err
}
// setup logger
var loggerHelper = &loggerHelperImpl{
version: config.Version,
personalizedLogger: personalizedLogger,
}
server := &Server{
server: serverMode,
conn: conn,
logger: loggerHelper,
config: config,
}
// pool to reuse packet buffers
server.bufPool = sync.Pool{
New: func() interface{} {
return make([]byte, server.GetConfig().PacketBufSize)
},
}
glog.Infof("Setting up throttle: Cache Size: %d - Cache Rate: %d - Request Rate: %d",
config.CacheSize, config.CacheRate, config.Rate)
throttle, err := NewThrottle(config.CacheSize, config.CacheRate, config.Rate)
if err != nil {
return nil, err
}
server.throttle = throttle
return server, nil
}