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