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