Implement outstanding query detection.

Copied from the standard library and adapted to Go DNS.
This commit is contained in:
Miek Gieben 2013-08-24 02:28:58 +00:00
parent d117fda34b
commit bb71be0271
3 changed files with 42 additions and 5 deletions

View File

@ -48,15 +48,14 @@ func (c *Client) exchangeMerge(m *Msg, a string, s net.Conn) (r *Msg, rtt time.D
} }
// This adds a bunch of garbage, TODO(miek). // This adds a bunch of garbage, TODO(miek).
t := "nop" t := "nop"
if t1, ok := TypeToString[r.Question[0].Qtype]; ok { if t1, ok := TypeToString[m.Question[0].Qtype]; ok {
t = t1 t = t1
} }
cl := "nop" cl := "nop"
if cl1, ok := ClassToString[r.Question[0].Qclass]; ok { if cl1, ok := ClassToString[m.Question[0].Qclass]; ok {
cl = cl1 cl = cl1
} }
key := r.Question[0].Name + t + cl r, rtt, err, shared := c.group.Do(m.Question[0].Name+t+cl, func() (*Msg, time.Duration, error) {
r, rtt, err, shared := c.group.Do(key, func() (*Msg, time.Duration, error) {
if s == nil { if s == nil {
return c.exchange(m, a) return c.exchange(m, a)
} }

View File

@ -41,6 +41,44 @@ func TestClientEDNS0(t *testing.T) {
} }
} }
func TestInflight(t *testing.T) {
m := new(Msg)
m.SetQuestion("miek.nl.", TypeDNSKEY)
c := new(Client)
c.Inflight = true
nr := 10
ch := make(chan time.Duration)
for i := 0; i < nr; i++ {
go func() {
_, rtt, _ := c.Exchange(m, "37.251.95.53:53")
ch <- rtt
}()
}
i := 0
var first time.Duration
// With inflight *all* rtt are identical, and by doing actual lookups
// the changes that this is a coincidence is small.
Loop:
for {
select {
case rtt := <-ch:
if i == 0 {
first = rtt
} else {
if first != rtt {
t.Log("All rtt should be equal")
t.Fail()
}
}
i++
if i == 10 {
break Loop
}
}
}
}
func TestClientTsigAXFR(t *testing.T) { func TestClientTsigAXFR(t *testing.T) {
m := new(Msg) m := new(Msg)
m.SetAxfr("miek.nl.") m.SetAxfr("miek.nl.")

View File

@ -46,7 +46,7 @@ func (g *singleflight) Do(key string, fn func() (*Msg, time.Duration, error)) (v
g.m[key] = c g.m[key] = c
g.Unlock() g.Unlock()
c.val, rtt, c.err = fn() c.val, c.rtt, c.err = fn()
c.wg.Done() c.wg.Done()
g.Lock() g.Lock()