Remove duplicates in answers

This commit is contained in:
Alvaro Saurin committed 2015-05-26 10:53:13 +02:00
1 parent 174b47d1db
commit db0ef5cf5c
1 file changed
+52 -11
+52 -11
View File
@@ -6,18 +6,52 @@ import (
"time"
)
type uniqZoneRecordKey struct {
name string
ipv4 IPv4
}
// A group of ZoneRecords where there are no duplicates (according to the name & IPv4)
type uniqZoneRecords map[uniqZoneRecordKey]ZoneRecord
func newUniqZoneRecords() uniqZoneRecords {
return make(uniqZoneRecords, 0)
}
// Add a new ZoneRecord to the group
func (uzr *uniqZoneRecords) add(zr ZoneRecord) {
key := uniqZoneRecordKey{zr.Name(), ipToIPv4(zr.IP())}
(*uzr)[key] = zr
}
// Return the group as an slice
func (uzr *uniqZoneRecords) toSlice() []ZoneRecord {
res := make([]ZoneRecord, len(*uzr))
i := 0
for _, r := range *uzr {
res[i] = r
i++
}
return res
}
//////////////////////////////////////////////////////////////////////////////
// Lookup in the database for locally-introduced information
func (zone *zoneDb) lookup(target string, lfun func(ns *namesSet) []*recordEntry) (res []ZoneRecord, err error) {
uniq := newUniqZoneRecords()
for identName, nameset := range zone.idents {
if identName != defaultRemoteIdent {
for _, ze := range lfun(nameset) {
res = append(res, ze)
uniq.add(ze)
}
}
}
if len(res) == 0 {
err = LookupError(target)
if len(uniq) == 0 {
return nil, LookupError(target)
} else {
return uniq.toSlice(), nil
}
return
}
// Perform a lookup for a name in the zone
@@ -63,16 +97,19 @@ func (zone *zoneDb) domainLookup(target string, lfun ZoneLookupFunc) (res []Zone
res = make([]ZoneRecord, len(lanswers))
zone.mx.Lock()
now := zone.clock.Now()
for i, answer := range lanswers {
res[i], err = zone.getNamesSet(defaultRemoteIdent).addIPToName(answer, now)
uniq := newUniqZoneRecords()
for _, answer := range lanswers {
r, err := zone.getNamesSet(defaultRemoteIdent).addIPToName(answer, now)
if err != nil {
zone.mx.Unlock()
Warning.Printf("[zonedb] '%s' insertion for %s failed: %s", answer, target, err)
return nil, err
}
uniq.add(r)
}
zone.mx.Unlock()
return
return uniq.toSlice(), nil
}
// Perform a lookup for a name in the zone
@@ -83,6 +120,7 @@ func (zone *zoneDb) DomainLookupName(name string) (res []ZoneRecord, err error)
zone.mx.RLock()
now := zone.clock.Now()
uniq := newUniqZoneRecords()
for identName, nameset := range zone.idents {
for _, ze := range nameset.getEntriesForName(name) {
// filter the entries with expired TTL
@@ -91,7 +129,7 @@ func (zone *zoneDb) DomainLookupName(name string) (res []ZoneRecord, err error)
Debug.Printf("[zonedb] '%s': expired entry '%s' ignored: removing", name, ze)
nameset.deleteName(name)
} else {
res = append(res, ze)
uniq.add(ze)
}
}
if identName != defaultRemoteIdent {
@@ -100,8 +138,9 @@ func (zone *zoneDb) DomainLookupName(name string) (res []ZoneRecord, err error)
}
zone.mx.RUnlock()
if len(res) > 0 {
if len(uniq) > 0 {
Debug.Printf("[zonedb] '%s' resolved in local database", name)
res = uniq.toSlice()
} else {
res, err = zone.domainLookup(name, zone.mdnsCli.LookupName)
}
@@ -126,6 +165,7 @@ func (zone *zoneDb) DomainLookupInaddr(inaddr string) (res []ZoneRecord, err err
zone.mx.RLock()
now := zone.clock.Now()
uniq := newUniqZoneRecords()
for identName, nameset := range zone.idents {
for _, ze := range nameset.getEntriesForIP(revIPv4) {
// filter the entries with expired TTL
@@ -134,7 +174,7 @@ func (zone *zoneDb) DomainLookupInaddr(inaddr string) (res []ZoneRecord, err err
Debug.Printf("[zonedb] '%s': expired entry '%s' ignored: removing", revIPv4, ze)
nameset.deleteIP(revIPv4)
} else {
res = append(res, ZoneRecord(ze))
uniq.add(ze)
if identName != defaultRemoteIdent {
nameset.touchName(ze.Name(), now)
}
@@ -143,8 +183,9 @@ func (zone *zoneDb) DomainLookupInaddr(inaddr string) (res []ZoneRecord, err err
}
zone.mx.RUnlock()
if len(res) > 0 {
if len(uniq) > 0 {
Debug.Printf("[zonedb] '%s' resolved in local database", inaddr)
res = uniq.toSlice()
} else {
res, err = zone.domainLookup(inaddr, zone.mdnsCli.LookupInaddr)
}