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