- Timestamp:
- 06/12/13 17:17:57 (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/DNSDB.pm
r521 r523 4883 4883 my %recflags; 4884 4884 4885 my $domsth = $dbh->prepare("SELECT domain_id,domain,status,changed FROM domains WHERE status=1");4886 my $recsth = $dbh->prepare("SELECT host,type,val,distance,weight,port,ttl,record_id,location ".4887 "FROM records WHERE domain_id=? AND type < 65280"); # Just exclude all types relating to rDNS4888 my $zonesth = $dbh->prepare("UPDATE domains SET changed='n' WHERE domain_id=?");4889 $domsth->execute();4890 while (my ($domid,$dom,$domstat,$changed) = $domsth->fetchrow_array) {4891 ##fixme: need to find a way to block opening symlinked files without introducing a race.4892 # O_NOFOLLOW4893 # If pathname is a symbolic link, then the open fails. This is a FreeBSD extension, which was4894 # added to Linux in version 2.1.126. Symbolic links in earlier components of the pathname will4895 # still be followed.4896 # but that doesn't help other platforms. :/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 case4910 ##fixme: handle case of record-with-location-that-doesn't-exist better.4911 # note this currently fails safe (tested) - records with a location that4912 # doesn't exist will not be sent to any client4913 # $loc = '' if !$lochash->{$loc};4914 4915 ##fixme: record validity timestamp. tinydns supports fiddling with timestamps.4916 # note $ttl must be set to 0 if we want to use tinydns's auto-expiring timestamps.4917 # timestamps are TAI644918 # ~~ 2^62 + time()4919 my $stamp = '';4920 4921 # support tinydns' auto-TTL4922 $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,4934 $dom, $host, $type, $val, $dist, $weight, $port, $ttl, $loc, $stamp)4935 if *ZONECACHE;4936 4937 $recflags{$recid} = 1;4938 4939 } # while ($recsth)4940 4941 close ZONECACHE; # force the file to be written4942 4943 # catch obvious write errors that leave an empty temp file4944 if (-s $tmpcache) {4945 rename $tmpcache, $cachefile4946 or die "Error overwriting cache file $cachefile with temporary file: $!\n";4947 }4948 4949 } # if $changed or cache filesize is 04950 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 file4955 # report the error, somehow.4956 } else {4957 # mark domain as unmodified. Only do this if no errors, that way4958 # 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 4966 } # while ($domsth)4967 4968 4885 # For reasons unknown, we can't sanely UNION these statements. Feh. 4969 4886 # Supposedly it should work though (note last 3 lines): … … 4980 4897 my $soasth = $dbh->prepare("SELECT host,type,val,distance,weight,port,ttl,record_id,location ". 4981 4898 "FROM records WHERE rdns_id=? AND type=6"); 4982 $recsth = $dbh->prepare("SELECT host,type,val,distance,weight,port,ttl,record_id,location ".4899 my $recsth = $dbh->prepare("SELECT host,type,val,distance,weight,port,ttl,record_id,location ". 4983 4900 "FROM records WHERE rdns_id=? AND not type=6 ". 4984 4901 "ORDER BY masklen(CAST(val AS inet)) DESC, CAST(val AS inet)"); 4985 4902 my $revsth = $dbh->prepare("SELECT rdns_id,revnet,status,changed FROM revzones WHERE status=1 ". 4986 4903 "ORDER BY masklen(revnet) DESC"); 4987 $zonesth = $dbh->prepare("UPDATE revzones SET changed='n' WHERE rdns_id=?");4904 my $zonesth = $dbh->prepare("UPDATE revzones SET changed='n' WHERE rdns_id=?"); 4988 4905 $revsth->execute(); 4989 4906 while (my ($revid,$revzone,$revstat,$changed) = $revsth->fetchrow_array) { … … 5058 4975 # export failures should recover a little more automatically. 5059 4976 $zonesth->execute($revid); 4977 } 4978 # Always stream the cache (even if stale or obsolete due to errors creating the new cache) 4979 open CACHE, "<$cachefile"; 4980 print $datafile $_ while <CACHE>; 4981 close CACHE; 4982 4983 } # while ($revsth) 4984 4985 my $domsth = $dbh->prepare("SELECT domain_id,domain,status,changed FROM domains WHERE status=1"); 4986 $recsth = $dbh->prepare("SELECT host,type,val,distance,weight,port,ttl,record_id,location ". 4987 "FROM records WHERE domain_id=?"); # Just exclude all types relating to rDNS 4988 # "FROM records WHERE domain_id=? AND type < 65280"); # Just exclude all types relating to rDNS 4989 $zonesth = $dbh->prepare("UPDATE domains SET changed='n' WHERE domain_id=?"); 4990 $domsth->execute(); 4991 while (my ($domid,$dom,$domstat,$changed) = $domsth->fetchrow_array) { 4992 ##fixme: need to find a way to block opening symlinked files without introducing a race. 4993 # O_NOFOLLOW 4994 # If pathname is a symbolic link, then the open fails. This is a FreeBSD extension, which was 4995 # added to Linux in version 2.1.126. Symbolic links in earlier components of the pathname will 4996 # still be followed. 4997 # but that doesn't help other platforms. :/ 4998 my $cachefile = "$self->{exportcache}/$dom"; 4999 my $tmpcache = "$self->{exportcache}/tmp.$dom.$$"; 5000 eval { 5001 5002 # only update the cache file if the zone has changed, or if the cache file has nothing in it. 5003 if ($changed || !-e $cachefile || -z $cachefile) { 5004 open ZONECACHE, ">$tmpcache" or die "Error creating temporary file $tmpcache: $!\n"; 5005 5006 $recsth->execute($domid); 5007 while (my ($host,$type,$val,$dist,$weight,$port,$ttl,$recid,$loc) = $recsth->fetchrow_array) { 5008 next if $recflags{$recid}; 5009 5010 $loc = '' if !$loc; # de-nullify - just in case 5011 ##fixme: handle case of record-with-location-that-doesn't-exist better. 5012 # note this currently fails safe (tested) - records with a location that 5013 # doesn't exist will not be sent to any client 5014 # $loc = '' if !$lochash->{$loc}; 5015 5016 ##fixme: record validity timestamp. tinydns supports fiddling with timestamps. 5017 # note $ttl must be set to 0 if we want to use tinydns's auto-expiring timestamps. 5018 # timestamps are TAI64 5019 # ~~ 2^62 + time() 5020 my $stamp = ''; 5021 5022 # support tinydns' auto-TTL 5023 $ttl = '' if $ttl == -1; 5024 5025 # Spaces are evil. 5026 $host =~ s/^\s+//; 5027 $host =~ s/\s+$//; 5028 if ($typemap{$type} ne 'TXT') { 5029 # Leading or trailng spaces could be legit in TXT records. 5030 $val =~ s/^\s+//; 5031 $val =~ s/\s+$//; 5032 } 5033 5034 _printrec_tiny(*ZONECACHE, 'n', \%recflags, 5035 $dom, $host, $type, $val, $dist, $weight, $port, $ttl, $loc, $stamp) 5036 if *ZONECACHE; 5037 5038 $recflags{$recid} = 1; 5039 5040 } # while ($recsth) 5041 5042 close ZONECACHE; # force the file to be written 5043 5044 # catch obvious write errors that leave an empty temp file 5045 if (-s $tmpcache) { 5046 rename $tmpcache, $cachefile 5047 or die "Error overwriting cache file $cachefile with temporary file: $!\n"; 5048 } 5049 5050 } # if $changed or cache filesize is 0 5051 5052 }; 5053 if ($@) { 5054 print "error writing new data for $dom: $@\n"; 5055 # error! something borked, and we should be able to fall back on the old cache file 5056 # report the error, somehow. 5057 } else { 5058 # mark domain as unmodified. Only do this if no errors, that way 5059 # export failures should recover a little more automatically. 5060 $zonesth->execute($domid); 5060 5061 } 5061 5062 # Always stream the cache (even if stale or obsolete due to errors creating the new cache)
Note:
See TracChangeset
for help on using the changeset viewer.