5 eval '(exit $?0)' && eval 'exec @PERL@ -S $0 ${1+"$@"}'
6 & eval 'exec @PERL@ -S $0 $argv:q'
9 require "newgetopt.pl";
11 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();
36 $USE_VERSION_SUFFIXES='@USE_VERSION_SUFFIXES@';
38 if ( $USE_VERSION_SUFFIXES =~ /^yes$/i ) {
42 $result = &NGetOpt ( "summary",
45 "waitdumping|wdumping",
52 "gestimate|gettingestimate",
56 "locale-independent-date-format",
62 if( defined $opt_config ) {
74 #untaint user input $ARGV[0]
76 if ($conf =~ /^([\w.-]+)$/) { # $1 is untainted
79 die "filename '$conf' has invalid characters.\n";
82 if ( ! -e "$confdir/$conf" ) {
83 print "Configuration directory '$confdir/$conf' doesn't exist\n";
86 if ( ! -d "$confdir/$conf" ) {
87 print "Configuration directory '$confdir/$conf' is not a directory\n";
94 chdir "$confdir/$conf";
96 $logdir=`$sbindir/amgetconf$suf logdir`;
99 $errfile="$logdir/amdump";
101 $nb_options = defined( $opt_summary ) +
102 defined( $opt_stats ) +
103 defined( $opt_dumping ) +
104 defined( $opt_waitdumping ) +
105 defined( $opt_waittaper ) +
106 defined( $opt_dumpingtape ) +
107 defined( $opt_writingtape ) +
108 defined( $opt_finished ) +
109 defined( $opt_estimate ) +
110 defined( $opt_gestimate ) +
111 defined( $opt_failed );
113 if($nb_options == 0 ) {
117 $opt_waitdumping = 1;
119 $opt_dumpingtape = 1;
120 $opt_writingtape = 1;
127 $unit=`$sbindir/amgetconf$suf displayunit`;
129 $unit =~ tr/A-Z/a-z/;
134 elsif($unit eq 'm') {
137 elsif($unit eq 'g') {
138 $unitdivisor = 1024*1024;
140 elsif($unit eq 't') {
141 $unitdivisor = 1024*1024*1024;
150 if( defined $opt_file) {
151 if( $opt_file =~ m,^/, ) {
152 $errfile = $opt_file;
154 $errfile = "$pwd/$opt_file";
155 $errfile = "$logdir/$opt_file" if ( ! (-f $errfile ));
159 $errfile="$logdir/amflush" if(! (-f $errfile));
161 if (-f "$logdir/amflush.1" && -f "$logdir/amdump.1" &&
162 -M "$logdir/amflush.1" < -M "$logdir/amdump.1") {
163 $errfile="$logdir/amflush.1";
165 $errfile="$logdir/amdump.1";
171 open(AMDUMP,"<$errfile") || die("$errfile: $!");
172 print "Using $errfile\n";
174 $start_degraded_mode = 0;
176 $label = ""; # -w fodder
177 $origsize = 0; # -w fodder
184 @dumpers_active = ();
186 $ntpartition{$nb_tape} = 0;
187 $ntsize{$nb_tape} = 0;
188 $ntesize{$nb_tape} = 0;
190 $driver_finished = 0;
191 $generating_schedule = 0;
193 while($lineX = <AMDUMP>) {
195 $lineX =~ s/[:\s]+$//g; #remove separator at end of line
196 next if $lineX eq "";
197 @line = "ewords('[:\s]+', 0, $lineX);
198 next if !defined $line[0];
200 if($line[0] eq "amdump" || $line[0] eq "amflush") {
201 if ($line[1] eq "start" && $line[2] eq "at") {
203 $datestr =~ s/.*start at //g;
204 if (!defined $opt_locale_independent_date_format) {
205 print "From " . $datestr . "\n";
207 } elsif($line[1] eq "datestamp") {
208 $gdatestamp = $line[2];
209 if(!defined $datestamp{$gdatestamp}) {
210 $datestamp{$gdatestamp} = 1;
211 push @datestamp, $gdatestamp;
213 } elsif($line[1] eq "starttime") {
214 $starttime=&set_starttime($line[2]);
215 } elsif($line[1] eq "starttime-locale-independent") {
216 if (defined $opt_locale_independent_date_format) {
217 printf "From " . $line[2] . " " . $line[3] . ":" . $line[4] . ":" . $line[5] . " " . $line[6] . "\n";
220 if($line[0] eq "amflush") {
223 } elsif($line[0] eq "planner") {
224 if($line[1] eq "timestamp") {
225 $gdatestamp = $line[2];
226 if(!defined $datestamp{$gdatestamp}) {
227 $datestamp{$gdatestamp} = 1;
228 push @datestamp, $gdatestamp;
231 elsif($line[1] eq "FAILED") {
232 #2:host 3:disk 4:datestamp 5:level 6:errmsg
236 $hostpart=&make_hostpart($host,$partition,$datestamp);
237 $dump_started{$hostpart}=-1;
238 $level{$hostpart}=$line[5];
239 $error{$hostpart}="planner: " . $line[6];
240 } elsif($line[1] eq "time") {
241 if($line[3] eq "got") {
242 if($line[4] eq "result") {
244 $partition = $line[9];
245 $hostpart=&make_hostpart($host,$partition,$gdatestamp);
246 $estimate{$hostpart}=1;
247 $level{$hostpart}=$line[10];
248 $line[12] =~ /(\d+)K/;
249 $esize{$hostpart}=$1 / $unitdivisor;
250 $partialestimate{$hostpart}=0;
251 $getest{$hostpart} = "";
252 } elsif($line[4] eq "partial") {
254 $partition = $line[10];
255 $hostpart=&make_hostpart($host,$partition,$gdatestamp);
257 $line[13] =~ /(-?\d+)K/;
260 $line[16] =~ /(-?\d+)K/;
263 $line[19] =~ /(-?\d+)K/;
265 if($size1 > 0 || $size2 > 0 || $size3 > 0) {
266 $estimate{$hostpart}=1;
267 $level{$hostpart}=$line[11];
268 $esize{$hostpart}=$size1 / $unitdivisor;
269 $partialestimate{$hostpart}=1;
270 if($size1 > 0) { $getest{$hostpart} =~ s/:$level1://; }
271 if($size2 > 0) { $getest{$hostpart} =~ s/:$level2://; }
272 if($size3 > 0) { $getest{$hostpart} =~ s/:$level3://; }
273 if($getest{$hostpart} eq "") {$partialestimate{$hostpart}=0;}
276 } elsif($line[3] eq "getting" &&
277 $line[4] eq "estimates" &&
278 $line[5] eq "took") {
282 } elsif($line[0] eq "setup_estimate") {
284 $partition = $line[2];
285 $hostpart=&make_hostpart($host,$partition,$gdatestamp);
286 $estimate{$hostpart}=0;
288 $degr_level{$hostpart}=-1;
290 $dump_started{$hostpart}=0;
291 $dump_finished{$hostpart}=0;
292 $taper_started{$hostpart}=0;
293 $taper_finished{$hostpart}=0;
294 $partialestimate{$hostpart}=0;
295 $error{$hostpart}="";
296 if($line[7] eq "last_level") {
297 $getest{$hostpart}="";
301 if($level1 != -1) { $getest{$hostpart} .= ":$level1:" };
302 if($level2 != -1) { $getest{$hostpart} .= ":$level2:" };
303 if($level3 != -1) { $getest{$hostpart} .= ":$level3:" };
305 } elsif($line[0] eq "GENERATING" &&
306 $line[1] eq "SCHEDULE") {
307 $generating_schedule=1;
308 } elsif($line[0] eq "--------") {
309 if ($generating_schedule == 1) {
310 $generating_schedule = 2;
311 } elsif ($generating_schedule == 2) {
312 $generating_schedule = 3;
314 } elsif($line[0] eq "DUMP") {
315 if($generating_schedule == 2 ) {
317 $partition = $line[3];
318 $datestamp = $line[4];
319 $hostpart=&make_hostpart($host,$partition,$datestamp);
320 $level{$hostpart}=$line[6];
321 $esize=$line[14]; #compressed size
322 $esize=32 if $esize<32;
323 $esize{$hostpart}=$esize / $unitdivisor;
324 if(!defined($line[25])) {
325 $degr_level{$hostpart}=-1;
327 $degr_level{$hostpart}=$line[17];
328 $esize=$line[25]; #compressed size
329 $esize=32 if $esize<32;
330 $degr_size{$hostpart}=$esize / $unitdivisor;
333 } elsif($line[0] eq "FLUSH") {
335 $partition = $line[2];
336 $datestamp = $line[3];
338 $holding_file = $line[5];
339 $hostpart=&make_hostpart($host,$partition,$datestamp);
341 $holding_file{$hostpart}=$holding_file;
342 $level{$hostpart}=$level;
343 } elsif($line[0] eq "driver") {
344 if($line[1] eq "pid") {
346 if (! $Amanda_process->process_alive($pid, "driver")) {
350 elsif($line[1] eq "start" && $line[2] eq "time") {
351 $start_time=$line[3];
352 $current_time=$line[3];
353 $dumpers_active[0]=0;
357 elsif($line[1] eq "tape" && $line[2] eq "size") {
358 $lineX =~ /^driver: start time (\S+)/;
359 $tape_size = $line[3] / $unitdivisor;
361 elsif($line[1] eq "adding" &&
362 $line[2] eq "holding" &&
363 $line[3] eq "disk") {
364 $holding_space += $line[8];
366 elsif($line[1] eq "send-cmd" && $line[2] eq "time") {
367 #print "send-cmd: " , $line[5] . " " . $line[6] . " " . $line[7] . "\n" if defined $line[5] && defined $line[6] && defined $line[7];
368 $current_time = $line[3];
369 if($line[5] =~ /dumper\d*/) {
371 if($line[6] eq "PORT-DUMP") {
372 #7:handle 8:port 9:host 10:amfeatures 11:disk 12:device 13:level ...
374 $partition = $line[11];
375 $hostpart=&make_hostpart($host,$partition,$gdatestamp);
377 $dump_started{$hostpart}=1;
378 $dump_time{$hostpart}=$current_time;
379 $dump_finished{$hostpart}=0;
380 if( $level{$hostpart} != $line[13] &&
381 $degr_level{$hostpart} == $line[13]) {
382 $level{$hostpart}=$degr_level{$hostpart};
383 $esize{$hostpart}=$degr_size{$hostpart};
385 if(! defined($busy_time{$dumper})) {
386 $busy_time{$dumper}=0;
388 $running_dumper{$dumper} = $hostpart;
389 $error{$hostpart}="";
390 $size{$hostpart} = 0;
392 if(! defined($dumpers_active[$dumpers_active])) {
393 $dumpers_active[$dumpers_active]=0;
395 if(! defined($dumpers_held[$dumpers_active])) {
396 $dumpers_held[$dumpers_active]={};
400 elsif($line[5] =~ /chunker\d*/) {
401 if($line[6] eq "PORT-WRITE") {
403 $partition=$line[11];
404 $hostpart=&make_hostpart($host,$partition,$gdatestamp);
406 $serial{$serial}=$hostpart;
407 $holding_file{$hostpart}=$line[8];
408 #$chunk_started{$hostpart}=1;
409 $chunk_time{$hostpart}=$current_time;
410 #$chunk_finished{$hostpart}=0;
412 elsif($line[6] eq "CONTINUE") {
413 #7:handle 8:filename 9:chunksize 10:use
415 $hostpart=$serial{$serial};
416 if($hostpart ne "") {
417 $dump_roomq{$hostpart}=undef;
418 $error{$hostpart}="";
422 elsif($line[5] =~ /taper/) {
423 if($line[6] eq "START-TAPER") {
425 $gdatestamp=$line[7];
426 if(!defined $datestamp{$gdatestamp}) {
427 $datestamp{$gdatestamp} = 1;
428 push @datestamp, $gdatestamp;
431 elsif($line[6] eq "FILE-WRITE") {
432 #7:handle 8:filename 9:host 10:disk 11:level 12:datestamp 13:splitsize
435 $partition=$line[10];
437 $ldatestamp=$line[12];
438 if(!defined $datestamp{$ldatestamp}) {
439 $datestamp{$ldatestamp} = 1;
440 push @datestamp, $ldatestamp;
442 $hostpart=&make_hostpart($host,$partition,$ldatestamp);
443 $serial{$serial}=$hostpart;
444 if(!defined $level{$hostpart}) {
445 $level{$hostpart} = $level;
447 $taper_started{$hostpart}=1;
448 $taper_finished{$hostpart}=0;
449 $taper_time{$hostpart}=$current_time;
452 elsif($line[6] eq "PORT-WRITE") {
453 #7:handle 8:host 9:disk 10:level 11:datestamp 12:splitsize 13:diskbuffer 14:fallback_splitsize
458 $ldatestamp=$line[11];
459 $hostpart=&make_hostpart($host,$partition,$ldatestamp);
460 $serial{$serial}=$hostpart;
461 $taper_started{$hostpart}=1;
462 $taper_finished{$hostpart}=0;
463 $taper_time{$hostpart}=$current_time;
468 elsif($line[1] eq "result" && $line[2] eq "time") {
469 #print "result: " , $line[5] . " " . $line[6] . " " . $line[7] . "\n" if defined $line[5] && defined $line[6] && defined $line[7];
470 $current_time = $line[3];
471 if($line[5] =~ /dumper\d+/) {
472 if($line[6] eq "FAILED" || $line[6] eq "TRY-AGAIN") {
476 $hostpart=$serial{$serial};
477 $dump_finished{$hostpart}=-1;
478 $busy_time{$line[5]}+=($current_time-$dump_time{$hostpart});
479 $running_dumper{$line[5]} = "0";
480 $dump_time{$hostpart}=$current_time;
481 $error{$hostpart}="dumper: $error";
485 elsif($line[6] eq "DONE") {
486 #7:handle 8:origsize 9:size ...
488 $origsize=$line[8] / $unitdivisor;
489 $outputsize=$line[9] / $unitdivisor;
490 $hostpart=$serial{$serial};
491 $size{$hostpart}=$outputsize;
492 $dump_finished{$hostpart}=1;
493 $busy_time{$line[5]}+=($current_time-$dump_time{$hostpart});
494 $running_dumper{$line[5]} = "0";
495 $dump_time{$hostpart}=$current_time;
496 $error{$hostpart}="";
499 elsif($line[6] eq "ABORT-FINISHED") {
502 $hostpart=$serial{$serial};
503 $dump_started{$hostpart}=0;
504 $dump_finished{$hostpart}=0;
505 $busy_time{$line[5]}+=($current_time-$dump_time{$hostpart});
506 $running_dumper{$line[5]} = "0";
507 $dump_time{$hostpart}=$current_time;
508 $error{$hostpart}="dumper: (aborted)";
512 elsif($line[5] =~ /chunker\d+/) {
513 if($line[6] eq "DONE" || $line[6] eq "PARTIAL") {
516 $outputsize=$line[8] / $unitdivisor;
517 $hostpart=$serial{$serial};
518 $size{$hostpart}=$outputsize;
519 $dump_finished{$hostpart}=1;
520 $busy_time{$line[5]}+=($current_time-$chunk_time{$hostpart});
521 $running_dumper{$line[5]} = "0";
522 $chunk_time{$hostpart}=$current_time;
523 $error{$hostpart}="";
524 if ($line[6] eq "PARTIAL") {
525 $partial{$hostpart} = 1;
528 $partial{$hostpart} = 0;
531 elsif($line[6] eq "FAILED") {
533 $hostpart=$serial{$serial};
534 $dump_finished{$hostpart}=-1;
535 $busy_time{$line[5]}+=($current_time-$chunk_time{$hostpart});
536 $running_dumper{$line[5]} = "0";
537 $chunk_time{$hostpart}=$current_time;
538 $error{$hostpart}="chunker: " .$line[8] if $error{$hostpart} eq "";
540 elsif($line[6] eq "RQ-MORE-DISK") {
543 $hostpart=$serial{$serial};
544 $dump_roomq{$hostpart}=1;
545 $error{$hostpart}="(waiting for holding disk space)";
548 elsif($line[5] eq "taper") {
549 if($line[6] eq "DONE" || $line[6] eq "PARTIAL") {
550 #7:handle 8:label 9:filenum 10:errstr
553 $hostpart=$serial{$serial};
554 $line[10] =~ /sec (\S+) kb (\d+) kps/;
555 $size=$2 / $unitdivisor;
556 $taper_finished{$hostpart}=1;
557 $busy_time{"taper"}+=($current_time-$taper_time{$hostpart});
558 $taper_time{$hostpart}=$current_time;
559 if(!defined $size{$hostpart}) {
560 $size{$hostpart}=$size;
562 $ntpartition{$nb_tape}++;
563 $ntsize{$nb_tape} += $size{$hostpart} - $ntchunk_size;
564 if(defined $esize{$hostpart} && $esize{$hostpart} > 1) {
565 $ntesize{$nb_tape} += $esize{$hostpart} - $ntchunk_size;
568 $ntesize{$nb_tape} += $size{$hostpart} - $ntchunk_size;
570 if ($line[6] eq "PARTIAL") {
571 $partial{$hostpart} = 1;
574 $partial{$hostpart} = 0;
576 if ($ntchunk_size > 0) {
577 $ntchunk{$nb_tape}++;
580 elsif($line[6] eq "PARTDONE") {
581 #7:handle 8:label 9:filenum 10:ksize 11:errstr
583 $hostpart=$serial{$serial};
584 #$line[11] =~ /.*kb (\d*) kps/;
585 #$size=$1 / $unitdivisor;
586 $size=$line[10] / $unitdivisor;
587 $tapedsize{$hostpart} += $size;
588 $ntchunk{$nb_tape}++;
589 $ntsize{$nb_tape} += $size;
590 $ntesize{$nb_tape} += $size;
591 $ntchunk_size += $size;
593 elsif($line[6] eq "REQUEST-NEW-TAPE") {
596 $hostpart=$serial{$serial};
597 if (defined $hostpart) {
598 $error{$hostpart} = "waiting for a new tape";
601 elsif($line[6] eq "NEW-TAPE") {
604 $hostpart=$serial{$serial};
605 if (defined $hostpart) {
606 $error{$hostpart} = "";
609 elsif($line[6] eq "TRY-AGAIN" || $line[6] eq "TAPE-ERROR") {
613 $hostpart=$serial{$serial};
614 if(defined $hostpart) {
615 $taper_finished{$hostpart}= $line[6] eq 'TAPE-ERROR' ? -2 : -1;
616 $busy_time{"taper"}+=($current_time-$taper_time{$hostpart});
617 $taper_time{$hostpart}=$current_time;
618 $error{$hostpart}="taper: $error";
621 elsif($line[6] eq "FAILED") {
622 #7:handle 8:INPUT- 9:TAPE- 10:input_message 11:tape_message
624 $hostpart=$serial{$serial};
625 if(defined $hostpart) {
626 if($line[9] eq "TAPE-ERROR") {
628 $taper_finished{$hostpart} = -2;
632 $taper_finished{$hostpart} = -1;
634 $busy_time{"taper"}+=($current_time-$taper_time{$hostpart});
635 $taper_time{$hostpart}=$current_time;
636 $error{$hostpart}="$error";
641 elsif($line[1] eq "finished-cmd" && $line[2] eq "time") {
642 $current_time=$line[3];
643 if($line[4] =~ /dumper\d+/) {
646 elsif($line[1] eq "dump" && $line[2] eq "failed") {
647 #3:handle 4: 5: 6:"too many dumper retry"
649 $hostpart=$serial{$serial};
650 $dump_started{$hostpart}=-1;
651 $dump_finished{$hostpart}=-2;
652 $error{$hostpart} .= "(" . $line[6] . ")";
654 elsif($line[1] eq "tape" && $line[2] eq "failed") {
655 #3:handle 4: 5: 6:"too many dumper retry"
657 $hostpart=$serial{$serial};
658 $taper_started{$hostpart}=-1;
659 $taper_finished{$hostpart}=-2;
660 $error{$hostpart} .= "(" . $line[6] . ")";
662 elsif($line[1] eq "state" && $line[2] eq "time") {
663 #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
664 $current_time=$line[3];
665 $status_taper=$line[10];
666 $idle_dumpers=$line[12];
668 $free{"kps"} = $line[6];
669 $free{"space"} = $line[8];
670 $qlen{"tapeq"} = $line[15];
671 $qlen{"runq"} = $line[17];
672 $qlen{"roomq"} = $line[19];
674 if(defined($dumpers_active)) {
675 if($status_driver ne "") {
676 $dumpers_active[$dumpers_active_prev]
677 +=$current_time-$state_time_prev;
678 $dumpers_held[$dumpers_active_prev]{$status_driver}
679 +=$current_time-$state_time_prev;
681 $state_time_prev=$current_time;
682 $dumpers_active_prev=$dumpers_active;
683 $status_driver=$line[16];
684 if(! defined($dumpers_held[$dumpers_active]{$status_driver})) {
685 $dumpers_held[$dumpers_active]{$status_driver}=0;
689 elsif($line[1] eq "FINISHED") {
690 $driver_finished = 1;
693 elsif($line[0] eq "dump") {
694 if($line[1] eq "of" &&
695 $line[2] eq "driver" &&
696 $line[3] eq "schedule" &&
697 $line[4] eq "after" &&
698 $line[5] eq "start" &&
699 $line[6] eq "degraded" &&
700 $line[7] eq "mode") {
701 $start_degraded_mode=1;
704 elsif($line[0] eq "taper") {
705 if($line[1] eq "slot") {
706 #2:slot 3:"wrote" 4:"label" 5:corrupted...
708 $lineX =~ /wrote label `(\S*)'/;
710 $ntlabel{$nb_tape} = $label;
711 $ntpartition{$nb_tape} = 0;
712 $ntsize{$nb_tape} = 0;
713 $ntesize{$nb_tape} = 0;
715 elsif($line[1] eq "wrote") {
716 #1:"wrote" 2:"label" 3:corrupted
718 $lineX =~ /wrote label `(\S*)'/;
720 $ntlabel{$nb_tape} = $label;
721 $ntpartition{$nb_tape} = 0;
722 $ntsize{$nb_tape} = 0;
723 $ntesize{$nb_tape} = 0;
725 elsif($line[1] eq "using") {
726 #1:"using" #2:"label" #3:`label' #4:date #5 `timestamp'
728 $lineX =~ /using label `(\S*)'/;
730 $ntlabel{$nb_tape} = $label;
731 $ntpartition{$nb_tape} = 0;
732 $ntsize{$nb_tape} = 0;
733 $ntesize{$nb_tape} = 0;
736 elsif($line[0] eq "splitting" &&
737 $line[1] eq "chunk" &&
738 $line[2] eq "that" &&
739 $line[3] eq "started" &&
741 $line[6] eq "after") {
742 $line[7] =~ /(\d*)kb/;
744 $ntchunk{$nb_tape}++;
745 $ntsize{$nb_tape} += $size / $unitdivisor;
746 $ntesize{$nb_tape} += $size / $unitdivisor;
747 $ntchunk_size += $size / $unitdivisor;
750 #print "Ignoring: $lineX\n";
756 if(defined $current_time) {
757 for ($d = 0; $d < $#dumpers_active; $d++) {
758 $the_dumper = "dumper$d";
759 if(defined($running_dumper{$the_dumper}) &&
760 $running_dumper{$the_dumper} ne "0") {
761 $busy_time{$the_dumper}+=($current_time-$dump_time{$running_dumper{$the_dumper}});
805 foreach $host (sort @hosts) {
806 foreach $partition (sort @$host) {
807 foreach $datestamp (sort @datestamp) {
808 $hostpart=&make_hostpart($host,$partition,$datestamp);
809 next if(!defined $estimate{$hostpart} && !defined $flush{$hostpart});
810 if(length("$host:$partition") > $maxnamelength) {
811 $maxnamelength = length("$host:$partition");
817 foreach $host (sort @hosts) {
818 foreach $partition (sort @$host) {
819 $qpartition = Amanda::Util::quote_string($partition);
820 foreach $datestamp (sort @datestamp) {
821 $hostpart=&make_hostpart($host,$partition,$datestamp);
822 next if(!defined $estimate{$hostpart} && !defined $flush{$hostpart});
824 if( (!defined $size{$hostpart} || $size{$hostpart} == 0) &&
825 defined $holding_file{$hostpart}) {
826 $size{$hostpart} = &dump_size($holding_file{$hostpart}) / (1024 * $unitdivisor);
829 if($estimate_done != 1 && !defined $flush{$hostpart}) {
830 if(defined $estimate{$hostpart}) {
831 if($estimate{$hostpart} != 1) {
832 if( defined $opt_gestimate ||
833 defined $opt_failed && $dead_run != 0) {
834 printf "%8s ", $datestamp if defined $opt_date;
835 printf "%-${maxnamelength}s", "$host:$qpartition";
838 print " failed: killed while";
839 $exit_status |= $STATUS_FAILED;
841 print " getting estimate\n";
845 if(defined $opt_estimate ||
846 (defined $opt_gestimate && $partialestimate{$hostpart} == 1) ||
847 (defined $opt_failed && $dead_run != 0 && $partialestimate{$hostpart} == 1)) {
848 printf "%8s ", $datestamp if defined $opt_date;
849 printf "%-${maxnamelength}s", "$host:$qpartition";
850 printf "%2d ", $level{$hostpart};
851 printf "%9d$unit", $esize{$hostpart};
852 if($partialestimate{$hostpart} == 1) {
854 print " failed: killed while";
855 $exit_status |= $STATUS_FAILED;
859 print " estimate done\n";
862 $estsize += $esize{$hostpart};
867 if(defined $estimate{$hostpart}) {
868 if($estimate{$hostpart} == 1) {
870 $estsize += $esize{$hostpart};
872 elsif (!defined $dump_started{$hostpart} || $dump_started{$hostpart} == 0) {
873 if( defined $opt_failed) {
874 printf "%8s ", $datestamp if defined $opt_date;
875 printf "%-${maxnamelength}s%2d ", "$host:$qpartition", $level{$hostpart};
876 printf " no estimate\n";
878 $exit_status |= $STATUS_FAILED;
880 $fsize+=$esize{$hostpart};
885 $flsize += $size{$hostpart};
888 if(defined $taper_started{$hostpart} &&
889 $taper_started{$hostpart}==1) {
890 if(defined $dump_started{$hostpart} &&
891 $dump_started{$hostpart} == 1 &&
892 $dump_finished{$hostpart} == -1) {
893 if(defined $opt_failed) {
894 printf "%8s ", $datestamp if defined $opt_date;
895 printf "%-${maxnamelength}s%2d ", "$host:$qpartition", $level{$hostpart};
896 printf "%9d$unit", $esize{$hostpart};
897 print " dump to tape failed: " . $error{$hostpart};
900 $exit_status |= $STATUS_FAILED;
902 $fsize+=$esize{$hostpart};
903 } elsif(defined $dump_started{$hostpart} &&
904 $dump_started{$hostpart} == 1 &&
905 $dump_finished{$hostpart} == 0 &&
906 $taper_started{$hostpart} == 1) {
907 if( defined $opt_dumpingtape ||
908 defined $opt_failed && $dead_run != 0) {
909 printf "%8s ", $datestamp if defined $opt_date;
910 printf "%-${maxnamelength}s%2d ", "$host:$qpartition", $level{$hostpart};
911 printf "%9d$unit", $esize{$hostpart};
913 print " failed: killed while";
914 $exit_status |= $STATUS_FAILED;
916 print " dumping to tape";
917 if(defined($tapedsize{$hostpart})) {
918 printf " (%d$unit done)", $tapedsize{$hostpart};
919 $dtsize += $tapedsize{$hostpart};
921 if( defined $starttime ) {
922 print " (", &showtime($taper_time{$hostpart}), ")";
927 $dtesize += $esize{$hostpart};
929 elsif($taper_finished{$hostpart} == 0) {
930 if( defined $opt_writingtape ||
931 defined $opt_failed && $dead_run != 0) {
932 printf "%8s ", $datestamp if defined $opt_date;
933 printf "%-${maxnamelength}s%2d ", "$host:$qpartition", $level{$hostpart};
934 printf "%9d$unit", $size{$hostpart};
936 print " failed: killed while";
937 $exit_status |= $STATUS_FAILED;
940 print " writing to tape";
943 print " flushing to tape";
945 if(defined($tapedsize{$hostpart})) {
946 printf " (%d$unit done)", $tapedsize{$hostpart};
948 if( defined $starttime ) {
949 print " (", &showtime($taper_time{$hostpart}), ")";
951 print ", ", $error{$hostpart} if defined($error{$hostpart} &&
952 $error{$hostpart} ne "");
956 $tasize += $size{$hostpart};
957 if(defined $esize{$hostpart}) {
958 $taesize += $esize{$hostpart};
961 $taesize += $size{$hostpart};
964 elsif($taper_finished{$hostpart} < 0) {
966 if(defined $size{$hostpart}) {
967 $xsize = $size{$hostpart};
969 elsif(defined $esize{$hostpart}) {
970 $xsize = $esize{$hostpart};
976 if(defined $esize{$hostpart}) {
977 $exsize += $esize{$hostpart};
983 if( defined $opt_failed ||
984 (defined $opt_waittaper && ($taper_finished{$hostpart} == -1))) {
985 printf "%8s ", $datestamp if defined $opt_date;
986 printf "%-${maxnamelength}s%2d ", "$host:$qpartition", $level{$hostpart};
987 printf "%9d$unit", $xsize;
989 print " failed to tape";
992 print " failed to flush";
994 print ": ",$error{$hostpart} if defined $error{$hostpart};
996 print " (will retry)" unless $taper_finished{$hostpart} < -1;
997 if( defined $starttime ) {
998 print " (", &showtime($taper_time{$hostpart}), ")";
1002 $exit_status |= $STATUS_TAPE;
1006 $tfesize += $exsize;
1008 if($in_flush == 0) {
1011 $twesize += $exsize;
1018 elsif($taper_finished{$hostpart} == 1) {
1019 if( defined $opt_finished ) {
1020 printf "%8s ", $datestamp if defined $opt_date;
1021 printf "%-${maxnamelength}s%2d ", "$host:$qpartition", $level{$hostpart};
1022 printf "%9d$unit", $size{$hostpart};
1023 if($in_flush == 0) {
1029 if( defined $starttime ) {
1030 print " (", &showtime($taper_time{$hostpart}), ")";
1032 if(defined $partial{$hostpart} && $partial{$hostpart} == 1) {
1034 $exit_status |= $STATUS_FAILED;
1040 $dsize += $size{$hostpart};
1041 $tsize += $size{$hostpart};
1042 $desize += $esize{$hostpart};
1043 if(defined $esize{$hostpart} && $esize{$hostpart} > 1) {
1044 $desize += $esize{$hostpart};
1045 $tesize += $esize{$hostpart};
1048 $desize += $size{$hostpart};
1049 $tesize += $size{$hostpart};
1053 printf "%8s ", $datestamp if defined $opt_date;
1054 printf "%-${maxnamelength}s%2d ", "$host:$qpartition", $level{$hostpart};
1055 print " unknown state TAPER\n";
1058 elsif(defined $dump_started{$hostpart}) {
1059 if($dump_started{$hostpart} == -1) {
1060 if( defined $opt_failed ) {
1061 printf "%8s ", $datestamp if defined $opt_date;
1062 printf "%-${maxnamelength}s%2d ", "$host:$qpartition", $level{$hostpart};
1063 printf " " . $error{$hostpart} . "\n";
1065 $exit_status |= $STATUS_FAILED;
1068 $fsize+=$esize{$hostpart};
1070 elsif($dump_started{$hostpart} == 0) {
1071 if($estimate{$hostpart} == 1) {
1072 if( defined $opt_waitdumping ) {
1073 printf "%8s ", $datestamp if defined $opt_date;
1074 printf "%-${maxnamelength}s%2d ", "$host:$qpartition", $level{$hostpart};
1075 printf "%9d$unit", $esize{$hostpart};
1076 print " wait for dumping $error{$hostpart}\n";
1078 if($driver_finished == 1) {
1079 $exit_status |= $STATUS_MISSING;
1082 $wsize += $esize{$hostpart};
1085 elsif($dump_started{$hostpart} == 1 &&
1086 $dump_finished{$hostpart} == -1) {
1087 if( defined $opt_failed ) {
1088 printf "%8s ", $datestamp if defined $opt_date;
1089 printf "%-${maxnamelength}s%2d ", "$host:$qpartition", $level{$hostpart};
1090 print " ", $error{$hostpart};
1091 if( defined $starttime ) {
1092 print " (", &showtime($dump_time{$hostpart}), ")";
1096 $exit_status |= $STATUS_FAILED;
1098 $fsize+=$esize{$hostpart};
1100 elsif($dump_started{$hostpart} == 1 &&
1101 $dump_finished{$hostpart} != 1) {
1102 if( defined $opt_dumping ||
1103 defined $opt_failed && $dead_run != 0) {
1104 printf "%8s ", $datestamp if defined $opt_date;
1105 printf "%-${maxnamelength}s%2d ", "$host:$qpartition", $level{$hostpart};
1106 printf "%9d$unit", $esize{$hostpart};
1108 print " failed: killed while";
1109 $exit_status |= $STATUS_FAILED;
1111 printf " dumping %8d$unit", $size{$hostpart};
1112 if($size{$hostpart} != 0) {
1113 printf " (%6.2f%%)", (100.0*$size{$hostpart})/$esize{$hostpart};
1115 if( defined $starttime ) {
1116 print " (", &showtime($dump_time{$hostpart}), ")";
1118 if(defined $dump_roomq{$hostpart}) {
1119 print " " . $error{$hostpart};
1124 $dusize += $size{$hostpart};
1125 $duesize += $esize{$hostpart};
1127 elsif($dump_finished{$hostpart} == 1 &&
1128 $taper_started{$hostpart} != 1) {
1129 if( defined $opt_waittaper ) {
1130 printf "%8s ", $datestamp if defined $opt_date;
1131 printf "%-${maxnamelength}s%2d ", "$host:$qpartition", $level{$hostpart};
1132 printf "%9d$unit", $size{$hostpart};
1134 if( defined $starttime ) {
1135 print " (", &showtime($dump_time{$hostpart}), ")";
1137 print ", wait for writing to tape";
1138 if(defined $partial{$hostpart} && $partial{$hostpart} == 1) {
1140 $exit_status |= $STATUS_FAILED;
1145 $dsize += $size{$hostpart};
1146 $desize += $esize{$hostpart};
1148 $twsize += $size{$hostpart};
1149 $twesize += $esize{$hostpart};
1152 printf "%8s ", $datestamp if defined $opt_date;
1153 printf "%-${maxnamelength}s%2d ", "$host:$qpartition", $level{$hostpart};
1154 print " unknown state DUMPER\n";
1157 elsif(defined $flush{$hostpart}) {
1158 if( defined $opt_waittaper ) {
1159 printf "%8s ", $datestamp if defined $opt_date;
1160 printf "%-${maxnamelength}s%2d ", "$host:$qpartition", $level{$hostpart};
1161 printf "%9d$unit", $size{$hostpart};
1162 print " waiting to flush";
1163 if(defined $partial{$hostpart} && $partial{$hostpart} == 1) {
1165 $exit_status |= $STATUS_FAILED;
1170 $wfsize += $size{$hostpart};
1172 elsif(defined $level{$hostpart}) {
1173 printf "%8s ", $datestamp if defined $opt_date;
1174 printf "%-${maxnamelength}s%2d ", "$host:$qpartition", $level{$hostpart};
1175 print " unknown state\n";
1182 if (defined $opt_summary) {
1184 print "SUMMARY part real estimated\n";
1185 print " size size\n";
1186 printf "partition : %3d\n", $nb_partition;
1187 printf "estimated : %3d %20d$unit\n", $epartition , $estsize;
1188 printf "flush : %3d %9d$unit\n", $flpartition, $flsize;
1189 printf "failed : %3d %20d$unit (%6.2f%%)\n",
1190 $fpartition , $fsize,
1191 $estsize ? ($fsize * 1.0 / $estsize) * 100 : 0.0;
1192 printf "wait for dumping: %3d %20d$unit (%6.2f%%)\n",
1193 $wpartition , $wsize,
1194 $estsize ? ($wsize * 1.0 / $estsize) * 100 : 0.0;
1195 if(defined($dtsize)) {
1196 printf "dumping to tape : %3d %9d$unit %9d$unit (%6.2f%%) (%6.2f%%)\n",
1197 $dtpartition, $dtsize, $dtesize,
1198 $dtsize ? ($dtsize * 1.0 / $dtesize) * 100 : 0.0,
1199 $estsize ? ($dtesize * 1.0 / $estsize) * 100 : 0.0;
1201 printf "dumping to tape : %3d %20d$unit (%6.2f%%)\n",
1202 $dtpartition, $dtesize,
1203 $estsize ? ($dtesize * 1.0 / $estsize) * 100 : 0.0;
1205 printf "dumping : %3d %9d$unit %9d$unit (%6.2f%%) (%6.2f%%)\n",
1206 $dupartition, $dusize, $duesize,
1207 $duesize ? ($dusize * 1.0 / $duesize) * 100 : 0.0,
1208 $estsize ? ($dusize * 1.0 / $estsize) * 100 : 0.0;
1209 printf "dumped : %3d %9d$unit %9d$unit (%6.2f%%) (%6.2f%%)\n",
1210 $dpartition , $dsize , $desize,
1211 $desize ? ($dsize * 1.0 / $desize) * 100 : 0.0,
1212 $estsize ? ($dsize * 1.0 / $estsize) * 100 : 0.0;
1213 printf "wait for writing: %3d %9d$unit %9d$unit (%6.2f%%) (%6.2f%%)\n",
1214 $twpartition, $twsize, $twesize,
1215 $twesize ? ($twsize * 1.0 / $twesize) * 100 : 0.0,
1216 $estsize ? ($twsize * 1.0 / $estsize) * 100 : 0.0;
1217 printf "wait to flush : %3d %9d$unit %9d$unit (%6.2f%%) (%6.2f%%)\n",
1218 $wfpartition, $wfsize, $wfsize, 100, 0;
1219 printf "writing to tape : %3d %9d$unit %9d$unit (%6.2f%%) (%6.2f%%)\n",
1220 $tapartition, $tasize, $taesize,
1221 $taesize ? ($tasize * 1.0 / $taesize) * 100 : 0.0,
1222 $estsize ? ($tasize * 1.0 / $estsize) * 100 : 0.0;
1223 printf "failed to tape : %3d %9d$unit %9d$unit (%6.2f%%) (%6.2f%%)\n",
1224 $tfpartition, $tfsize, $tfesize,
1225 $tfesize ? ($tfsize * 1.0 / $tfesize) * 100 : 0.0,
1226 $estsize ? ($tfsize * 1.0 / $estsize) * 100 : 0.0;
1227 printf "taped : %3d %9d$unit %9d$unit (%6.2f%%) (%6.2f%%)\n",
1228 $tpartition , $tsize , $tesize,
1229 $tesize ? ($tsize * 1.0 / $tesize) * 100 : 0.0,
1230 ($estsize+$flsize) ? ($tsize * 1.0 / ($estsize + $flsize)) * 100 : 0.0;
1231 if($nb_tape > 1 || $tape_size != 0) {
1232 for($i=1; $i <= $nb_tape; $i++) {
1233 if($tape_size != 0) {
1234 printf " tape %-3d : %3d %9d$unit %9d$unit (%6.2f%%) %s",
1235 $i, $ntpartition{$i}, $ntsize{$i}, $ntesize{$i}, 100*$ntsize{$i}/$tape_size, $ntlabel{$i};
1238 printf " tape %-3d : %3d %9d$unit %9d$unit %s",
1239 $i, $ntpartition{$i}, $ntsize{$i}, $ntesize{$i}, $ntlabel{$i};
1241 if(defined($ntchunk{$i}) && $ntchunk{$i} > 0) {
1242 printf " (%d chunks)", $ntchunk{$i};
1247 if($idle_dumpers == 0) {
1248 printf "all dumpers active\n";
1251 $c1 = ($idle_dumpers == 1) ? "" : "s";
1252 $c2 = ($idle_dumpers < 10) ? " " : "";
1253 $c3 = ($idle_dumpers == 1) ? " " : "";
1254 printf "%d dumper%s idle%s %s: %s\n", $idle_dumpers, $c1, $c2, $c3, $status_driver;
1256 if($status_taper eq "writing" && defined($qlen{"tapeq"})) {
1257 printf "taper writing, tapeq: %d\n", $qlen{"tapeq"};
1260 printf "taper idle\n";
1262 if (defined ($free{"kps"})) {
1263 printf "network free kps: %9d\n", $free{"kps"};
1265 if (defined ($free{"space"})) {
1266 if ($holding_space) {
1267 $hs = ($free{"space"} * 1.0 / $holding_space) * 100;
1271 printf "holding space : %9d$unit (%6.2f%%)\n", ($free{"space"}/$unitdivisor), $hs;
1275 if(defined $opt_stats) {
1276 if(defined($current_time) && $current_time != $start_time) {
1277 $total_time=$current_time-$start_time;
1278 foreach $key (sort byprocess keys %busy_time) {
1279 printf "%8s busy : %8s (%6.2f%%)\n",
1280 $key, &busytime($busy_time{$key}),
1281 ($busy_time{$key} * 1.0 / $total_time) * 100;
1283 for ($d = 0; $d <= $#dumpers_active; $d++) {
1284 $l = sprintf "%2d dumper%s busy%s : %8s (%6.2f%%)",
1285 $d, ($d == 1) ? "" : "s", ($d == 1) ? " " : "",
1286 &busytime($dumpers_active[$d]),
1287 ($dumpers_active[$d] * 1.0 / $total_time) * 100;
1290 $s2 = " " x length($l);
1291 $r = $dumpers_held[$d];
1292 foreach $key (sort valuesort keys %$r) {
1294 unless $dumpers_held[$d]{$key} >= 1;
1295 printf "%s%20s: %8s (%6.2f%%)\n",
1298 &busytime($dumpers_held[$d]{$key}),
1299 ($dumpers_held[$d]{$key} * 1.0 / $dumpers_active[$d]) * 100;
1311 sub make_hostpart() {
1312 local($host,$partition,$datestamp) = @_;
1314 if(! defined($hosts{$host})) {
1319 foreach $pp (sort @$host) {
1320 $new_part = 0 if ($pp eq $partition);
1322 push @$host, $partition if $new_part==1;
1324 my($hostpart) = "$host$partition$datestamp";
1325 if(!defined $datestamp{$datestamp}) {
1326 $datestamp{$datestamp} = 1;
1327 push @datestamp, $datestamp;
1334 my(@tmp_a) = split(/(\d*)$/, $a, 2);
1335 my(@tmp_b) = split(/(\d*)$/, $b, 2);
1336 return ($tmp_a[0] cmp $tmp_b[0]) || ($tmp_a[1] <=> $tmp_b[1]);
1340 $r->{$b} <=> $r->{$a};
1344 local($filename) = @_;
1347 local($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
1348 $atime,$mtime,$ctime,$blksize,$blocks);
1349 while ($filename ne "") {
1350 $filename = "$filename.tmp" if (!(-e "$filename"));
1351 $filename = "/dev/null" if (!(-e "$filename"));
1352 ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
1353 $atime,$mtime,$ctime,$blksize,$blocks) = stat($filename);
1354 $size=$size-32768 if $size > 32768;
1356 open(DUMP,$filename);
1359 if(/^CONT_FILENAME=(.*)$/) { $filename = $1; last }
1360 last if /^To restore, position tape at start of file and run/;
1375 @MoY = ('Jan','Feb','Mar','Apr','May','Jun',
1376 'Jul','Aug','Sep','Oct','Nov','Dec');
1378 # Preset an array of values in case some parts are not passed as
1379 # arguments. This lets the date, etc, be omitted and default to
1388 # See if this argument looks like a month name.
1394 $month = $month + 1;
1401 # See if this is a day of the month.
1403 if ($a =~ /^\d+$/ && $a >= 1 && $a <= 32) {
1408 # See if the next argument looks like a time.
1410 if ($a =~ /^(\d+):(\d+)/) {
1413 if ($a =~ /^(\d+):(\d+):(\d+)/) {
1419 # See if this is a year.
1421 if ($a =~ /^\d\d\d\d$/ && $a >= 1900) {
1427 $time = &timelocal (@tl);
1432 sub set_starttime() {
1437 # Preset an array of values in case some parts are not passed as
1438 # arguments. This lets the date, etc, be omitted and default to
1444 $tl[5] = substr($date, 0, 4) if(length($date) >= 4);
1445 $tl[4] = substr($date, 4, 2)-1 if(length($date) >= 6);
1446 $tl[3] = substr($date, 6, 2) if(length($date) >= 8);
1447 $tl[2] = substr($date, 8, 2) if(length($date) >= 10);
1448 $tl[1] = substr($date, 10, 2) if(length($date) >= 12);
1449 $tl[0] = substr($date, 12, 2) if(length($date) >= 14);
1451 $time = &timelocal (@tl);
1459 my($oneday)=24*60*60;
1461 @now=localtime($starttime+$delta);
1462 if($delta > $oneday) {
1463 $result=sprintf("%d+",$delta/$oneday);
1467 $result.=sprintf("%d:%02d:%02d",$now[2],$now[1],$now[0]);
1473 my($oneday)=24*60*60;
1475 if($busy > $oneday) {
1476 $days=int($busy/$oneday);
1477 $result=sprintf("%d+",$busy/$oneday);
1478 $busy-=$days*$oneday;
1482 $hours=int($busy/60/60);
1483 $busy-=$hours*60*60;
1484 $minutes=int($busy/60);
1487 $result.=sprintf("%d:%02d:%02d",$hours,$minutes,$seconds);
1492 print "amstatus [--config] config [--file amdump_file]\n";
1493 print " [--summary] [--dumping] [--waitdumping] [--waittaper]\n";
1494 print " [--dumpingtape] [--writingtape] [--finished] [--failed]\n";
1495 print " [--estimate] [--gestimate] [--stats] [--date] [--locale-independent-date-format]\n";