* clients: Upstreams cache: refactor

don't use a separate container
This commit is contained in:
Simon Zolin 2020-01-09 17:29:53 +03:00
parent 87bcb67f8f
commit 995373c74b
1 changed files with 27 additions and 38 deletions

View File

@ -37,6 +37,11 @@ type Client struct {
BlockedServices []string BlockedServices []string
Upstreams []string // list of upstream servers to be used for the client's requests Upstreams []string // list of upstream servers to be used for the client's requests
// Upstream objects:
// nil: not yet initialized
// not nil, but empty: initialized, no good upstreams
// not nil, not empty: Upstreams ready to be used
upstreamObjects []upstream.Upstream
} }
type clientSource uint type clientSource uint
@ -62,11 +67,6 @@ type clientsContainer struct {
list map[string]*Client // name -> client list map[string]*Client // name -> client
idIndex map[string]*Client // IP -> client idIndex map[string]*Client // IP -> client
ipHost map[string]*ClientHost // IP -> Hostname ipHost map[string]*ClientHost // IP -> Hostname
// cache for Upstream instances that are used in the case
// when custom DNS servers are configured for a client
upstreamsCache map[string][]upstream.Upstream // name -> []Upstream
lock sync.Mutex lock sync.Mutex
// dhcpServer is used for looking up clients IP addresses by MAC addresses // dhcpServer is used for looking up clients IP addresses by MAC addresses
@ -84,7 +84,6 @@ func (clients *clientsContainer) Init(objects []clientObject, dhcpServer *dhcpd.
clients.list = make(map[string]*Client) clients.list = make(map[string]*Client)
clients.idIndex = make(map[string]*Client) clients.idIndex = make(map[string]*Client)
clients.ipHost = make(map[string]*ClientHost) clients.ipHost = make(map[string]*ClientHost)
clients.upstreamsCache = make(map[string][]upstream.Upstream)
clients.dhcpServer = dhcpServer clients.dhcpServer = dhcpServer
clients.addFromConfig(objects) clients.addFromConfig(objects)
@ -198,6 +197,12 @@ func (clients *clientsContainer) Find(ip string) (Client, bool) {
return clients.findByIP(ip) return clients.findByIP(ip)
} }
func upstreamArrayCopy(a []upstream.Upstream) []upstream.Upstream {
a2 := make([]upstream.Upstream, len(a))
copy(a2, a)
return a2
}
// FindUpstreams looks for upstreams configured for the client // FindUpstreams looks for upstreams configured for the client
// If no client found for this IP, or if no custom upstreams are configured, // If no client found for this IP, or if no custom upstreams are configured,
// this method returns nil // this method returns nil
@ -210,31 +215,22 @@ func (clients *clientsContainer) FindUpstreams(ip string) []upstream.Upstream {
return nil return nil
} }
if len(c.Upstreams) == 0 { if c.upstreamObjects == nil {
return nil c.upstreamObjects = make([]upstream.Upstream, 0)
}
upstreams, ok := clients.upstreamsCache[c.Name]
if ok {
return upstreams
}
for _, us := range c.Upstreams { for _, us := range c.Upstreams {
u, err := upstream.AddressToUpstream(us, upstream.Options{Timeout: dnsforward.DefaultTimeout}) u, err := upstream.AddressToUpstream(us, upstream.Options{Timeout: dnsforward.DefaultTimeout})
if err != nil { if err != nil {
log.Error("upstream.AddressToUpstream: %s: %s", us, err) log.Error("upstream.AddressToUpstream: %s: %s", us, err)
continue continue
} }
upstreams = append(upstreams, u) c.upstreamObjects = append(c.upstreamObjects, u)
}
} }
if len(upstreams) == 0 { if len(c.upstreamObjects) == 0 {
clients.upstreamsCache[c.Name] = nil return nil
} else {
clients.upstreamsCache[c.Name] = upstreams
} }
return upstreamArrayCopy(c.upstreamObjects)
return upstreams
} }
// Find searches for a client by IP (and does not lock anything) // Find searches for a client by IP (and does not lock anything)
@ -390,9 +386,6 @@ func (clients *clientsContainer) Del(name string) bool {
// update Name index // update Name index
delete(clients.list, name) delete(clients.list, name)
// update upstreams cache
delete(clients.upstreamsCache, name)
// update ID index // update ID index
for _, id := range c.IDs { for _, id := range c.IDs {
delete(clients.idIndex, id) delete(clients.idIndex, id)
@ -461,11 +454,7 @@ func (clients *clientsContainer) Update(name string, c Client) error {
} }
// update upstreams cache // update upstreams cache
if old.Name != c.Name { c.upstreamObjects = nil
delete(clients.upstreamsCache, old.Name)
} else {
delete(clients.upstreamsCache, c.Name)
}
*old = c *old = c
return nil return nil