5 eval '(exit $?0)' && eval 'exec @PERL@ -S $0 ${1+"$@"}'
6 & eval 'exec @PERL@ -S $0 $argv:q'
10 use lib '@amperldir@';
17 delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV', 'PATH'};
18 $ENV{'PATH'} = "/bin:/usr/bin:/usr/sbin:/sbin"; # force known path
20 $confdir="@CONFIG_DIR@";
22 $prefix=$prefix; # avoid warnings about possible typo
23 $exec_prefix="@exec_prefix@";
24 $exec_prefix=$exec_prefix; # ditto
27 my $Amanda_process = Amanda::Process->new(0);
28 $Amanda_process->load_ps_table();
50 my $opt_locale_independent_date_format;
53 print "amstatus [--file amdump_file]\n";
54 print " [--summary] [--dumping] [--waitdumping] [--waittaper]\n";
55 print " [--dumpingtape] [--writingtape] [--finished] [--failed]\n";
56 print " [--estimate] [--gestimate] [--stats] [--date]\n";
57 print " [--locale-independent-date-format]\n";
58 print " [--config] <config>\n";
62 Getopt::Long::Configure(qw{ bundling });
64 'summary' => \$opt_summary,
65 'stats|statistics' => \$opt_stats,
66 'dumping|d' => \$opt_dumping,
67 'waitdumping|wdumping' => \$opt_waitdumping,
68 'waittaper|wtaper' => \$opt_waittaper,
69 'dumpingtape|dtape' => \$opt_dumpingtape,
70 'writingtape|wtape' => \$opt_writingtape,
71 'finished' => \$opt_finished,
72 'failed|error' => \$opt_failed,
73 'estimate' => \$opt_estimate,
74 'gestimate|gettingestimate' => \$opt_gestimate,
76 'config|c:s' => \$opt_config,
77 'file:s' => \$opt_file,
78 'locale-independent-date-format' => \$opt_locale_independent_date_format,
82 if( defined $opt_config ) {
94 #untaint user input $ARGV[0]
96 if ($conf =~ /^([\w.-]+)$/) { # $1 is untainted
99 die "filename '$conf' has invalid characters.\n";
102 if ( ! -e "$confdir/$conf" ) {
103 print "Configuration directory '$confdir/$conf' doesn't exist\n";
106 if ( ! -d "$confdir/$conf" ) {
107 print "Configuration directory '$confdir/$conf' is not a directory\n";
114 chdir "$confdir/$conf";
116 $logdir=`$sbindir/amgetconf logdir`;
119 $errfile="$logdir/amdump";
121 $nb_options = defined( $opt_summary ) +
122 defined( $opt_stats ) +
123 defined( $opt_dumping ) +
124 defined( $opt_waitdumping ) +
125 defined( $opt_waittaper ) +
126 defined( $opt_dumpingtape ) +
127 defined( $opt_writingtape ) +
128 defined( $opt_finished ) +
129 defined( $opt_estimate ) +
130 defined( $opt_gestimate ) +
131 defined( $opt_failed );
133 if($nb_options == 0 ) {
137 $opt_waitdumping = 1;
139 $opt_dumpingtape = 1;
140 $opt_writingtape = 1;
147 $unit=`$sbindir/amgetconf displayunit`;
149 $unit =~ tr/A-Z/a-z/;
154 elsif($unit eq 'm') {
157 elsif($unit eq 'g') {
158 $unitdivisor = 1024*1024;
160 elsif($unit eq 't') {
161 $unitdivisor = 1024*1024*1024;
170 if( defined $opt_file) {
171 if( $opt_file =~ m,^/, ) {
172 $errfile = $opt_file;
174 $errfile = "$pwd/$opt_file";
175 $errfile = "$logdir/$opt_file" if ( ! (-f $errfile ));
179 $errfile="$logdir/amflush" if(! (-f $errfile));
181 if (-f "$logdir/amflush.1" && -f "$logdir/amdump.1" &&
182 -M "$logdir/amflush.1" < -M "$logdir/amdump.1") {
183 $errfile="$logdir/amflush.1";
185 $errfile="$logdir/amdump.1";
191 open(AMDUMP,"<$errfile") || die("$errfile: $!");
192 print "Using $errfile\n";
194 my %taper_status_file;
196 $start_degraded_mode = 0;
198 $label = ""; # -w fodder
199 $origsize = 0; # -w fodder
202 $status_taper = "Searching for a new tape";
206 @dumpers_active = ();
208 $ntpartition{$nb_tape} = 0;
209 $ntsize{$nb_tape} = 0;
210 $ntesize{$nb_tape} = 0;
212 $driver_finished = 0;
213 $generating_schedule = 0;
215 while($lineX = <AMDUMP>) {
217 $lineX =~ s/[:\s]+$//g; #remove separator at end of line
218 next if $lineX eq "";
219 @line = "ewords('[:\s]+', 0, $lineX);
220 next if !defined $line[0];
222 if($line[0] eq "amdump" || $line[0] eq "amflush") {
223 if ($line[1] eq "start" && $line[2] eq "at") {
225 $datestr =~ s/.*start at //g;
226 if (!defined $opt_locale_independent_date_format) {
227 print "From " . $datestr . "\n";
229 } elsif($line[1] eq "datestamp") {
230 $gdatestamp = $line[2];
231 if(!defined $datestamp{$gdatestamp}) {
232 $datestamp{$gdatestamp} = 1;
233 push @datestamp, $gdatestamp;
235 } elsif($line[1] eq "starttime") {
236 $starttime=&set_starttime($line[2]);
237 } elsif($line[1] eq "starttime-locale-independent") {
238 if (defined $opt_locale_independent_date_format) {
239 printf "From " . $line[2] . " " . $line[3] . ":" . $line[4] . ":" . $line[5] . " " . $line[6] . "\n";
242 if($line[0] eq "amflush") {
245 } elsif($line[0] eq "planner") {
246 if($line[1] eq "timestamp") {
247 $gdatestamp = $line[2];
248 if(!defined $datestamp{$gdatestamp}) {
249 $datestamp{$gdatestamp} = 1;
250 push @datestamp, $gdatestamp;
253 elsif($line[1] eq "FAILED") {
254 #2:host 3:disk 4:datestamp 5:level 6:errmsg
258 $hostpart=&make_hostpart($host,$partition,$datestamp);
259 $dump_started{$hostpart}=-1;
260 $level{$hostpart}=$line[5];
261 $error{$hostpart}="planner: " . $line[6];
262 } elsif($line[1] eq "time") {
263 if($line[3] eq "got") {
264 if($line[4] eq "result") {
266 $partition = $line[9];
267 $hostpart=&make_hostpart($host,$partition,$gdatestamp);
268 $estimate{$hostpart}=1;
269 $level{$hostpart}=$line[10];
270 $line[12] =~ /(\d+)K/;
271 $esize{$hostpart}=$1 / $unitdivisor;
272 $partialestimate{$hostpart}=0;
273 $getest{$hostpart} = "";
274 } elsif($line[4] eq "partial") {
276 $partition = $line[10];
277 $hostpart=&make_hostpart($host,$partition,$gdatestamp);
279 $line[13] =~ /(-?\d+)K/;
282 $line[16] =~ /(-?\d+)K/;
285 $line[19] =~ /(-?\d+)K/;
287 if($size1 > 0 || $size2 > 0 || $size3 > 0) {
288 $estimate{$hostpart}=1;
289 $level{$hostpart}=$line[11];
290 $esize{$hostpart}=$size1 / $unitdivisor;
291 $partialestimate{$hostpart}=1;
292 if($size1 > 0) { $getest{$hostpart} =~ s/:$level1://; }
293 if($size2 > 0) { $getest{$hostpart} =~ s/:$level2://; }
294 if($size3 > 0) { $getest{$hostpart} =~ s/:$level3://; }
295 if($getest{$hostpart} eq "") {$partialestimate{$hostpart}=0;}
298 } elsif($line[3] eq "getting" &&
299 $line[4] eq "estimates" &&
300 $line[5] eq "took") {
304 } elsif($line[0] eq "setup_estimate") {
306 $partition = $line[2];
307 $hostpart=&make_hostpart($host,$partition,$gdatestamp);
308 $estimate{$hostpart}=0;
310 $degr_level{$hostpart}=-1;
312 $dump_started{$hostpart}=0;
313 $dump_finished{$hostpart}=0;
314 $taper_started{$hostpart}=0;
315 $taper_finished{$hostpart}=0;
316 $partialestimate{$hostpart}=0;
317 $error{$hostpart}="";
318 if($line[7] eq "last_level") {
319 $getest{$hostpart}="";
323 if($level1 != -1) { $getest{$hostpart} .= ":$level1:" };
324 if($level2 != -1) { $getest{$hostpart} .= ":$level2:" };
325 if($level3 != -1) { $getest{$hostpart} .= ":$level3:" };
327 } elsif($line[0] eq "GENERATING" &&
328 $line[1] eq "SCHEDULE") {
329 $generating_schedule=1;
330 } elsif($line[0] eq "--------") {
331 if ($generating_schedule == 1) {
332 $generating_schedule = 2;
333 } elsif ($generating_schedule == 2) {
334 $generating_schedule = 3;
336 } elsif($line[0] eq "DUMP") {
337 if($generating_schedule == 2 ) {
339 $partition = $line[3];
340 $datestamp = $line[4];
341 $hostpart=&make_hostpart($host,$partition,$datestamp);
342 $level{$hostpart}=$line[6];
343 $esize=$line[14]; #compressed size
344 $esize=32 if $esize<32;
345 $esize{$hostpart}=$esize / $unitdivisor;
346 if(!defined($line[25])) {
347 $degr_level{$hostpart}=-1;
349 $degr_level{$hostpart}=$line[17];
350 $esize=$line[25]; #compressed size
351 $esize=32 if $esize<32;
352 $degr_size{$hostpart}=$esize / $unitdivisor;
355 } elsif($line[0] eq "FLUSH") {
357 $partition = $line[2];
358 $datestamp = $line[3];
360 $holding_file = $line[5];
361 $hostpart=&make_hostpart($host,$partition,$datestamp);
363 $dump_finished{$hostpart}=0;
364 $holding_file{$hostpart}=$holding_file;
365 $level{$hostpart}=$level;
366 } elsif($line[0] eq "driver") {
367 if($line[1] eq "pid") {
369 if (! $Amanda_process->process_alive($pid, "driver")) {
373 elsif($line[1] eq "start" && $line[2] eq "time") {
374 $start_time=$line[3];
375 $current_time=$line[3];
376 $dumpers_active[0]=0;
380 elsif($line[1] eq "tape" && $line[2] eq "size") {
381 $lineX =~ /^driver: start time (\S+)/;
382 $tape_size = $line[3] / $unitdivisor;
384 elsif($line[1] eq "adding" &&
385 $line[2] eq "holding" &&
386 $line[3] eq "disk") {
387 $holding_space += $line[8];
389 elsif($line[1] eq "send-cmd" && $line[2] eq "time") {
390 #print "send-cmd: " , $line[5] . " " . $line[6] . " " . $line[7] . "\n" if defined $line[5] && defined $line[6] && defined $line[7];
391 $current_time = $line[3];
392 if($line[5] =~ /dumper\d*/) {
394 if($line[6] eq "PORT-DUMP") {
395 #7:handle 8:port 9:host 10:amfeatures 11:disk 12:device 13:level ...
397 $partition = $line[11];
398 $hostpart=&make_hostpart($host,$partition,$gdatestamp);
400 $dumper_to_serial{$line[5]} = $serial;
401 $dump_started{$hostpart}=1;
402 $dump_time{$hostpart}=$current_time;
403 $dump_finished{$hostpart}=0;
404 if( $level{$hostpart} != $line[13] &&
405 $degr_level{$hostpart} == $line[13]) {
406 $level{$hostpart}=$degr_level{$hostpart};
407 $esize{$hostpart}=$degr_size{$hostpart};
409 if(! defined($busy_time{$dumper})) {
410 $busy_time{$dumper}=0;
412 $running_dumper{$dumper} = $hostpart;
413 $error{$hostpart}="";
414 $taper_error{$hostpart}="";
415 $size{$hostpart} = 0;
417 if(! defined($dumpers_active[$dumpers_active])) {
418 $dumpers_active[$dumpers_active]=0;
420 if(! defined($dumpers_held[$dumpers_active])) {
421 $dumpers_held[$dumpers_active]={};
425 elsif($line[5] =~ /chunker\d*/) {
426 if($line[6] eq "PORT-WRITE") {
428 $partition=$line[11];
429 $hostpart=&make_hostpart($host,$partition,$gdatestamp);
431 $chunker_to_serial{$line[5]} = $serial;
432 $serial{$serial}=$hostpart;
433 $holding_file{$hostpart}=$line[8];
434 #$chunk_started{$hostpart}=1;
435 $chunk_time{$hostpart}=$current_time;
436 #$chunk_finished{$hostpart}=0;
437 $size{$hostpart} = 0;
439 elsif($line[6] eq "CONTINUE") {
440 #7:handle 8:filename 9:chunksize 10:use
442 $hostpart=$serial{$serial};
443 if($hostpart ne "") {
444 $dump_roomq{$hostpart}=undef;
445 $error{$hostpart}="";
449 elsif($line[5] =~ /taper/) {
450 if($line[6] eq "START-TAPER") {
452 $gdatestamp=$line[8];
453 if(!defined $datestamp{$gdatestamp}) {
454 $datestamp{$gdatestamp} = 1;
455 push @datestamp, $gdatestamp;
457 $status_taper = "Searching for a new tape";
459 elsif($line[6] eq "NEW-TAPE") {
461 $status_taper = "Searching for a new tape";
463 elsif($line[6] eq "NO-NEW-TAPE") {
464 #7:name 8:handle 9:errmsg
467 $status_taper = $error;
469 elsif($line[6] eq "FILE-WRITE") {
470 #7:name 8:handle 9:filename 10:host 11:disk 12:level 13:datestamp 14:splitsize
474 $partition=$line[11];
476 $ldatestamp=$line[13];
477 $status_taper = "Writing $host:$partition";
478 if(!defined $datestamp{$ldatestamp}) {
479 $datestamp{$ldatestamp} = 1;
480 push @datestamp, $ldatestamp;
482 $hostpart=&make_hostpart($host,$partition,$ldatestamp);
483 $serial{$serial}=$hostpart;
484 if(!defined $level{$hostpart}) {
485 $level{$hostpart} = $level;
487 $taper_started{$hostpart}=1;
488 $taper_finished{$hostpart}=0;
489 $taper_time{$hostpart}=$current_time;
490 $taper_error{$hostpart}="";
491 $taper_name{$hostpart} = $name;
492 $worker_to_serial{$name} = $serial;
493 $tapedsize{$hostpart} = 0;
495 elsif($line[6] eq "PORT-WRITE") {
496 #7:name 8:handle 9:host 10:disk 11:level 12:datestamp 13:splitsize 14:diskbuffer 15:fallback_splitsize
500 $partition=$line[10];
502 $ldatestamp=$line[12];
503 $status_taper = "Writing $host:$partition";
504 $hostpart=&make_hostpart($host,$partition,$ldatestamp);
505 $serial{$serial}=$hostpart;
506 $taper_started{$hostpart}=1;
507 $taper_finished{$hostpart}=0;
508 $taper_time{$hostpart}=$current_time;
509 $taper_error{$hostpart}="";
510 $taper_name{$hostpart} = $name;
511 $worker_to_serial{$name} = $serial;
512 $tapedsize{$hostpart} = 0;
513 $size{$hostpart} = 0;
515 elsif($line[6] eq "TAKE-SCRIBE-FROM") {
516 #7:name1 #8:handle #9:name2
520 $hostpart=$serial{$serial};
521 $taper_nb{$name1} = $taper_nb{$name2};
522 $taper_nb{$name2} = 0;
523 if (defined $hostpart) {
524 $error{$hostpart} = $olderror{$hostpart};
529 elsif($line[1] eq "result" && $line[2] eq "time") {
530 #print "result: " , $line[5] . " " . $line[6] . " " . $line[7] . "\n" if defined $line[5] && defined $line[6] && defined $line[7];
531 $current_time = $line[3];
532 if($line[5] =~ /dumper\d+/) {
533 if($line[6] eq "(eof)") {
535 $line[7] = $dumper_to_serial{$line[5]};
536 $line[8] = "dumper CRASH";
538 if($line[6] eq "FAILED" || $line[6] eq "TRY-AGAIN") {
542 $hostpart=$serial{$serial};
543 if ($taper_started{$hostpart} == 1) {
544 $dump_finished{$hostpart}=-1;
546 $dump_finished{$hostpart}=-3;
548 $busy_time{$line[5]}+=($current_time-$dump_time{$hostpart});
549 $running_dumper{$line[5]} = "0";
550 $dump_time{$hostpart}=$current_time;
551 if (!$taper_error{$hostpart}) {
552 $error{$hostpart}="dumper: $error";
557 elsif($line[6] eq "DONE") {
558 #7:handle 8:origsize 9:size ...
560 $origsize=$line[8] / $unitdivisor;
561 $outputsize=$line[9] / $unitdivisor;
562 $hostpart=$serial{$serial};
563 $size{$hostpart}=$outputsize;
564 $dump_finished{$hostpart}=1;
565 $busy_time{$line[5]}+=($current_time-$dump_time{$hostpart});
566 $running_dumper{$line[5]} = "0";
567 $dump_time{$hostpart}=$current_time;
568 $error{$hostpart}="";
571 elsif($line[6] eq "ABORT-FINISHED") {
574 $hostpart=$serial{$serial};
575 $dump_started{$hostpart}=0;
576 if ($taper_started{$hostpart} == 1) {
577 $dump_finished{$hostpart}=-1;
579 $dump_finished{$hostpart}=-3;
581 $busy_time{$line[5]}+=($current_time-$dump_time{$hostpart});
582 $running_dumper{$line[5]} = "0";
583 $dump_time{$hostpart}=$current_time;
584 $error{$hostpart}="dumper: (aborted)";
588 elsif($line[5] =~ /chunker\d+/) {
589 if($line[6] eq "(eof)") {
591 $line[7] = $chunker_to_serial{$line[5]};
592 $line[8] = "chunker CRASH";
594 if($line[6] eq "DONE" || $line[6] eq "PARTIAL") {
597 $outputsize=$line[8] / $unitdivisor;
598 $hostpart=$serial{$serial};
599 $size{$hostpart}=$outputsize;
600 if ($line[6] eq "DONE") {
601 $dump_finished{$hostpart}=1;
603 $dump_finished{$hostpart}=-3;
605 $busy_time{$line[5]}+=($current_time-$chunk_time{$hostpart});
606 $running_dumper{$line[5]} = "0";
607 $chunk_time{$hostpart}=$current_time;
608 if ($line[6] eq "PARTIAL") {
609 $partial{$hostpart} = 1;
612 $partial{$hostpart} = 0;
613 $error{$hostpart}="";
616 elsif($line[6] eq "FAILED") {
618 $hostpart=$serial{$serial};
619 $dump_finished{$hostpart}=-1;
620 $busy_time{$line[5]}+=($current_time-$chunk_time{$hostpart});
621 $running_dumper{$line[5]} = "0";
622 $chunk_time{$hostpart}=$current_time;
623 $error{$hostpart}="chunker: " .$line[8] if $error{$hostpart} eq "";
625 elsif($line[6] eq "RQ-MORE-DISK") {
628 $hostpart=$serial{$serial};
629 $dump_roomq{$hostpart}=1;
630 $error{$hostpart}="(waiting for holding disk space)";
633 elsif($line[5] eq "taper") {
634 if($line[6] eq "(eof)") {
636 foreach $worker (keys %worker_to_serial) {
637 $serial = $worker_to_serial{$worker};
638 $hostpart=$serial{$serial};
639 if(defined $hostpart) {
640 $error= "taper CRASH";
641 $taper_finished{$hostpart} = -2;
642 $status_taper = $error;
643 $busy_time{"taper"}+=($current_time-$taper_time{$hostpart});
644 $taper_time{$hostpart}=$current_time;
645 $error{$hostpart}="$error";
646 undef $worker_to_serial{$worker};
648 undef $taper_status_file{$hostpart};
651 elsif($line[6] eq "DONE" || $line[6] eq "PARTIAL") {
652 #DONE: 7:handle 8:label 9:filenum 10:errstr
653 #PARTIAL: 7:handle 8:INPUT-* 9:TAPE-* 10:errstr 11:INPUT-MSG 12:TAPE-MSG
656 $status_taper = "Idle";
657 $hostpart=$serial{$serial};
658 $line[10] =~ /sec (\S+) (kb|bytes) (\d+) kps/;
660 $size=$3 / $unitdivisor;
662 $size=$3 / ( $unitdivisor * 1024);
664 $taper_finished{$hostpart}=1;
665 $busy_time{"taper"}+=($current_time-$taper_time{$hostpart});
666 $taper_time{$hostpart}=$current_time;
667 if(!defined $size{$hostpart}) {
668 $size{$hostpart}=$size;
670 $ntape = $taper_nb{$taper_name{$hostpart}};
671 $ntpartition{$ntape}++ if defined $ntape;
672 if ($line[6] eq "PARTIAL") {
673 $partial{$hostpart} = 1;
674 if ($line[9] eq "TAPE-ERROR") {
675 $error{$hostpart} = "taper: $line[12]";
676 $taper_error{$hostpart} = "taper: $line[12]";
680 $partial{$hostpart} = 0;
682 undef $taper_status_file{$hostpart};
683 undef $worker_to_serial{$taper_name{$hostpart}};
685 elsif($line[6] eq "PARTDONE") {
686 #7:handle 8:label 9:filenum 10:ksize 11:errstr
688 $hostpart=$serial{$serial};
689 #$line[11] =~ /.*kb (\d*) kps/;
690 #$size=$1 / $unitdivisor;
691 $size=$line[10] / $unitdivisor;
692 $tapedsize{$hostpart} += $size;
693 $ntape = $taper_nb{$taper_name{$hostpart}};
695 $ntsize{$ntape} += $size;
696 $ntesize{$ntape} += $size;
698 elsif($line[6] eq "REQUEST-NEW-TAPE") {
701 $old_status_taper = $status_taper;
702 $status_taper = "Asking for a new tape";
703 $hostpart=$serial{$serial};
704 if (defined $hostpart and
705 !defined($olderror{$hostpart})) {
706 $olderror{$hostpart} = $error{$hostpart};
707 $error{$hostpart} = "waiting for a new tape";
710 elsif($line[6] eq "NEW-TAPE") {
713 $status_taper = $old_status_taper;
714 $hostpart=$serial{$serial};
716 $taper_nb{$taper_name{$hostpart}} = $nb_tape;
718 $ntlabel{$nb_tape} = $label;
719 $ntpartition{$nb_tape} = 0;
720 $ntsize{$nb_tape} = 0;
721 $ntesize{$nb_tape} = 0;
722 if (defined $hostpart) {
723 $error{$hostpart} = $olderror{$hostpart};
726 elsif($line[6] eq "TAPER-OK") {
728 $status_taper = "Idle";
730 elsif($line[6] eq "TAPE-ERROR") {
733 $status_taper = $error;
734 $exit_status |= $STATUS_TAPE;
735 undef $taper_status_file{$hostpart};
737 elsif($line[6] eq "FAILED") {
738 #7:handle 8:INPUT- 9:TAPE- 10:input_message 11:tape_message
740 $hostpart=$serial{$serial};
741 if(defined $hostpart) {
742 if($line[9] eq "TAPE-ERROR") {
744 $taper_finished{$hostpart} = -2;
745 $status_taper = $error;
746 } elsif($line[9] eq "TAPE-CONFIG") {
747 $tape_config{$hostpart} = $error;
749 $tape_config{$hostpart} = $error;
750 $taper_finished{$hostpart} = -2;
751 $status_taper = $error;
752 } else { # INPUT-ERROR
754 $error = $error{$hostpart} if defined $error{$hostpart};
755 $taper_finished{$hostpart} = -1;
756 $status_taper = "Idle";
758 $busy_time{"taper"}+=($current_time-$taper_time{$hostpart});
759 $taper_time{$hostpart}=$current_time;
760 $error{$hostpart}="$error";
762 undef $taper_status_file{$hostpart};
763 undef $worker_to_serial{$taper_name{$hostpart}};
767 elsif($line[1] eq "finished-cmd" && $line[2] eq "time") {
768 $current_time=$line[3];
769 if($line[4] =~ /dumper\d+/) {
772 elsif($line[1] eq "dump" && $line[2] eq "failed") {
773 #3:handle 4: 5: 6:"too many dumper retry"
775 $hostpart=$serial{$serial};
776 $dump_started{$hostpart}=-1;
777 $dump_finished{$hostpart}=-2;
778 $error{$hostpart} .= "(" . $line[6] . ")";
780 elsif($line[1] eq "tape" && $line[2] eq "failed") {
781 #3:handle 4: 5: 6:"too many dumper retry"
783 $hostpart=$serial{$serial};
784 $taper_started{$hostpart}=-1;
785 $taper_finished{$hostpart}=-2;
786 $error{$hostpart} .= "(" . $line[6] . ")";
788 elsif($line[1] eq "state" && $line[2] eq "time") {
789 #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
790 $current_time=$line[3];
791 $idle_dumpers=$line[12];
793 $free{"kps"} = $line[6];
794 $free{"space"} = $line[8];
795 $qlen{"tapeq"} = $line[15];
796 $qlen{"runq"} = $line[17];
797 $qlen{"roomq"} = $line[19];
799 if(defined($dumpers_active)) {
800 if($status_driver ne "") {
801 $dumpers_active[$dumpers_active_prev]
802 +=$current_time-$state_time_prev;
803 $dumpers_held[$dumpers_active_prev]{$status_driver}
804 +=$current_time-$state_time_prev;
806 $state_time_prev=$current_time;
807 $dumpers_active_prev=$dumpers_active;
808 $status_driver=$line[23];
809 if(! defined($dumpers_held[$dumpers_active]{$status_driver})) {
810 $dumpers_held[$dumpers_active]{$status_driver}=0;
814 elsif($line[1] eq "FINISHED") {
815 $driver_finished = 1;
818 elsif($line[0] eq "dump") {
819 if($line[1] eq "of" &&
820 $line[2] eq "driver" &&
821 $line[3] eq "schedule" &&
822 $line[4] eq "after" &&
823 $line[5] eq "start" &&
824 $line[6] eq "degraded" &&
825 $line[7] eq "mode") {
826 $start_degraded_mode=1;
829 elsif($line[0] eq "taper") {
830 if($line[1] eq "wrote") {
831 #1:"wrote" 2:"label" 3:label
834 #$ntlabel{$nb_tape} = $label;
835 #$ntpartition{$nb_tape} = 0;
836 #$ntsize{$nb_tape} = 0;
837 #$ntesize{$nb_tape} = 0;
839 elsif($line[1] eq "status" && $line[2] eq "file") {
840 #1:"status" #2:"file:" #3:hostname #4:diskname #5:filename
842 #$partition = $line[4];
843 #Which datestamp to use?
844 #$hostpart=&make_hostpart($host,$partition,$datestamp);
845 #assume $hostpart is already set.
846 $taper_status_file{$hostpart} = $line[5];
849 elsif($line[0] eq "splitting" &&
850 $line[1] eq "chunk" &&
851 $line[2] eq "that" &&
852 $line[3] eq "started" &&
854 $line[6] eq "after") {
855 $line[7] =~ /(\d*)kb/;
857 $ntchunk{$nb_tape}++;
858 $ntsize{$nb_tape} += $size / $unitdivisor;
859 $ntesize{$nb_tape} += $size / $unitdivisor;
862 #print "Ignoring: $lineX\n";
868 if(defined $current_time) {
869 for ($d = 0; $d < $#dumpers_active; $d++) {
870 $the_dumper = "dumper$d";
871 if(defined($running_dumper{$the_dumper}) &&
872 $running_dumper{$the_dumper} ne "0") {
873 $busy_time{$the_dumper}+=($current_time-$dump_time{$running_dumper{$the_dumper}});
917 foreach $host (sort @hosts) {
918 foreach $partition (sort @$host) {
919 foreach $datestamp (sort @datestamp) {
920 $hostpart=&make_hostpart($host,$partition,$datestamp);
921 next if(!defined $estimate{$hostpart} && !defined $flush{$hostpart});
922 if(length("$host:$partition") > $maxnamelength) {
923 $maxnamelength = length("$host:$partition");
929 foreach $host (sort @hosts) {
930 foreach $partition (sort @$host) {
931 $qpartition = Amanda::Util::quote_string($partition);
932 foreach $datestamp (sort @datestamp) {
933 $hostpart=&make_hostpart($host,$partition,$datestamp);
934 next if(!defined $estimate{$hostpart} && !defined $flush{$hostpart});
936 if( (!defined $size{$hostpart} || $size{$hostpart} == 0) &&
937 defined $holding_file{$hostpart}) {
938 $size{$hostpart} = &dump_size($holding_file{$hostpart}) / (1024 * $unitdivisor);
941 if($estimate_done != 1 && !defined $flush{$hostpart}) {
942 if(defined $estimate{$hostpart}) {
943 if($estimate{$hostpart} != 1) {
944 if( defined $opt_gestimate ||
945 defined $opt_failed && $dead_run != 0) {
946 printf "%8s ", $datestamp if defined $opt_date;
947 printf "%-${maxnamelength}s", "$host:$qpartition";
950 print " failed: killed while";
951 $exit_status |= $STATUS_FAILED;
953 print " getting estimate\n";
957 if(defined $opt_estimate ||
958 (defined $opt_gestimate && $partialestimate{$hostpart} == 1) ||
959 (defined $opt_failed && $dead_run != 0 && $partialestimate{$hostpart} == 1)) {
960 printf "%8s ", $datestamp if defined $opt_date;
961 printf "%-${maxnamelength}s", "$host:$qpartition";
962 printf "%2d ", $level{$hostpart};
963 printf "%9d$unit", $esize{$hostpart};
964 if($partialestimate{$hostpart} == 1) {
966 print " failed: killed while";
967 $exit_status |= $STATUS_FAILED;
971 print " estimate done\n";
974 $estsize += $esize{$hostpart};
979 if(defined $estimate{$hostpart}) {
980 if($estimate{$hostpart} == 1) {
982 $estsize += $esize{$hostpart};
984 elsif (!defined $dump_started{$hostpart} || $dump_started{$hostpart} == 0) {
985 if( defined $opt_failed) {
986 printf "%8s ", $datestamp if defined $opt_date;
987 printf "%-${maxnamelength}s%2d ", "$host:$qpartition", $level{$hostpart};
988 printf " no estimate\n";
990 $exit_status |= $STATUS_FAILED;
992 $fsize+=$esize{$hostpart};
997 $flsize += $size{$hostpart};
1000 if(defined $taper_started{$hostpart} &&
1001 $taper_started{$hostpart}==1) {
1002 if(defined $dump_started{$hostpart} &&
1003 $dump_started{$hostpart} == 1 &&
1004 $dump_finished{$hostpart} == -1) {
1005 if(defined $opt_failed) {
1006 printf "%8s ", $datestamp if defined $opt_date;
1007 printf "%-${maxnamelength}s%2d ", "$host:$qpartition", $level{$hostpart};
1008 printf "%9d$unit", $esize{$hostpart};
1009 print " dump to tape failed: " . $error{$hostpart};
1012 $exit_status |= $STATUS_FAILED;
1014 $fsize+=$esize{$hostpart};
1015 } elsif(defined $dump_started{$hostpart} &&
1016 $dump_started{$hostpart} == 1 &&
1017 $dump_finished{$hostpart} == 0 &&
1018 $taper_started{$hostpart} == 1) {
1019 if( defined $opt_dumpingtape ||
1020 defined $opt_failed && $dead_run != 0) {
1021 printf "%8s ", $datestamp if defined $opt_date;
1022 printf "%-${maxnamelength}s%2d ", "$host:$qpartition", $level{$hostpart};
1023 printf "%9d$unit", $esize{$hostpart};
1025 print " failed: killed while";
1026 $exit_status |= $STATUS_FAILED;
1028 print " dumping to tape";
1029 $size = $tapedsize{$hostpart};
1030 if ($taper_status_file{$hostpart} && -f $taper_status_file{$hostpart} &&
1031 open FF, "<$taper_status_file{$hostpart}") {
1033 if (defined $line) {
1035 $value = $line / ($unitdivisor * 1024);
1037 $size = $value if (!defined($size) || $value > $size);
1042 if(defined($size)) {
1043 printf " (%d$unit done (%0.2f%%))", $size, 100.0 * $size/$esize{$hostpart};
1046 if( defined $starttime ) {
1047 print " (", &showtime($taper_time{$hostpart}), ")";
1052 $dtesize += $esize{$hostpart};
1054 elsif($taper_finished{$hostpart} == 0) {
1055 if( defined $opt_writingtape ||
1056 defined $opt_failed && $dead_run != 0) {
1057 printf "%8s ", $datestamp if defined $opt_date;
1058 printf "%-${maxnamelength}s%2d ", "$host:$qpartition", $level{$hostpart};
1059 printf "%9d$unit", $size{$hostpart};
1061 print " failed: killed while";
1062 $exit_status |= $STATUS_FAILED;
1064 if($in_flush == 0) {
1065 if (defined $dump_finished{$hostpart}) {
1066 if ($dump_finished{$hostpart} == 1) {
1067 print " dump done,";
1069 $exit_status |= $STATUS_FAILED;
1070 print " dump failed: ", $error{$hostpart}, ",";
1072 $fsize+=$esize{$hostpart};
1075 print " writing to tape";
1078 print " flushing to tape";
1080 $size = $tapedsize{$hostpart};
1081 if ($taper_status_file{$hostpart} && -f $taper_status_file{$hostpart} &&
1082 open FF, "<$taper_status_file{$hostpart}") {
1084 if (defined $line) {
1086 $value = $line / ($unitdivisor * 1024);
1088 $size = $value if (!defined($size) || $value > $size);
1093 if(defined($size) and defined($size{$hostpart}) and $size{$hostpart} > 0) {
1094 printf " (%d$unit done (%0.2f%%))", $size, 100.0 * $size/$size{$hostpart};
1096 if( defined $starttime ) {
1097 print " (", &showtime($taper_time{$hostpart}), ")";
1099 print ", ", $error{$hostpart} if (defined($error{$hostpart}) &&
1100 $error{$hostpart} ne "" &&
1101 (!defined $dump_finished{$hostpart} ||
1102 $dump_finished{$hostpart} != -3));
1106 $tasize += $size{$hostpart};
1107 if(defined $esize{$hostpart}) {
1108 $taesize += $esize{$hostpart};
1111 $taesize += $size{$hostpart};
1113 if (defined $dump_finished{$hostpart} && $dump_finished{$hostpart} == 1) {
1115 $dsize += $size{$hostpart};
1116 if(defined $esize{$hostpart} && $esize{$hostpart} > 1) {
1117 $desize += $esize{$hostpart};
1119 $desize += $size{$hostpart};
1123 elsif($taper_finished{$hostpart} < 0) {
1125 if(defined $size{$hostpart}) {
1126 $xsize = $size{$hostpart};
1128 elsif(defined $esize{$hostpart}) {
1129 $xsize = $esize{$hostpart};
1135 if(defined $esize{$hostpart}) {
1136 $exsize += $esize{$hostpart};
1142 if( defined $opt_failed ||
1143 (defined $opt_waittaper && ($taper_finished{$hostpart} == -1))) {
1144 printf "%8s ", $datestamp if defined $opt_date;
1145 printf "%-${maxnamelength}s%2d ", "$host:$qpartition", $level{$hostpart};
1146 printf "%9d$unit", $xsize;
1147 print " dump done," if defined $dump_finished{$hostpart} && $dump_finished{$hostpart} == 1;
1148 if($in_flush == 0) {
1149 if ($tape_config{$hostpart}) {
1150 print " taping delayed because of config";
1152 print " failed to tape";
1156 if ($tape_config{$hostpart}) {
1157 print " flushing delayed because of config";
1159 print " failed to flush";
1162 print ": ",$error{$hostpart} if defined $error{$hostpart};
1164 print " (will retry)" unless $taper_finished{$hostpart} < -1;
1165 if( defined $starttime ) {
1166 print " (", &showtime($taper_time{$hostpart}), ")";
1170 $exit_status |= $STATUS_TAPE;
1174 $tfesize += $exsize;
1176 if($in_flush == 0) {
1179 $twesize += $exsize;
1185 if (defined $dump_finished{$hostpart} && $dump_finished{$hostpart} == 1) {
1187 $dsize += $size{$hostpart};
1188 if(defined $esize{$hostpart} && $esize{$hostpart} > 1) {
1189 $desize += $esize{$hostpart};
1191 $desize += $size{$hostpart};
1195 elsif($taper_finished{$hostpart} == 1) {
1196 if( defined $opt_finished ) {
1197 printf "%8s ", $datestamp if defined $opt_date;
1198 printf "%-${maxnamelength}s%2d ", "$host:$qpartition", $level{$hostpart};
1199 printf "%9d$unit", $size{$hostpart};
1200 if($in_flush == 0) {
1201 if (defined $dump_finished{$hostpart} && $dump_finished{$hostpart} == -3) {
1202 $exit_status |= $STATUS_FAILED;
1203 print " dump failed: ", $error{$hostpart}, ",";
1205 $fsize+=$esize{$hostpart};
1212 if( defined $starttime ) {
1213 print " (", &showtime($taper_time{$hostpart}), ")";
1215 if(defined $partial{$hostpart} && $partial{$hostpart} == 1) {
1217 $exit_status |= $STATUS_FAILED;
1221 if (defined $dump_finished{$hostpart} && $dump_finished{$hostpart} == 1) {
1223 $dsize += $size{$hostpart};
1224 if(defined $esize{$hostpart} && $esize{$hostpart} > 1) {
1225 $desize += $esize{$hostpart};
1227 $desize += $size{$hostpart};
1231 $tsize += $size{$hostpart};
1232 if(defined $esize{$hostpart} && $esize{$hostpart} > 1) {
1233 $tesize += $esize{$hostpart};
1236 $tesize += $size{$hostpart};
1240 printf "%8s ", $datestamp if defined $opt_date;
1241 printf "%-${maxnamelength}s%2d ", "$host:$qpartition", $level{$hostpart};
1242 print " unknown state TAPER\n";
1245 elsif(defined $dump_started{$hostpart}) {
1246 if($dump_started{$hostpart} == -1) {
1247 if( defined $opt_failed ) {
1248 printf "%8s ", $datestamp if defined $opt_date;
1249 printf "%-${maxnamelength}s%2d ", "$host:$qpartition", $level{$hostpart};
1250 printf "failed: " . $error{$hostpart} . "\n";
1252 $exit_status |= $STATUS_FAILED;
1255 $fsize+=$esize{$hostpart};
1257 elsif($dump_started{$hostpart} == 0) {
1258 if($estimate{$hostpart} == 1) {
1259 if( defined $opt_waitdumping ) {
1260 printf "%8s ", $datestamp if defined $opt_date;
1261 printf "%-${maxnamelength}s%2d ", "$host:$qpartition", $level{$hostpart};
1262 printf "%9d$unit", $esize{$hostpart};
1264 print " failed: process terminated while";
1265 $exit_status |= $STATUS_FAILED;
1267 print " waiting for dumping $error{$hostpart}\n";
1269 if($driver_finished == 1) {
1270 $exit_status |= $STATUS_MISSING;
1273 $wsize += $esize{$hostpart};
1276 elsif($dump_started{$hostpart} == 1 &&
1277 ($dump_finished{$hostpart} == -1 ||
1278 $dump_finished{$hostpart} == -3)) {
1279 if( defined $opt_failed ) {
1280 printf "%8s ", $datestamp if defined $opt_date;
1281 printf "%-${maxnamelength}s%2d ", "$host:$qpartition", $level{$hostpart};
1282 print "backup failed: ", $error{$hostpart};
1283 if( defined $starttime ) {
1284 print " (", &showtime($dump_time{$hostpart}), ")";
1288 $exit_status |= $STATUS_FAILED;
1290 $fsize+=$esize{$hostpart};
1292 elsif($dump_started{$hostpart} == 1 &&
1293 $dump_finished{$hostpart} == 0) {
1294 if( defined $opt_dumping ||
1295 defined $opt_failed && $dead_run != 0) {
1296 printf "%8s ", $datestamp if defined $opt_date;
1297 printf "%-${maxnamelength}s%2d ", "$host:$qpartition", $level{$hostpart};
1298 printf "%9d$unit", $esize{$hostpart};
1300 print " failed: killed while";
1301 $exit_status |= $STATUS_FAILED;
1303 printf " dumping %8d$unit", $size{$hostpart};
1304 if($size{$hostpart} != 0) {
1305 printf " (%6.2f%%)", (100.0*$size{$hostpart})/$esize{$hostpart};
1307 if( defined $starttime ) {
1308 print " (", &showtime($dump_time{$hostpart}), ")";
1310 if(defined $dump_roomq{$hostpart}) {
1311 print " " . $error{$hostpart};
1316 $dusize += $size{$hostpart};
1317 $duesize += $esize{$hostpart};
1319 elsif($dump_finished{$hostpart} == 1 &&
1320 $taper_started{$hostpart} != 1) {
1321 if( defined $opt_waittaper ) {
1322 printf "%8s ", $datestamp if defined $opt_date;
1323 printf "%-${maxnamelength}s%2d ", "$host:$qpartition", $level{$hostpart};
1324 printf "%9d$unit", $size{$hostpart};
1326 if( defined $starttime ) {
1327 print " (", &showtime($dump_time{$hostpart}), ")";
1331 print " process terminated while";
1333 print " waiting for writing to tape";
1334 if(defined $partial{$hostpart} && $partial{$hostpart} == 1) {
1336 $exit_status |= $STATUS_FAILED;
1341 $dsize += $size{$hostpart};
1342 $desize += $esize{$hostpart};
1344 $twsize += $size{$hostpart};
1345 $twesize += $esize{$hostpart};
1348 printf "%8s ", $datestamp if defined $opt_date;
1349 printf "%-${maxnamelength}s%2d ", "$host:$qpartition", $level{$hostpart};
1350 print " unknown state DUMPER\n";
1353 elsif(defined $flush{$hostpart}) {
1354 if( defined $opt_waittaper ) {
1355 printf "%8s ", $datestamp if defined $opt_date;
1356 printf "%-${maxnamelength}s%2d ", "$host:$qpartition", $level{$hostpart};
1357 printf "%9d$unit", $size{$hostpart};
1359 print " process terminated while";
1361 print " waiting to flush";
1362 if(defined $partial{$hostpart} && $partial{$hostpart} == 1) {
1364 $exit_status |= $STATUS_FAILED;
1369 $wfsize += $size{$hostpart};
1371 elsif(defined $level{$hostpart}) {
1372 printf "%8s ", $datestamp if defined $opt_date;
1373 printf "%-${maxnamelength}s%2d ", "$host:$qpartition", $level{$hostpart};
1374 print " unknown state\n";
1381 if (defined $opt_summary) {
1383 print "SUMMARY part real estimated\n";
1384 print " size size\n";
1385 printf "partition : %3d\n", $nb_partition;
1386 printf "estimated : %3d %20d$unit\n", $epartition , $estsize;
1387 printf "flush : %3d %9d$unit\n", $flpartition, $flsize;
1388 printf "failed : %3d %20d$unit (%6.2f%%)\n",
1389 $fpartition , $fsize,
1390 $estsize ? ($fsize * 1.0 / $estsize) * 100 : 0.0;
1391 printf "wait for dumping: %3d %20d$unit (%6.2f%%)\n",
1392 $wpartition , $wsize,
1393 $estsize ? ($wsize * 1.0 / $estsize) * 100 : 0.0;
1394 if(defined($dtsize)) {
1395 printf "dumping to tape : %3d %9d$unit %9d$unit (%6.2f%%) (%6.2f%%)\n",
1396 $dtpartition, $dtsize, $dtesize,
1397 $dtsize ? ($dtsize * 1.0 / $dtesize) * 100 : 0.0,
1398 $estsize ? ($dtesize * 1.0 / $estsize) * 100 : 0.0;
1400 printf "dumping to tape : %3d %20d$unit (%6.2f%%)\n",
1401 $dtpartition, $dtesize,
1402 $estsize ? ($dtesize * 1.0 / $estsize) * 100 : 0.0;
1404 printf "dumping : %3d %9d$unit %9d$unit (%6.2f%%) (%6.2f%%)\n",
1405 $dupartition, $dusize, $duesize,
1406 $duesize ? ($dusize * 1.0 / $duesize) * 100 : 0.0,
1407 $estsize ? ($dusize * 1.0 / $estsize) * 100 : 0.0;
1408 printf "dumped : %3d %9d$unit %9d$unit (%6.2f%%) (%6.2f%%)\n",
1409 $dpartition , $dsize , $desize,
1410 $desize ? ($dsize * 1.0 / $desize) * 100 : 0.0,
1411 $estsize ? ($dsize * 1.0 / $estsize) * 100 : 0.0;
1412 printf "wait for writing: %3d %9d$unit %9d$unit (%6.2f%%) (%6.2f%%)\n",
1413 $twpartition, $twsize, $twesize,
1414 $twesize ? ($twsize * 1.0 / $twesize) * 100 : 0.0,
1415 $estsize ? ($twsize * 1.0 / $estsize) * 100 : 0.0;
1416 printf "wait to flush : %3d %9d$unit %9d$unit (%6.2f%%) (%6.2f%%)\n",
1417 $wfpartition, $wfsize, $wfsize, 100, 0;
1418 printf "writing to tape : %3d %9d$unit %9d$unit (%6.2f%%) (%6.2f%%)\n",
1419 $tapartition, $tasize, $taesize,
1420 $taesize ? ($tasize * 1.0 / $taesize) * 100 : 0.0,
1421 $estsize ? ($tasize * 1.0 / $estsize) * 100 : 0.0;
1422 printf "failed to tape : %3d %9d$unit %9d$unit (%6.2f%%) (%6.2f%%)\n",
1423 $tfpartition, $tfsize, $tfesize,
1424 $tfesize ? ($tfsize * 1.0 / $tfesize) * 100 : 0.0,
1425 $estsize ? ($tfsize * 1.0 / $estsize) * 100 : 0.0;
1426 printf "taped : %3d %9d$unit %9d$unit (%6.2f%%) (%6.2f%%)\n",
1427 $tpartition , $tsize , $tesize,
1428 $tesize ? ($tsize * 1.0 / $tesize) * 100 : 0.0,
1429 ($estsize+$flsize) ? ($tsize * 1.0 / ($estsize + $flsize)) * 100 : 0.0;
1430 if($nb_tape > 1 || $tape_size != 0) {
1431 for($i=1; $i <= $nb_tape; $i++) {
1432 if($tape_size != 0) {
1433 printf " tape %-3d : %3d %9d$unit %9d$unit (%6.2f%%) %s",
1434 $i, $ntpartition{$i}, $ntsize{$i}, $ntesize{$i}, 100*$ntsize{$i}/$tape_size, $ntlabel{$i};
1437 printf " tape %-3d : %3d %9d$unit %9d$unit %s",
1438 $i, $ntpartition{$i}, $ntsize{$i}, $ntesize{$i}, $ntlabel{$i};
1440 if(defined($ntchunk{$i}) && $ntchunk{$i} > 0) {
1441 printf " (%d chunks)", $ntchunk{$i};
1446 if($idle_dumpers == 0) {
1447 printf "all dumpers active\n";
1450 $c1 = ($idle_dumpers == 1) ? "" : "s";
1451 $c2 = ($idle_dumpers < 10) ? " " : "";
1452 $c3 = ($idle_dumpers == 1) ? " " : "";
1453 printf "%d dumper%s idle%s %s: %s\n", $idle_dumpers, $c1, $c2, $c3, $status_driver;
1456 printf "taper status: $status_taper\n";
1457 if (defined $qlen{"tapeq"}) {
1458 printf "taper qlen: %d\n", $qlen{"tapeq"};
1460 if (defined ($free{"kps"})) {
1461 printf "network free kps: %9d\n", $free{"kps"};
1463 if (defined ($free{"space"})) {
1464 if ($holding_space) {
1465 $hs = ($free{"space"} * 1.0 / $holding_space) * 100;
1469 printf "holding space : %9d$unit (%6.2f%%)\n", ($free{"space"}/$unitdivisor), $hs;
1473 if(defined $opt_stats) {
1474 if(defined($current_time) && $current_time != $start_time) {
1475 $total_time=$current_time-$start_time;
1476 foreach $key (sort byprocess keys %busy_time) {
1477 printf "%8s busy : %8s (%6.2f%%)\n",
1478 $key, &busytime($busy_time{$key}),
1479 ($busy_time{$key} * 1.0 / $total_time) * 100;
1481 for ($d = 0; $d <= $#dumpers_active; $d++) {
1482 $l = sprintf "%2d dumper%s busy%s : %8s (%6.2f%%)",
1483 $d, ($d == 1) ? "" : "s", ($d == 1) ? " " : "",
1484 &busytime($dumpers_active[$d]),
1485 ($dumpers_active[$d] * 1.0 / $total_time) * 100;
1488 $s2 = " " x length($l);
1489 $r = $dumpers_held[$d];
1490 foreach $key (sort valuesort keys %$r) {
1492 unless $dumpers_held[$d]{$key} >= 1;
1493 printf "%s%20s: %8s (%6.2f%%)\n",
1496 &busytime($dumpers_held[$d]{$key}),
1497 ($dumpers_held[$d]{$key} * 1.0 / $dumpers_active[$d]) * 100;
1509 sub make_hostpart() {
1510 local($host,$partition,$datestamp) = @_;
1512 if(! defined($hosts{$host})) {
1517 foreach $pp (sort @$host) {
1518 $new_part = 0 if ($pp eq $partition);
1520 push @$host, $partition if $new_part==1;
1522 my($hostpart) = "$host$partition$datestamp";
1523 if(!defined $datestamp{$datestamp}) {
1524 $datestamp{$datestamp} = 1;
1525 push @datestamp, $datestamp;
1532 my(@tmp_a) = split(/(\d*)$/, $a, 2);
1533 my(@tmp_b) = split(/(\d*)$/, $b, 2);
1534 return ($tmp_a[0] cmp $tmp_b[0]) || ($tmp_a[1] <=> $tmp_b[1]);
1538 $r->{$b} <=> $r->{$a};
1542 local($filename) = @_;
1545 local($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
1546 $atime,$mtime,$ctime,$blksize,$blocks);
1547 while ($filename ne "") {
1548 $filename = "$filename.tmp" if (!(-e "$filename"));
1549 $filename = "/dev/null" if (!(-e "$filename"));
1550 ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
1551 $atime,$mtime,$ctime,$blksize,$blocks) = stat($filename);
1552 $size=$size-32768 if $size > 32768;
1554 open(DUMP,$filename);
1557 if(/^CONT_FILENAME=(.*)$/) { $filename = $1; last }
1558 last if /^To restore, position tape at start of file and run/;
1573 @MoY = ('Jan','Feb','Mar','Apr','May','Jun',
1574 'Jul','Aug','Sep','Oct','Nov','Dec');
1576 # Preset an array of values in case some parts are not passed as
1577 # arguments. This lets the date, etc, be omitted and default to
1586 # See if this argument looks like a month name.
1592 $month = $month + 1;
1599 # See if this is a day of the month.
1601 if ($a =~ /^\d+$/ && $a >= 1 && $a <= 32) {
1606 # See if the next argument looks like a time.
1608 if ($a =~ /^(\d+):(\d+)/) {
1611 if ($a =~ /^(\d+):(\d+):(\d+)/) {
1617 # See if this is a year.
1619 if ($a =~ /^\d\d\d\d$/ && $a >= 1900) {
1625 $time = &timelocal (@tl);
1630 sub set_starttime() {
1635 # Preset an array of values in case some parts are not passed as
1636 # arguments. This lets the date, etc, be omitted and default to
1642 $tl[5] = substr($date, 0, 4) if(length($date) >= 4);
1643 $tl[4] = substr($date, 4, 2)-1 if(length($date) >= 6);
1644 $tl[3] = substr($date, 6, 2) if(length($date) >= 8);
1645 $tl[2] = substr($date, 8, 2) if(length($date) >= 10);
1646 $tl[1] = substr($date, 10, 2) if(length($date) >= 12);
1647 $tl[0] = substr($date, 12, 2) if(length($date) >= 14);
1649 $time = &timelocal (@tl);
1657 my($oneday) = 24*60*60;
1659 my @starttime = localtime($starttime);
1660 my @now = localtime($starttime+$delta);
1661 $now_yday = $now[7];
1664 if ($starttime[5] < $now[5]) {
1665 my $days_in_year = 364;
1666 my $startime1 = $starttime;
1667 while ($startime1 < $starttime+$delta) {
1668 my @starttime1 = localtime($starttime);
1669 if ($starttime1[7] > $days_in_year) {
1670 $days_in_year = $starttime1[7];
1672 $startime1 += $oneday;
1674 $now_yday += $days_in_year+1;
1677 if ($starttime[7] < $now_yday) {
1678 $result=sprintf("%d+", $now_yday - $starttime[7]);
1682 $result.=sprintf("%d:%02d:%02d",$now[2],$now[1],$now[0]);
1688 my($oneday)=24*60*60;
1690 if($busy > $oneday) {
1691 $days=int($busy/$oneday);
1692 $result=sprintf("%d+",$busy/$oneday);
1693 $busy-=$days*$oneday;
1697 $hours=int($busy/60/60);
1698 $busy-=$hours*60*60;
1699 $minutes=int($busy/60);
1702 $result.=sprintf("%d:%02d:%02d",$hours,$minutes,$seconds);