]> git.ipfire.org Git - thirdparty/dnspython.git/commitdiff
Add indexing to Message.find_rrset()
authorBob Halley <halley@dnspython.org>
Fri, 2 Sep 2005 05:23:26 +0000 (05:23 +0000)
committerBob Halley <halley@dnspython.org>
Fri, 2 Sep 2005 05:23:26 +0000 (05:23 +0000)
Original author: Bob Halley <halley@dnspython.org>
Date: 2004-08-14 20:17:32

ChangeLog
dns/message.py

index 72bbda3a2c403f992b66f95dd244eac55e5e9ff9..e9cbfe69792d2a99fcc9f9de2114ed9ab7eeb48c 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,8 +1,14 @@
+2004-08-14  Bob Halley  <halley@dnspython.org>
+
+       * dns/message.py (Message.find_rrset): find_rrset() now uses an
+       index, vastly improving the from_wire() performance of large
+       messages such as zone transfers.
+
 2004-08-07  Bob Halley  <halley@dnspython.org>
 
        * (Version 1.3.2 released)
 
-2004-08-04  Bob Halley  <halley@nominum.com>
+2004-08-04  Bob Halley  <halley@dnspython.org>
 
        * dns/query.py: sending queries to a nameserver via IPv6 now
        works.
index e46470ed02cec528a369245791633df984c01f6e..007fb9743ced03edd0eb4f315b8601a00b420cca 100644 (file)
@@ -122,6 +122,10 @@ class Message(object):
     message sequence?  This variable is used when validating TSIG signatures
     on messages which are part of a zone transfer.
     @type first: bool
+    @ivar index: An index of rrsets in the message.  The index key is
+    (section, name, rdclass, rdtype, covers, deleting).  Indexing can be
+    disabled by setting the index to None.
+    @type index: dict
     """
 
     def __init__(self, id=None):
@@ -151,6 +155,7 @@ class Message(object):
         self.had_tsig = False
         self.multi = False
         self.first = True
+        self.index = {}
 
     def __repr__(self):
         return '<DNS message, ID ' + `self.id` + '>'
@@ -265,6 +270,18 @@ class Message(object):
                 return False
         return True
 
+    def section_number(self, section):
+        if section is self.question:
+            return 0
+        elif section is self.answer:
+            return 1
+        elif section is self.authority:
+            return 2
+        elif section is self.additional:
+            return 3
+        else:
+            raise ValueError, 'unknown section'
+
     def find_rrset(self, section, name, rdclass, rdtype,
                    covers=dns.rdatatype.NONE, deleting=None, create=False,
                    force_unique=False):
@@ -292,14 +309,23 @@ class Message(object):
         @raises KeyError: the RRset was not found and create was False
         @rtype: dns.rrset.RRset object"""
 
+        key = (self.section_number(section),
+               name, rdclass, rdtype, covers, deleting)
         if not force_unique:
-            for rrset in section:
-                if rrset.match(name, rdclass, rdtype, covers, deleting):
+            if not self.index is None:
+                rrset = self.index.get(key)
+                if not rrset is None:
                     return rrset
+            else:
+                for rrset in section:
+                    if rrset.match(name, rdclass, rdtype, covers, deleting):
+                        return rrset
         if not create:
             raise KeyError
         rrset = dns.rrset.RRset(name, rdclass, rdtype, covers, deleting)
         section.append(rrset)
+        if not self.index is None:
+            self.index[key] = rrset
         return rrset
 
     def get_rrset(self, section, name, rdclass, rdtype,