engine: more performance improvements
This commit is contained in:
@@ -112,23 +112,35 @@ type geositeDomain struct {
|
||||
}
|
||||
|
||||
type geositeMatcher struct {
|
||||
Domains []geositeDomain
|
||||
Domains []geositeDomain // legacy slow path for tests and manual construction
|
||||
Plain []geositeDomain
|
||||
Regex []geositeDomain
|
||||
Root map[string]geositeDomain
|
||||
Full map[string]geositeDomain
|
||||
// Attributes are matched using "and" logic - if you have multiple attributes here,
|
||||
// a domain must have all of those attributes to be considered a match.
|
||||
Attrs []string
|
||||
}
|
||||
|
||||
func (m *geositeMatcher) matchDomain(domain geositeDomain, host HostInfo) bool {
|
||||
// Match attributes first
|
||||
if len(m.Attrs) > 0 {
|
||||
if len(domain.Attrs) == 0 {
|
||||
func (m *geositeMatcher) attrsMatch(domain geositeDomain) bool {
|
||||
if len(m.Attrs) == 0 {
|
||||
return true
|
||||
}
|
||||
if len(domain.Attrs) == 0 {
|
||||
return false
|
||||
}
|
||||
for _, attr := range m.Attrs {
|
||||
if !domain.Attrs[attr] {
|
||||
return false
|
||||
}
|
||||
for _, attr := range m.Attrs {
|
||||
if !domain.Attrs[attr] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (m *geositeMatcher) matchDomain(domain geositeDomain, host HostInfo) bool {
|
||||
// Match attributes first
|
||||
if !m.attrsMatch(domain) {
|
||||
return false
|
||||
}
|
||||
|
||||
switch domain.Type {
|
||||
@@ -152,7 +164,35 @@ func (m *geositeMatcher) matchDomain(domain geositeDomain, host HostInfo) bool {
|
||||
}
|
||||
|
||||
func (m *geositeMatcher) Match(host HostInfo) bool {
|
||||
for _, domain := range m.Domains {
|
||||
if host.Name == "" {
|
||||
return false
|
||||
}
|
||||
if domain, ok := m.Full[host.Name]; ok && m.attrsMatch(domain) {
|
||||
return true
|
||||
}
|
||||
for name := host.Name; name != ""; {
|
||||
if domain, ok := m.Root[name]; ok && m.attrsMatch(domain) {
|
||||
return true
|
||||
}
|
||||
idx := strings.IndexByte(name, '.')
|
||||
if idx < 0 {
|
||||
break
|
||||
}
|
||||
name = name[idx+1:]
|
||||
}
|
||||
for _, domain := range m.Plain {
|
||||
if m.matchDomain(domain, host) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
if len(m.Plain) == 0 && len(m.Regex) == 0 && len(m.Root) == 0 && len(m.Full) == 0 {
|
||||
for _, domain := range m.Domains {
|
||||
if m.matchDomain(domain, host) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, domain := range m.Regex {
|
||||
if m.matchDomain(domain, host) {
|
||||
return true
|
||||
}
|
||||
@@ -161,45 +201,53 @@ func (m *geositeMatcher) Match(host HostInfo) bool {
|
||||
}
|
||||
|
||||
func newGeositeMatcher(list *v2geo.GeoSite, attrs []string) (*geositeMatcher, error) {
|
||||
domains := make([]geositeDomain, len(list.Domain))
|
||||
for i, domain := range list.Domain {
|
||||
matcher := &geositeMatcher{
|
||||
Root: make(map[string]geositeDomain),
|
||||
Full: make(map[string]geositeDomain),
|
||||
Attrs: attrs,
|
||||
}
|
||||
for _, domain := range list.Domain {
|
||||
var compiled geositeDomain
|
||||
switch domain.Type {
|
||||
case v2geo.Domain_Plain:
|
||||
domains[i] = geositeDomain{
|
||||
compiled = geositeDomain{
|
||||
Type: geositeDomainPlain,
|
||||
Value: domain.Value,
|
||||
Attrs: domainAttributeToMap(domain.Attribute),
|
||||
}
|
||||
matcher.Plain = append(matcher.Plain, compiled)
|
||||
case v2geo.Domain_Regex:
|
||||
regex, err := regexp.Compile(domain.Value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
domains[i] = geositeDomain{
|
||||
compiled = geositeDomain{
|
||||
Type: geositeDomainRegex,
|
||||
Value: domain.Value,
|
||||
Regex: regex,
|
||||
Attrs: domainAttributeToMap(domain.Attribute),
|
||||
}
|
||||
matcher.Regex = append(matcher.Regex, compiled)
|
||||
case v2geo.Domain_Full:
|
||||
domains[i] = geositeDomain{
|
||||
compiled = geositeDomain{
|
||||
Type: geositeDomainFull,
|
||||
Value: domain.Value,
|
||||
Attrs: domainAttributeToMap(domain.Attribute),
|
||||
}
|
||||
matcher.Full[domain.Value] = compiled
|
||||
case v2geo.Domain_RootDomain:
|
||||
domains[i] = geositeDomain{
|
||||
compiled = geositeDomain{
|
||||
Type: geositeDomainRoot,
|
||||
Value: domain.Value,
|
||||
Attrs: domainAttributeToMap(domain.Attribute),
|
||||
}
|
||||
matcher.Root[domain.Value] = compiled
|
||||
default:
|
||||
return nil, errors.New("unsupported domain type")
|
||||
}
|
||||
matcher.Domains = append(matcher.Domains, compiled)
|
||||
}
|
||||
return &geositeMatcher{
|
||||
Domains: domains,
|
||||
Attrs: attrs,
|
||||
}, nil
|
||||
return matcher, nil
|
||||
}
|
||||
|
||||
func domainAttributeToMap(attrs []*v2geo.Domain_Attribute) map[string]bool {
|
||||
|
||||
Reference in New Issue
Block a user