Index: trunk/DNSDB/ExportBIND.pm
===================================================================
--- trunk/DNSDB/ExportBIND.pm	(revision 850)
+++ trunk/DNSDB/ExportBIND.pm	(revision 851)
@@ -76,4 +76,97 @@
 print "open zonefile for '$loc', '$zonepath'\n";
     }
+
+    eval {
+
+      # write fresh records if:
+      #  - we are not using the cache
+      #  - force_refresh is set
+      #  - the zone has changed
+      #  - the cache file does not exist
+      #  - the cache file is empty
+      if (!$self->{usecache} || $self->{force_refresh} || $changed || !-e $cachefile || -z $cachefile) {
+        if ($self->{usecache}) {
+          open ZONECACHE, ">$tmpcache" or die "Error creating temporary file $tmpcache: $!\n";
+          $zonefilehandle = *ZONECACHE;
+        }
+
+        # need to fetch this separately since the rest of the records all (should) have real IPs in val
+        $soasth->execute($revid);
+        my (@zsoa) = $soasth->fetchrow_array();
+        $self->_printrec_tiny($zonefilehandle, $zsoa[7], 'y',\%recflags,$revzone,
+          $zsoa[0],$zsoa[1],$zsoa[2],$zsoa[3],$zsoa[4],$zsoa[5],$zsoa[6],$zsoa[8],'');
+
+        $recsth->execute($revid);
+        my $fullzone = _ZONE($tmpzone, 'ZONE', 'r', '.').($tmpzone->{isv6} ? '.ip6.arpa' : '.in-addr.arpa');
+
+        while (my ($host, $type, $val, $dist, $weight, $port, $ttl, $recid, $loc, $stamp, $expires, $stampactive)
+                = $recsth->fetchrow_array) {
+          next if $recflags{$recid};
+
+          # Check for out-of-zone data
+          if ($val =~ /\.arpa$/) {
+            # val is non-IP
+            if ($val !~ /$fullzone$/) {
+              warn "Not exporting out-of-zone record $val $typemap{$type} $host, $ttl (zone $tmpzone)\n";
+              next;
+            }
+          } else {
+            my $ipval = new NetAddr::IP $val;
+            if (!$tmpzone->contains($ipval)) {
+              warn "Not exporting out-of-zone record $val $typemap{$type} $host, $ttl (zone $tmpzone)\n";
+              next;
+            }
+          } # is $val a raw .arpa name?
+
+          # Spaces are evil.
+          $val =~ s/^\s+//;
+          $val =~ s/\s+$//;
+          if ($typemap{$type} ne 'TXT') {
+            # Leading or trailng spaces could be legit in TXT records.
+            $host =~ s/^\s+//;
+            $host =~ s/\s+$//;
+          }
+
+          $self->_printrec_tiny($zonefilehandle, $recid, 'y', \%recflags, $revzone,
+            $host, $type, $val, $dist, $weight, $port, $ttl, $loc, $stamp, $expires, $stampactive);
+
+          $recflags{$recid} = 1;
+
+        } # while ($recsth)
+
+        if ($self->{usecache}) {
+          close ZONECACHE; # force the file to be written
+          # catch obvious write errors that leave an empty temp file
+          if (-s $tmpcache) {
+            rename $tmpcache, $cachefile
+              or die "Error overwriting cache file $cachefile with temporary file: $!\n";
+          }
+        }
+
+      } # if $changed or cache filesize is 0
+
+    };
+    if ($@) {
+      die "error writing ".($self->{usecache} ? 'new data for ' : '')."$revzone: $@\n";
+      # error!  something borked, and we should be able to fall back on the old cache file
+      # report the error, somehow.
+    } else {
+      # mark zone as unmodified.  Only do this if no errors, that way
+      # export failures should recover a little more automatically.
+      $zonesth->execute($revid);
+    }
+
+#    if ($self->{usecache}) {
+#      # We've already made as sure as we can that a cached zone file is "good",
+#      # although possibly stale/obsolete due to errors creating a new one.
+#      eval {
+#        open CACHE, "<$cachefile" or die $!;
+#        print $datafile $_ or die "error copying cached $revzone to master file: $!" while <CACHE>;
+#        close CACHE;
+#      };
+#      die $@ if $@;
+#    }
+
+
 
     $soasth->execute($revid);
