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