chiark / gitweb /
Properly document new backlog file resilience
[inn-innduct.git] / backends / mod-active.in
1 #! /usr/bin/perl
2 # fixscript will replace this line with require innshellvars.pl
3
4 # batch-active-update
5 # Author: David Lawrence <tale@isc.org>
6
7 # Reads a series of ctlinnd newgroup/rmgroup/changegroup commands, such as
8 # is output by checkgroups and actsync, and efficiently handles them all at
9 # once.  Input can come from command line files or stdin, a la awk/sed.
10
11 $oldact = $inn::active;         # active file location
12 $oldact = $inn::active;         # active file location (same; shut up, perl -w)
13 $newact = "$oldact.new$$";      # temporary name for new active file
14 $actime = "$oldact.times";      # active.times file
15 $pausemsg = 'batch active update, ok'; # message to be used for pausing?
16 $diff_flags = '';               # Flags for diff(1); default chosen if null.
17
18 $0 =~ s#^.*/##;
19
20 die "$0: must run as $inn::newsuser user"
21   unless $> == (getpwnam($inn::newsuser))[2];
22
23 $debug = -t STDOUT ? 1 : 0;
24
25 $| = 1;                # show output as it happens (for an rsh/ssh pipe)
26
27 # Guess at best flags for a condensed diff listing.  The
28 # checks for alternative operating systems is incomplete.
29 unless ($diff_flags) {
30   if (`diff -v 2>&1` =~ /GNU/) {
31     $diff_flags = '-U0';
32   } elsif ($^O =~ /^(dec_osf|solaris)$/) {
33     $diff_flags = '-C0';
34   } elsif ($^O eq 'nextstep') {
35     $diff_flags = '-c0';
36   } else {
37     $diff_flags = '-c';
38   }
39 }
40
41 print "reading list of groups to update\n" if $debug;
42
43 $eval  = "while (<OLDACT>) {\n";
44 $eval .= "  \$group = (split)[0];\n";
45
46 while (<>) {
47   if (/^\s*\S*ctlinnd newgroup (\S+) (\S)/) {
48     $toadd{$1} = $2;
49   } elsif (/^\s*\S*ctlinnd rmgroup (\S+)/) {
50     $eval .= "  next if \$group eq '$1';\n";
51   } elsif (/^\s*\S*ctlinnd changegroup (\S+) (\S)/) {
52     $eval .= "  s/ \\S+\$/ $2/ if \$group eq '$1';\n";
53   }
54 }
55
56 $eval .= "  delete \$toadd{\$group};\n";
57 $eval .= "  if (!print(NEWACT \$_)) {\n";
58 $eval .= "    die \"\$0: writing \$newact failed (\$!), aborting\\n\";\n";
59 $eval .= "  }\n";
60 $eval .= "}\n";
61
62 &ctlinnd("pause $pausemsg");
63
64 open(OLDACT, "< $oldact") || die "$0: open $oldact: $!\n";
65 open(NEWACT, "> $newact") || die "$0: open $newact: $!\n";
66
67 print "rewriting active file\n" if $debug;
68 eval $eval;
69 for (sort keys %toadd) {
70   $add = "$_ 0000000000 0000000001 $toadd{$_}\n";
71   if (!print( NEWACT $add)) {
72     &ctlinnd("go $pausemsg");
73     die "$0: writing $newact failed ($!), aborting\n";
74   }
75 }
76
77 close(OLDACT) || warn "$0: close $oldact: $!\n";
78 close(NEWACT) || warn "$0: close $newact: $!\n";
79
80 if (!rename("$oldact", "$oldact.old")) {
81   warn "$0: rename $oldact $oldact.old: $!\n";
82 }
83
84 if (!rename("$newact", "$oldact")) {
85   die "$0: rename $newact $oldact: $!\n";
86 }
87
88 &ctlinnd("reload active 'updated from checkgroups'");
89 system("diff $diff_flags $oldact.old $oldact");
90 &ctlinnd("go $pausemsg");
91
92 print "updating $actime\n" if $debug;
93 if (open(TIMES, ">> $actime")) {
94   $time = time;
95   for (sort keys %toadd) {
96     print TIMES "$_ $time checkgroups-update\n" || last;
97   }
98   close(TIMES) || warn "$0: close $actime: $!\n";
99 } else {
100   warn "$0: $actime not updated: $!\n";
101 }
102
103 exit 0;
104
105 sub
106 ctlinnd
107
108 {
109   local($command) = @_;
110
111   print "ctlinnd $command\n" if $debug;
112   if (system("$inn::newsbin/ctlinnd -s $command")) {
113     die "$0: \"$command\" failed, aborting\n";
114   }
115 }