Remove RRCache locking and clean up attributes

This commit is contained in:
Daniel 2020-09-30 17:16:45 +02:00
parent 7b5803482c
commit 7d9454f29a
3 changed files with 46 additions and 54 deletions

View file

@ -215,9 +215,7 @@ func checkCache(ctx context.Context, q *Query) *RRCache {
// Check if the cache will expire soon and start an async request. // Check if the cache will expire soon and start an async request.
if rrCache.ExpiresSoon() { if rrCache.ExpiresSoon() {
// Set flag that we are refreshing this entry. // Set flag that we are refreshing this entry.
rrCache.Lock() rrCache.RequestingNew = true
rrCache.requestingNew = true
rrCache.Unlock()
log.Tracer(ctx).Tracef( log.Tracer(ctx).Tracef(
"resolver: cache for %s will expire in %s, refreshing async now", "resolver: cache for %s will expire in %s, refreshing async now",
@ -397,7 +395,7 @@ resolveLoop:
// Check if we want to use an older cache instead. // Check if we want to use an older cache instead.
if oldCache != nil { if oldCache != nil {
oldCache.isBackup = true oldCache.IsBackup = true
switch { switch {
case err != nil: case err != nil:

View file

@ -196,9 +196,9 @@ func handleMDNSMessages(ctx context.Context, messages chan *dns.Msg) error {
if saveFullRequest { if saveFullRequest {
// get from database // get from database
rrCache, err = GetRRCache(question.Name, dns.Type(question.Qtype)) rrCache, err = GetRRCache(question.Name, dns.Type(question.Qtype))
// if we have no cached entry, or it has been updated less more than two seconds ago, or if it expired: // if we have no cached entry, or it has been updated more than two seconds ago, or if it expired:
// create new and do not append // create new and do not append
if err != nil || rrCache.updated < time.Now().Add(-2*time.Second).Unix() || rrCache.TTL < time.Now().Unix() { if err != nil || rrCache.Modified < time.Now().Add(-2*time.Second).Unix() || rrCache.Expired() {
rrCache = &RRCache{ rrCache = &RRCache{
Domain: question.Name, Domain: question.Name,
Question: dns.Type(question.Qtype), Question: dns.Type(question.Qtype),

View file

@ -5,7 +5,6 @@ import (
"fmt" "fmt"
"math/rand" "math/rand"
"net" "net"
"sync"
"time" "time"
"github.com/safing/portbase/log" "github.com/safing/portbase/log"
@ -15,31 +14,37 @@ import (
"github.com/miekg/dns" "github.com/miekg/dns"
) )
// RRCache is used to cache DNS data // RRCache is a single-use structure to hold a DNS response.
// Persistence is handled through NameRecords because of a limitation of the
// underlying dns library.
//nolint:maligned // TODO //nolint:maligned // TODO
type RRCache struct { type RRCache struct {
sync.Mutex // Respnse Header
Domain string
Question dns.Type
RCode int
Domain string // constant // Response Content
Question dns.Type // constant Answer []dns.RR
RCode int // constant Ns []dns.RR
Extra []dns.RR
TTL int64
Answer []dns.RR // mutable (mixing, non-standard formats) // Source Information
Ns []dns.RR // constant Server string
Extra []dns.RR // constant ServerScope int8
TTL int64 // constant ServerInfo string
Server string // constant // Metadata about the request and handling
ServerScope int8 // constant ServedFromCache bool
ServerInfo string // constant RequestingNew bool
IsBackup bool
Filtered bool
FilteredEntries []string
servedFromCache bool // mutable // Modified holds when this entry was last changed, ie. saved to database.
requestingNew bool // mutable // This field is only populated when the entry comes from the cache.
isBackup bool // mutable Modified int64
Filtered bool // mutable
FilteredEntries []string // mutable
updated int64 // mutable
} }
// ID returns the ID of the RRCache consisting of the domain and question type. // ID returns the ID of the RRCache consisting of the domain and question type.
@ -59,9 +64,6 @@ func (rrCache *RRCache) ExpiresSoon() bool {
// Clean sets all TTLs to 17 and sets cache expiry with specified minimum. // Clean sets all TTLs to 17 and sets cache expiry with specified minimum.
func (rrCache *RRCache) Clean(minExpires uint32) { func (rrCache *RRCache) Clean(minExpires uint32) {
rrCache.Lock()
defer rrCache.Unlock()
var lowestTTL uint32 = 0xFFFFFFFF var lowestTTL uint32 = 0xFFFFFFFF
var header *dns.RR_Header var header *dns.RR_Header
@ -200,7 +202,8 @@ func GetRRCache(domain string, question dns.Type) (*RRCache, error) {
rrCache.Server = nameRecord.Server rrCache.Server = nameRecord.Server
rrCache.ServerScope = nameRecord.ServerScope rrCache.ServerScope = nameRecord.ServerScope
rrCache.ServerInfo = nameRecord.ServerInfo rrCache.ServerInfo = nameRecord.ServerInfo
rrCache.servedFromCache = true rrCache.ServedFromCache = true
rrCache.Modified = nameRecord.Meta().Modified
return rrCache, nil return rrCache, nil
} }
@ -217,26 +220,16 @@ func parseRR(section []dns.RR, entry string) []dns.RR {
return section return section
} }
// ServedFromCache marks the RRCache as served from cache.
func (rrCache *RRCache) ServedFromCache() bool {
return rrCache.servedFromCache
}
// RequestingNew informs that it has expired and new RRs are being fetched.
func (rrCache *RRCache) RequestingNew() bool {
return rrCache.requestingNew
}
// Flags formats ServedFromCache and RequestingNew to a condensed, flag-like format. // Flags formats ServedFromCache and RequestingNew to a condensed, flag-like format.
func (rrCache *RRCache) Flags() string { func (rrCache *RRCache) Flags() string {
var s string var s string
if rrCache.servedFromCache { if rrCache.ServedFromCache {
s += "C" s += "C"
} }
if rrCache.requestingNew { if rrCache.RequestingNew {
s += "R" s += "R"
} }
if rrCache.isBackup { if rrCache.IsBackup {
s += "B" s += "B"
} }
if rrCache.Filtered { if rrCache.Filtered {
@ -255,21 +248,22 @@ func (rrCache *RRCache) ShallowCopy() *RRCache {
Domain: rrCache.Domain, Domain: rrCache.Domain,
Question: rrCache.Question, Question: rrCache.Question,
RCode: rrCache.RCode, RCode: rrCache.RCode,
Answer: rrCache.Answer,
Ns: rrCache.Ns, Answer: rrCache.Answer,
Extra: rrCache.Extra, Ns: rrCache.Ns,
TTL: rrCache.TTL, Extra: rrCache.Extra,
TTL: rrCache.TTL,
Server: rrCache.Server, Server: rrCache.Server,
ServerScope: rrCache.ServerScope, ServerScope: rrCache.ServerScope,
ServerInfo: rrCache.ServerInfo, ServerInfo: rrCache.ServerInfo,
updated: rrCache.updated, ServedFromCache: rrCache.ServedFromCache,
servedFromCache: rrCache.servedFromCache, RequestingNew: rrCache.RequestingNew,
requestingNew: rrCache.requestingNew, IsBackup: rrCache.IsBackup,
isBackup: rrCache.isBackup,
Filtered: rrCache.Filtered, Filtered: rrCache.Filtered,
FilteredEntries: rrCache.FilteredEntries, FilteredEntries: rrCache.FilteredEntries,
Modified: rrCache.Modified,
} }
} }
@ -308,7 +302,7 @@ func (rrCache *RRCache) ReplyWithDNS(ctx context.Context, request *dns.Msg) *dns
// GetExtraRRs returns a slice of RRs with additional informational records. // GetExtraRRs returns a slice of RRs with additional informational records.
func (rrCache *RRCache) GetExtraRRs(ctx context.Context, query *dns.Msg) (extra []dns.RR) { func (rrCache *RRCache) GetExtraRRs(ctx context.Context, query *dns.Msg) (extra []dns.RR) {
// Add cache status and source of data. // Add cache status and source of data.
if rrCache.servedFromCache { if rrCache.ServedFromCache {
extra = addExtra(ctx, extra, "served from cache, resolved by "+rrCache.ServerInfo) extra = addExtra(ctx, extra, "served from cache, resolved by "+rrCache.ServerInfo)
} else { } else {
extra = addExtra(ctx, extra, "freshly resolved by "+rrCache.ServerInfo) extra = addExtra(ctx, extra, "freshly resolved by "+rrCache.ServerInfo)
@ -320,10 +314,10 @@ func (rrCache *RRCache) GetExtraRRs(ctx context.Context, query *dns.Msg) (extra
} else { } else {
extra = addExtra(ctx, extra, fmt.Sprintf("record valid for %s", time.Until(time.Unix(rrCache.TTL, 0)).Round(time.Second))) extra = addExtra(ctx, extra, fmt.Sprintf("record valid for %s", time.Until(time.Unix(rrCache.TTL, 0)).Round(time.Second)))
} }
if rrCache.requestingNew { if rrCache.RequestingNew {
extra = addExtra(ctx, extra, "async request to refresh the cache has been started") extra = addExtra(ctx, extra, "async request to refresh the cache has been started")
} }
if rrCache.isBackup { if rrCache.IsBackup {
extra = addExtra(ctx, extra, "this record is served because a fresh request failed") extra = addExtra(ctx, extra, "this record is served because a fresh request failed")
} }