Article 8659 of comp.lang.perl: Xref: feenix.metronet.com alt.sources:2388 comp.lang.perl:8659 news.software.b:2867 Newsgroups: alt.sources,comp.lang.perl,news.software.b Path: feenix.metronet.com!news.ecn.bgu.edu!usenet.ins.cwru.edu!gatech!swrinde!sgiblab!a2i!dhesi From: dhesi@rahul.net (Rahul Dhesi) Subject: update 'min' and 'max' fields in 'active' file Message-ID: Followup-To: alt.sources.d,comp.lang.perl,news.software.b Sender: news@rahul.net (Usenet News) Nntp-Posting-Host: bolero Organization: a2i network Date: Mon, 6 Dec 1993 09:21:14 GMT Lines: 254 Checksum: 204823036 (verify with 'brik') Submitter: Rahul Dhesi Archive-name: perl-source/dhesi/updminmax #! /usr/bin/perl # (C) Copyright 1993 Rahul Dhesi, All rights reserved. # Permission for copying and creation of derivative works is granted, # provided this copyright notice is preserved, to anybody who # does not discriminate against the copyright owner. # $Source: /news/bin/RCS/updminmax,v $ # $Id: updminmax,v 1.17 1993/12/06 09:12:31 news Exp $ # # Update min and max fields in active file. Based on ideas in # two shell scripts that come with C-News. This program # gets newsgroup names from the active file, gets the article numbers # from the spool directory for each newsgroup, and corrects the min # and max fields in the active file. It is useful for keeping the # min field updated. It is also useful for correcting errors in the # max field, which have been known to occur occasionally. A field length # of 5 digits for the min field and 10 digits for the max field # is forced -- this can be changed in the code by revising two # sprintf statements. The entire news system is locked while this program # runs. At the a2i network this program completes in about 8 to 10 # minutes. Locking is done by creating a symbolic link. # # This script is offered "as is", though it appears to work under # SunOS 4.1.1 running C-News derived from the May 1992 release and # using perl 4.019. $myname = "updminmax"; # Configuration information $NEWSCTL = '/news/lib'; # news lib (where active file resides) $NEWSARTS = '/news/news'; # news spool (where articles reside) # following will be changed only rarely $ACTIVE = 'active'; # name of active file $BACKUP = "$ACTIVE.before.$myname"; # back up active file by this name $INF = (1 << 30); # large no. bigger than all article numbers $ona2i = 0; # are we on the a2i network? $RCSHEADER = '$Source: /news/bin/RCS/updminmax,v $' . "\n" . '$Id: updminmax,v 1.17 1993/12/06 09:12:31 news Exp $'; $usage = "usage: $myname [-vtxnmCD] arg ... (or -h for help)"; if ($ARGV[0] =~ "^-.+" ) { require "getopts.pl"; &Getopts("vtxhnmCD"); } $debug = $opt_x; $trace = $opt_t; $verbose = $debug || $trace || $opt_v; $nolock = $opt_n; $clean = $opt_C; $diff = $opt_D; $summarize_max = $opt_m; if ($opt_h) { &givehelp(); exit(0); } chdir($NEWSCTL) || die "$myname: error: can't cd to $NEWSCTL: $!\n"; open(ACTIVE, $ACTIVE) || die "$myname: error: can't read $ACTIVE file: $!\n"; if (! $trace) { $newactive = "$ACTIVE.new.$$"; unlink($newactive); (-f $newactive) && die "$myname: error: can't unlink $newactive\n"; open(NEWACTIVE, ">$newactive") || die "$myname: error: can't write to $newactive\n"; } if ($verbose) { $| = 1; } # trap signals so we can unlock any lock on a signal $SIG{'INT'} = 'signal'; $SIG{'TERM'} = 'signal'; $SIG{'QUIT'} = 'signal'; $SIG{'TERM'} = 'signal'; $SIG{'PIPE'} = 'signal'; # lock news system -- will wait forever for lock &newslock() unless $nolock; $trace && print "$myname: TRACE: no writes to disk\n"; # do it eval '&main'; &newsunlock unless $nolock; $@ && die $@; exit; sub main { while () { ($group, $max, $min, $fourth) = split(' ', $_); (! $fourth) && die "$myname: fatal: less than 4 fields in $ACTIVE\n"; ($dir = $group) =~ s#\.#/#g; # map ng name to directory name if (opendir(DIR, "$NEWSARTS/$dir")) { $newmax = 0; $newmin = $INF; # infinity # find min and max fields by reading directory entries while ($entry = readdir(DIR)) { if ($entry =~ /^\d+$/) { # if all numeric if ($entry < $newmin) { $newmin = $entry; } if ($entry > $newmax) { $newmax = $entry; } } elsif ($debug) { if ($entry ne '.' && $entry ne '..' && $entry ne '.overview') { print "non-numeric: $NEWSARTS/$dir/$entry\n"; } } } if ($newmin == $INF) { # no articles found $newmax = $max; # old value of max $newmin = $max + 1; # .. and min is one higher } # don't let max get smaller. if ($newmax < $max) { $newmax = $max; } $newmin = sprintf("%05u", $newmin); $newmax = sprintf("%010u", $newmax); print NEWACTIVE "$group $newmax $newmin $fourth\n"; $verbose && print "$group $newmax $newmin $fourth\n"; if ($summarize_max && $max != $newmax) { printf "ng %20s max $max -> $newmax, min $min -> $newmin\n", $group; } } else { if ($clean) { $verbose && "$myname: omitting $group: no spool directory\n"; } else { print NEWACTIVE "$group $max $min $fourth\n"; $verbose && print "$group $max $min $fourth\n"; } } } close(ACTIVE); close(NEWACTIVE); if (! $trace) { if ($diff) { system "diff -u $ACTIVE $newactive > $ACTIVE.diff 2>&1"; } $oldlen = `wc -l < '$ACTIVE'`; chop $oldlen; $newlen = `wc -l < $newactive`; chop $newlen; if ($oldlen == $newlen) { # a2i use only -- preserve a numbered copy of the active file $ona2i && system("/news/bin/jab -P $ACTIVE"); unlink $BACKUP; link($ACTIVE, $BACKUP) || warn "$myname: could not link $ACTIVE to $BACKUP: $!\n"; rename($newactive, $ACTIVE) || die "$myname: error: rename $newactive $ACTIVE: $!\n"; } else { die "$myname: $newactive is bad; aborting, leaving $ACTIVE unchanged\n"; } } } ## sub usage_error { ## local($msg) = @_; ## if ($msg) { ## die "$msg\n"; ## } else { ## die "$usage\n"; ## } ## } sub givehelp { ## require 'local/page.pl'; ## &page(< $ltemp\n"; return; } open(LTEMP, ">$ltemp") || die "$myname: error: news lock failed\n"; print LTEMP "$$" || die "$myname: error: news lock failed\n"; close(LTEMP); for ( ; ; ) { if (symlink($ltemp, $lock)) { push(@UNLOCK_LIST, $lock); $debug && print "$myname: debug: locked: $lock -> $ltemp\n"; return; } $verbose && print "$myname: debug: waiting 30 seconds for lock\n"; sleep(30); } } sub newsunlock { if (@UNLOCK_LIST) { $verbose && print "newsunlock: unlink @UNLOCK_LIST\n"; (! $trace) && unlink @UNLOCK_LIST; } else { $verbose && print "newsunlock: empty UNLOCK_LIST\n"; } } # signal handler # -- newsunlock, then exit sub signal { &newsunlock(); unlink $newactive; exit; } ##### == END == .