]> git.ipfire.org Git - thirdparty/dnspython.git/commitdiff
take servers out of the mix based on rcode; add exponential backoff
authorBob Halley <halley@dnspython.org>
Fri, 2 Sep 2005 05:33:05 +0000 (05:33 +0000)
committerBob Halley <halley@dnspython.org>
Fri, 2 Sep 2005 05:33:05 +0000 (05:33 +0000)
Original author: Bob Halley <halley@dnspython.org>
Date: 2005-06-04 20:55:45

dns/resolver.py

index 6d4fa913b370b95addee49356b9280a8f39d747e..38e45d39aaab77c902f66766af68afa5d7328a68 100644 (file)
@@ -424,6 +424,16 @@ class Resolver(object):
         finally:
             lm.Close()
 
+    def _compute_timeout(self, start):
+        now = time.time()
+        if now < start:
+            # Time going backwards is bad.  Just give up.
+            raise Timeout
+        duration = now - start
+        if duration >= self.lifetime:
+            raise Timeout
+        return min(self.lifetime - duration, self.timeout)
+
     def query(self, qname, rdtype=dns.rdatatype.A, rdclass=dns.rdataclass.IN,
               tcp=False):
         """Query nameservers to find the answer to the question.
@@ -481,18 +491,12 @@ class Resolver(object):
             # make a copy of the servers list so we can alter it later.
             #
             nameservers = self.nameservers[:]
+            backoff = 0.10
             while response is None:
                 if len(nameservers) == 0:
                     raise NoNameservers
                 for nameserver in nameservers:
-                    now = time.time()
-                    if now < start:
-                        # Time going backwards is bad.  Just give up.
-                        raise Timeout
-                    duration = now - start
-                    if duration >= self.lifetime:
-                        raise Timeout
-                    timeout = min(self.lifetime - duration, self.timeout)
+                    timeout = self._compute_timeout(start)
                     try:
                         if tcp:
                             response = dns.query.tcp(request, nameserver,
@@ -526,7 +530,26 @@ class Resolver(object):
                     if rcode == dns.rcode.NOERROR or \
                            rcode == dns.rcode.NXDOMAIN:
                         break
+                    #
+                    # We got a response, but we're not happy with the
+                    # rcode in it.  Remove the server from the mix if
+                    # the rcode isn't SERVFAIL.
+                    #
+                    if rcode != dns.rcode.SERVFAIL:
+                        nameservers.remove(nameserver)
                     response = None
+                #
+                # All nameservers failed!
+                #
+                if len(nameservers) > 0:
+                    #
+                    # But we still have servers to try.  Sleep a bit
+                    # so we don't pound them!
+                    #
+                    timeout = self._compute_timeout(start)
+                    sleep_time = min(timeout, backoff)
+                    backoff *= 2
+                    time.sleep(sleep_time)
             if response.rcode() == dns.rcode.NXDOMAIN:
                 continue
             all_nxdomain = False