Changeset 521


Ignore:
Timestamp:
06/12/13 16:58:14 (11 years ago)
Author:
Kris Deugau
Message:

/trunk

Finally commit a fix for the caching system so that it really
exports things properly. See #38.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/DNSDB.pm

    r518 r521  
    48954895#              still be followed.
    48964896# but that doesn't help other platforms.  :/
    4897     sysopen(ZONECACHE, "$self->{exportcache}/$dom", O_RDWR|O_CREAT);
    4898     flock(ZONECACHE, LOCK_EX);
    4899     if ($changed || -s "$self->{exportcache}/$dom" == 0) {
    4900       $recsth->execute($domid);
    4901       while (my ($host,$type,$val,$dist,$weight,$port,$ttl,$recid,$loc) = $recsth->fetchrow_array) {
    4902         next if $recflags{$recid};
    4903 
    4904         $loc = '' if !$loc;     # de-nullify - just in case
     4897    my $cachefile = "$self->{exportcache}/$dom";
     4898    my $tmpcache = "$self->{exportcache}/tmp.$dom.$$";
     4899    eval {
     4900
     4901      # only update the cache file if the zone has changed, or if the cache file has nothing in it.
     4902      if ($changed || !-e $cachefile || -z $cachefile) {
     4903        open ZONECACHE, ">$tmpcache" or die "Error creating temporary file $tmpcache: $!\n";
     4904
     4905        $recsth->execute($domid);
     4906        while (my ($host,$type,$val,$dist,$weight,$port,$ttl,$recid,$loc) = $recsth->fetchrow_array) {
     4907          next if $recflags{$recid};
     4908
     4909          $loc = '' if !$loc;   # de-nullify - just in case
    49054910##fixme:  handle case of record-with-location-that-doesn't-exist better.
    49064911# note this currently fails safe (tested) - records with a location that
     
    49124917# timestamps are TAI64
    49134918# ~~ 2^62 + time()
    4914         my $stamp = '';
    4915 
    4916         # support tinydns' auto-TTL
    4917         $ttl = '' if $ttl == -1;
    4918 
    4919         # Spaces are evil.
    4920         $host =~ s/^\s+//;
    4921         $host =~ s/\s+$//;
    4922         if ($typemap{$type} ne 'TXT') {
    4923           # Leading or trailng spaces could be legit in TXT records.
    4924           $val =~ s/^\s+//;
    4925           $val =~ s/\s+$//;
    4926         }
    4927 
    4928         _printrec_tiny(*ZONECACHE, 'n', \%recflags,
     4919          my $stamp = '';
     4920
     4921          # support tinydns' auto-TTL
     4922          $ttl = '' if $ttl == -1;
     4923
     4924          # Spaces are evil.
     4925          $host =~ s/^\s+//;
     4926          $host =~ s/\s+$//;
     4927          if ($typemap{$type} ne 'TXT') {
     4928            # Leading or trailng spaces could be legit in TXT records.
     4929            $val =~ s/^\s+//;
     4930            $val =~ s/\s+$//;
     4931          }
     4932
     4933          _printrec_tiny(*ZONECACHE, 'n', \%recflags,
    49294934                $dom, $host, $type, $val, $dist, $weight, $port, $ttl, $loc, $stamp)
    49304935                if *ZONECACHE;
    49314936
    4932         # in case the zone shrunk, get rid of garbage at the end of the file.
    4933         truncate(ZONECACHE, tell(ZONECACHE));
    4934 
    4935         $recflags{$recid} = 1;
    4936       } # while ($recsth)
    4937     }
    4938     # stream from cache, whether freshly created or existing
    4939     print $datafile $_ while <ZONECACHE>;
    4940     close ZONECACHE;
    4941     # mark domain as unmodified
    4942     $zonesth->execute($domid);
     4937          $recflags{$recid} = 1;
     4938
     4939        } # while ($recsth)
     4940
     4941        close ZONECACHE; # force the file to be written
     4942
     4943        # catch obvious write errors that leave an empty temp file
     4944        if (-s $tmpcache) {
     4945          rename $tmpcache, $cachefile
     4946            or die "Error overwriting cache file $cachefile with temporary file: $!\n";
     4947        }
     4948
     4949      } # if $changed or cache filesize is 0
     4950
     4951    };
     4952    if ($@) {
     4953      print "error writing new data for $dom: $@\n";
     4954      # error!  something borked, and we should be able to fall back on the old cache file
     4955      # report the error, somehow.
     4956    } else {
     4957      # mark domain as unmodified.  Only do this if no errors, that way
     4958      # export failures should recover a little more automatically.
     4959      $zonesth->execute($domid);
     4960    }
     4961    # Always stream the cache (even if stale or obsolete due to errors creating the new cache)
     4962    open CACHE, "<$cachefile";
     4963    print $datafile $_ while <CACHE>;
     4964    close CACHE;
     4965
    49434966  } # while ($domsth)
    4944 
    4945   my $revsth = $dbh->prepare("SELECT rdns_id,revnet,status,changed FROM revzones WHERE status=1 ".
    4946         "ORDER BY masklen(revnet) DESC");
    49474967
    49484968# For reasons unknown, we can't sanely UNION these statements.  Feh.
     
    49634983        "FROM records WHERE rdns_id=? AND not type=6 ".
    49644984        "ORDER BY masklen(CAST(val AS inet)) DESC, CAST(val AS inet)");
     4985  my $revsth = $dbh->prepare("SELECT rdns_id,revnet,status,changed FROM revzones WHERE status=1 ".
     4986        "ORDER BY masklen(revnet) DESC");
    49654987  $zonesth = $dbh->prepare("UPDATE revzones SET changed='n' WHERE rdns_id=?");
    49664988  $revsth->execute();
     
    49734995# but that doesn't help other platforms.  :/
    49744996    my $tmpzone = NetAddr::IP->new($revzone);
    4975     sysopen(ZONECACHE, "$self->{exportcache}/".$tmpzone->network->addr, O_RDWR|O_CREAT);
    4976     flock(ZONECACHE, LOCK_EX);
    4977     if ($changed || -s "$self->{exportcache}/".$tmpzone->network->addr == 0) {
    4978       # need to fetch this separately since the rest of the records all (should) have real IPs in val
    4979       $soasth->execute($revid);
    4980       my (@zsoa) = $soasth->fetchrow_array();
    4981       _printrec_tiny(*ZONECACHE,'y',\%recflags,$revzone,
    4982         $zsoa[0],$zsoa[1],$zsoa[2],$zsoa[3],$zsoa[4],$zsoa[5],$zsoa[6],$zsoa[8],'');
    4983 
    4984       $recsth->execute($revid);
    4985       while (my ($host,$type,$val,$dist,$weight,$port,$ttl,$recid,$loc) = $recsth->fetchrow_array) {
    4986         next if $recflags{$recid};
    4987 
    4988         $loc = '' if !$loc;     # de-nullify - just in case
     4997##fixme:  locations/views?  subnet mask?  need to avoid possible collisions with zone/superzone
     4998##        (eg /20 vs /24, starting on .0.0)
     4999    my $cz = $tmpzone->network->addr."-".$tmpzone->masklen;
     5000    my $cachefile = "$self->{exportcache}/$cz";
     5001    my $tmpcache = "$self->{exportcache}/tmp.$cz.$$";
     5002    eval {
     5003
     5004      # only update the cache file if the zone has changed, or if the cache file has nothing in it.
     5005      if ($changed || !-e $cachefile || -z $cachefile) {
     5006        open ZONECACHE, ">$tmpcache" or die "Error creating temporary file $tmpcache: $!\n";
     5007
     5008        # need to fetch this separately since the rest of the records all (should) have real IPs in val
     5009        $soasth->execute($revid);
     5010        my (@zsoa) = $soasth->fetchrow_array();
     5011        _printrec_tiny(*ZONECACHE,'y',\%recflags,$revzone,
     5012          $zsoa[0],$zsoa[1],$zsoa[2],$zsoa[3],$zsoa[4],$zsoa[5],$zsoa[6],$zsoa[8],'');
     5013
     5014        $recsth->execute($revid);
     5015        while (my ($host,$type,$val,$dist,$weight,$port,$ttl,$recid,$loc) = $recsth->fetchrow_array) {
     5016          next if $recflags{$recid};
     5017
     5018          $loc = '' if !$loc;   # de-nullify - just in case
    49895019##fixme:  handle case of record-with-location-that-doesn't-exist better.
    49905020# note this currently fails safe (tested) - records with a location that
     
    49965026# timestamps are TAI64
    49975027# ~~ 2^62 + time()
    4998         my $stamp = '';
    4999 
    5000         # support tinydns' auto-TTL
    5001         $ttl = '' if $ttl == -1;
    5002 
    5003         _printrec_tiny(*ZONECACHE, 'y', \%recflags, $revzone,
    5004                 $host, $type, $val, $dist, $weight, $port, $ttl, $loc, $stamp)
     5028          my $stamp = '';
     5029
     5030          # support tinydns' auto-TTL
     5031          $ttl = '' if $ttl == -1;
     5032
     5033          _printrec_tiny(*ZONECACHE, 'y', \%recflags, $revzone,
     5034            $host, $type, $val, $dist, $weight, $port, $ttl, $loc, $stamp)
    50055035                if *ZONECACHE;
    50065036
    5007         # in case the zone shrunk, get rid of garbage at the end of the file.
    5008         truncate(ZONECACHE, tell(ZONECACHE));
    5009 
    5010         $recflags{$recid} = 1;
    5011       } # while ($recsth)
    5012     }
    5013     # stream from cache, whether freshly created or existing
    5014     print $datafile $_ while <ZONECACHE>;
    5015     close ZONECACHE;
    5016     # mark zone as unmodified
    5017     $zonesth->execute($revid);
     5037          $recflags{$recid} = 1;
     5038
     5039        } # while ($recsth)
     5040
     5041        close ZONECACHE; # force the file to be written
     5042
     5043        # catch obvious write errors that leave an empty temp file
     5044        if (-s $tmpcache) {
     5045          rename $tmpcache, $cachefile
     5046            or die "Error overwriting cache file $cachefile with temporary file: $!\n";
     5047        }
     5048
     5049      } # if $changed or cache filesize is 0
     5050
     5051    };
     5052    if ($@) {
     5053      print "error writing new data for $revzone: $@\n";
     5054      # error!  something borked, and we should be able to fall back on the old cache file
     5055      # report the error, somehow.
     5056    } else {
     5057      # mark zone as unmodified.  Only do this if no errors, that way
     5058      # export failures should recover a little more automatically.
     5059      $zonesth->execute($revid);
     5060    }
     5061    # Always stream the cache (even if stale or obsolete due to errors creating the new cache)
     5062    open CACHE, "<$cachefile";
     5063    print $datafile $_ while <CACHE>;
     5064    close CACHE;
     5065
    50185066  } # while ($domsth)
    50195067
Note: See TracChangeset for help on using the changeset viewer.