162 lines
3.6 KiB
Go
162 lines
3.6 KiB
Go
package resolver
|
|
|
|
import "strings"
|
|
|
|
func ClassifyLiveBatchHost(
|
|
host string,
|
|
cache DomainCacheState,
|
|
cacheSourceForHost func(string) DomainCacheSource,
|
|
wildcards WildcardMatcher,
|
|
) (priority int, nxHeavy bool) {
|
|
h := strings.TrimSpace(strings.ToLower(host))
|
|
if h == "" {
|
|
return 2, false
|
|
}
|
|
if wildcards.IsExact(h) {
|
|
return 1, false
|
|
}
|
|
source := cacheSourceForHost(h)
|
|
rec, ok := cache.Domains[h]
|
|
if !ok {
|
|
return 2, false
|
|
}
|
|
entry := GetCacheEntryBySource(rec, source)
|
|
if entry == nil {
|
|
return 2, false
|
|
}
|
|
stored := NormalizeCacheIPs(entry.IPs)
|
|
state := NormalizeDomainState(entry.State, entry.Score)
|
|
errKind, hasErr := NormalizeCacheErrorKind(entry.LastErrorKind)
|
|
nxHeavy = hasErr && errKind == DNSErrorNXDomain && (state == DomainStateQuarantine || state == DomainStateHardQuar || entry.Score <= -10)
|
|
|
|
switch {
|
|
case len(stored) > 0:
|
|
return 1, false
|
|
case state == DomainStateActive || state == DomainStateStable || state == DomainStateSuspect:
|
|
return 1, false
|
|
case nxHeavy:
|
|
return 3, true
|
|
default:
|
|
return 2, false
|
|
}
|
|
}
|
|
|
|
func SplitLiveBatchCandidates(
|
|
candidates []string,
|
|
cache DomainCacheState,
|
|
cacheSourceForHost func(string) DomainCacheSource,
|
|
wildcards WildcardMatcher,
|
|
) (p1, p2, p3 []string, nxHeavyTotal int) {
|
|
for _, host := range candidates {
|
|
h := strings.TrimSpace(strings.ToLower(host))
|
|
if h == "" {
|
|
continue
|
|
}
|
|
prio, nxHeavy := ClassifyLiveBatchHost(h, cache, cacheSourceForHost, wildcards)
|
|
switch prio {
|
|
case 1:
|
|
p1 = append(p1, h)
|
|
case 3:
|
|
nxHeavyTotal++
|
|
p3 = append(p3, h)
|
|
case 2:
|
|
p2 = append(p2, h)
|
|
default:
|
|
if nxHeavy {
|
|
nxHeavyTotal++
|
|
p3 = append(p3, h)
|
|
} else {
|
|
p2 = append(p2, h)
|
|
}
|
|
}
|
|
}
|
|
return p1, p2, p3, nxHeavyTotal
|
|
}
|
|
|
|
func PickAdaptiveLiveBatch(
|
|
candidates []string,
|
|
target int,
|
|
now int,
|
|
nxHeavyPct int,
|
|
cache DomainCacheState,
|
|
cacheSourceForHost func(string) DomainCacheSource,
|
|
wildcards WildcardMatcher,
|
|
) ([]string, int, int, int, int, int) {
|
|
if len(candidates) == 0 {
|
|
return nil, 0, 0, 0, 0, 0
|
|
}
|
|
if target <= 0 {
|
|
p1, p2, p3, nxTotal := SplitLiveBatchCandidates(candidates, cache, cacheSourceForHost, wildcards)
|
|
return append([]string(nil), candidates...), len(p1), len(p2), len(p3), nxTotal, 0
|
|
}
|
|
if target > len(candidates) {
|
|
target = len(candidates)
|
|
}
|
|
if nxHeavyPct < 0 {
|
|
nxHeavyPct = 0
|
|
}
|
|
if nxHeavyPct > 100 {
|
|
nxHeavyPct = 100
|
|
}
|
|
|
|
start := now % len(candidates)
|
|
if start < 0 {
|
|
start = 0
|
|
}
|
|
rotated := make([]string, 0, len(candidates))
|
|
for i := 0; i < len(candidates); i++ {
|
|
idx := (start + i) % len(candidates)
|
|
rotated = append(rotated, candidates[idx])
|
|
}
|
|
p1, p2, p3, nxTotal := SplitLiveBatchCandidates(rotated, cache, cacheSourceForHost, wildcards)
|
|
out := make([]string, 0, target)
|
|
selectedP1 := 0
|
|
selectedP2 := 0
|
|
selectedP3 := 0
|
|
|
|
take := func(src []string, n int) ([]string, int) {
|
|
if n <= 0 || len(src) == 0 {
|
|
return src, 0
|
|
}
|
|
if n > len(src) {
|
|
n = len(src)
|
|
}
|
|
out = append(out, src[:n]...)
|
|
return src[n:], n
|
|
}
|
|
|
|
remain := target
|
|
var took int
|
|
p1, took = take(p1, remain)
|
|
selectedP1 += took
|
|
remain = target - len(out)
|
|
p2, took = take(p2, remain)
|
|
selectedP2 += took
|
|
remain = target - len(out)
|
|
|
|
p3Cap := (target * nxHeavyPct) / 100
|
|
if nxHeavyPct > 0 && p3Cap == 0 {
|
|
p3Cap = 1
|
|
}
|
|
if len(out) == 0 && len(p3) > 0 && p3Cap == 0 {
|
|
p3Cap = 1
|
|
}
|
|
if p3Cap > remain {
|
|
p3Cap = remain
|
|
}
|
|
p3, took = take(p3, p3Cap)
|
|
selectedP3 += took
|
|
|
|
if len(out) == 0 && len(p3) > 0 && target > 0 {
|
|
remain = target - len(out)
|
|
p3, took = take(p3, remain)
|
|
selectedP3 += took
|
|
}
|
|
|
|
nxSkipped := nxTotal - selectedP3
|
|
if nxSkipped < 0 {
|
|
nxSkipped = 0
|
|
}
|
|
return out, selectedP1, selectedP2, selectedP3, nxTotal, nxSkipped
|
|
}
|