--- /dev/null
+#!@PERL@ -Tw
+#
+
+# Run perl.
+eval '(exit $?0)' && eval 'exec @PERL@ -S $0 ${1+"$@"}'
+ & eval 'exec @PERL@ -S $0 $argv:q'
+ if 0;
+
+require "newgetopt.pl";
+use Time::Local;
+use Text::ParseWords;
+
+delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV', 'PATH'};
+$ENV{'PATH'} = "/bin:/usr/bin:/usr/sbin:/sbin"; # force known path
+
+$confdir="@CONFIG_DIR@";
+$prefix='@prefix@';
+$prefix=$prefix; # avoid warnings about possible typo
+$exec_prefix="@exec_prefix@";
+$exec_prefix=$exec_prefix; # ditto
+$sbindir="@sbindir@";
+
+#$STATUS_STRANGE = 2;
+$STATUS_FAILED = 4;
+$STATUS_MISSING = 8;
+$STATUS_TAPE = 16;
+$exit_status = 0;
+
+$USE_VERSION_SUFFIXES='@USE_VERSION_SUFFIXES@';
+$suf = '';
+if ( $USE_VERSION_SUFFIXES =~ /^yes$/i ) {
+ $suf='-@VERSION@';
+}
+
+$result = &NGetOpt ( "summary",
+ "stats|statistics",
+ "dumping|d",
+ "waitdumping|wdumping",
+ "waittaper|wtaper",
+ "dumpingtape|dtape",
+ "writingtape|wtape",
+ "finished",
+ "failed|error",
+ "estimate",
+ "gestimate|gettingestimate",
+ "date",
+ "config|c:s",
+ "file:s",
+ "locale-independent-date-format",
+ );
+if($result !=1 ) {
+ &usage();
+}
+
+if( defined $opt_config ) {
+ $conf = $opt_config;
+}
+else {
+ if($#ARGV == 0 ) {
+ $conf=$ARGV[0];
+ }
+ else {
+ &usage();
+ }
+}
+
+#untaint user input $ARGV[0]
+
+if ($conf =~ /^([\w.-]+)$/) { # $1 is untainted
+ $conf = $1;
+} else {
+ die "filename '$conf' has invalid characters.\n";
+}
+
+if ( ! -e "$confdir/$conf" ) {
+ print "Configuration directory '" . $confdir/$conf . "' doesn't exist\n";
+ exit 1;
+}
+if ( ! -d "$confdir/$conf" ) {
+ print "Configuration directory '" . $confdir/$conf . "' is not a directory\n";
+ exit 1;
+ }
+
+
+$pwd = `pwd`;
+chomp $pwd;
+chdir "$confdir/$conf";
+
+$logdir=`$sbindir/amgetconf$suf logdir`;
+exit 1 if $? != 0;
+chomp $logdir;
+$errfile="$logdir/amdump";
+
+$nb_options = defined( $opt_summary ) +
+ defined( $opt_stats ) +
+ defined( $opt_dumping ) +
+ defined( $opt_waitdumping ) +
+ defined( $opt_waittaper ) +
+ defined( $opt_dumpingtape ) +
+ defined( $opt_writingtape ) +
+ defined( $opt_finished ) +
+ defined( $opt_estimate ) +
+ defined( $opt_gestimate ) +
+ defined( $opt_failed );
+
+if($nb_options == 0 ) {
+ $opt_summary = 1;
+ $opt_stats = 1;
+ $opt_dumping = 1;
+ $opt_waitdumping = 1;
+ $opt_waittaper = 1;
+ $opt_dumpingtape = 1;
+ $opt_writingtape = 1;
+ $opt_finished = 1;
+ $opt_failed = 1;
+ $opt_gestimate = 1;
+ $opt_estimate = 1;
+}
+
+$unit=`$sbindir/amgetconf$suf displayunit`;
+chomp($unit);
+$unit =~ tr/A-Z/a-z/;
+$unitdivisor=1;
+if($unit eq 'k') {
+ $unitdivisor = 1;
+}
+elsif($unit eq 'm') {
+ $unitdivisor = 1024;
+}
+elsif($unit eq 'g') {
+ $unitdivisor = 1024*1024;
+}
+elsif($unit eq 't') {
+ $unitdivisor = 1024*1024*1024;
+}
+else {
+ $unit = 'k';
+ $unitdivisor = 1;
+}
+
+
+if( defined $opt_file) {
+ if( $opt_file =~ m,^/, ) {
+ $errfile = $opt_file;
+ } else {
+ $errfile = "$pwd/$opt_file";
+ $errfile = "$logdir/$opt_file" if ( ! (-f $errfile ));
+ }
+}
+else {
+ $errfile="$logdir/amflush" if(! (-f $errfile));
+ if (! -f $errfile) {
+ if (-f "$logdir/amflush.1" && -f "$logdir/amdump.1" &&
+ -M "$logdir/amflush.1" < -M "$logdir/amdump.1") {
+ $errfile="$logdir/amflush.1";
+ } else {
+ $errfile="$logdir/amdump.1";
+ }
+ }
+}
+
+open(AMDUMP,"<$errfile") || die("$errfile: $!");
+print "Using $errfile\n";
+
+$start_degraded_mode = 0;
+
+$label = ""; # -w fodder
+$origsize = 0; # -w fodder
+$idle_dumpers = 0;
+$status_driver = "";
+$status_taper = 0;
+$estimate_done = 0;
+$holding_space = 0;
+$start_time = 0;
+@dumpers_active = ();
+$nb_tape = 0;
+$ntpartition{$nb_tape} = 0;
+$ntsize{$nb_tape} = 0;
+$ntesize{$nb_tape} = 0;
+$tape_size = 0;
+$driver_finished = 0;
+$generating_schedule = 0;
+
+while($lineX = <AMDUMP>) {
+ chomp $lineX;
+ $lineX =~ s/[:\s]+$//g; #remove separator at end of line
+ next if $lineX eq "";
+ @line = "ewords('[:\s]+', 0, $lineX);
+ next if !defined $line[0];
+
+ if($line[0] eq "amdump" || $line[0] eq "amflush") {
+ if ($line[1] eq "start" && $line[2] eq "at") {
+ $datestr = $lineX;
+ $datestr =~ s/.*start at //g;
+ if (!defined $opt_locale_independent_date_format) {
+ print "From " . $datestr . "\n";
+ }
+ } elsif($line[1] eq "datestamp") {
+ $gdatestamp = $line[2];
+ if(!defined $datestamp{$gdatestamp}) {
+ $datestamp{$gdatestamp} = 1;
+ push @datestamp, $gdatestamp;
+ }
+ } elsif($line[1] eq "starttime") {
+ $starttime=&set_starttime($line[2]);
+ } elsif($line[1] eq "starttime-locale-independent") {
+ if (defined $opt_locale_independent_date_format) {
+ printf "From " . $line[2] . " " . $line[3] . ":" . $line[4] . ":" . $line[5] . " " . $line[6] . "\n";
+ }
+ }
+ if($line[0] eq "amflush") {
+ $estimate_done=1;
+ }
+ } elsif($line[0] eq "planner") {
+ if($line[1] eq "timestamp") {
+ $gdatestamp = $line[2];
+ if(!defined $datestamp{$gdatestamp}) {
+ $datestamp{$gdatestamp} = 1;
+ push @datestamp, $gdatestamp;
+ }
+ }
+ elsif($line[1] eq "FAILED") {
+ #2:host 3:disk 4:datestamp 5:level 6:errmsg
+ $host=$line[2];
+ $partition=$line[3];
+ $datestamp=$line[4];
+ $hostpart=&make_hostpart($host,$partition,$datestamp);
+ $dump_started{$hostpart}=-1;
+ $level{$hostpart}=$line[5];
+ $error{$hostpart}="planner: " . $line[6];
+ } elsif($line[1] eq "time") {
+ if($line[3] eq "got") {
+ if($line[4] eq "result") {
+ $host = $line[7];
+ $partition = $line[9];
+ $hostpart=&make_hostpart($host,$partition,$gdatestamp);
+ $estimate{$hostpart}=1;
+ $level{$hostpart}=$line[10];
+ $line[12] =~ /(\d+)K/;
+ $esize{$hostpart}=$1 / $unitdivisor;
+ $partialestimate{$hostpart}=0;
+ $getest{$hostpart} = "";
+ } elsif($line[4] eq "partial") {
+ $host = $line[8];
+ $partition = $line[10];
+ $hostpart=&make_hostpart($host,$partition,$gdatestamp);
+ $level1 = $line[11];
+ $line[13] =~ /(-?\d+)K/;
+ $size1 = $1;
+ $level2 = $line[14];
+ $line[16] =~ /(-?\d+)K/;
+ $size2 = $1;
+ $level3 = $line[17];
+ $line[19] =~ /(-?\d+)K/;
+ $size3 = $1;
+ if($size1 > 0 || $size2 > 0 || $size3 > 0) {
+ $estimate{$hostpart}=1;
+ $level{$hostpart}=$line[11];
+ $esize{$hostpart}=$size1 / $unitdivisor;
+ $partialestimate{$hostpart}=1;
+ if($size1 > 0) { $getest{$hostpart} =~ s/:$level1://; }
+ if($size2 > 0) { $getest{$hostpart} =~ s/:$level2://; }
+ if($size3 > 0) { $getest{$hostpart} =~ s/:$level3://; }
+ if($getest{$hostpart} eq "") {$partialestimate{$hostpart}=0;}
+ }
+ }
+ } elsif($line[3] eq "getting" &&
+ $line[4] eq "estimates" &&
+ $line[5] eq "took") {
+ $estimate_done=1;
+ }
+ }
+ } elsif($line[0] eq "setup_estimate") {
+ $host = $line[1];
+ $partition = $line[2];
+ $hostpart=&make_hostpart($host,$partition,$gdatestamp);
+ $estimate{$hostpart}=0;
+ $level{$hostpart}=0;
+ $degr_level{$hostpart}=-1;
+ $esize{$hostpart}=0;
+ $dump_started{$hostpart}=0;
+ $dump_finished{$hostpart}=0;
+ $taper_started{$hostpart}=0;
+ $taper_finished{$hostpart}=0;
+ $partialestimate{$hostpart}=0;
+ $error{$hostpart}="";
+ if($line[7] eq "last_level") {
+ $getest{$hostpart}="";
+ $level1 = $line[15];
+ $level2 = $line[17];
+ $level3 = $line[19];
+ if($level1 != -1) { $getest{$hostpart} .= ":$level1:" };
+ if($level2 != -1) { $getest{$hostpart} .= ":$level2:" };
+ if($level3 != -1) { $getest{$hostpart} .= ":$level3:" };
+ }
+ } elsif($line[0] eq "GENERATING" &&
+ $line[1] eq "SCHEDULE") {
+ $generating_schedule=1;
+ } elsif($line[0] eq "--------") {
+ if ($generating_schedule == 1) {
+ $generating_schedule = 2;
+ } elsif ($generating_schedule == 2) {
+ $generating_schedule = 3;
+ }
+ } elsif($line[0] eq "DUMP") {
+ if($generating_schedule == 2 ) {
+ $host = $line[1];
+ $partition = $line[3];
+ $datestamp = $line[4];
+ $hostpart=&make_hostpart($host,$partition,$datestamp);
+ $level{$hostpart}=$line[6];
+ $esize=$line[14]; #compressed size
+ $esize=32 if $esize<32;
+ $esize{$hostpart}=$esize / $unitdivisor;
+ if(!defined($line[22])) {
+ $degr_level{$hostpart}=-1;
+ } else {
+ $degr_level{$hostpart}=$line[18];
+ $esize=$line[25]; #compressed size
+ $esize=32 if $esize<32;
+ $degr_size{$hostpart}=$esize / $unitdivisor;
+ }
+ }
+ } elsif($line[0] eq "FLUSH") {
+ $host = $line[1];
+ $partition = $line[2];
+ $datestamp = $line[3];
+ $level = $line[4];
+ $holding_file = $line[5];
+ $hostpart=&make_hostpart($host,$partition,$datestamp);
+ $flush{$hostpart}=0;
+ $holding_file{$hostpart}=$holding_file;
+ $level{$hostpart}=$level;
+ } elsif($line[0] eq "driver") {
+ if($line[1] eq "start" && $line[2] eq "time") {
+ $start_time=$line[3];
+ $current_time=$line[3];
+ $dumpers_active[0]=0;
+ $dumpers_held[0]={};
+ $dumpers_active=0;
+ }
+ elsif($line[1] eq "tape" && $line[2] eq "size") {
+ $lineX =~ /^driver: start time (\S+)/;
+ $tape_size = $line[3] / $unitdivisor;
+ }
+ elsif($line[1] eq "adding" &&
+ $line[2] eq "holding" &&
+ $line[3] eq "disk") {
+ $holding_space += $line[8];
+ }
+ elsif($line[1] eq "send-cmd" && $line[2] eq "time") {
+ #print "send-cmd: " , $line[5] . " " . $line[6] . " " . $line[7] . "\n" if defined $line[5] && defined $line[6] && defined $line[7];
+ $current_time = $line[3];
+ if($line[5] =~ /dumper\d*/) {
+ $dumper = $line[5];
+ if($line[6] eq "PORT-DUMP") {
+ #7:handle 8:port 9:host 10:amfeatures 11:disk 12:device 13:level ...
+ $host = $line[9];
+ $partition = $line[11];
+ $hostpart=&make_hostpart($host,$partition,$gdatestamp);
+ $serial=$line[7];
+ $dump_started{$hostpart}=1;
+ $dump_time{$hostpart}=$current_time;
+ $dump_finished{$hostpart}=0;
+ if( $level{$hostpart} != $line[13] &&
+ $degr_level{$hostpart} == $line[13]) {
+ $level{$hostpart}=$degr_level{$hostpart};
+ $esize{$hostpart}=$degr_size{$hostpart};
+ }
+ if(! defined($busy_time{$dumper})) {
+ $busy_time{$dumper}=0;
+ }
+ $running_dumper{$dumper} = $hostpart;
+ $error{$hostpart}="";
+ $size{$hostpart} = 0;
+ $dumpers_active++;
+ if(! defined($dumpers_active[$dumpers_active])) {
+ $dumpers_active[$dumpers_active]=0;
+ }
+ if(! defined($dumpers_held[$dumpers_active])) {
+ $dumpers_held[$dumpers_active]={};
+ }
+ }
+ }
+ elsif($line[5] =~ /chunker\d*/) {
+ if($line[6] eq "PORT-WRITE") {
+ $host=$line[9];
+ $partition=$line[11];
+ $hostpart=&make_hostpart($host,$partition,$gdatestamp);
+ $serial=$line[7];
+ $serial{$serial}=$hostpart;
+ $holding_file{$hostpart}=$line[8];
+ #$chunk_started{$hostpart}=1;
+ $chunk_time{$hostpart}=$current_time;
+ #$chunk_finished{$hostpart}=0;
+ }
+ elsif($line[6] eq "CONTINUE") {
+ #7:handle 8:filename 9:chunksize 10:use
+ $serial=$line[7];
+ $hostpart=$serial{$serial};
+ if($hostpart ne "") {
+ $dump_roomq{$hostpart}=undef;
+ $error{$hostpart}="";
+ }
+ }
+ }
+ elsif($line[5] =~ /taper/) {
+ if($line[6] eq "START-TAPER") {
+ #7:timestamp
+ $gdatestamp=$line[7];
+ if(!defined $datestamp{$gdatestamp}) {
+ $datestamp{$gdatestamp} = 1;
+ push @datestamp, $gdatestamp;
+ }
+ }
+ elsif($line[6] eq "FILE-WRITE") {
+ #7:handle 8:filename 9:host 10:disk 11:level 12:datestamp 13:splitsize
+ $serial=$line[7];
+ $host=$line[9];
+ $partition=$line[10];
+ $level=$line[11];
+ $ldatestamp=$line[12];
+ if(!defined $datestamp{$ldatestamp}) {
+ $datestamp{$ldatestamp} = 1;
+ push @datestamp, $ldatestamp;
+ }
+ $hostpart=&make_hostpart($host,$partition,$ldatestamp);
+ $serial{$serial}=$hostpart;
+ if(!defined $level{$hostpart}) {
+ $level{$hostpart} = $level;
+ }
+ $taper_started{$hostpart}=1;
+ $taper_finished{$hostpart}=0;
+ $taper_time{$hostpart}=$current_time;
+ $ntchunk_size = 0;
+ }
+ elsif($line[6] eq "PORT-WRITE") {
+ #7:handle 8:host 9:disk 10:level 11:datestamp 12:splitsize 13:diskbuffer 14:fallback_splitsize
+ $serial=$line[7];
+ $host=$line[8];
+ $partition=$line[9];
+ $level=$line[10];
+ $ldatestamp=$line[11];
+ $hostpart=&make_hostpart($host,$partition,$ldatestamp);
+ $serial{$serial}=$hostpart;
+ $taper_started{$hostpart}=1;
+ $taper_finished{$hostpart}=0;
+ $taper_time{$hostpart}=$current_time;
+ $ntchunk_size = 0;
+ }
+ }
+ }
+ elsif($line[1] eq "result" && $line[2] eq "time") {
+ #print "result: " , $line[5] . " " . $line[6] . " " . $line[7] . "\n" if defined $line[5] && defined $line[6] && defined $line[7];
+ $current_time = $line[3];
+ if($line[5] =~ /dumper\d+/) {
+ if($line[6] eq "FAILED" || $line[6] eq "TRY-AGAIN") {
+ #7:handle 8:message
+ $serial = $line[7];
+ $error = $line[8];
+ $hostpart=$serial{$serial};
+ $dump_finished{$hostpart}=-1;
+ $busy_time{$line[5]}+=($current_time-$dump_time{$hostpart});
+ $running_dumper{$line[5]} = "0";
+ $dump_time{$hostpart}=$current_time;
+ $error{$hostpart}="dumper: $error";
+ $dumpers_active--;
+
+ }
+ elsif($line[6] eq "DONE") {
+ #7:handle 8:origsize 9:size ...
+ $serial=$line[7];
+ $origsize=$line[8] / $unitdivisor;
+ $outputsize=$line[9] / $unitdivisor;
+ $hostpart=$serial{$serial};
+ $size{$hostpart}=$outputsize;
+ $dump_finished{$hostpart}=1;
+ $busy_time{$line[5]}+=($current_time-$dump_time{$hostpart});
+ $running_dumper{$line[5]} = "0";
+ $dump_time{$hostpart}=$current_time;
+ $error{$hostpart}="";
+ $dumpers_active--;
+ }
+ elsif($line[6] eq "ABORT-FINISHED") {
+ #7:handle
+ $serial=$line[7];
+ $hostpart=$serial{$serial};
+ $dump_started{$hostpart}=0;
+ $dump_finished{$hostpart}=0;
+ $busy_time{$line[5]}+=($current_time-$dump_time{$hostpart});
+ $running_dumper{$line[5]} = "0";
+ $dump_time{$hostpart}=$current_time;
+ $error{$hostpart}="dumper: (aborted)";
+ $dumpers_active--;
+ }
+ }
+ elsif($line[5] =~ /chunker\d+/) {
+ if($line[6] eq "DONE" || $line[6] eq "PARTIAL") {
+ #7:handle 8:size
+ $serial=$line[7];
+ $outputsize=$line[8] / $unitdivisor;
+ $hostpart=$serial{$serial};
+ $size{$hostpart}=$outputsize;
+ $dump_finished{$hostpart}=1;
+ $busy_time{$line[5]}+=($current_time-$chunk_time{$hostpart});
+ $running_dumper{$line[5]} = "0";
+ $chunk_time{$hostpart}=$current_time;
+ $error{$hostpart}="";
+ if ($line[6] eq "PARTIAL") {
+ $partial{$hostpart} = 1;
+ }
+ else {
+ $partial{$hostpart} = 0;
+ }
+ }
+ elsif($line[6] eq "FAILED") {
+ $serial=$line[7];
+ $hostpart=$serial{$serial};
+ $dump_finished{$hostpart}=-1;
+ $busy_time{$line[5]}+=($current_time-$chunk_time{$hostpart});
+ $running_dumper{$line[5]} = "0";
+ $chunk_time{$hostpart}=$current_time;
+ $error{$hostpart}="chunker: " .$line[8] if $error{$hostpart} eq "";
+ }
+ elsif($line[6] eq "RQ-MORE-DISK") {
+ #7:handle
+ $serial=$line[7];
+ $hostpart=$serial{$serial};
+ $dump_roomq{$hostpart}=1;
+ $error{$hostpart}="(waiting for holding disk space)";
+ }
+ }
+ elsif($line[5] eq "taper") {
+ if($line[6] eq "DONE" || $line[6] eq "PARTIAL") {
+ #7:handle 8:label 9:filenum 10:errstr
+ $serial=$line[7];
+ $label=$line[8];
+ $hostpart=$serial{$serial};
+ $line[10] =~ /sec (\S+) kb (\d+) kps/;
+ $size=$2 / $unitdivisor;
+ $taper_finished{$hostpart}=1;
+ $busy_time{"taper"}+=($current_time-$taper_time{$hostpart});
+ $taper_time{$hostpart}=$current_time;
+ if(!defined $size{$hostpart}) {
+ $size{$hostpart}=$size;
+ }
+ $ntpartition{$nb_tape}++;
+ $ntsize{$nb_tape} += $size{$hostpart} - $ntchunk_size;
+ if(defined $esize{$hostpart} && $esize{$hostpart} > 1) {
+ $ntesize{$nb_tape} += $esize{$hostpart} - $ntchunk_size;
+ }
+ else {
+ $ntesize{$nb_tape} += $size{$hostpart} - $ntchunk_size;
+ }
+ if ($line[6] eq "PARTIAL") {
+ $partial{$hostpart} = 1;
+ }
+ else {
+ $partial{$hostpart} = 0;
+ }
+ if ($ntchunk_size > 0) {
+ $ntchunk{$nb_tape}++;
+ }
+ }
+ elsif($line[6] eq "PARTDONE") {
+ #7:handle 8:label 9:filenum 10:ksize 11:errstr
+ $serial=$line[7];
+ $hostpart=$serial{$serial};
+ #$line[11] =~ /.*kb (\d*) kps/;
+ #$size=$1 / $unitdivisor;
+ $size=$line[10] / $unitdivisor;
+ $tapedsize{$hostpart} += $size;
+ $ntchunk{$nb_tape}++;
+ $ntsize{$nb_tape} += $size;
+ $ntesize{$nb_tape} += $size;
+ $ntchunk_size += $size;
+ }
+ elsif($line[6] eq "REQUEST-NEW-TAPE") {
+ #7:serial
+ $serial=$line[7];
+ $hostpart=$serial{$serial};
+ if (defined $hostpart) {
+ $error{$hostpart} = "waiting for a new tape";
+ }
+ }
+ elsif($line[6] eq "NEW-TAPE") {
+ #7:serial #8:label
+ $serial=$line[7];
+ $hostpart=$serial{$serial};
+ if (defined $hostpart) {
+ $error{$hostpart} = "";
+ }
+ }
+ elsif($line[6] eq "TRY-AGAIN" || $line[6] eq "TAPE-ERROR") {
+ #7:handle 8:errstr
+ $serial=$line[7];
+ $error=$line[8];
+ $hostpart=$serial{$serial};
+ if(defined $hostpart) {
+ $taper_finished{$hostpart}= $line[6] eq 'TAPE-ERROR' ? -2 : -1;
+ $busy_time{"taper"}+=($current_time-$taper_time{$hostpart});
+ $taper_time{$hostpart}=$current_time;
+ $error{$hostpart}="taper: $error";
+ }
+ }
+ elsif($line[6] eq "FAILED") {
+ #7:handle 8:INPUT- 9:TAPE- 10:input_message 11:tape_message
+ $serial=$line[7];
+ $hostpart=$serial{$serial};
+ if(defined $hostpart) {
+ if($line[9] eq "TAPE-ERROR") {
+ $error=$line[11];
+ $taper_finished{$hostpart} = -2;
+ }
+ else {
+ $error=$line[10];
+ $taper_finished{$hostpart} = -1;
+ }
+ $busy_time{"taper"}+=($current_time-$taper_time{$hostpart});
+ $taper_time{$hostpart}=$current_time;
+ $error{$hostpart}="$error";
+ }
+ }
+ }
+ }
+ elsif($line[1] eq "finished-cmd" && $line[2] eq "time") {
+ $current_time=$line[3];
+ if($line[4] =~ /dumper\d+/) {
+ }
+ }
+ elsif($line[1] eq "dump" && $line[2] eq "failed") {
+ #3:handle 4: 5: 6:"too many dumper retry"
+ $serial=$line[3];
+ $hostpart=$serial{$serial};
+ $dump_started{$hostpart}=-1;
+ $dump_finished{$hostpart}=-2;
+ $error{$hostpart} .= "(" . $line[6] . ")";
+ }
+ elsif($line[1] eq "tape" && $line[2] eq "failed") {
+ #3:handle 4: 5: 6:"too many dumper retry"
+ $serial=$line[3];
+ $hostpart=$serial{$serial};
+ $taper_started{$hostpart}=-1;
+ $taper_finished{$hostpart}=-2;
+ $error{$hostpart} .= "(" . $line[6] . ")";
+ }
+ elsif($line[1] eq "state" && $line[2] eq "time") {
+ #3:time 4:"free" 5:"kps" 6:free 7:"space" 8:space 9:"taper" 10:taper 11:"idle-dumpers" 12:idle-dumpers 13:"qlen" 14:"tapeq" 15:tapeq 16:"runq" 17:runq 18:"roomq" 19:roomq 20:"wakeup" 21:wakeup 22:"driver-idle" 23:driver-idle
+ $current_time=$line[3];
+ $status_taper=$line[10];
+ $idle_dumpers=$line[12];
+
+ $free{"kps"} = $line[6];
+ $free{"space"} = $line[8];
+ $qlen{"tapeq"} = $line[15];
+ $qlen{"runq"} = $line[17];
+ $qlen{"roomq"} = $line[19];
+
+ if(defined($dumpers_active)) {
+ if($status_driver ne "") {
+ $dumpers_active[$dumpers_active_prev]
+ +=$current_time-$state_time_prev;
+ $dumpers_held[$dumpers_active_prev]{$status_driver}
+ +=$current_time-$state_time_prev;
+ }
+ $state_time_prev=$current_time;
+ $dumpers_active_prev=$dumpers_active;
+ $status_driver=$line[16];
+ if(! defined($dumpers_held[$dumpers_active]{$status_driver})) {
+ $dumpers_held[$dumpers_active]{$status_driver}=0;
+ }
+ }
+ }
+ elsif($line[1] eq "FINISHED") {
+ $driver_finished = 1;
+ }
+ }
+ elsif($line[0] eq "dump") {
+ if($line[1] eq "of" &&
+ $line[2] eq "driver" &&
+ $line[3] eq "schedule" &&
+ $line[4] eq "after" &&
+ $line[5] eq "start" &&
+ $line[6] eq "degraded" &&
+ $line[7] eq "mode") {
+ $start_degraded_mode=1;
+ }
+ }
+ elsif($line[0] eq "taper") {
+ if($line[1] eq "slot") {
+ #2:slot 3:"wrote" 4:"label" 5:corrupted...
+ $nb_tape++;
+ $lineX =~ /wrote label `(\S*)'/;
+ $label = $1;
+ $ntlabel{$nb_tape} = $label;
+ $ntpartition{$nb_tape} = 0;
+ $ntsize{$nb_tape} = 0;
+ $ntesize{$nb_tape} = 0;
+ }
+ elsif($line[1] eq "wrote") {
+ #1:"wrote" 2:"label" 3:corrupted
+ $nb_tape++;
+ $lineX =~ /wrote label `(\S*)'/;
+ $label = $1;
+ $ntlabel{$nb_tape} = $label;
+ $ntpartition{$nb_tape} = 0;
+ $ntsize{$nb_tape} = 0;
+ $ntesize{$nb_tape} = 0;
+ }
+ }
+ elsif($line[0] eq "splitting" &&
+ $line[1] eq "chunk" &&
+ $line[2] eq "that" &&
+ $line[3] eq "started" &&
+ $line[4] eq "at" &&
+ $line[6] eq "after") {
+ $line[7] =~ /(\d*)kb/;
+ $size = $1;
+ $ntchunk{$nb_tape}++;
+ $ntsize{$nb_tape} += $size / $unitdivisor;
+ $ntesize{$nb_tape} += $size / $unitdivisor;
+ $ntchunk_size += $size / $unitdivisor;
+ }
+ else {
+ #print "Ignoring: $lineX\n";
+ }
+}
+
+close(AMDUMP);
+
+if(defined $current_time) {
+ for ($d = 0; $d < $#dumpers_active; $d++) {
+ $the_dumper = "dumper$d";
+ if(defined($running_dumper{$the_dumper}) &&
+ $running_dumper{$the_dumper} ne "0") {
+ $busy_time{$the_dumper}+=($current_time-$dump_time{$running_dumper{$the_dumper}});
+ }
+ }
+}
+
+print "\n";
+
+$nb_partition = 0;
+
+$epartition = 0;
+$estsize = 0;
+$fpartition = 0;
+$fsize = 0;
+$wpartition = 0;
+$wsize = 0;
+
+$flpartition = 0;
+$flsize = 0;
+$wfpartition = 0;
+$wfsize = 0;
+
+$dtpartition = 0;
+$dtesize = 0;
+$dupartition = 0;
+$dusize = 0;
+$duesize = 0;
+$dpartition = 0;
+$dsize = 0;
+$desize = 0;
+
+$twpartition = 0;
+$twsize = 0;
+$twesize = 0;
+$tapartition = 0;
+$tasize = 0;
+$taesize = 0;
+$tfpartition = 0;
+$tfsize = 0;
+$tfesize = 0;
+$tpartition = 0;
+$tsize = 0;
+$tesize = 0;
+
+$maxnamelength = 10;
+foreach $host (sort @hosts) {
+ foreach $partition (sort @$host) {
+ foreach $datestamp (sort @datestamp) {
+ $hostpart=&make_hostpart($host,$partition,$datestamp);
+ next if(!defined $estimate{$hostpart} && !defined $flush{$hostpart});
+ if(length("$host:$partition") > $maxnamelength) {
+ $maxnamelength = length("$host:$partition");
+ }
+ }
+ }
+}
+
+foreach $host (sort @hosts) {
+ foreach $partition (sort @$host) {
+ foreach $datestamp (sort @datestamp) {
+ $hostpart=&make_hostpart($host,$partition,$datestamp);
+ next if(!defined $estimate{$hostpart} && !defined $flush{$hostpart});
+ $nb_partition++;
+ if( (!defined $size{$hostpart} || $size{$hostpart} == 0) &&
+ defined $holding_file{$hostpart}) {
+ $size{$hostpart} = &dump_size($holding_file{$hostpart}) / (1024 * $unitdivisor);
+ }
+ $in_flush=0;
+ if($estimate_done != 1 && !defined $flush{$hostpart}) {
+ if(defined $estimate{$hostpart}) {
+ if($estimate{$hostpart} != 1) {
+ if( defined $opt_gestimate) {
+ printf "%8s ", $datestamp if defined $opt_date;
+ printf "%-${maxnamelength}s", "$host:$partition";
+ print " getting estimate\n";
+ }
+ }
+ else {
+ if(defined $opt_estimate ||
+ (defined $opt_gestimate && $partialestimate{$hostpart} == 1)) {
+ printf "%8s ", $datestamp if defined $opt_date;
+ printf "%-${maxnamelength}s", "$host:$partition";
+ printf "%2d ", $level{$hostpart};
+ printf "%9d$unit", $esize{$hostpart};
+ if($partialestimate{$hostpart} == 1) {
+ print " partial";
+ }
+ print " estimate done\n";
+ }
+ $epartition++;
+ $estsize += $esize{$hostpart};
+ }
+ }
+ }
+ else {
+ if(defined $estimate{$hostpart}) {
+ if($estimate{$hostpart} == 1) {
+ $epartition++;
+ $estsize += $esize{$hostpart};
+ }
+ elsif (!defined $dump_started{$hostpart} || $dump_started{$hostpart} == 0) {
+ if( defined $opt_failed) {
+ printf "%8s ", $datestamp if defined $opt_date;
+ printf "%-${maxnamelength}s%2d ", "$host:$partition", $level{$hostpart};
+ printf " no estimate\n";
+ }
+ $exit_status |= $STATUS_FAILED;
+ $fpartition++;
+ $fsize+=$esize{$hostpart};
+ }
+ }
+ else {
+ $flpartition++;
+ $flsize += $size{$hostpart};
+ $in_flush=1;
+ }
+ if(defined $taper_started{$hostpart} &&
+ $taper_started{$hostpart}==1) {
+ if(defined $dump_started{$hostpart}) {
+ $dpartition++;
+ if(defined($size{$hostpart})) {
+ $dsize += $size{$hostpart};
+ }
+ else {
+ $dsize += $esize{$hostpart};
+ }
+ $desize += $esize{$hostpart};
+ }
+ if(defined $dump_started{$hostpart} &&
+ $dump_started{$hostpart} == 1 &&
+ $dump_finished{$hostpart} == -1) {
+ if(defined $opt_failed) {
+ printf "%8s ", $datestamp if defined $opt_date;
+ printf "%-${maxnamelength}s%2d ", "$host:$partition", $level{$hostpart};
+ printf "%9d$unit", $esize{$hostpart};
+ print " dump to tape failed: " . $error{$hostpart};
+ print "\n";
+ }
+ $exit_status |= $STATUS_FAILED;
+ $fpartition++;
+ $fsize+=$esize{$hostpart};
+ } elsif(defined $dump_started{$hostpart} &&
+ $dump_started{$hostpart} == 1 &&
+ $dump_finished{$hostpart} == 0 &&
+ $taper_started{$hostpart} == 1) {
+ if( defined $opt_dumpingtape ) {
+ printf "%8s ", $datestamp if defined $opt_date;
+ printf "%-${maxnamelength}s%2d ", "$host:$partition", $level{$hostpart};
+ printf "%9d$unit", $esize{$hostpart};
+ print " dumping to tape";
+ if( defined $starttime ) {
+ print " (", &showtime($taper_time{$hostpart}), ")";
+ }
+ print "\n";
+ }
+ $dtpartition++;
+ $dtesize += $esize{$hostpart};
+ }
+ elsif($taper_finished{$hostpart} == 0) {
+ if( defined $opt_writingtape ) {
+ printf "%8s ", $datestamp if defined $opt_date;
+ printf "%-${maxnamelength}s%2d ", "$host:$partition", $level{$hostpart};
+ printf "%9d$unit", $size{$hostpart};
+ if($in_flush == 0) {
+ print " writing to tape";
+ }
+ else {
+ print " flushing to tape";
+ }
+ if(defined($tapedsize{$hostpart})) {
+ printf " (%d$unit done)", $tapedsize{$hostpart};
+ }
+ if( defined $starttime ) {
+ print " (", &showtime($taper_time{$hostpart}), ")";
+ }
+ print ", ", $error{$hostpart} if defined($error{$hostpart} &&
+ $error{$hostpart} ne "");
+ print "\n";
+ }
+ $tapartition++;
+ $tasize += $size{$hostpart};
+ if(defined $esize{$hostpart}) {
+ $taesize += $esize{$hostpart};
+ }
+ else {
+ $taesize += $size{$hostpart};
+ }
+ }
+ elsif($taper_finished{$hostpart} < 0) {
+
+ if(defined $size{$hostpart}) {
+ $xsize = $size{$hostpart};
+ }
+ elsif(defined $esize{$hostpart}) {
+ $xsize = $esize{$hostpart};
+ }
+ else {
+ $xsize = 0;
+ }
+
+ if(defined $esize{$hostpart}) {
+ $exsize += $esize{$hostpart};
+ }
+ else {
+ $exsize += $xsize;
+ }
+
+ if( defined $opt_failed ||
+ (defined $opt_waittaper && ($taper_finished{$hostpart} == -1))) {
+ printf "%8s ", $datestamp if defined $opt_date;
+ printf "%-${maxnamelength}s%2d ", "$host:$partition", $level{$hostpart};
+ printf "%9d$unit", $xsize;
+ if($in_flush == 0) {
+ print " failed to tape";
+ }
+ else {
+ print " failed to flush";
+ }
+ print ": ",$error{$hostpart} if defined $error{$hostpart};
+
+ print " (will retry)" unless $taper_finished{$hostpart} < -1;
+ if( defined $starttime ) {
+ print " (", &showtime($taper_time{$hostpart}), ")";
+ }
+ print "\n";
+ }
+ $exit_status |= $STATUS_TAPE;
+
+ $tfpartition++;
+ $tfsize += $xsize;
+ $tfesize += $exsize;
+
+ if($in_flush == 0) {
+ $twpartition++;
+ $twsize += $xsize;
+ $twesize += $exsize;
+ }
+ else {
+ $wfpartition++;
+ $wfsize += $xsize;
+ }
+ }
+ elsif($taper_finished{$hostpart} == 1) {
+ if( defined $opt_finished ) {
+ printf "%8s ", $datestamp if defined $opt_date;
+ printf "%-${maxnamelength}s%2d ", "$host:$partition", $level{$hostpart};
+ printf "%9d$unit", $size{$hostpart};
+ if($in_flush == 0) {
+ print " finished";
+ }
+ else {
+ print " flushed";
+ }
+ if( defined $starttime ) {
+ print " (", &showtime($taper_time{$hostpart}), ")";
+ }
+ if(defined $partial{$hostpart} && $partial{$hostpart} == 1) {
+ print ", PARTIAL";
+ $exit_status |= $STATUS_FAILED;
+ }
+ print "\n";
+ }
+ $tpartition++;
+ $tsize += $size{$hostpart};
+ if(defined $esize{$hostpart} && $esize{$hostpart} > 1) {
+ $tesize += $esize{$hostpart};
+ }
+ else {
+ $tesize += $size{$hostpart};
+ }
+ }
+ else {
+ printf "%8s ", $datestamp if defined $opt_date;
+ printf "%-${maxnamelength}s%2d ", "$host:$partition", $level{$hostpart};
+ print " unknown state TAPER\n";
+ }
+ }
+ elsif(defined $dump_started{$hostpart}) {
+ if($dump_started{$hostpart} == -1) {
+ if( defined $opt_failed ) {
+ printf "%8s ", $datestamp if defined $opt_date;
+ printf "%-${maxnamelength}s%2d ", "$host:$partition", $level{$hostpart};
+ printf " " . $error{$hostpart} . "\n";
+ }
+ $exit_status |= $STATUS_FAILED;
+
+ $fpartition++;
+ $fsize+=$esize{$hostpart};
+ }
+ elsif($dump_started{$hostpart} == 0) {
+ if($estimate{$hostpart} == 1) {
+ if( defined $opt_waitdumping ) {
+ printf "%8s ", $datestamp if defined $opt_date;
+ printf "%-${maxnamelength}s%2d ", "$host:$partition", $level{$hostpart};
+ printf "%9d$unit", $esize{$hostpart};
+ print " wait for dumping $error{$hostpart}\n";
+ }
+ if($driver_finished == 1) {
+ $exit_status |= $STATUS_MISSING;
+ }
+ $wpartition++;
+ $wsize += $esize{$hostpart};
+ }
+ }
+ elsif($dump_started{$hostpart} == 1 &&
+ $dump_finished{$hostpart} == -1) {
+ if( defined $opt_failed ) {
+ printf "%8s ", $datestamp if defined $opt_date;
+ printf "%-${maxnamelength}s%2d ", "$host:$partition", $level{$hostpart};
+ print " ", $error{$hostpart};
+ if( defined $starttime ) {
+ print " (", &showtime($dump_time{$hostpart}), ")";
+ }
+ print "\n";
+ }
+ $exit_status |= $STATUS_FAILED;
+ $fpartition++;
+ $fsize+=$esize{$hostpart};
+ }
+ elsif($dump_started{$hostpart} == 1 &&
+ $dump_finished{$hostpart} != 1) {
+ if( defined $opt_dumping ) {
+ printf "%8s ", $datestamp if defined $opt_date;
+ printf "%-${maxnamelength}s%2d ", "$host:$partition", $level{$hostpart};
+ printf "%9d$unit", $esize{$hostpart};
+ printf " dumping %8d$unit", $size{$hostpart};
+ if($size{$hostpart} != 0) {
+ printf " (%6.2f%%)", (100.0*$size{$hostpart})/$esize{$hostpart};
+ }
+ if( defined $starttime ) {
+ print " (", &showtime($dump_time{$hostpart}), ")";
+ }
+ if(defined $dump_roomq{$hostpart}) {
+ print " " . $error{$hostpart};
+ }
+ print "\n";
+ }
+ $dupartition++;
+ $dusize += $size{$hostpart};
+ $duesize += $esize{$hostpart};
+ }
+ elsif($dump_finished{$hostpart} == 1 &&
+ $taper_started{$hostpart} != 1) {
+ if( defined $opt_waittaper ) {
+ printf "%8s ", $datestamp if defined $opt_date;
+ printf "%-${maxnamelength}s%2d ", "$host:$partition", $level{$hostpart};
+ printf "%9d$unit", $size{$hostpart};
+ print " dump done";
+ if( defined $starttime ) {
+ print " (", &showtime($dump_time{$hostpart}), ")";
+ }
+ print ", wait for writing to tape";
+ if(defined $partial{$hostpart} && $partial{$hostpart} == 1) {
+ print ", PARTIAL";
+ $exit_status |= $STATUS_FAILED;
+ }
+ print "\n";
+ }
+ $dpartition++;
+ $dsize += $size{$hostpart};
+ $desize += $esize{$hostpart};
+ $twpartition++;
+ $twsize += $size{$hostpart};
+ $twesize += $esize{$hostpart};
+ }
+ else {
+ printf "%8s ", $datestamp if defined $opt_date;
+ printf "%-${maxnamelength}s%2d ", "$host:$partition", $level{$hostpart};
+ print " unknown state DUMPER\n";
+ }
+ }
+ elsif(defined $flush{$hostpart}) {
+ if( defined $opt_waittaper ) {
+ printf "%8s ", $datestamp if defined $opt_date;
+ printf "%-${maxnamelength}s%2d ", "$host:$partition", $level{$hostpart};
+ printf "%9d$unit", $size{$hostpart};
+ print " waiting to flush";
+ if(defined $partial{$hostpart} && $partial{$hostpart} == 1) {
+ print ", PARTIAL";
+ $exit_status |= $STATUS_FAILED;
+ }
+ print "\n";
+ }
+ $wfpartition++;
+ $wfsize += $size{$hostpart};
+ }
+ elsif(defined $level{$hostpart}) {
+ printf "%8s ", $datestamp if defined $opt_date;
+ printf "%-${maxnamelength}s%2d ", "$host:$partition", $level{$hostpart};
+ print " unknown state\n";
+ }
+ }
+ }
+ }
+}
+
+if (defined $opt_summary) {
+ print "\n";
+ print "SUMMARY part real estimated\n";
+ print " size size\n";
+ printf "partition : %3d\n", $nb_partition;
+ printf "estimated : %3d %20d$unit\n", $epartition , $estsize;
+ printf "flush : %3d %9d$unit\n", $flpartition, $flsize;
+ printf "failed : %3d %20d$unit (%6.2f%%)\n",
+ $fpartition , $fsize,
+ $estsize ? ($fsize * 1.0 / $estsize) * 100 : 0.0;
+ printf "wait for dumping: %3d %20d$unit (%6.2f%%)\n",
+ $wpartition , $wsize,
+ $estsize ? ($wsize * 1.0 / $estsize) * 100 : 0.0;
+ printf "dumping to tape : %3d %20d$unit (%6.2f%%)\n",
+ $dtpartition, $dtesize,
+ $estsize ? ($dtesize * 1.0 / $estsize) * 100 : 0.0;
+ printf "dumping : %3d %9d$unit %9d$unit (%6.2f%%) (%6.2f%%)\n",
+ $dupartition, $dusize, $duesize,
+ $duesize ? ($dusize * 1.0 / $duesize) * 100 : 0.0,
+ $estsize ? ($dusize * 1.0 / $estsize) * 100 : 0.0;
+ printf "dumped : %3d %9d$unit %9d$unit (%6.2f%%) (%6.2f%%)\n",
+ $dpartition , $dsize , $desize,
+ $desize ? ($dsize * 1.0 / $desize) * 100 : 0.0,
+ $estsize ? ($dsize * 1.0 / $estsize) * 100 : 0.0;
+ printf "wait for writing: %3d %9d$unit %9d$unit (%6.2f%%) (%6.2f%%)\n",
+ $twpartition, $twsize, $twesize,
+ $twesize ? ($twsize * 1.0 / $twesize) * 100 : 0.0,
+ $estsize ? ($twsize * 1.0 / $estsize) * 100 : 0.0;
+ printf "wait to flush : %3d %9d$unit %9d$unit (%6.2f%%) (%6.2f%%)\n",
+ $wfpartition, $wfsize, $wfsize, 100, 0;
+ printf "writing to tape : %3d %9d$unit %9d$unit (%6.2f%%) (%6.2f%%)\n",
+ $tapartition, $tasize, $taesize,
+ $taesize ? ($tasize * 1.0 / $taesize) * 100 : 0.0,
+ $estsize ? ($tasize * 1.0 / $estsize) * 100 : 0.0;
+ printf "failed to tape : %3d %9d$unit %9d$unit (%6.2f%%) (%6.2f%%)\n",
+ $tfpartition, $tfsize, $tfesize,
+ $tfesize ? ($tfsize * 1.0 / $tfesize) * 100 : 0.0,
+ $estsize ? ($tfsize * 1.0 / $estsize) * 100 : 0.0;
+ printf "taped : %3d %9d$unit %9d$unit (%6.2f%%) (%6.2f%%)\n",
+ $tpartition , $tsize , $tesize,
+ $tesize ? ($tsize * 1.0 / $tesize) * 100 : 0.0,
+ ($estsize+$flsize) ? ($tsize * 1.0 / ($estsize + $flsize)) * 100 : 0.0;
+ if($nb_tape > 1 || $tape_size != 0) {
+ for($i=1; $i <= $nb_tape; $i++) {
+ if($tape_size != 0) {
+ printf " tape %-3d : %3d %9d$unit %9d$unit (%6.2f%%) %s",
+ $i, $ntpartition{$i}, $ntsize{$i}, $ntesize{$i}, 100*$ntsize{$i}/$tape_size, $ntlabel{$i};
+ }
+ else {
+ printf " tape %-3d : %3d %9d$unit %9d$unit %s",
+ $i, $ntpartition{$i}, $ntsize{$i}, $ntesize{$i}, $ntlabel{$i};
+ }
+ if(defined($ntchunk{$i}) && $ntchunk{$i} > 0) {
+ printf " (%d chunks)", $ntchunk{$i};
+ }
+ print "\n";
+ }
+ }
+ if($idle_dumpers == 0) {
+ printf "all dumpers active\n";
+ }
+ else {
+ $c1 = ($idle_dumpers == 1) ? "" : "s";
+ $c2 = ($idle_dumpers < 10) ? " " : "";
+ $c3 = ($idle_dumpers == 1) ? " " : "";
+ printf "%d dumper%s idle%s %s: %s\n", $idle_dumpers, $c1, $c2, $c3, $status_driver;
+ }
+ if($status_taper eq "writing" && defined($qlen{"tapeq:"})) {
+ printf "taper writing, tapeq: %d\n", $qlen{"tapeq:"};
+ }
+ else {
+ printf "taper idle\n";
+ }
+ if (defined ($free{"kps:"})) {
+ printf "network free kps: %9d\n", $free{"kps:"};
+ }
+ if (defined ($free{"space:"})) {
+ if ($holding_space) {
+ $hs = ($free{"space:"} * 1.0 / $holding_space) * 100;
+ } else {
+ $hs = 0.0;
+ }
+ printf "holding space : %9d$unit (%6.2f%%)\n", ($free{"space:"}/$unitdivisor), $hs;
+ }
+}
+
+if(defined $opt_stats) {
+ if(defined($current_time) && $current_time != $start_time) {
+ $total_time=$current_time-$start_time;
+ foreach $key (sort byprocess keys %busy_time) {
+ printf "%8s busy : %8s (%6.2f%%)\n",
+ $key, &busytime($busy_time{$key}),
+ ($busy_time{$key} * 1.0 / $total_time) * 100;
+ }
+ for ($d = 0; $d <= $#dumpers_active; $d++) {
+ $l = sprintf "%2d dumper%s busy%s : %8s (%6.2f%%)",
+ $d, ($d == 1) ? "" : "s", ($d == 1) ? " " : "",
+ &busytime($dumpers_active[$d]),
+ ($dumpers_active[$d] * 1.0 / $total_time) * 100;
+ print $l;
+ $s1 = "";
+ $s2 = " " x length($l);
+ $r = $dumpers_held[$d];
+ foreach $key (sort valuesort keys %$r) {
+ next
+ unless $dumpers_held[$d]{$key} >= 1;
+ printf "%s%20s: %8s (%6.2f%%)\n",
+ $s1,
+ $key,
+ &busytime($dumpers_held[$d]{$key}),
+ ($dumpers_held[$d]{$key} * 1.0 / $dumpers_active[$d]) * 100;
+ $s1 = $s2;
+ }
+ if ($s1 eq "") {
+ print "\n";
+ }
+ }
+ }
+}
+
+exit $exit_status;
+
+sub make_hostpart() {
+ local($host,$partition,$datestamp) = @_;
+
+ if(! defined($hosts{$host})) {
+ push @hosts, $host;
+ $hosts{$host}=1;
+ }
+ my($new_part) = 1;
+ foreach $pp (sort @$host) {
+ $new_part = 0 if ($pp eq $partition);
+ }
+ push @$host, $partition if $new_part==1;
+
+ my($hostpart) = "$host$partition$datestamp";
+ if(!defined $datestamp{$datestamp}) {
+ $datestamp{$datestamp} = 1;
+ push @datestamp, $datestamp;
+ }
+
+ return $hostpart;
+}
+
+sub byprocess() {
+ my(@tmp_a) = split(/(\d*)$/, $a, 2);
+ my(@tmp_b) = split(/(\d*)$/, $b, 2);
+ return ($tmp_a[0] cmp $tmp_b[0]) || ($tmp_a[1] <=> $tmp_b[1]);
+}
+
+sub valuesort() {
+ $r->{$b} <=> $r->{$a};
+}
+
+sub dump_size() {
+ local($filename) = @_;
+ local($size);
+ local($dsize) = 0;
+ local($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
+ $atime,$mtime,$ctime,$blksize,$blocks);
+ while ($filename ne "") {
+ $filename = "$filename.tmp" if (!(-e "$filename"));
+ $filename = "/dev/null" if (!(-e "$filename"));
+ ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
+ $atime,$mtime,$ctime,$blksize,$blocks) = stat($filename);
+ $size=$size-32768 if $size > 32768;
+ $dsize += $size;
+ open(DUMP,$filename);
+ $filename = "";
+ while(<DUMP>) {
+ if(/^CONT_FILENAME=(.*)$/) { $filename = $1; last }
+ last if /^To restore, position tape at start of file and run/;
+ }
+ close(DUMP);
+ }
+ return $dsize;
+}
+
+sub unctime() {
+ my (@MoY);
+ my (@tl);
+ my ($a);
+ my ($m);
+ my ($month);
+ my ($time);
+
+ @MoY = ('Jan','Feb','Mar','Apr','May','Jun',
+ 'Jul','Aug','Sep','Oct','Nov','Dec');
+
+ # Preset an array of values in case some parts are not passed as
+ # arguments. This lets the date, etc, be omitted and default to
+ # today.
+
+ @tl = localtime;
+
+ foreach $a (@_) {
+ next
+ if ($a eq '');
+
+ # See if this argument looks like a month name.
+
+ $month = 0;
+ foreach $m (@MoY) {
+ last
+ if ($m eq $a);
+ $month = $month + 1;
+ }
+ if ($month < 12) {
+ $tl[4] = $month;
+ next;
+ }
+
+ # See if this is a day of the month.
+
+ if ($a =~ /^\d+$/ && $a >= 1 && $a <= 32) {
+ $tl[3] = $a;
+ next;
+ }
+
+ # See if the next argument looks like a time.
+
+ if ($a =~ /^(\d+):(\d+)/) {
+ $tl[2] = $1;
+ $tl[1] = $2;
+ if ($a =~ /^(\d+):(\d+):(\d+)/) {
+ $tl[0] = $3;
+ }
+ next;
+ }
+
+ # See if this is a year.
+
+ if ($a =~ /^\d\d\d\d$/ && $a >= 1900) {
+ $tl[5] = $a;
+ next;
+ }
+ }
+
+ $time = &timelocal (@tl);
+
+ return $time;
+}
+
+sub set_starttime() {
+ my (@tl);
+ my ($time);
+ my ($date);
+
+ # Preset an array of values in case some parts are not passed as
+ # arguments. This lets the date, etc, be omitted and default to
+ # today.
+
+ ($date)=@_;
+ @tl = localtime;
+
+ $tl[5] = substr($date, 0, 4) if(length($date) >= 4);
+ $tl[4] = substr($date, 4, 2)-1 if(length($date) >= 6);
+ $tl[3] = substr($date, 6, 2) if(length($date) >= 8);
+ $tl[2] = substr($date, 8, 2) if(length($date) >= 10);
+ $tl[1] = substr($date, 10, 2) if(length($date) >= 12);
+ $tl[0] = substr($date, 12, 2) if(length($date) >= 14);
+
+ $time = &timelocal (@tl);
+
+ return $time;
+}
+
+
+sub showtime() {
+ my($delta)=shift;
+ my($oneday)=24*60*60;
+
+ @now=localtime($starttime+$delta);
+ if($delta > $oneday) {
+ $result=sprintf("%d+",$delta/$oneday);
+ } else {
+ $result="";
+ }
+ $result.=sprintf("%d:%02d:%02d",$now[2],$now[1],$now[0]);
+ return $result;
+}
+
+sub busytime() {
+ my($busy)=shift;
+ my($oneday)=24*60*60;
+
+ if($busy > $oneday) {
+ $days=int($busy/$oneday);
+ $result=sprintf("%d+",$busy/$oneday);
+ $busy-=$days*$oneday;
+ } else {
+ $result="";
+ }
+ $hours=int($busy/60/60);
+ $busy-=$hours*60*60;
+ $minutes=int($busy/60);
+ $busy-=$minutes*60;
+ $seconds=$busy;
+ $result.=sprintf("%d:%02d:%02d",$hours,$minutes,$seconds);
+ return $result;
+}
+
+sub usage() {
+ print "amstatus [--config] config [--file amdump_file]\n";
+ print " [--summary] [--dumping] [--waitdumping] [--waittaper]\n";
+ print " [--dumpingtape] [--writingtape] [--finished] [--failed]\n";
+ print " [--estimate] [--gestimate] [--stats] [--date] [--locale-independent-date-format]\n";
+ exit 0;
+}