diff options
author | Bob Halley <halley@dnspython.org> | 2021-11-28 14:54:22 -0800 |
---|---|---|
committer | Bob Halley <halley@dnspython.org> | 2021-11-28 14:54:22 -0800 |
commit | 726b522a014cb486d16e468196f0b1d6be483952 (patch) | |
tree | a1a883b159ce5fb187b33b34ae5231c26733550e | |
parent | c706e26e990856311e35f46cb58eaf333e80ed2f (diff) | |
download | dnspython-new-unversioned-zone-txn.tar.gz |
Make unversioned zone txn node-based for greater simplicity and future usesnew-unversioned-zone-txn
(e.g. CNAME-and-other-data work).
-rw-r--r-- | dns/zone.py | 103 |
1 files changed, 36 insertions, 67 deletions
diff --git a/dns/zone.py b/dns/zone.py index 2f99b1b..a8179bf 100644 --- a/dns/zone.py +++ b/dns/zone.py @@ -790,104 +790,73 @@ class Zone(dns.transaction.TransactionManager): class Transaction(dns.transaction.Transaction): - _deleted_rdataset = dns.rdataset.Rdataset(dns.rdataclass.ANY, - dns.rdatatype.ANY) - def __init__(self, zone, replacement, read_only): super().__init__(zone, replacement, read_only) - self.rdatasets = {} + self.nodes = {} + if not self.replacement: + self.nodes.update(self.zone.nodes) + self.nodes_changed = False @property def zone(self): return self.manager def _get_rdataset(self, name, rdtype, covers): - rdataset = self.rdatasets.get((name, rdtype, covers)) - if rdataset is self._deleted_rdataset: + name = self.zone._validate_name(name) + node = self.nodes.get(name) + if node is None: return None - elif rdataset is None and not self.replacement: - rdataset = self.zone.get_rdataset(name, rdtype, covers) - return rdataset + return node.get_rdataset(self.zone.rdclass, rdtype, covers) def _put_rdataset(self, name, rdataset): assert not self.read_only - self.zone._validate_name(name) - self.rdatasets[(name, rdataset.rdtype, rdataset.covers)] = rdataset + name = self.zone._validate_name(name) + node = self.nodes.get(name) + if node is None: + node = self.zone.node_factory() + self.nodes[name] = node + node.replace_rdataset(rdataset) + self.nodes_changed = True def _delete_name(self, name): assert not self.read_only - # First remove any changes involving the name - remove = [] - for key in self.rdatasets: - if key[0] == name: - remove.append(key) - if len(remove) > 0: - for key in remove: - del self.rdatasets[key] - # Next add deletion records for any rdatasets matching the - # name in the zone - node = self.zone.get_node(name) - if node is not None: - for rdataset in node.rdatasets: - self.rdatasets[(name, rdataset.rdtype, rdataset.covers)] = \ - self._deleted_rdataset + if name in self.nodes: + del self.nodes[name] + self.nodes_changed = True def _delete_rdataset(self, name, rdtype, covers): assert not self.read_only - try: - del self.rdatasets[(name, rdtype, covers)] - except KeyError: - pass - rdataset = self.zone.get_rdataset(name, rdtype, covers) - if rdataset is not None: - self.rdatasets[(name, rdataset.rdtype, rdataset.covers)] = \ - self._deleted_rdataset + name = self.zone._validate_name(name) + node = self.nodes.get(name) + if node is not None: + pre_len = len(node) + node.delete_rdataset(self.zone.rdclass, rdtype, covers) + post_len = len(node) + if post_len < pre_len: + self.nodes_changed = True + if post_len == 0: + del self.nodes[name] def _name_exists(self, name): - for key, rdataset in self.rdatasets.items(): - if key[0] == name: - if rdataset != self._deleted_rdataset: - return True - else: - return None - self.zone._validate_name(name) - if self.zone.get_node(name): - return True - return False + name = self.zone._validate_name(name) + node = self.nodes.get(name) + return node is not None def _changed(self): - if self.read_only: - return False - else: - return len(self.rdatasets) > 0 + return self.nodes_changed def _end_transaction(self, commit): if commit and self._changed(): - if self.replacement: - self.zone.nodes = {} - for (name, rdtype, covers), rdataset in \ - self.rdatasets.items(): - if rdataset is self._deleted_rdataset: - self.zone.delete_rdataset(name, rdtype, covers) - else: - self.zone.replace_rdataset(name, rdataset) + self.zone.nodes = self.nodes def _set_origin(self, origin): if self.zone.origin is None: self.zone.origin = origin def _iterate_rdatasets(self): - # Expensive but simple! Use a versioned zone for efficient txn - # iteration. - if self.replacement: - rdatasets = self.rdatasets - else: - rdatasets = {} - for (name, rdataset) in self.zone.iterate_rdatasets(): - rdatasets[(name, rdataset.rdtype, rdataset.covers)] = rdataset - rdatasets.update(self.rdatasets) - for (name, _, _), rdataset in rdatasets.items(): - yield (name, rdataset) + for (name, node) in self.nodes.items(): + for rdataset in node.rdatasets: + yield (name, rdataset) def from_text(text, origin=None, rdclass=dns.rdataclass.IN, |