- Timestamp:
- 06/12/13 16:58:14 (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/DNSDB.pm
r518 r521 4895 4895 # still be followed. 4896 4896 # 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 4905 4910 ##fixme: handle case of record-with-location-that-doesn't-exist better. 4906 4911 # note this currently fails safe (tested) - records with a location that … … 4912 4917 # timestamps are TAI64 4913 4918 # ~~ 2^62 + time() 4914 my $stamp = '';4915 4916 # support tinydns' auto-TTL4917 $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, 4929 4934 $dom, $host, $type, $val, $dist, $weight, $port, $ttl, $loc, $stamp) 4930 4935 if *ZONECACHE; 4931 4936 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 4943 4966 } # 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");4947 4967 4948 4968 # For reasons unknown, we can't sanely UNION these statements. Feh. … … 4963 4983 "FROM records WHERE rdns_id=? AND not type=6 ". 4964 4984 "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"); 4965 4987 $zonesth = $dbh->prepare("UPDATE revzones SET changed='n' WHERE rdns_id=?"); 4966 4988 $revsth->execute(); … … 4973 4995 # but that doesn't help other platforms. :/ 4974 4996 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 4989 5019 ##fixme: handle case of record-with-location-that-doesn't-exist better. 4990 5020 # note this currently fails safe (tested) - records with a location that … … 4996 5026 # timestamps are TAI64 4997 5027 # ~~ 2^62 + time() 4998 4999 5000 5001 5002 5003 5004 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) 5005 5035 if *ZONECACHE; 5006 5036 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 5018 5066 } # while ($domsth) 5019 5067
Note:
See TracChangeset
for help on using the changeset viewer.