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