2c32d1b34c3ce9d1fc33a5843e8ac8914b5583dc
[debian/amanda] / server-src / amstatus.pl
1 #!@PERL@ -Tw
2 #
3
4 # Run perl.
5 eval '(exit $?0)' && eval 'exec @PERL@ -S $0 ${1+"$@"}'
6          & eval 'exec @PERL@ -S $0 $argv:q'
7                 if 0;
8
9 require "newgetopt.pl";
10 use Time::Local;
11 use Text::ParseWords;
12
13 delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV', 'PATH'};
14 $ENV{'PATH'} = "/bin:/usr/bin:/usr/sbin:/sbin";       # force known path
15
16 $confdir="@CONFIG_DIR@";
17 $prefix='@prefix@';
18 $prefix=$prefix;                # avoid warnings about possible typo
19 $exec_prefix="@exec_prefix@";
20 $exec_prefix=$exec_prefix;      # ditto
21 $sbindir="@sbindir@";
22
23 #$STATUS_STRANGE =  2;
24 $STATUS_FAILED  =  4;
25 $STATUS_MISSING =  8;
26 $STATUS_TAPE    = 16;
27 $exit_status    =  0;
28
29 $USE_VERSION_SUFFIXES='@USE_VERSION_SUFFIXES@';
30 $suf = '';
31 if ( $USE_VERSION_SUFFIXES =~ /^yes$/i ) {
32         $suf='-@VERSION@';
33 }
34
35 $result = &NGetOpt (    "summary",
36                         "stats|statistics",
37                         "dumping|d",
38                         "waitdumping|wdumping",
39                         "waittaper|wtaper",
40                         "dumpingtape|dtape",
41                         "writingtape|wtape",
42                         "finished",
43                         "failed|error",
44                         "estimate",
45                         "gestimate|gettingestimate",
46                         "date",
47                         "config|c:s",
48                         "file:s",
49                         "locale-independent-date-format",
50                         );
51 if($result !=1 ) {
52         &usage();
53 }
54
55 if( defined $opt_config ) {
56         $conf = $opt_config;
57 }
58 else {
59         if($#ARGV == 0 ) {
60                 $conf=$ARGV[0];
61         }
62         else {
63                 &usage();
64         }
65 }
66
67 #untaint user input $ARGV[0]
68
69 if ($conf =~ /^([\w.-]+)$/) {          # $1 is untainted
70    $conf = $1;
71 } else {
72     die "filename '$conf' has invalid characters.\n";
73 }
74
75 if ( ! -e "$confdir/$conf" ) {
76     print "Configuration directory '" . $confdir/$conf . "' doesn't exist\n";
77     exit 1;
78 }
79 if ( ! -d "$confdir/$conf" ) {
80     print "Configuration directory '" . $confdir/$conf . "' is not a directory\n";
81     exit 1;
82  }
83
84
85 $pwd = `pwd`;
86 chomp $pwd;
87 chdir "$confdir/$conf";
88
89 $logdir=`$sbindir/amgetconf$suf logdir`;
90 exit 1 if $? != 0;
91 chomp $logdir;
92 $errfile="$logdir/amdump";
93
94 $nb_options = defined( $opt_summary ) +
95                                   defined( $opt_stats ) +
96                                   defined( $opt_dumping ) +
97                                   defined( $opt_waitdumping ) +
98                                   defined( $opt_waittaper ) +
99                                   defined( $opt_dumpingtape ) +
100                                   defined( $opt_writingtape ) +
101                                   defined( $opt_finished ) +
102                                   defined( $opt_estimate ) +
103                                   defined( $opt_gestimate ) +
104                                   defined( $opt_failed );
105
106 if($nb_options == 0 ) {
107         $opt_summary     = 1;
108         $opt_stats       = 1; 
109         $opt_dumping     = 1;
110         $opt_waitdumping = 1;
111         $opt_waittaper   = 1;
112         $opt_dumpingtape = 1;
113         $opt_writingtape = 1;
114         $opt_finished    = 1;
115         $opt_failed      = 1;
116         $opt_gestimate   = 1;
117         $opt_estimate    = 1;
118 }
119
120 $unit=`$sbindir/amgetconf$suf displayunit`;
121 chomp($unit);
122 $unit =~ tr/A-Z/a-z/;
123 $unitdivisor=1;
124 if($unit eq 'k') {
125   $unitdivisor = 1;
126 }
127 elsif($unit eq 'm') {
128   $unitdivisor = 1024;
129 }
130 elsif($unit eq 'g') {
131   $unitdivisor = 1024*1024;
132 }
133 elsif($unit eq 't') {
134   $unitdivisor = 1024*1024*1024;
135 }
136 else {
137   $unit = 'k';
138   $unitdivisor = 1;
139 }
140
141
142 if( defined $opt_file) {
143         if( $opt_file =~ m,^/, ) {
144                 $errfile = $opt_file;
145         } else {
146                 $errfile = "$pwd/$opt_file";
147                 $errfile = "$logdir/$opt_file" if ( ! (-f $errfile ));
148         }
149 }
150 else {
151         $errfile="$logdir/amflush" if(! (-f $errfile));
152         if (! -f $errfile) {
153                 if (-f "$logdir/amflush.1" && -f "$logdir/amdump.1" &&
154                     -M "$logdir/amflush.1"  < -M "$logdir/amdump.1") {
155                         $errfile="$logdir/amflush.1";
156                 } else {
157                         $errfile="$logdir/amdump.1";
158                 }
159         }
160 }
161
162 open(AMDUMP,"<$errfile") || die("$errfile: $!");
163 print "Using $errfile\n";
164
165 $start_degraded_mode = 0;
166
167 $label = "";                                    # -w fodder
168 $origsize = 0;                                  # -w fodder
169 $idle_dumpers = 0;
170 $status_driver = "";
171 $status_taper = 0;
172 $estimate_done = 0;
173 $holding_space = 0;
174 $start_time = 0;
175 @dumpers_active = ();
176 $nb_tape = 0;
177 $ntpartition{$nb_tape} = 0;
178 $ntsize{$nb_tape} = 0;
179 $ntesize{$nb_tape} = 0;
180 $tape_size = 0;
181 $driver_finished = 0;
182 $generating_schedule = 0;
183
184 while($lineX = <AMDUMP>) {
185         chomp $lineX;
186         $lineX =~ s/[:\s]+$//g; #remove separator at end of line
187         next if $lineX eq "";
188         @line = &quotewords('[:\s]+', 0, $lineX);
189         next if !defined $line[0];
190
191         if($line[0] eq "amdump" || $line[0] eq "amflush") {
192                 if ($line[1] eq "start" && $line[2] eq "at") {
193                         $datestr = $lineX;
194                         $datestr =~ s/.*start at //g;
195                         if (!defined $opt_locale_independent_date_format) {
196                                 print "From " . $datestr . "\n";
197                         }
198                 } elsif($line[1] eq "datestamp") {
199                         $gdatestamp = $line[2];
200                         if(!defined $datestamp{$gdatestamp}) {
201                                 $datestamp{$gdatestamp} = 1;
202                                 push @datestamp, $gdatestamp;
203                         }
204                 } elsif($line[1] eq "starttime") {
205                         $starttime=&set_starttime($line[2]);
206                 } elsif($line[1] eq "starttime-locale-independent") {
207                         if (defined $opt_locale_independent_date_format) {
208                                 printf "From " . $line[2] . " " . $line[3] . ":" . $line[4] . ":" . $line[5] . " " . $line[6] . "\n";
209                         }
210                 }
211                 if($line[0] eq "amflush") {
212                         $estimate_done=1;
213                 }
214         } elsif($line[0] eq "planner") {
215                 if($line[1] eq "timestamp") {
216                         $gdatestamp = $line[2];
217                         if(!defined $datestamp{$gdatestamp}) {
218                                 $datestamp{$gdatestamp} = 1;
219                                 push @datestamp, $gdatestamp;
220                         }
221                 }
222                 elsif($line[1] eq "FAILED") {
223                         #2:host 3:disk 4:datestamp 5:level 6:errmsg
224                         $host=$line[2];
225                         $partition=$line[3];
226                         $datestamp=$line[4];
227                         $hostpart=&make_hostpart($host,$partition,$datestamp);
228                         $dump_started{$hostpart}=-1;
229                         $level{$hostpart}=$line[5];
230                         $error{$hostpart}="planner: " . $line[6];
231         } elsif($line[1] eq "time") {
232                 if($line[3] eq "got") {
233                                 if($line[4] eq "result") {
234                                         $host = $line[7];
235                                         $partition = $line[9];
236                                         $hostpart=&make_hostpart($host,$partition,$gdatestamp);
237                                         $estimate{$hostpart}=1;
238                                         $level{$hostpart}=$line[10];
239                                         $line[12] =~ /(\d+)K/;
240                                         $esize{$hostpart}=$1 / $unitdivisor;
241                                         $partialestimate{$hostpart}=0;
242                                         $getest{$hostpart} = "";
243                                 } elsif($line[4] eq "partial") {
244                                         $host = $line[8];
245                                         $partition = $line[10];
246                                         $hostpart=&make_hostpart($host,$partition,$gdatestamp);
247                                         $level1 = $line[11];
248                                         $line[13] =~ /(-?\d+)K/;
249                                         $size1 = $1;
250                                         $level2 = $line[14];
251                                         $line[16] =~ /(-?\d+)K/;
252                                         $size2 = $1;
253                                         $level3 = $line[17];
254                                         $line[19] =~ /(-?\d+)K/;
255                                         $size3 = $1;
256                                         if($size1 > 0 || $size2 > 0 || $size3 > 0) {
257                                                 $estimate{$hostpart}=1;
258                                                 $level{$hostpart}=$line[11];
259                                                 $esize{$hostpart}=$size1 / $unitdivisor;
260                                                 $partialestimate{$hostpart}=1;
261                                                 if($size1 > 0) { $getest{$hostpart} =~ s/:$level1://; }
262                                                 if($size2 > 0) { $getest{$hostpart} =~ s/:$level2://; }
263                                                 if($size3 > 0) { $getest{$hostpart} =~ s/:$level3://; }
264                                                 if($getest{$hostpart} eq "") {$partialestimate{$hostpart}=0;}
265                                         }
266                                 }
267                         } elsif($line[3] eq "getting" &&
268                                           $line[4] eq "estimates" &&
269                                           $line[5] eq "took") {
270                                 $estimate_done=1;
271                         }
272                 }
273         } elsif($line[0] eq "setup_estimate") {
274                 $host = $line[1];
275                 $partition = $line[2];
276                 $hostpart=&make_hostpart($host,$partition,$gdatestamp);
277                 $estimate{$hostpart}=0;
278                 $level{$hostpart}=0;
279                 $degr_level{$hostpart}=-1;
280                 $esize{$hostpart}=0;
281                 $dump_started{$hostpart}=0;
282                 $dump_finished{$hostpart}=0;
283                 $taper_started{$hostpart}=0;
284                 $taper_finished{$hostpart}=0;
285                 $partialestimate{$hostpart}=0;
286                 $error{$hostpart}="";
287                 if($line[7] eq "last_level") {
288                         $getest{$hostpart}="";
289                         $level1 = $line[15];
290                         $level2 = $line[17];
291                         $level3 = $line[19];
292                         if($level1 != -1) { $getest{$hostpart} .= ":$level1:" };
293                         if($level2 != -1) { $getest{$hostpart} .= ":$level2:" };
294                         if($level3 != -1) { $getest{$hostpart} .= ":$level3:" };
295                 }
296         } elsif($line[0] eq "GENERATING" &&
297                                 $line[1] eq "SCHEDULE") {
298                 $generating_schedule=1;
299         } elsif($line[0] eq "--------") {
300                 if ($generating_schedule == 1) {
301                         $generating_schedule = 2;
302                 } elsif ($generating_schedule == 2) {
303                         $generating_schedule = 3;
304                 }
305         } elsif($line[0] eq "DUMP") {
306                 if($generating_schedule == 2 ) {
307                         $host = $line[1];
308                         $partition = $line[3];
309                         $datestamp = $line[4];
310                         $hostpart=&make_hostpart($host,$partition,$datestamp);
311                         $level{$hostpart}=$line[6];
312                         $esize=$line[14];       #compressed size
313                         $esize=32 if $esize<32;
314                         $esize{$hostpart}=$esize / $unitdivisor;
315                         if(!defined($line[22])) {
316                                 $degr_level{$hostpart}=-1;
317                         } else {
318                                 $degr_level{$hostpart}=$line[18];
319                                 $esize=$line[25];       #compressed size
320                                 $esize=32 if $esize<32;
321                                 $degr_size{$hostpart}=$esize / $unitdivisor;
322                         }
323                 }
324         } elsif($line[0] eq "FLUSH") {
325                 $host = $line[1];
326                 $partition = $line[2];
327                 $datestamp = $line[3];
328                 $level = $line[4];
329                 $holding_file = $line[5];
330                 $hostpart=&make_hostpart($host,$partition,$datestamp);
331                 $flush{$hostpart}=0;
332                 $holding_file{$hostpart}=$holding_file;
333                 $level{$hostpart}=$level;
334         } elsif($line[0] eq "driver") {
335                 if($line[1] eq "start" && $line[2] eq "time") {
336                         $start_time=$line[3];
337                         $current_time=$line[3];
338                         $dumpers_active[0]=0;
339                         $dumpers_held[0]={};
340                         $dumpers_active=0;
341                 }
342                 elsif($line[1] eq "tape" && $line[2] eq "size") {
343                         $lineX =~ /^driver: start time (\S+)/;
344                         $tape_size = $line[3] / $unitdivisor;
345                 }
346                 elsif($line[1] eq "adding" &&
347                            $line[2] eq "holding" &&
348                                 $line[3] eq "disk") {
349                         $holding_space += $line[8];
350                 }
351                 elsif($line[1] eq "send-cmd" && $line[2] eq "time") {
352                         #print "send-cmd: " , $line[5] . " " . $line[6] . " " . $line[7] . "\n" if defined $line[5] && defined $line[6] && defined $line[7];
353                         $current_time = $line[3];
354                         if($line[5] =~ /dumper\d*/) {
355                                 $dumper = $line[5];
356                                 if($line[6] eq "PORT-DUMP") {
357                                         #7:handle 8:port 9:host 10:amfeatures 11:disk 12:device 13:level ...
358                                         $host = $line[9];
359                                         $partition = $line[11];
360                                         $hostpart=&make_hostpart($host,$partition,$gdatestamp);
361                                         $serial=$line[7];
362                                         $dump_started{$hostpart}=1;
363                                         $dump_time{$hostpart}=$current_time;
364                                         $dump_finished{$hostpart}=0;
365                                         if(     $level{$hostpart} != $line[13] &&
366                                            $degr_level{$hostpart} == $line[13]) {
367                                                 $level{$hostpart}=$degr_level{$hostpart};
368                                                 $esize{$hostpart}=$degr_size{$hostpart};
369                                         }
370                                         if(! defined($busy_time{$dumper})) {
371                                                 $busy_time{$dumper}=0;
372                                         }
373                                         $running_dumper{$dumper} = $hostpart;
374                                         $error{$hostpart}="";
375                                         $size{$hostpart} = 0;
376                                         $dumpers_active++;
377                                         if(! defined($dumpers_active[$dumpers_active])) {
378                                                 $dumpers_active[$dumpers_active]=0;
379                                         }
380                                         if(! defined($dumpers_held[$dumpers_active])) {
381                                                 $dumpers_held[$dumpers_active]={};
382                                         }
383                                 }
384                         }
385                         elsif($line[5] =~ /chunker\d*/) {
386                                 if($line[6] eq "PORT-WRITE") {
387                                         $host=$line[9];
388                                         $partition=$line[11];
389                                         $hostpart=&make_hostpart($host,$partition,$gdatestamp);
390                                         $serial=$line[7];
391                                         $serial{$serial}=$hostpart;
392                                         $holding_file{$hostpart}=$line[8];
393                                         #$chunk_started{$hostpart}=1;
394                                         $chunk_time{$hostpart}=$current_time;
395                                         #$chunk_finished{$hostpart}=0;
396                                 }
397                                 elsif($line[6] eq "CONTINUE") {
398                                         #7:handle 8:filename 9:chunksize 10:use
399                                         $serial=$line[7];
400                                         $hostpart=$serial{$serial};
401                                         if($hostpart ne "") {
402                                                 $dump_roomq{$hostpart}=undef;
403                                                 $error{$hostpart}="";
404                                         }
405                                 }
406                         }
407                         elsif($line[5] =~ /taper/) {
408                                 if($line[6] eq "START-TAPER") {
409                                         #7:timestamp
410                                         $gdatestamp=$line[7];
411                                         if(!defined $datestamp{$gdatestamp}) {
412                                                 $datestamp{$gdatestamp} = 1;
413                                                 push @datestamp, $gdatestamp;
414                                         }
415                                 }
416                                 elsif($line[6] eq "FILE-WRITE") {
417                                         #7:handle 8:filename 9:host 10:disk 11:level 12:datestamp 13:splitsize
418                                         $serial=$line[7];
419                                         $host=$line[9];
420                                         $partition=$line[10];
421                                         $level=$line[11];
422                                         $ldatestamp=$line[12];
423                                         if(!defined $datestamp{$ldatestamp}) {
424                                                 $datestamp{$ldatestamp} = 1;
425                                                 push @datestamp, $ldatestamp;
426                                         }
427                                         $hostpart=&make_hostpart($host,$partition,$ldatestamp);
428                                         $serial{$serial}=$hostpart;
429                                         if(!defined $level{$hostpart}) {
430                                                 $level{$hostpart} = $level;
431                                         }
432                                         $taper_started{$hostpart}=1;
433                                         $taper_finished{$hostpart}=0;
434                                         $taper_time{$hostpart}=$current_time;
435                                         $ntchunk_size = 0;
436                                 }
437                                 elsif($line[6] eq "PORT-WRITE") {
438                                         #7:handle 8:host 9:disk 10:level 11:datestamp 12:splitsize 13:diskbuffer 14:fallback_splitsize
439                                         $serial=$line[7];
440                                         $host=$line[8];
441                                         $partition=$line[9];
442                                         $level=$line[10];
443                                         $ldatestamp=$line[11];
444                                         $hostpart=&make_hostpart($host,$partition,$ldatestamp);
445                                         $serial{$serial}=$hostpart;
446                                         $taper_started{$hostpart}=1;
447                                         $taper_finished{$hostpart}=0;
448                                         $taper_time{$hostpart}=$current_time;
449                                         $ntchunk_size = 0;
450                                 }
451                         }
452                 }
453                 elsif($line[1] eq "result" && $line[2] eq "time") {
454                         #print "result: " , $line[5] . " " . $line[6] . " " . $line[7] . "\n" if defined $line[5] && defined $line[6] && defined $line[7];
455                         $current_time = $line[3];
456                         if($line[5] =~ /dumper\d+/) {
457                                 if($line[6] eq "FAILED" || $line[6] eq "TRY-AGAIN") {
458                                         #7:handle 8:message
459                                         $serial = $line[7];
460                                         $error = $line[8];
461                                         $hostpart=$serial{$serial};
462                               $dump_finished{$hostpart}=-1;
463                                         $busy_time{$line[5]}+=($current_time-$dump_time{$hostpart});
464                               $running_dumper{$line[5]} = "0";
465                               $dump_time{$hostpart}=$current_time;
466                               $error{$hostpart}="dumper: $error";
467                               $dumpers_active--;
468
469                                 }
470                                 elsif($line[6] eq "DONE") {
471                                         #7:handle 8:origsize 9:size ...
472                                         $serial=$line[7];
473                                         $origsize=$line[8] / $unitdivisor;
474                                         $outputsize=$line[9] / $unitdivisor;
475                                         $hostpart=$serial{$serial};
476                                         $size{$hostpart}=$outputsize;
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}="";
482                                         $dumpers_active--;
483                                 }
484                                 elsif($line[6] eq "ABORT-FINISHED") {
485                                         #7:handle
486                                         $serial=$line[7];
487                                         $hostpart=$serial{$serial};
488                                         $dump_started{$hostpart}=0;
489                                         $dump_finished{$hostpart}=0;
490                                         $busy_time{$line[5]}+=($current_time-$dump_time{$hostpart});
491                                         $running_dumper{$line[5]} = "0";
492                                         $dump_time{$hostpart}=$current_time;
493                                         $error{$hostpart}="dumper: (aborted)";
494                                         $dumpers_active--;
495                                 }
496                         }
497                         elsif($line[5] =~ /chunker\d+/) {
498                                 if($line[6] eq "DONE" || $line[6] eq "PARTIAL") {
499                                         #7:handle 8:size
500                                         $serial=$line[7];
501                                         $outputsize=$line[8] / $unitdivisor;
502                                         $hostpart=$serial{$serial};
503                                         $size{$hostpart}=$outputsize;
504                                         $dump_finished{$hostpart}=1;
505                                         $busy_time{$line[5]}+=($current_time-$chunk_time{$hostpart});
506                                         $running_dumper{$line[5]} = "0";
507                                         $chunk_time{$hostpart}=$current_time;
508                                         $error{$hostpart}="";
509                                         if ($line[6] eq "PARTIAL") {
510                                                 $partial{$hostpart} = 1;
511                                         }
512                                         else {
513                                                 $partial{$hostpart} = 0;
514                                         }
515                                 }
516                                 elsif($line[6] eq "FAILED") {
517                                         $serial=$line[7];
518                                         $hostpart=$serial{$serial};
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}="chunker: " .$line[8] if $error{$hostpart} eq "";
524                                 }
525                                 elsif($line[6] eq "RQ-MORE-DISK") {
526                                         #7:handle
527                                         $serial=$line[7];
528                                         $hostpart=$serial{$serial};
529                                         $dump_roomq{$hostpart}=1;
530                                         $error{$hostpart}="(waiting for holding disk space)";
531                                 }
532                         }
533                         elsif($line[5] eq "taper") {
534                                 if($line[6] eq "DONE" || $line[6] eq "PARTIAL") {
535                                         #7:handle 8:label 9:filenum 10:errstr
536                                         $serial=$line[7];
537                                         $label=$line[8];
538                                         $hostpart=$serial{$serial};
539                                         $line[10] =~ /sec (\S+) kb (\d+) kps/;
540                                         $size=$2 / $unitdivisor;
541                                         $taper_finished{$hostpart}=1;
542                                         $busy_time{"taper"}+=($current_time-$taper_time{$hostpart});
543                                         $taper_time{$hostpart}=$current_time;
544                                         if(!defined $size{$hostpart}) {
545                                                 $size{$hostpart}=$size;
546                                         }
547                                         $ntpartition{$nb_tape}++;
548                                         $ntsize{$nb_tape} += $size{$hostpart} - $ntchunk_size;
549                                         if(defined $esize{$hostpart} && $esize{$hostpart} > 1) {
550                                                 $ntesize{$nb_tape} += $esize{$hostpart} - $ntchunk_size;
551                                         }
552                                         else {
553                                                 $ntesize{$nb_tape} += $size{$hostpart} - $ntchunk_size;
554                                         }
555                                         if ($line[6] eq "PARTIAL") {
556                                                 $partial{$hostpart} = 1;
557                                         }
558                                         else {
559                                                 $partial{$hostpart} = 0;
560                                         }
561                                         if ($ntchunk_size > 0) {
562                                                 $ntchunk{$nb_tape}++;
563                                         }
564                                 }
565                                 elsif($line[6] eq "PARTDONE") {
566                                         #7:handle 8:label 9:filenum 10:ksize 11:errstr
567                                         $serial=$line[7];
568                                         $hostpart=$serial{$serial};
569                                         #$line[11] =~ /.*kb (\d*) kps/;
570                                         #$size=$1 / $unitdivisor;
571                                         $size=$line[10] / $unitdivisor;
572                                         $tapedsize{$hostpart} += $size;
573                                         $ntchunk{$nb_tape}++;
574                                         $ntsize{$nb_tape} += $size;
575                                         $ntesize{$nb_tape} += $size;
576                                         $ntchunk_size += $size;
577                                 }
578                                 elsif($line[6] eq "REQUEST-NEW-TAPE") {
579                                         #7:serial
580                                         $serial=$line[7];
581                                         $hostpart=$serial{$serial};
582                                         if (defined $hostpart) {
583                                                 $error{$hostpart} = "waiting for a new tape";
584                                         }
585                                 }
586                                 elsif($line[6] eq "NEW-TAPE") {
587                                         #7:serial #8:label
588                                         $serial=$line[7];
589                                         $hostpart=$serial{$serial};
590                                         if (defined $hostpart) {
591                                                 $error{$hostpart} = "";
592                                         }
593                                 }
594                                 elsif($line[6] eq "TRY-AGAIN" || $line[6] eq "TAPE-ERROR") {
595                                         #7:handle 8:errstr
596                                         $serial=$line[7];
597                                         $error=$line[8];
598                                         $hostpart=$serial{$serial};
599                                         if(defined $hostpart) {
600                                                 $taper_finished{$hostpart}= $line[6] eq 'TAPE-ERROR' ? -2 : -1;
601                                                 $busy_time{"taper"}+=($current_time-$taper_time{$hostpart});
602                                                 $taper_time{$hostpart}=$current_time;
603                                                 $error{$hostpart}="taper: $error";
604                                         }
605                                 }
606                                 elsif($line[6] eq "FAILED") {
607                                         #7:handle 8:INPUT- 9:TAPE- 10:input_message 11:tape_message
608                                    $serial=$line[7];
609                                         $hostpart=$serial{$serial};
610                                         if(defined $hostpart) {
611                                                 if($line[9] eq "TAPE-ERROR") {
612                                                         $error=$line[11];
613                                                         $taper_finished{$hostpart} = -2;
614                                                 }
615                                                 else {
616                                                         $error=$line[10];
617                                                         $taper_finished{$hostpart} = -1;
618                                                 }
619                                                 $busy_time{"taper"}+=($current_time-$taper_time{$hostpart});
620                                                 $taper_time{$hostpart}=$current_time;
621                                                 $error{$hostpart}="$error";
622                                         }
623                                 }
624                         }
625                 }
626                 elsif($line[1] eq "finished-cmd" && $line[2] eq "time") {
627                         $current_time=$line[3];
628                         if($line[4] =~ /dumper\d+/) {
629                         }
630                 }
631                 elsif($line[1] eq "dump" && $line[2] eq "failed") {
632                         #3:handle 4: 5: 6:"too many dumper retry"
633                         $serial=$line[3];
634                         $hostpart=$serial{$serial};
635                         $dump_started{$hostpart}=-1;
636                         $dump_finished{$hostpart}=-2;
637                         $error{$hostpart} .= "(" . $line[6] . ")";
638                 }
639                 elsif($line[1] eq "tape" && $line[2] eq "failed") {
640                         #3:handle 4: 5: 6:"too many dumper retry"
641                         $serial=$line[3];
642                         $hostpart=$serial{$serial};
643                         $taper_started{$hostpart}=-1;
644                         $taper_finished{$hostpart}=-2;
645                         $error{$hostpart} .= "(" . $line[6] . ")";
646                 }
647                 elsif($line[1] eq "state" && $line[2] eq "time") {
648                         #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
649                         $current_time=$line[3];
650                         $status_taper=$line[10];
651                         $idle_dumpers=$line[12];
652
653                         $free{"kps"} = $line[6];
654                         $free{"space"} = $line[8];
655                         $qlen{"tapeq"} = $line[15];
656                         $qlen{"runq"} = $line[17];
657                         $qlen{"roomq"} = $line[19];
658
659                         if(defined($dumpers_active)) {
660                                 if($status_driver ne "") {
661                                         $dumpers_active[$dumpers_active_prev]
662                                                 +=$current_time-$state_time_prev;
663                                         $dumpers_held[$dumpers_active_prev]{$status_driver}
664                                                 +=$current_time-$state_time_prev;
665                                 }
666                                 $state_time_prev=$current_time;
667                                 $dumpers_active_prev=$dumpers_active;
668                                 $status_driver=$line[16];
669                                 if(! defined($dumpers_held[$dumpers_active]{$status_driver})) {
670                                         $dumpers_held[$dumpers_active]{$status_driver}=0;
671                                 }
672                         }
673                 }
674            elsif($line[1] eq "FINISHED") {
675                         $driver_finished = 1;
676                 }
677         }
678         elsif($line[0] eq "dump") {
679                 if($line[1] eq "of" &&
680                         $line[2] eq "driver" &&
681                         $line[3] eq "schedule" &&
682                         $line[4] eq "after" &&
683                         $line[5] eq "start" &&
684                         $line[6] eq "degraded" &&
685                         $line[7] eq "mode") {
686                         $start_degraded_mode=1;
687                 }
688         }
689         elsif($line[0] eq "taper") {
690                 if($line[1] eq "slot") {
691                         #2:slot 3:"wrote" 4:"label" 5:corrupted...
692                         $nb_tape++;
693                         $lineX =~ /wrote label `(\S*)'/;
694                         $label = $1;
695                         $ntlabel{$nb_tape} = $label;
696                         $ntpartition{$nb_tape} = 0;
697                         $ntsize{$nb_tape} = 0;
698                         $ntesize{$nb_tape} = 0;
699                 }
700                 elsif($line[1] eq "wrote") {
701                         #1:"wrote" 2:"label" 3:corrupted
702                         $nb_tape++;
703                         $lineX =~ /wrote label `(\S*)'/;
704                         $label = $1;
705                         $ntlabel{$nb_tape} = $label;
706                         $ntpartition{$nb_tape} = 0;
707                         $ntsize{$nb_tape} = 0;
708                         $ntesize{$nb_tape} = 0;
709                 }
710         }
711    elsif($line[0] eq "splitting" &&
712                          $line[1] eq "chunk" &&
713                          $line[2] eq "that" &&
714                          $line[3] eq "started" &&
715                          $line[4] eq "at" &&
716                          $line[6] eq "after") {
717                 $line[7] =~ /(\d*)kb/;
718                 $size = $1;
719                 $ntchunk{$nb_tape}++;
720            $ntsize{$nb_tape} += $size / $unitdivisor;
721                 $ntesize{$nb_tape} += $size / $unitdivisor;
722                 $ntchunk_size += $size / $unitdivisor;
723         }
724         else {
725                 #print "Ignoring: $lineX\n";
726         }
727 }
728
729 close(AMDUMP);
730
731 if(defined $current_time) {
732         for ($d = 0; $d < $#dumpers_active; $d++) {
733                 $the_dumper = "dumper$d";
734                 if(defined($running_dumper{$the_dumper}) &&
735                    $running_dumper{$the_dumper} ne "0") {
736                         $busy_time{$the_dumper}+=($current_time-$dump_time{$running_dumper{$the_dumper}});
737                 }
738         }
739 }
740
741 print "\n";
742
743 $nb_partition = 0;
744
745 $epartition = 0;
746 $estsize = 0;
747 $fpartition = 0;
748 $fsize = 0;
749 $wpartition = 0;
750 $wsize = 0;
751
752 $flpartition = 0;
753 $flsize = 0;
754 $wfpartition = 0;
755 $wfsize = 0;
756
757 $dtpartition = 0;
758 $dtesize = 0;
759 $dupartition = 0;
760 $dusize = 0;
761 $duesize = 0;
762 $dpartition = 0;
763 $dsize = 0;
764 $desize = 0;
765
766 $twpartition = 0;
767 $twsize = 0;
768 $twesize = 0;
769 $tapartition = 0;
770 $tasize = 0;
771 $taesize = 0;
772 $tfpartition = 0;
773 $tfsize = 0;
774 $tfesize = 0;
775 $tpartition = 0;
776 $tsize = 0;
777 $tesize = 0;
778
779 $maxnamelength = 10;
780 foreach $host (sort @hosts) {
781         foreach $partition (sort @$host) {
782                 foreach $datestamp (sort @datestamp) {
783                         $hostpart=&make_hostpart($host,$partition,$datestamp);
784                         next if(!defined $estimate{$hostpart} && !defined $flush{$hostpart});
785                         if(length("$host:$partition") > $maxnamelength) {
786                                 $maxnamelength = length("$host:$partition");
787                         }
788                 }
789         }
790 }
791
792 foreach $host (sort @hosts) {
793         foreach $partition (sort @$host) {
794            foreach $datestamp (sort @datestamp) {
795                         $hostpart=&make_hostpart($host,$partition,$datestamp);
796                         next if(!defined $estimate{$hostpart} && !defined $flush{$hostpart});
797                         $nb_partition++;
798                         if( (!defined $size{$hostpart} || $size{$hostpart} == 0) &&
799                                  defined $holding_file{$hostpart}) {
800                                 $size{$hostpart} = &dump_size($holding_file{$hostpart}) / (1024 * $unitdivisor);
801                         }
802                         $in_flush=0;
803                         if($estimate_done != 1 && !defined $flush{$hostpart}) {
804                                 if(defined $estimate{$hostpart}) {
805                                         if($estimate{$hostpart} != 1) {
806                                                 if( defined $opt_gestimate) {
807                                                         printf "%8s ", $datestamp if defined $opt_date;
808                                                         printf "%-${maxnamelength}s", "$host:$partition";
809                                                         print "              getting estimate\n";
810                                                 }
811                                         }
812                                         else {
813                                                 if(defined $opt_estimate ||
814                                                         (defined $opt_gestimate && $partialestimate{$hostpart} == 1)) {
815                                                         printf "%8s ", $datestamp if defined $opt_date;
816                                                         printf "%-${maxnamelength}s", "$host:$partition";
817                                                         printf "%2d ",  $level{$hostpart};
818                                                         printf "%9d$unit", $esize{$hostpart};
819                                                         if($partialestimate{$hostpart} == 1) {
820                                                                 print " partial";
821                                                         }
822                                                         print " estimate done\n";
823                                                 }
824                                                 $epartition++;
825                                                 $estsize += $esize{$hostpart};
826                                         }
827                                 }
828                         }
829                         else {
830                                 if(defined $estimate{$hostpart}) {
831                                         if($estimate{$hostpart} == 1) {
832                                                 $epartition++;
833                                                 $estsize += $esize{$hostpart};
834                                         }
835                                         elsif (!defined $dump_started{$hostpart} || $dump_started{$hostpart} == 0) {
836                                                 if( defined $opt_failed) {
837                                                         printf "%8s ", $datestamp if defined $opt_date;
838                                                         printf "%-${maxnamelength}s%2d ", "$host:$partition", $level{$hostpart};
839                                                         printf "           no estimate\n";
840                                                 }
841                                                 $exit_status |= $STATUS_FAILED;
842                                                 $fpartition++;
843                                                 $fsize+=$esize{$hostpart};
844                                         }
845                                 }
846                                 else {
847                                         $flpartition++;
848                                         $flsize += $size{$hostpart};
849                                         $in_flush=1;
850                                 }
851                                 if(defined $taper_started{$hostpart} &&
852                                                 $taper_started{$hostpart}==1) {
853                                         if(defined $dump_started{$hostpart}) {
854                                                 $dpartition++;
855                                                 if(defined($size{$hostpart})) {
856                                                         $dsize += $size{$hostpart};
857                                                 }
858                                                 else {
859                                                         $dsize += $esize{$hostpart};
860                                                 }
861                                                 $desize += $esize{$hostpart};
862                                         }
863                                         if(defined $dump_started{$hostpart} &&
864                                                 $dump_started{$hostpart} == 1 &&
865                                                         $dump_finished{$hostpart} == -1) {
866                                                 if(defined $opt_failed) {
867                                                         printf "%8s ", $datestamp if defined $opt_date;
868                                                         printf "%-${maxnamelength}s%2d ", "$host:$partition", $level{$hostpart};
869                                                         printf "%9d$unit", $esize{$hostpart};
870                                                         print " dump to tape failed: " . $error{$hostpart};
871                                                         print "\n";
872                                                 }
873                                                 $exit_status |= $STATUS_FAILED;
874                                                 $fpartition++;
875                                                 $fsize+=$esize{$hostpart};
876                                         } elsif(defined $dump_started{$hostpart} &&
877                                                 $dump_started{$hostpart} == 1 &&
878                                                         $dump_finished{$hostpart} == 0 &&
879                                                         $taper_started{$hostpart} == 1) {
880                                                 if( defined $opt_dumpingtape ) {
881                                                         printf "%8s ", $datestamp if defined $opt_date;
882                                                         printf "%-${maxnamelength}s%2d ", "$host:$partition", $level{$hostpart};
883                                                         printf "%9d$unit", $esize{$hostpart};
884                                                         print " dumping to tape";
885                                                         if( defined $starttime ) {
886                                                                 print " (", &showtime($taper_time{$hostpart}), ")";
887                                                         }
888                                                         print "\n";
889                                                 }
890                                                 $dtpartition++;
891                                                 $dtesize += $esize{$hostpart};
892                                         }
893                                         elsif($taper_finished{$hostpart} == 0) {
894                                                 if( defined $opt_writingtape ) {
895                                                         printf "%8s ", $datestamp if defined $opt_date;
896                                                         printf "%-${maxnamelength}s%2d ", "$host:$partition", $level{$hostpart};
897                                                         printf "%9d$unit", $size{$hostpart};
898                                                         if($in_flush == 0) {
899                                                                 print " writing to tape";
900                                                         }
901                                                         else {
902                                                                 print " flushing to tape";
903                                                         }
904                                                         if(defined($tapedsize{$hostpart})) {
905                                                                 printf " (%d$unit done)", $tapedsize{$hostpart};
906                                                         }
907                                                         if( defined $starttime ) {
908                                                                 print " (", &showtime($taper_time{$hostpart}), ")";
909                                                         }
910                                                         print ", ", $error{$hostpart} if defined($error{$hostpart} &&
911                                                                                                                                            $error{$hostpart} ne "");
912                                                         print "\n";
913                                                 }
914                                                 $tapartition++;
915                                                 $tasize += $size{$hostpart};
916                                                 if(defined $esize{$hostpart}) {
917                                                         $taesize += $esize{$hostpart};
918                                                 }
919                                                 else {
920                                                         $taesize += $size{$hostpart};
921                                                 }
922                                         }
923                                         elsif($taper_finished{$hostpart} < 0) {
924
925                                                 if(defined $size{$hostpart}) {
926                                                         $xsize = $size{$hostpart};
927                                                 }
928                                                 elsif(defined $esize{$hostpart}) {
929                                                         $xsize = $esize{$hostpart};
930                                                 }
931                                                 else {
932                                                         $xsize = 0;
933                                                 }
934
935                                                 if(defined $esize{$hostpart}) {
936                                                         $exsize += $esize{$hostpart};
937                                                 }
938                                                 else {
939                                                         $exsize += $xsize;
940                                                 }
941
942                                                 if( defined $opt_failed  ||
943                                                          (defined $opt_waittaper && ($taper_finished{$hostpart} == -1))) {
944                                                         printf "%8s ", $datestamp if defined $opt_date;
945                                                         printf "%-${maxnamelength}s%2d ", "$host:$partition", $level{$hostpart};
946                                                         printf "%9d$unit", $xsize;
947                                                         if($in_flush == 0) {
948                                                                 print " failed to tape";
949                                                         }
950                                                         else {
951                                                                 print " failed to flush";
952                                                         }
953                                                         print ": ",$error{$hostpart} if defined $error{$hostpart};
954                                                 
955                                                         print " (will retry)" unless $taper_finished{$hostpart} < -1;
956                                                         if( defined $starttime ) {
957                                                                 print " (", &showtime($taper_time{$hostpart}), ")";
958                                                         }
959                                                         print "\n";
960                                                 }
961                                                 $exit_status |= $STATUS_TAPE;
962
963                                                 $tfpartition++;
964                                                 $tfsize += $xsize;
965                                                 $tfesize += $exsize;
966
967                                                 if($in_flush == 0) {
968                                                         $twpartition++;
969                                                         $twsize += $xsize;
970                                                         $twesize += $exsize;
971                                                 }
972                                                 else {
973                                                         $wfpartition++;
974                                                         $wfsize += $xsize;
975                                                 }
976                                         }
977                                         elsif($taper_finished{$hostpart} == 1) {
978                                                 if( defined $opt_finished ) {
979                                                         printf "%8s ", $datestamp if defined $opt_date;
980                                                         printf "%-${maxnamelength}s%2d ", "$host:$partition", $level{$hostpart};
981                                                         printf "%9d$unit", $size{$hostpart};
982                                                         if($in_flush == 0) {
983                                                                 print " finished";
984                                                         }
985                                                         else {
986                                                                 print " flushed";
987                                                         }
988                                                         if( defined $starttime ) {
989                                                                 print " (", &showtime($taper_time{$hostpart}), ")";
990                                                         }
991                                                         if(defined $partial{$hostpart} && $partial{$hostpart} == 1) {
992                                                                 print ", PARTIAL";
993                                                                 $exit_status |= $STATUS_FAILED;
994                                                         }
995                                                         print "\n";
996                                                 }
997                                                 $tpartition++;
998                                                 $tsize += $size{$hostpart};
999                                                 if(defined $esize{$hostpart} && $esize{$hostpart} > 1) {
1000                                                         $tesize += $esize{$hostpart};
1001                                                 }
1002                                                 else {
1003                                                         $tesize += $size{$hostpart};
1004                                                 }
1005                                         }
1006                                         else {
1007                                                 printf "%8s ", $datestamp if defined $opt_date;
1008                                                 printf "%-${maxnamelength}s%2d ", "$host:$partition", $level{$hostpart};
1009                                                 print " unknown state TAPER\n";
1010                                         }
1011                                 }
1012                                 elsif(defined $dump_started{$hostpart}) {
1013                                         if($dump_started{$hostpart} == -1) {
1014                                                 if( defined $opt_failed ) {
1015                                                         printf "%8s ", $datestamp if defined $opt_date;
1016                                                         printf "%-${maxnamelength}s%2d ", "$host:$partition", $level{$hostpart};
1017                                                         printf " " . $error{$hostpart} . "\n";
1018                                                 }
1019                                                 $exit_status |= $STATUS_FAILED;
1020
1021                                                 $fpartition++;
1022                                                 $fsize+=$esize{$hostpart};
1023                                         }
1024                                         elsif($dump_started{$hostpart} == 0) {
1025                                                 if($estimate{$hostpart} == 1) {
1026                                                         if( defined $opt_waitdumping ) {
1027                                                                 printf "%8s ", $datestamp if defined $opt_date;
1028                                                                 printf "%-${maxnamelength}s%2d ", "$host:$partition", $level{$hostpart};
1029                                                                 printf "%9d$unit", $esize{$hostpart};
1030                                                                 print " wait for dumping $error{$hostpart}\n";
1031                                                         }
1032                                                         if($driver_finished == 1) {
1033                                                                 $exit_status |= $STATUS_MISSING;
1034                                                         }
1035                                                         $wpartition++;
1036                                                         $wsize += $esize{$hostpart};
1037                                                 }
1038                                         }
1039                                         elsif($dump_started{$hostpart} == 1 &&
1040                                                         $dump_finished{$hostpart} == -1) {
1041                                                 if( defined $opt_failed ) {
1042                                                         printf "%8s ", $datestamp if defined $opt_date;
1043                                                         printf "%-${maxnamelength}s%2d ", "$host:$partition", $level{$hostpart};
1044                                                         print " ", $error{$hostpart};
1045                                                         if( defined $starttime ) {
1046                                                                 print " (", &showtime($dump_time{$hostpart}), ")";
1047                                                         }
1048                                                         print "\n";
1049                                                 }
1050                                                 $exit_status |= $STATUS_FAILED;
1051                                                 $fpartition++;
1052                                                 $fsize+=$esize{$hostpart};
1053                                         }
1054                                         elsif($dump_started{$hostpart} == 1 &&
1055                                                         $dump_finished{$hostpart} != 1) {
1056                                                 if( defined $opt_dumping ) {
1057                                                         printf "%8s ", $datestamp if defined $opt_date;
1058                                                         printf "%-${maxnamelength}s%2d ", "$host:$partition", $level{$hostpart};
1059                                                         printf "%9d$unit", $esize{$hostpart};
1060                                                         printf " dumping %8d$unit", $size{$hostpart};
1061                                                         if($size{$hostpart} != 0) {
1062                                                                 printf " (%6.2f%%)", (100.0*$size{$hostpart})/$esize{$hostpart};
1063                                                         }
1064                                                         if( defined $starttime ) {
1065                                                                 print " (", &showtime($dump_time{$hostpart}), ")";
1066                                                         }
1067                                                         if(defined $dump_roomq{$hostpart}) {
1068                                                                 print " " . $error{$hostpart};
1069                                                         }
1070                                                         print "\n";
1071                                                 }
1072                                                 $dupartition++;
1073                                                 $dusize += $size{$hostpart};
1074                                                 $duesize += $esize{$hostpart};
1075                                         }
1076                                         elsif($dump_finished{$hostpart} == 1 &&
1077                                                         $taper_started{$hostpart} != 1) {
1078                                                 if( defined $opt_waittaper ) {
1079                                                         printf "%8s ", $datestamp if defined $opt_date;
1080                                                         printf "%-${maxnamelength}s%2d ", "$host:$partition", $level{$hostpart};
1081                                                         printf "%9d$unit", $size{$hostpart};
1082                                                         print " dump done";
1083                                                         if( defined $starttime ) {
1084                                                                 print " (", &showtime($dump_time{$hostpart}), ")";
1085                                                         }
1086                                                         print ", wait for writing to tape";
1087                                                         if(defined $partial{$hostpart} && $partial{$hostpart} == 1) {
1088                                                                 print ", PARTIAL";
1089                                                                 $exit_status |= $STATUS_FAILED;
1090                                                         }
1091                                                         print "\n";
1092                                                 }
1093                                                 $dpartition++;
1094                                                 $dsize += $size{$hostpart};
1095                                                 $desize += $esize{$hostpart};
1096                                                 $twpartition++;
1097                                                 $twsize += $size{$hostpart};
1098                                                 $twesize += $esize{$hostpart};
1099                                         }
1100                                         else {
1101                                                 printf "%8s ", $datestamp if defined $opt_date;
1102                                                 printf "%-${maxnamelength}s%2d ", "$host:$partition", $level{$hostpart};
1103                                                 print " unknown state DUMPER\n";
1104                                         }
1105                                 }
1106                                 elsif(defined $flush{$hostpart}) {
1107                                         if( defined $opt_waittaper ) {
1108                                                 printf "%8s ", $datestamp if defined $opt_date;
1109                                                 printf "%-${maxnamelength}s%2d ", "$host:$partition", $level{$hostpart};
1110                                                 printf "%9d$unit", $size{$hostpart};
1111                                                 print " waiting to flush";
1112                                                 if(defined $partial{$hostpart} && $partial{$hostpart} == 1) {
1113                                                         print ", PARTIAL";
1114                                                         $exit_status |= $STATUS_FAILED;
1115                                                 }
1116                                                 print "\n";
1117                                         }
1118                                         $wfpartition++;
1119                                         $wfsize += $size{$hostpart};
1120                                 }
1121                                 elsif(defined $level{$hostpart}) {
1122                                         printf "%8s ", $datestamp if defined $opt_date;
1123                                         printf "%-${maxnamelength}s%2d ", "$host:$partition", $level{$hostpart};
1124                                         print " unknown state\n";
1125                                 }
1126                         }
1127                 }
1128         }
1129 }
1130
1131 if (defined $opt_summary) {
1132         print "\n";
1133         print  "SUMMARY          part      real  estimated\n";
1134         print  "                           size       size\n";
1135         printf "partition       : %3d\n", $nb_partition;
1136         printf "estimated       : %3d %20d$unit\n", $epartition , $estsize;
1137         printf "flush           : %3d %9d$unit\n", $flpartition, $flsize;
1138         printf "failed          : %3d %20d$unit           (%6.2f%%)\n",
1139                 $fpartition , $fsize,
1140                 $estsize ? ($fsize * 1.0 / $estsize) * 100 : 0.0;
1141         printf "wait for dumping: %3d %20d$unit           (%6.2f%%)\n",
1142                 $wpartition , $wsize,
1143                 $estsize ? ($wsize * 1.0 / $estsize) * 100 : 0.0;
1144         printf "dumping to tape : %3d %20d$unit           (%6.2f%%)\n",
1145                 $dtpartition, $dtesize,
1146                 $estsize ? ($dtesize * 1.0 / $estsize) * 100 : 0.0;
1147         printf "dumping         : %3d %9d$unit %9d$unit (%6.2f%%) (%6.2f%%)\n",
1148                 $dupartition, $dusize, $duesize,
1149                 $duesize ? ($dusize * 1.0 / $duesize) * 100 : 0.0,
1150                 $estsize ? ($dusize * 1.0 / $estsize) * 100 : 0.0;
1151         printf "dumped          : %3d %9d$unit %9d$unit (%6.2f%%) (%6.2f%%)\n",
1152                 $dpartition , $dsize , $desize,
1153                 $desize ? ($dsize * 1.0 / $desize) * 100 : 0.0,
1154                 $estsize ? ($dsize * 1.0 / $estsize) * 100 : 0.0;
1155         printf "wait for writing: %3d %9d$unit %9d$unit (%6.2f%%) (%6.2f%%)\n",
1156                 $twpartition, $twsize, $twesize,
1157                 $twesize ? ($twsize * 1.0 / $twesize) * 100 : 0.0,
1158                 $estsize ? ($twsize * 1.0 / $estsize) * 100 : 0.0;
1159         printf "wait to flush   : %3d %9d$unit %9d$unit (%6.2f%%) (%6.2f%%)\n",
1160                 $wfpartition, $wfsize, $wfsize, 100, 0;
1161         printf "writing to tape : %3d %9d$unit %9d$unit (%6.2f%%) (%6.2f%%)\n",
1162                 $tapartition, $tasize, $taesize,
1163                 $taesize ? ($tasize * 1.0 / $taesize) * 100 : 0.0,
1164                 $estsize ? ($tasize * 1.0 / $estsize) * 100 : 0.0;
1165         printf "failed to tape  : %3d %9d$unit %9d$unit (%6.2f%%) (%6.2f%%)\n",
1166                 $tfpartition, $tfsize, $tfesize,
1167                 $tfesize ? ($tfsize * 1.0 / $tfesize) * 100 : 0.0,
1168                 $estsize ? ($tfsize * 1.0 / $estsize) * 100 : 0.0;
1169         printf "taped           : %3d %9d$unit %9d$unit (%6.2f%%) (%6.2f%%)\n",
1170                 $tpartition , $tsize , $tesize,
1171                 $tesize ? ($tsize * 1.0 / $tesize) * 100 : 0.0,
1172                 ($estsize+$flsize) ? ($tsize * 1.0 / ($estsize + $flsize)) * 100 : 0.0;
1173         if($nb_tape > 1 || $tape_size != 0) {
1174                 for($i=1; $i <= $nb_tape; $i++) {
1175                         if($tape_size != 0) {
1176                                 printf "  tape %-3d      : %3d %9d$unit %9d$unit (%6.2f%%) %s",
1177                                         $i, $ntpartition{$i}, $ntsize{$i}, $ntesize{$i}, 100*$ntsize{$i}/$tape_size, $ntlabel{$i};
1178                         }
1179                         else {
1180                                 printf "  tape %-3d      : %3d %9d$unit %9d$unit %s",
1181                                         $i, $ntpartition{$i}, $ntsize{$i}, $ntesize{$i}, $ntlabel{$i};
1182                         }
1183                         if(defined($ntchunk{$i}) && $ntchunk{$i} > 0) {
1184                                 printf " (%d chunks)", $ntchunk{$i};
1185                         }
1186                         print "\n";
1187                 }
1188         }
1189         if($idle_dumpers == 0) {
1190                 printf "all dumpers active\n";
1191         }
1192         else {
1193                 $c1 = ($idle_dumpers == 1) ? "" : "s";
1194                 $c2 = ($idle_dumpers < 10) ? " " : "";
1195                 $c3 = ($idle_dumpers == 1) ? " " : "";
1196                 printf "%d dumper%s idle%s %s: %s\n", $idle_dumpers, $c1, $c2, $c3, $status_driver;
1197         }
1198         if($status_taper eq "writing" && defined($qlen{"tapeq:"})) {
1199                 printf "taper writing, tapeq: %d\n", $qlen{"tapeq:"};
1200         }
1201         else {
1202                 printf "taper idle\n";
1203         }
1204         if (defined ($free{"kps:"})) {
1205                 printf "network free kps: %9d\n", $free{"kps:"};
1206         }
1207         if (defined ($free{"space:"})) {
1208                 if ($holding_space) {
1209                         $hs = ($free{"space:"} * 1.0 / $holding_space) * 100;
1210                 } else {
1211                         $hs = 0.0;
1212                 }
1213                 printf "holding space   : %9d$unit (%6.2f%%)\n", ($free{"space:"}/$unitdivisor), $hs;
1214         }
1215 }
1216
1217 if(defined $opt_stats) {
1218         if(defined($current_time) && $current_time != $start_time) {
1219                 $total_time=$current_time-$start_time;
1220                 foreach $key (sort byprocess keys %busy_time) {
1221                         printf "%8s busy   : %8s  (%6.2f%%)\n",
1222                                 $key, &busytime($busy_time{$key}),
1223                                 ($busy_time{$key} * 1.0 / $total_time) * 100;
1224                 }
1225                 for ($d = 0; $d <= $#dumpers_active; $d++) {
1226                         $l = sprintf "%2d dumper%s busy%s : %8s  (%6.2f%%)",
1227                                 $d, ($d == 1) ? "" : "s", ($d == 1) ? " " : "",
1228                                 &busytime($dumpers_active[$d]),
1229                                 ($dumpers_active[$d] * 1.0 / $total_time) * 100;
1230                         print $l;
1231                         $s1 = "";
1232                         $s2 = " " x length($l);
1233                         $r = $dumpers_held[$d];
1234                         foreach $key (sort valuesort keys %$r) {
1235                                 next
1236                                   unless $dumpers_held[$d]{$key} >= 1;
1237                                 printf "%s%20s: %8s  (%6.2f%%)\n",
1238                                         $s1,
1239                                         $key,
1240                                         &busytime($dumpers_held[$d]{$key}),
1241                                         ($dumpers_held[$d]{$key} * 1.0 / $dumpers_active[$d]) * 100;
1242                                 $s1 = $s2;
1243                         }
1244                         if ($s1 eq "") {
1245                                 print "\n";
1246                         }
1247                 }
1248         }
1249 }
1250
1251 exit $exit_status;
1252
1253 sub make_hostpart() {
1254         local($host,$partition,$datestamp) = @_;
1255
1256         if(! defined($hosts{$host})) {
1257                 push @hosts, $host;
1258                 $hosts{$host}=1;
1259         }
1260         my($new_part) = 1;
1261         foreach $pp (sort @$host) {
1262                 $new_part = 0 if ($pp eq $partition);
1263         }
1264         push @$host, $partition if $new_part==1;
1265
1266         my($hostpart) = "$host$partition$datestamp";
1267         if(!defined $datestamp{$datestamp}) {
1268                 $datestamp{$datestamp} = 1;
1269                 push @datestamp, $datestamp;
1270         }
1271
1272         return $hostpart;
1273 }
1274
1275 sub byprocess() {
1276         my(@tmp_a) = split(/(\d*)$/, $a, 2);
1277         my(@tmp_b) = split(/(\d*)$/, $b, 2);
1278         return ($tmp_a[0] cmp $tmp_b[0]) || ($tmp_a[1] <=> $tmp_b[1]);
1279 }                               
1280  
1281 sub valuesort() {
1282         $r->{$b} <=> $r->{$a};
1283 }
1284
1285 sub dump_size() {
1286         local($filename) = @_;
1287         local($size);
1288         local($dsize) = 0;
1289         local($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
1290                    $atime,$mtime,$ctime,$blksize,$blocks);
1291         while ($filename ne "") {
1292                 $filename = "$filename.tmp" if (!(-e "$filename"));
1293                 $filename = "/dev/null" if (!(-e "$filename"));
1294                 ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
1295                                 $atime,$mtime,$ctime,$blksize,$blocks) = stat($filename);
1296                 $size=$size-32768 if $size > 32768;
1297                 $dsize += $size;
1298                 open(DUMP,$filename);
1299                 $filename = "";
1300                 while(<DUMP>) {
1301                         if(/^CONT_FILENAME=(.*)$/) { $filename = $1; last }
1302                         last if /^To restore, position tape at start of file and run/;
1303                 }
1304                 close(DUMP);
1305         }
1306         return $dsize;
1307 }
1308
1309 sub unctime() {
1310         my (@MoY);
1311         my (@tl);
1312         my ($a);
1313         my ($m);
1314         my ($month);
1315         my ($time);
1316
1317         @MoY = ('Jan','Feb','Mar','Apr','May','Jun',
1318                 'Jul','Aug','Sep','Oct','Nov','Dec');
1319
1320         # Preset an array of values in case some parts are not passed as
1321         # arguments.  This lets the date, etc, be omitted and default to
1322         # today.
1323
1324         @tl = localtime;
1325
1326         foreach $a (@_) {
1327                 next
1328                   if ($a eq '');
1329
1330                 # See if this argument looks like a month name.
1331
1332                 $month = 0;
1333                 foreach $m (@MoY) {
1334                         last
1335                           if ($m eq $a);
1336                         $month = $month + 1;
1337                 }
1338                 if ($month < 12) {
1339                         $tl[4] = $month;
1340                         next;
1341                 }
1342
1343                 # See if this is a day of the month.
1344
1345                 if ($a =~ /^\d+$/ && $a >= 1 && $a <= 32) {
1346                         $tl[3] = $a;
1347                         next;
1348                 }
1349
1350                 # See if the next argument looks like a time.
1351
1352                 if ($a =~ /^(\d+):(\d+)/) {
1353                         $tl[2] = $1;
1354                         $tl[1] = $2;
1355                         if ($a =~ /^(\d+):(\d+):(\d+)/) {
1356                                 $tl[0] = $3;
1357                         }
1358                         next;
1359                 }
1360
1361                 # See if this is a year.
1362
1363                 if ($a =~ /^\d\d\d\d$/ && $a >= 1900) {
1364                         $tl[5] = $a;
1365                         next;
1366                 }
1367         }
1368
1369         $time = &timelocal (@tl);
1370
1371         return $time;
1372 }
1373
1374 sub set_starttime() {
1375         my (@tl);
1376         my ($time);
1377         my ($date);
1378
1379         # Preset an array of values in case some parts are not passed as
1380         # arguments.  This lets the date, etc, be omitted and default to
1381         # today.
1382
1383         ($date)=@_;
1384         @tl = localtime;
1385
1386         $tl[5] = substr($date,  0, 4)   if(length($date) >= 4);
1387         $tl[4] = substr($date,  4, 2)-1 if(length($date) >= 6);
1388         $tl[3] = substr($date,  6, 2)   if(length($date) >= 8);
1389         $tl[2] = substr($date,  8, 2)   if(length($date) >= 10);
1390         $tl[1] = substr($date, 10, 2)   if(length($date) >= 12);
1391         $tl[0] = substr($date, 12, 2)   if(length($date) >= 14);
1392
1393         $time = &timelocal (@tl);
1394
1395         return $time;
1396 }
1397
1398
1399 sub showtime() {
1400         my($delta)=shift;
1401         my($oneday)=24*60*60;
1402
1403         @now=localtime($starttime+$delta);
1404         if($delta > $oneday) {
1405                 $result=sprintf("%d+",$delta/$oneday);
1406         } else {
1407                 $result="";
1408         }
1409         $result.=sprintf("%d:%02d:%02d",$now[2],$now[1],$now[0]);
1410         return $result;
1411 }
1412
1413 sub busytime() {
1414         my($busy)=shift;
1415         my($oneday)=24*60*60;
1416
1417         if($busy > $oneday) {
1418                 $days=int($busy/$oneday);
1419                 $result=sprintf("%d+",$busy/$oneday);
1420                 $busy-=$days*$oneday;
1421         } else {
1422                 $result="";
1423         }
1424         $hours=int($busy/60/60);
1425         $busy-=$hours*60*60;
1426         $minutes=int($busy/60);
1427         $busy-=$minutes*60;
1428         $seconds=$busy;
1429         $result.=sprintf("%d:%02d:%02d",$hours,$minutes,$seconds);
1430         return $result;
1431 }
1432
1433 sub usage() {
1434         print "amstatus [--config] config [--file amdump_file]\n";
1435         print "         [--summary] [--dumping] [--waitdumping] [--waittaper]\n";
1436         print "         [--dumpingtape] [--writingtape] [--finished] [--failed]\n";
1437         print "         [--estimate] [--gestimate] [--stats] [--date] [--locale-independent-date-format]\n";
1438         exit 0;
1439 }