2 * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3 * Copyright (c) 1991-1998, 2000 University of Maryland at College Park
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of U.M. not be used in advertising or
11 * publicity pertaining to distribution of the software without specific,
12 * written prior permission. U.M. makes no representations about the
13 * suitability of this software for any purpose. It is provided "as is"
14 * without express or implied warranty.
16 * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
18 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
20 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 * Author: James da Silva, Systems Design and Analysis Group
24 * Computer Science Department
25 * University of Maryland at College Park
28 * $Id: reporter.c,v 1.44.2.17.4.6.2.16.2.6 2005/03/29 16:35:11 martinea Exp $
30 * nightly Amanda Report generator
51 /* don't have (or need) a skipped type except internally to reporter */
52 #define L_SKIPPED L_MARKER
54 typedef struct line_s {
59 typedef struct timedata_s {
61 float origsize, outsize;
68 typedef struct repdata_s {
74 struct repdata_s *next;
77 #define data(dp) ((repdata_t *)(dp)->up)
79 struct cumulative_stats {
80 int dumpdisks, tapedisks;
81 double taper_time, dumper_time;
82 double outsize, origsize, tapesize;
83 double coutsize, corigsize; /* compressed dump only */
86 int dumpdisks[10], tapedisks[10]; /* by-level breakdown of disk count */
88 typedef struct taper_s {
91 double coutsize, corigsize;
96 taper_t *stats_by_tape = NULL;
97 taper_t *current_tape = NULL;
99 float total_time, startup_time, planner_time;
101 /* count files to tape */
105 char *today_datestamp;
106 char *tape_labels = NULL;
107 int last_run_tapes = 0;
108 static int degraded_mode = 0; /* defined in driverio too */
113 char *tapestart_error = NULL;
115 FILE *logfile, *mailf;
123 line_t *errsum = NULL;
124 line_t *errdet = NULL;
125 line_t *notes = NULL;
127 static char MaxWidthsRequested = 0; /* determined via config data */
130 long int unitdivisor;
132 /* local functions */
133 int contline_next P((void));
134 void addline P((line_t **lp, char *str));
135 void usage P((void));
136 int main P((int argc, char **argv));
138 void copy_template_file P((char *lbl_templ));
139 void do_postscript_output P((void));
140 void handle_start P((void));
141 void handle_finish P((void));
142 void handle_note P((void));
143 void handle_summary P((void));
144 void handle_stats P((void));
145 void handle_error P((void));
146 void handle_disk P((void));
147 repdata_t *handle_success P((void));
148 void handle_strange P((void));
149 void handle_failed P((void));
150 void generate_missing P((void));
151 void output_tapeinfo P((void));
152 void output_lines P((line_t *lp, FILE *f));
153 void output_stats P((void));
154 void output_summary P((void));
155 void sort_disks P((void));
156 int sort_by_time P((disk_t *a, disk_t *b));
157 int sort_by_name P((disk_t *a, disk_t *b));
158 void bogus_line P((void));
159 char *nicedate P((int datestamp));
160 static char *prefix P((char *host, char *disk, int level));
161 repdata_t *find_repdata P((disk_t *dp, char *datestamp, int level));
164 static int ColWidth(int From, int To) {
166 for (i=From; i<=To && ColumnData[i].Name != NULL; i++) {
167 Width+= ColumnData[i].PrefixSpace + ColumnData[i].Width;
172 static char *Rule(int From, int To) {
174 int Leng= ColWidth(0, ColumnDataCount());
175 char *RuleSpace= alloc(Leng+1);
176 ThisLeng= ColWidth(From, To);
177 for (i=0;i<ColumnData[From].PrefixSpace; i++)
179 for (; i<ThisLeng; i++)
181 RuleSpace[ThisLeng]= '\0';
185 static char *TextRule(int From, int To, char *s) {
186 ColumnInfo *cd= &ColumnData[From];
187 int leng, nbrules, i, txtlength;
188 int RuleSpaceSize= ColWidth(0, ColumnDataCount());
189 char *RuleSpace= alloc(RuleSpaceSize), *tmp;
192 if(leng >= (RuleSpaceSize - cd->PrefixSpace))
193 leng = RuleSpaceSize - cd->PrefixSpace - 1;
194 ap_snprintf(RuleSpace, RuleSpaceSize, "%*s%*.*s ", cd->PrefixSpace, "",
196 txtlength = cd->PrefixSpace + leng + 1;
197 nbrules = ColWidth(From,To) - txtlength;
198 for(tmp=RuleSpace + txtlength, i=nbrules ; i>0; tmp++,i--)
204 char *sDivZero(float a, float b, int cn) {
205 ColumnInfo *cd= &ColumnData[cn];
206 static char PrtBuf[256];
208 ap_snprintf(PrtBuf, sizeof(PrtBuf),
209 "%*s", cd->Width, "-- ");
211 ap_snprintf(PrtBuf, sizeof(PrtBuf),
212 cd->Format, cd->Width, cd->Precision, a/b);
228 void addline(lp, str)
234 /* allocate new line node */
235 new = (line_t *) alloc(sizeof(line_t));
237 new->str = stralloc(str);
239 /* add to end of list */
240 for(p = *lp, q = NULL; p != NULL; q = p, p = p->next);
241 if(q == NULL) *lp = new;
247 error("Usage: amreport conf [-f output-file] [-l logfile] [-p postscript-file]");
258 char *logfname, *psfname, *outfname, *subj_str = NULL;
261 unsigned long malloc_hist_1, malloc_size_1;
262 unsigned long malloc_hist_2, malloc_size_2;
263 char *mail_cmd = NULL, *printer_cmd = NULL;
265 char my_cwd[STR_SIZE];
266 char *ColumnSpec = "";
270 for(fd = 3; fd < FD_SETSIZE; fd++) {
272 * Make sure nobody spoofs us with a lot of extra open files
273 * that would cause an open we do to get a very high file
274 * descriptor, which in turn might be used as an index into
275 * an array (e.g. an fd_set).
280 set_pname("amreport");
282 malloc_size_1 = malloc_inuse(&malloc_hist_1);
284 /* Process options */
286 erroutput_type = ERR_INTERACTIVE;
291 if (getcwd(my_cwd, sizeof(my_cwd)) == NULL) {
292 error("cannot determine current working directory");
296 config_dir = stralloc2(my_cwd, "/");
297 if ((config_name = strrchr(my_cwd, '/')) != NULL) {
298 config_name = stralloc(config_name + 1);
301 if (argv[1][0] == '-') {
305 config_name = stralloc(argv[1]);
306 config_dir = vstralloc(CONFIG_DIR, "/", config_name, "/", NULL);
308 while((opt = getopt(argc, argv, "f:l:p:")) != EOF) {
311 if (outfname != NULL) {
312 error("you may specify at most one -f");
314 if (*optarg == '/') {
315 outfname = stralloc(optarg);
317 outfname = vstralloc(my_cwd, "/", optarg, NULL);
321 if (logfname != NULL) {
322 error("you may specify at most one -l");
324 if (*optarg == '/') {
325 logfname = stralloc(optarg);
327 logfname = vstralloc(my_cwd, "/", optarg, NULL);
331 if (psfname != NULL) {
332 error("you may specify at most one -p");
334 if (*optarg == '/') {
335 psfname = stralloc(optarg);
337 psfname = vstralloc(my_cwd, "/", optarg, NULL);
358 printf("You must run amreport with '-f <output file>' because configure\n");
359 printf("didn't find a mailer.\n");
366 /* read configuration files */
368 conffile = stralloc2(config_dir, CONFFILE_NAME);
369 if(read_conffile(conffile)) {
370 error("errors processing config file \"%s\"", conffile);
373 conf_diskfile = getconf_str(CNF_DISKFILE);
374 if (*conf_diskfile == '/') {
375 conf_diskfile = stralloc(conf_diskfile);
377 conf_diskfile = stralloc2(config_dir, conf_diskfile);
379 if((diskq = read_diskfile(conf_diskfile)) == NULL) {
380 error("could not load disklist \"%s\"", conf_diskfile);
382 amfree(conf_diskfile);
383 conf_tapelist = getconf_str(CNF_TAPELIST);
384 if (*conf_tapelist == '/') {
385 conf_tapelist = stralloc(conf_tapelist);
387 conf_tapelist = stralloc2(config_dir, conf_tapelist);
389 if(read_tapelist(conf_tapelist)) {
390 error("could not read tapelist \"%s\"", conf_tapelist);
392 amfree(conf_tapelist);
393 conf_infofile = getconf_str(CNF_INFOFILE);
394 if (*conf_infofile == '/') {
395 conf_infofile = stralloc(conf_infofile);
397 conf_infofile = stralloc2(config_dir, conf_infofile);
399 if(open_infofile(conf_infofile)) {
400 error("could not open info db \"%s\"", conf_infofile);
402 amfree(conf_infofile);
404 today_datestamp = construct_datestamp(NULL);
406 displayunit = getconf_str(CNF_DISPLAYUNIT);
407 unitdivisor = getconf_unit_divisor();
409 ColumnSpec = getconf_str(CNF_COLUMNSPEC);
410 if(SetColumDataFromString(ColumnData, ColumnSpec, &errstr) < 0) {
412 curprog = P_REPORTER;
417 ColumnSpec = ""; /* use the default */
418 if(SetColumDataFromString(ColumnData, ColumnSpec, &errstr) < 0) {
420 curprog = P_REPORTER;
427 for (cn = 0; ColumnData[cn].Name != NULL; cn++) {
428 if (ColumnData[cn].MaxWidth) {
429 MaxWidthsRequested = 1;
437 conf_logdir = getconf_str(CNF_LOGDIR);
438 if (*conf_logdir == '/') {
439 conf_logdir = stralloc(conf_logdir);
441 conf_logdir = stralloc2(config_dir, conf_logdir);
443 logfname = vstralloc(conf_logdir, "/", "log", NULL);
447 if((logfile = fopen(logfname, "r")) == NULL) {
449 curprog = P_REPORTER;
450 curstr = vstralloc("could not open log ",
459 while(logfile && get_logline(logfile)) {
461 case L_START: handle_start(); break;
462 case L_FINISH: handle_finish(); break;
464 case L_INFO: handle_note(); break;
465 case L_WARNING: handle_note(); break;
467 case L_SUMMARY: handle_summary(); break;
468 case L_STATS: handle_stats(); break;
470 case L_ERROR: handle_error(); break;
471 case L_FATAL: handle_error(); break;
473 case L_DISK: handle_disk(); break;
475 case L_SUCCESS: handle_success(); break;
476 case L_STRANGE: handle_strange(); break;
477 case L_FAIL: handle_failed(); break;
481 curprog = P_REPORTER;
482 curstr = stralloc2("unexpected log line: ", curstr);
492 subj_str = vstralloc(getconf_str(CNF_ORG),
493 " ", amflush_run ? "AMFLUSH" : "AMANDA",
494 " ", "MAIL REPORT FOR",
495 " ", nicedate(run_datestamp ? atoi(run_datestamp) : 0),
498 /* lookup the tapetype and printer type from the amanda.conf file. */
499 tp = lookup_tapetype(getconf_str(CNF_TAPETYPE));
500 printer = getconf_str(CNF_PRINTER);
502 /* ignore SIGPIPE so if a child process dies we do not also go away */
503 signal(SIGPIPE, SIG_IGN);
505 /* open pipe to mailer */
508 /* output to a file */
509 if((mailf = fopen(outfname,"w")) == NULL) {
510 error("could not open output file: %s %s", outfname, strerror(errno));
512 fprintf(mailf, "To: %s\n", getconf_str(CNF_MAILTO));
513 fprintf(mailf, "Subject: %s\n\n", subj_str);
517 mail_cmd = vstralloc(MAILER,
518 " -s", " \"", subj_str, "\"",
519 " ", getconf_str(CNF_MAILTO),
521 if((mailf = popen(mail_cmd, "w")) == NULL)
522 error("could not open pipe to \"%s\": %s",
523 mail_cmd, strerror(errno));
527 /* open pipe to print spooler if necessary) */
530 /* if the postscript_label_template (tp->lbl_templ) field is not */
531 /* the empty string (i.e. it is set to something), open the */
532 /* postscript debugging file for writing. */
533 if ((strcmp(tp->lbl_templ, "")) != 0) {
534 if ((postscript = fopen(psfname, "w")) == NULL) {
536 curprog = P_REPORTER;
537 curstr = vstralloc("could not open ",
548 if (strcmp(printer, "") != 0) /* alternate printer is defined */
549 /* print to the specified printer */
551 printer_cmd = vstralloc(LPRCMD, " ", LPRFLAG, printer, NULL);
553 printer_cmd = vstralloc(LPRCMD, NULL);
556 /* print to the default printer */
557 printer_cmd = vstralloc(LPRCMD, NULL);
560 if ((strcmp(tp->lbl_templ, "")) != 0) {
562 if ((postscript = popen(printer_cmd, "w")) == NULL) {
564 curprog = P_REPORTER;
565 curstr = vstralloc("could not open pipe to ",
575 curprog = P_REPORTER;
576 curstr = stralloc("no printer command defined");
586 if(!got_finish) fputs("*** THE DUMPS DID NOT FINISH PROPERLY!\n\n", mailf);
591 fprintf(mailf,"\nFAILURE AND STRANGE DUMP SUMMARY:\n");
592 output_lines(errsum, mailf);
594 fputs("\n\n", mailf);
599 fprintf(mailf,"\n\014\nFAILED AND STRANGE DUMP DETAILS:\n");
600 output_lines(errdet, mailf);
603 fprintf(mailf,"\n\014\nNOTES:\n");
604 output_lines(notes, mailf);
607 if(sortq.head != NULL) {
608 fprintf(mailf,"\n\014\nDUMP SUMMARY:\n");
611 fprintf(mailf,"\n(brought to you by Amanda version %s)\n",
615 do_postscript_output();
619 /* close postscript file */
620 if (psfname && postscript) {
621 /* it may be that postscript is NOT opened */
625 if (postscript != NULL && pclose(postscript) != 0)
626 error("printer command failed: %s", printer_cmd);
630 /* close output file */
635 if(pclose(mailf) != 0)
636 error("mail command failed: %s", mail_cmd);
640 amfree(run_datestamp);
648 malloc_size_2 = malloc_inuse(&malloc_hist_2);
650 if(malloc_size_1 != malloc_size_2) {
651 malloc_list(fileno(stderr), malloc_hist_1, malloc_hist_2);
659 #define mb(f) ((f)/1024) /* kbytes -> mbutes */
660 #define du(f) ((f)/unitdivisor) /* kbytes -> displayunit */
661 #define pct(f) ((f)*100.0) /* percent */
662 #define hrmn(f) ((int)(f)+30)/3600, (((int)(f)+30)%3600)/60
663 #define mnsc(f) ((int)(f+0.5))/60, ((int)(f+0.5)) % 60
665 #define divzero(fp,a,b) \
669 fprintf((fp)," -- "); \
670 else if ((q = (a)/q) >= 999.95) \
671 fprintf((fp), "###.#"); \
673 fprintf((fp), "%5.1f",q); \
675 #define divzero_wide(fp,a,b) \
679 fprintf((fp)," -- "); \
680 else if ((q = (a)/q) >= 99999.95) \
681 fprintf((fp), "#####.#"); \
683 fprintf((fp), "%7.1f",q); \
688 tapetype_t *tp = lookup_tapetype(getconf_str(CNF_TAPETYPE));
689 int tapesize, marksize, lv, first;
691 tapesize = tp->length;
692 marksize = tp->filemark;
694 stats[2].dumpdisks = stats[0].dumpdisks + stats[1].dumpdisks;
695 stats[2].tapedisks = stats[0].tapedisks + stats[1].tapedisks;
696 stats[2].outsize = stats[0].outsize + stats[1].outsize;
697 stats[2].origsize = stats[0].origsize + stats[1].origsize;
698 stats[2].tapesize = stats[0].tapesize + stats[1].tapesize;
699 stats[2].coutsize = stats[0].coutsize + stats[1].coutsize;
700 stats[2].corigsize = stats[0].corigsize + stats[1].corigsize;
701 stats[2].taper_time = stats[0].taper_time + stats[1].taper_time;
702 stats[2].dumper_time = stats[0].dumper_time + stats[1].dumper_time;
704 if(!got_finish) /* no driver finish line, estimate total run time */
705 total_time = stats[2].taper_time + planner_time;
707 fprintf(mailf,"STATISTICS:\n");
709 " Total Full Incr.\n");
711 " -------- -------- --------\n");
714 "Estimate Time (hrs:min) %2d:%02d\n", hrmn(planner_time));
717 "Run Time (hrs:min) %2d:%02d\n", hrmn(total_time));
720 "Dump Time (hrs:min) %2d:%02d %2d:%02d %2d:%02d\n",
721 hrmn(stats[2].dumper_time), hrmn(stats[0].dumper_time),
722 hrmn(stats[1].dumper_time));
725 "Output Size (meg) %8.1f %8.1f %8.1f\n",
726 mb(stats[2].outsize), mb(stats[0].outsize), mb(stats[1].outsize));
729 "Original Size (meg) %8.1f %8.1f %8.1f\n",
730 mb(stats[2].origsize), mb(stats[0].origsize),
731 mb(stats[1].origsize));
733 fprintf(mailf, "Avg Compressed Size (%%) ");
734 divzero(mailf, pct(stats[2].coutsize),stats[2].corigsize);
736 divzero(mailf, pct(stats[0].coutsize),stats[0].corigsize);
738 divzero(mailf, pct(stats[1].coutsize),stats[1].corigsize);
740 if(stats[1].dumpdisks > 0) fputs(" (level:#disks ...)", mailf);
744 "Filesystems Dumped %4d %4d %4d",
745 stats[2].dumpdisks, stats[0].dumpdisks, stats[1].dumpdisks);
747 if(stats[1].dumpdisks > 0) {
749 for(lv = 1; lv < 10; lv++) if(dumpdisks[lv]) {
750 fputs(first?" (":" ", mailf);
752 fprintf(mailf, "%d:%d", lv, dumpdisks[lv]);
758 fprintf(mailf, "Avg Dump Rate (k/s) ");
759 divzero_wide(mailf, stats[2].outsize,stats[2].dumper_time);
761 divzero_wide(mailf, stats[0].outsize,stats[0].dumper_time);
763 divzero_wide(mailf, stats[1].outsize,stats[1].dumper_time);
768 "Tape Time (hrs:min) %2d:%02d %2d:%02d %2d:%02d\n",
769 hrmn(stats[2].taper_time), hrmn(stats[0].taper_time),
770 hrmn(stats[1].taper_time));
773 "Tape Size (meg) %8.1f %8.1f %8.1f\n",
774 mb(stats[2].tapesize), mb(stats[0].tapesize),
775 mb(stats[1].tapesize));
777 fprintf(mailf, "Tape Used (%%) ");
778 divzero(mailf, pct(stats[2].tapesize+marksize*stats[2].tapedisks),tapesize);
780 divzero(mailf, pct(stats[0].tapesize+marksize*stats[0].tapedisks),tapesize);
782 divzero(mailf, pct(stats[1].tapesize+marksize*stats[1].tapedisks),tapesize);
784 if(stats[1].tapedisks > 0) fputs(" (level:#disks ...)", mailf);
788 "Filesystems Taped %4d %4d %4d",
789 stats[2].tapedisks, stats[0].tapedisks, stats[1].tapedisks);
791 if(stats[1].tapedisks > 0) {
793 for(lv = 1; lv < 10; lv++) if(tapedisks[lv]) {
794 fputs(first?" (":" ", mailf);
796 fprintf(mailf, "%d:%d", lv, tapedisks[lv]);
802 fprintf(mailf, "Avg Tp Write Rate (k/s) ");
803 divzero_wide(mailf, stats[2].tapesize,stats[2].taper_time);
805 divzero_wide(mailf, stats[0].tapesize,stats[0].taper_time);
807 divzero_wide(mailf, stats[1].tapesize,stats[1].taper_time);
811 int label_length = strlen(stats_by_tape->label) + 5;
812 fprintf(mailf,"\nUSAGE BY TAPE:\n");
813 fprintf(mailf," %-*s Time Size %% Nb\n",
814 label_length, "Label");
815 for(current_tape = stats_by_tape; current_tape != NULL;
816 current_tape = current_tape->next) {
817 fprintf(mailf, " %-*s", label_length, current_tape->label);
818 fprintf(mailf, " %2d:%02d", hrmn(current_tape->taper_time));
819 fprintf(mailf, " %8.0f%s ", du(current_tape->coutsize), displayunit);
820 divzero(mailf, pct(current_tape->coutsize +
821 marksize * current_tape->tapedisks),
823 fprintf(mailf, " %4d\n", current_tape->tapedisks);
831 void output_tapeinfo()
837 if (last_run_tapes > 0) {
839 fprintf(mailf, "The dumps were flushed to tape%s %s.\n",
840 last_run_tapes == 1 ? "" : "s",
841 tape_labels ? tape_labels : "");
843 fprintf(mailf, "These dumps were to tape%s %s.\n",
844 last_run_tapes == 1 ? "" : "s",
845 tape_labels ? tape_labels : "");
850 "*** A TAPE ERROR OCCURRED: %s.\n", tapestart_error);
851 fputs("Some dumps may have been left in the holding disk.\n", mailf);
853 "Run amflush%s to flush them to tape.\n",
854 amflush_run ? " again" : "");
857 tp = lookup_last_reusable_tape(skip);
859 run_tapes = getconf_int(CNF_RUNTAPES);
862 fputs("The next tape Amanda expects to use is: ", mailf);
864 fprintf(mailf, "The next %d tapes Amanda expects to used are: ",
867 while(run_tapes > 0) {
869 fprintf(mailf, "%s", tp->label);
871 fputs("a new tape", mailf);
873 if(run_tapes > 1) fputs(", ", mailf);
877 tp = lookup_last_reusable_tape(skip);
881 lasttp = lookup_tapepos(lookup_nb_tape());
882 run_tapes = getconf_int(CNF_RUNTAPES);
883 if(lasttp && run_tapes > 0 && lasttp->datestamp == 0) {
885 while(lasttp && run_tapes > 0 && lasttp->datestamp == 0) {
887 lasttp = lasttp->prev;
890 lasttp = lookup_tapepos(lookup_nb_tape());
892 fprintf(mailf, "The next new tape already labelled is: %s.\n",
896 fprintf(mailf, "The next %d new tapes already labelled are: %s", c,
898 lasttp = lasttp->prev;
900 while(lasttp && c > 0 && lasttp->datestamp == 0) {
901 fprintf(mailf, ", %s", lasttp->label);
902 lasttp = lasttp->prev;
905 fprintf(mailf, ".\n");
912 void output_lines(lp, f)
930 int sort_by_time(a, b)
933 return data(b)->dumper.sec - data(a)->dumper.sec;
936 int sort_by_name(a, b)
941 rc = strcmp(a->host->hostname, b->host->hostname);
942 if(rc == 0) rc = strcmp(a->name, b->name);
950 sortq.head = sortq.tail = NULL;
951 while(!empty(*diskq)) {
952 dp = dequeue_disk(diskq);
953 if(data(dp) == NULL) { /* create one */
954 find_repdata(dp, run_datestamp, 0);
956 insert_disk(&sortq, dp, sort_by_name);
960 void CheckStringMax(ColumnInfo *cd, char *s) {
968 void CheckIntMax(ColumnInfo *cd, int n) {
972 ap_snprintf(testBuf, sizeof(testBuf),
973 cd->Format, cd->Width, cd->Precision, n);
980 void CheckFloatMax(ColumnInfo *cd, double d) {
984 ap_snprintf(testBuf, sizeof(testBuf),
985 cd->Format, cd->Width, cd->Precision, d);
1000 static int TapeTime;
1001 static int TapeRate;
1003 void CalcMaxWidth() {
1004 /* we have to look for columspec's, that require the recalculation.
1005 * we do here the same loops over the sortq as is done in
1006 * output_summary. So, if anything is changed there, we have to
1007 * change this here also.
1013 for(dp = sortq.head; dp != NULL; dp = dp->next) {
1015 for(repdata = data(dp); repdata != NULL; repdata = repdata->next) {
1017 char TimeRateBuffer[40];
1019 CheckStringMax(&ColumnData[HostName], dp->host->hostname);
1020 CheckStringMax(&ColumnData[Disk], dp->name);
1021 if (repdata->dumper.result == L_BOGUS &&
1022 repdata->taper.result == L_BOGUS)
1024 CheckIntMax(&ColumnData[Level], repdata->level);
1025 if(repdata->dumper.result == L_SUCCESS) {
1026 CheckFloatMax(&ColumnData[OrigKB], du(repdata->dumper.origsize));
1027 CheckFloatMax(&ColumnData[OutKB], du(repdata->dumper.outsize));
1028 if(dp->compress == COMP_NONE)
1031 f = repdata->dumper.origsize;
1032 CheckStringMax(&ColumnData[Disk],
1033 sDivZero(pct(repdata->dumper.outsize), f, Compress));
1036 ap_snprintf(TimeRateBuffer, sizeof(TimeRateBuffer),
1037 "%3d:%02d", mnsc(repdata->dumper.sec));
1039 ap_snprintf(TimeRateBuffer, sizeof(TimeRateBuffer),
1041 CheckStringMax(&ColumnData[DumpTime], TimeRateBuffer);
1043 CheckFloatMax(&ColumnData[DumpRate], repdata->dumper.kps);
1046 cd= &ColumnData[TapeTime];
1047 if(repdata->taper.result == L_FAIL) {
1048 CheckStringMax(cd, "FAILED");
1051 if(repdata->taper.result == L_SUCCESS)
1052 ap_snprintf(TimeRateBuffer, sizeof(TimeRateBuffer),
1053 "%3d:%02d", mnsc(repdata->taper.sec));
1055 ap_snprintf(TimeRateBuffer, sizeof(TimeRateBuffer),
1057 CheckStringMax(cd, TimeRateBuffer);
1059 cd= &ColumnData[TapeRate];
1060 if(repdata->taper.result == L_SUCCESS)
1061 CheckFloatMax(cd, repdata->taper.kps);
1063 CheckStringMax(cd, "N/A ");
1069 void output_summary()
1073 char *ds="DUMPER STATS";
1074 char *ts=" TAPER STATS";
1077 int i, h, w1, wDump, wTape;
1078 float outsize, origsize;
1081 HostName = StringToColumn("HostName");
1082 Disk = StringToColumn("Disk");
1083 Level = StringToColumn("Level");
1084 OrigKB = StringToColumn("OrigKB");
1085 OutKB = StringToColumn("OutKB");
1086 Compress = StringToColumn("Compress");
1087 DumpTime = StringToColumn("DumpTime");
1088 DumpRate = StringToColumn("DumpRate");
1089 TapeTime = StringToColumn("TapeTime");
1090 TapeRate = StringToColumn("TapeRate");
1092 /* at first determine if we have to recalculate our widths */
1093 if (MaxWidthsRequested)
1096 /* title for Dumper-Stats */
1097 w1= ColWidth(HostName, Level);
1098 wDump= ColWidth(OrigKB, DumpRate);
1099 wTape= ColWidth(TapeTime, TapeRate);
1101 /* print centered top titles */
1108 fprintf(mailf, "%*s", w1+h, "");
1109 fprintf(mailf, "%-*s", wDump-h, ds);
1116 fprintf(mailf, "%*s", h, "");
1117 fprintf(mailf, "%-*s", wTape-h, ts);
1120 /* print the titles */
1121 for (i=0; ColumnData[i].Name != NULL; i++) {
1123 ColumnInfo *cd= &ColumnData[i];
1124 fprintf(mailf, "%*s", cd->PrefixSpace, "");
1125 if (cd->Format[1] == '-')
1129 if(strcmp(cd->Title,"ORIG-KB") == 0) {
1130 /* cd->Title must be re-allocated in write-memory */
1131 cd->Title = stralloc("ORIG-KB");
1132 cd->Title[5] = displayunit[0];
1134 if(strcmp(cd->Title,"OUT-KB") == 0) {
1135 /* cd->Title must be re-allocated in write-memory */
1136 cd->Title = stralloc("OUT-KB");
1137 cd->Title[4] = displayunit[0];
1139 fprintf(mailf, fmt, cd->Width, cd->Title);
1143 /* print the rules */
1144 fputs(tmp=Rule(HostName, Level), mailf); amfree(tmp);
1145 fputs(tmp=Rule(OrigKB, DumpRate), mailf); amfree(tmp);
1146 fputs(tmp=Rule(TapeTime, TapeRate), mailf); amfree(tmp);
1149 for(dp = sortq.head; dp != NULL; dp = dp->next) {
1152 char TimeRateBuffer[40];
1153 for(repdata = data(dp); repdata != NULL; repdata = repdata->next) {
1156 cd= &ColumnData[HostName];
1157 fprintf(mailf, "%*s", cd->PrefixSpace, "");
1158 fprintf(mailf, cd->Format, cd->Width, cd->Width, dp->host->hostname);
1160 cd= &ColumnData[Disk];
1161 fprintf(mailf, "%*s", cd->PrefixSpace, "");
1162 devlen= strlen(dp->name);
1163 if (devlen > cd->Width) {
1165 fprintf(mailf, cd->Format, cd->Width-1, cd->Precision-1,
1166 dp->name+devlen - (cd->Width-1) );
1169 fprintf(mailf, cd->Format, cd->Width, cd->Width, dp->name);
1171 cd= &ColumnData[Level];
1172 if (repdata->dumper.result == L_BOGUS &&
1173 repdata->taper.result == L_BOGUS) {
1175 fprintf(mailf, "%*s%s\n", cd->PrefixSpace+cd->Width, "",
1176 tmp=TextRule(OrigKB, TapeRate, "NO FILE TO FLUSH"));
1178 fprintf(mailf, "%*s%s\n", cd->PrefixSpace+cd->Width, "",
1179 tmp=TextRule(OrigKB, TapeRate, "MISSING"));
1185 fprintf(mailf, "%*s", cd->PrefixSpace, "");
1186 fprintf(mailf, cd->Format, cd->Width, cd->Precision,repdata->level);
1188 if (repdata->dumper.result == L_SKIPPED) {
1189 fprintf(mailf, "%s\n",
1190 tmp=TextRule(OrigKB, TapeRate, "SKIPPED"));
1194 if (repdata->dumper.result == L_FAIL) {
1195 fprintf(mailf, "%s\n",
1196 tmp=TextRule(OrigKB, TapeRate, "FAILED"));
1201 if(repdata->dumper.result == L_SUCCESS)
1202 origsize = repdata->dumper.origsize;
1204 origsize = repdata->taper.origsize;
1206 if(repdata->taper.result == L_SUCCESS)
1207 outsize = repdata->taper.outsize;
1209 outsize = repdata->dumper.outsize;
1211 cd= &ColumnData[OrigKB];
1212 fprintf(mailf, "%*s", cd->PrefixSpace, "");
1214 fprintf(mailf, cd->Format, cd->Width, cd->Precision, du(origsize));
1216 fprintf(mailf, "%*.*s", cd->Width, cd->Width, "N/A");
1218 cd= &ColumnData[OutKB];
1219 fprintf(mailf, "%*s", cd->PrefixSpace, "");
1221 fprintf(mailf, cd->Format, cd->Width, cd->Precision, du(outsize));
1223 cd= &ColumnData[Compress];
1224 fprintf(mailf, "%*s", cd->PrefixSpace, "");
1226 if(dp->compress == COMP_NONE)
1228 else if(origsize < 1.0)
1233 fputs(sDivZero(pct(outsize), f, Compress), mailf);
1235 cd= &ColumnData[DumpTime];
1236 fprintf(mailf, "%*s", cd->PrefixSpace, "");
1237 if(repdata->dumper.result == L_SUCCESS)
1238 ap_snprintf(TimeRateBuffer, sizeof(TimeRateBuffer),
1239 "%3d:%02d", mnsc(repdata->dumper.sec));
1241 ap_snprintf(TimeRateBuffer, sizeof(TimeRateBuffer),
1243 fprintf(mailf, cd->Format, cd->Width, cd->Width, TimeRateBuffer);
1245 cd= &ColumnData[DumpRate];
1246 fprintf(mailf, "%*s", cd->PrefixSpace, "");
1247 if(repdata->dumper.result == L_SUCCESS)
1248 fprintf(mailf, cd->Format, cd->Width, cd->Precision, repdata->dumper.kps);
1250 fprintf(mailf, "%*s", cd->Width, "N/A ");
1252 cd= &ColumnData[TapeTime];
1253 fprintf(mailf, "%*s", cd->PrefixSpace, "");
1254 if(repdata->taper.result == L_FAIL) {
1255 fprintf(mailf, "%s\n",
1256 tmp=TextRule(TapeTime, TapeRate, "FAILED "));
1261 if(repdata->taper.result == L_SUCCESS)
1262 ap_snprintf(TimeRateBuffer, sizeof(TimeRateBuffer),
1263 "%3d:%02d", mnsc(repdata->taper.sec));
1265 ap_snprintf(TimeRateBuffer, sizeof(TimeRateBuffer),
1267 fprintf(mailf, cd->Format, cd->Width, cd->Width, TimeRateBuffer);
1269 cd= &ColumnData[TapeRate];
1270 fprintf(mailf, "%*s", cd->PrefixSpace, "");
1271 if(repdata->taper.result == L_SUCCESS)
1272 fprintf(mailf, cd->Format, cd->Width, cd->Precision, repdata->taper.kps);
1274 fprintf(mailf, "%*s", cd->Width, "N/A ");
1283 printf("line %d of log is bogus\n", curlinenum);
1287 char *nicedate(datestamp)
1290 * Formats an integer of the form YYYYMMDD into the string
1291 * "Monthname DD, YYYY". A pointer to the statically allocated string
1292 * is returned, so it must be copied to other storage (or just printed)
1293 * before calling nicedate() again.
1296 static char nice[64];
1297 static char *months[13] = { "BogusMonth",
1298 "January", "February", "March", "April", "May", "June",
1299 "July", "August", "September", "October", "November", "December"
1301 int year, month, day;
1303 year = datestamp / 10000;
1304 day = datestamp % 100;
1305 month = (datestamp / 100) % 100;
1307 ap_snprintf(nice, sizeof(nice), "%s %d, %d", months[month], day, year);
1314 static int started = 0;
1324 skip_whitespace(s, ch);
1325 #define sc "datestamp"
1326 if(ch == '\0' || strncmp(s - 1, sc, sizeof(sc)-1) != 0) {
1333 skip_whitespace(s, ch);
1339 skip_non_whitespace(s, ch);
1341 run_datestamp = newstralloc(run_datestamp, fp);
1344 skip_whitespace(s, ch);
1346 if(ch == '\0' || strncmp(s - 1, sc, sizeof(sc)-1) != 0) {
1353 skip_whitespace(s, ch);
1359 skip_non_whitespace(s, ch);
1362 label = stralloc(fp);
1366 fp = vstralloc(tape_labels, ", ", label, NULL);
1367 amfree(tape_labels);
1370 tape_labels = stralloc(label);
1375 if(stats_by_tape == NULL) {
1376 stats_by_tape = current_tape = (taper_t *)alloc(sizeof(taper_t));
1379 current_tape->next = (taper_t *)alloc(sizeof(taper_t));
1380 current_tape = current_tape->next;
1382 current_tape->label = label;
1383 current_tape->taper_time = 0.0;
1384 current_tape->coutsize = 0.0;
1385 current_tape->corigsize = 0.0;
1386 current_tape->tapedisks = 0;
1387 current_tape->next = NULL;
1407 skip_whitespace(s, ch);
1409 if(ch == '\0' || strncmp(s - 1, sc, sizeof(sc)-1) != 0) {
1410 return; /* ignore bogus line */
1415 skip_whitespace(s, ch);
1421 skip_non_whitespace(s, ch);
1423 run_datestamp = newstralloc(run_datestamp, fp);
1428 if(amflush_run && normal_run) {
1431 " reporter: both amflush and planner output in log, ignoring amflush.");
1436 void handle_finish()
1442 if(curprog == P_DRIVER || curprog == P_AMFLUSH || curprog == P_PLANNER) {
1446 skip_whitespace(s, ch);
1448 if(ch == '\0' || strncmp(s - 1, sc, sizeof(sc)-1) != 0) {
1456 skip_whitespace(s, ch);
1461 skip_non_whitespace(s, ch); /* ignore the date string */
1463 skip_whitespace(s, ch);
1465 if(ch == '\0' || strncmp(s - 1, sc, sizeof(sc)-1) != 0) {
1466 /* older planner doesn't write time */
1467 if(curprog == P_PLANNER) return;
1475 skip_whitespace(s, ch);
1480 if(sscanf(s - 1, "%f", &a_time) != 1) {
1484 if(curprog == P_PLANNER) {
1485 planner_time = a_time;
1488 total_time = a_time;
1499 if(curprog == P_DRIVER) {
1503 skip_whitespace(s, ch);
1504 #define sc "startup time"
1505 if(ch == '\0' || strncmp(s - 1, sc, sizeof(sc)-1) != 0) {
1513 skip_whitespace(s, ch);
1518 if(sscanf(s - 1, "%f", &startup_time) != 1) {
1522 planner_time = startup_time;
1531 str = vstralloc(" ", program_str[curprog], ": ", curstr, NULL);
1532 addline(¬es, str);
1541 char *s = NULL, *nl;
1544 if(curlog == L_ERROR && curprog == P_TAPER) {
1548 skip_whitespace(s, ch);
1549 #define sc "no-tape"
1550 if(ch == '\0' || strncmp(s - 1, sc, sizeof(sc)-1) != 0) {
1558 skip_whitespace(s, ch);
1560 if((nl = strchr(s - 1, '\n')) != NULL) {
1563 tapestart_error = newstralloc(tapestart_error, s - 1);
1568 /* else some other tape error, handle like other errors */
1570 s = vstralloc(" ", program_str[curprog], ": ",
1571 logtype_str[curlog], " ", curstr, NULL);
1572 addline(&errsum, s);
1578 void handle_summary()
1591 char *hostname = NULL, *diskname = NULL;
1593 if(curprog != P_PLANNER && curprog != P_AMFLUSH) {
1599 for(dp = diskq->head; dp != NULL; dp = dp->next)
1607 skip_whitespace(s, ch);
1613 skip_non_whitespace(s, ch);
1615 hostname = newstralloc(hostname, fp);
1618 skip_whitespace(s, ch);
1624 skip_non_whitespace(s, ch);
1626 diskname = newstralloc(diskname, fp);
1629 dp = lookup_disk(hostname, diskname);
1631 dp = add_disk(hostname, diskname);
1639 repdata_t *handle_success()
1642 float sec, kps, kbytes, origkb;
1647 char *hostname = NULL;
1648 char *diskname = NULL;
1653 if(curprog != P_TAPER && curprog != P_DUMPER && curprog != P_PLANNER) {
1661 skip_whitespace(s, ch);
1667 skip_non_whitespace(s, ch);
1669 hostname = stralloc(fp);
1672 skip_whitespace(s, ch);
1679 skip_non_whitespace(s, ch);
1681 diskname = stralloc(fp);
1684 skip_whitespace(s, ch);
1692 skip_non_whitespace(s, ch);
1694 datestamp = stralloc(fp);
1697 level = atoi(datestamp);
1699 datestamp = newstralloc(datestamp, run_datestamp);
1702 skip_whitespace(s, ch);
1703 if(ch == '\0' || sscanf(s - 1, "%d", &level) != 1) {
1710 skip_integer(s, ch);
1713 skip_whitespace(s, ch);
1714 /* Planner success messages (for skipped
1715 dumps) do not contain statistics */
1716 if(curprog != P_PLANNER) {
1717 if(curprog != P_DUMPER ||
1718 sscanf(s - 1,"[sec %f kb %f kps %f orig-kb %f",
1719 &sec, &kbytes, &kps, &origkb) != 4) {
1721 if(sscanf(s - 1,"[sec %f kb %f kps %f",
1722 &sec, &kbytes, &kps) != 3) {
1731 if(origkb == 0.0) origkb = 0.1;
1736 dp = lookup_disk(hostname, diskname);
1740 str = vstralloc(" ", prefix(hostname, diskname, level),
1741 " ", "ERROR [not in disklist]",
1743 addline(&errsum, str);
1751 repdata = find_repdata(dp, datestamp, level);
1753 if(curprog == P_PLANNER) {
1754 repdata->dumper.result = L_SKIPPED;
1761 if(curprog == P_TAPER)
1762 sp = &(repdata->taper);
1763 else sp = &(repdata->dumper);
1772 get_info(hostname, diskname, &inf);
1773 tm = localtime(&inf.inf[level].date);
1774 Idatestamp = 10000*(tm->tm_year+1900) +
1775 100*(tm->tm_mon+1) + tm->tm_mday;
1777 if(atoi(datestamp) == Idatestamp) {
1778 /* grab original size from record */
1779 origkb = (double)inf.inf[level].size;
1788 sp->result = L_SUCCESS;
1789 sp->datestamp = repdata->datestamp;
1792 sp->origsize = origkb;
1793 sp->outsize = kbytes;
1795 if(curprog == P_TAPER) {
1796 if(current_tape == NULL) {
1797 error("current_tape == NULL");
1799 stats[i].taper_time += sec;
1800 sp->filenum = ++tapefcount;
1801 sp->tapelabel = current_tape->label;
1802 tapedisks[level] +=1;
1803 stats[i].tapedisks +=1;
1804 stats[i].tapesize += kbytes;
1805 current_tape->taper_time += sec;
1806 current_tape->coutsize += kbytes;
1807 current_tape->corigsize += origkb;
1808 current_tape->tapedisks += 1;
1811 if(curprog == P_DUMPER) {
1812 stats[i].dumper_time += sec;
1813 if(dp->compress == COMP_NONE) {
1814 sp->origsize = kbytes;
1817 stats[i].coutsize += kbytes;
1818 stats[i].corigsize += sp->origsize;
1820 dumpdisks[level] +=1;
1821 stats[i].dumpdisks +=1;
1822 stats[i].origsize += sp->origsize;
1823 stats[i].outsize += kbytes;
1829 void handle_strange()
1832 char *strangestr = NULL;
1835 repdata = handle_success();
1837 addline(&errdet,"");
1838 str = vstralloc("/-- ", prefix(repdata->disk->host->hostname,
1839 repdata->disk->name, repdata->level),
1842 addline(&errdet, str);
1845 while(contline_next()) {
1846 get_logline(logfile);
1847 #define sc "sendbackup: warning "
1848 if(strncmp(curstr, sc, sizeof(sc)-1) == 0) {
1849 strangestr = newstralloc(strangestr, curstr+sizeof(sc)-1);
1851 addline(&errdet, curstr);
1853 addline(&errdet,"\\--------");
1855 str = vstralloc(" ", prefix(repdata->disk->host->hostname,
1856 repdata->disk->name, repdata->level),
1857 " ", "STRANGE", " ", strangestr,
1859 addline(&errsum, str);
1864 void handle_failed()
1884 skip_whitespace(s, ch);
1890 skip_non_whitespace(s, ch);
1893 skip_whitespace(s, ch);
1899 skip_non_whitespace(s, ch);
1902 skip_whitespace(s, ch);
1908 skip_non_whitespace(s, ch);
1910 datestamp = stralloc(fp);
1912 if(strlen(datestamp) < 3) { /* there is no datestamp, it's the level */
1913 level = atoi(datestamp);
1914 datestamp = newstralloc(datestamp, run_datestamp);
1916 else { /* read the level */
1917 skip_whitespace(s, ch);
1918 if(ch == '\0' || sscanf(s - 1, "%d", &level) != 1) {
1923 skip_integer(s, ch);
1926 skip_whitespace(s, ch);
1933 if((s = strchr(errstr, '\n')) != NULL) {
1937 dp = lookup_disk(hostname, diskname);
1939 str = vstralloc(" ", prefix(hostname, diskname, level),
1940 " ", "ERROR [not in disklist]",
1942 addline(&errsum, str);
1945 repdata = find_repdata(dp, datestamp, level);
1947 if(curprog == P_TAPER)
1948 sp = &(repdata->taper);
1949 else sp = &(repdata->dumper);
1951 if(sp->result != L_SUCCESS)
1952 sp->result = L_FAIL;
1956 str = vstralloc(" ", prefix(hostname, diskname, level),
1960 addline(&errsum, str);
1963 if(curprog == P_DUMPER) {
1964 addline(&errdet,"");
1965 str = vstralloc("/-- ", prefix(hostname, diskname, level),
1969 addline(&errdet, str);
1971 while(contline_next()) {
1972 get_logline(logfile);
1973 addline(&errdet, curstr);
1975 addline(&errdet,"\\--------");
1980 void generate_missing()
1985 for(dp = diskq->head; dp != NULL; dp = dp->next) {
1986 if(dp->todo && data(dp) == NULL) {
1987 str = vstralloc(" ", prefix(dp->host->hostname, dp->name, -987),
1988 " ", "RESULTS MISSING",
1990 addline(&errsum, str);
1997 prefix (host, disk, level)
2004 char number[NUM_STR_SIZE];
2005 static char *str = NULL;
2007 ap_snprintf(number, sizeof(number), "%d", level);
2009 strncpy(h, host, sizeof(h)-1);
2011 strncpy(h, "(host?)", sizeof(h)-1);
2013 h[sizeof(h)-1] = '\0';
2014 for(l = strlen(h); l < sizeof(h)-1; l++) {
2017 str = newvstralloc(str,
2019 " ", disk ? disk : "(disk?)",
2020 level != -987 ? " lev " : "",
2021 level != -987 ? number : "",
2026 void copy_template_file(lbl_templ)
2033 if (strchr(lbl_templ, '/') == NULL) {
2034 lbl_templ = stralloc2(config_dir, lbl_templ);
2036 lbl_templ = stralloc(lbl_templ);
2038 if ((fd = open(lbl_templ, 0)) < 0) {
2040 curprog = P_REPORTER;
2041 curstr = vstralloc("could not open PostScript template file ",
2048 afclose(postscript);
2051 while ((numread = read(fd, buf, sizeof(buf))) > 0) {
2052 if (fwrite(buf, numread, 1, postscript) != 1) {
2054 curprog = P_REPORTER;
2055 curstr = vstralloc("error copying PostScript template file ",
2062 afclose(postscript);
2068 curprog = P_REPORTER;
2069 curstr = vstralloc("error reading PostScript template file ",
2076 afclose(postscript);
2083 repdata_t *find_repdata(dp, datestamp, level)
2088 repdata_t *repdata, *prev;
2091 datestamp = run_datestamp;
2093 for(repdata = data(dp); repdata != NULL && (repdata->level != level || strcmp(repdata->datestamp,datestamp)!=0); repdata = repdata->next) {
2097 repdata = (repdata_t *)alloc(sizeof(repdata_t));
2098 memset(repdata, '\0',sizeof(repdata_t));
2100 repdata->datestamp = stralloc(datestamp ? datestamp : "");
2101 repdata->level = level;
2102 repdata->dumper.result = L_BOGUS;
2103 repdata->taper.result = L_BOGUS;
2104 repdata->next = NULL;
2106 prev->next = repdata;
2108 dp->up = (void *)repdata;
2114 void do_postscript_output()
2116 tapetype_t *tp = lookup_tapetype(getconf_str(CNF_TAPETYPE));
2119 float outsize, origsize;
2120 int tapesize, marksize;
2122 tapesize = tp->length;
2123 marksize = tp->filemark;
2125 for(current_tape = stats_by_tape; current_tape != NULL;
2126 current_tape = current_tape->next) {
2128 if (current_tape->label == NULL) {
2132 copy_template_file(tp->lbl_templ);
2134 /* generate a few elements */
2135 fprintf(postscript,"(%s) DrawDate\n\n",
2136 nicedate(run_datestamp ? atoi(run_datestamp) : 0));
2137 fprintf(postscript,"(Amanda Version %s) DrawVers\n",version());
2138 fprintf(postscript,"(%s) DrawTitle\n", current_tape->label);
2141 fprintf(postscript, "(Total Size: %6.1f MB) DrawStat\n",
2142 mb(current_tape->coutsize));
2143 fprintf(postscript, "(Tape Used (%%) ");
2144 divzero(postscript, pct(current_tape->coutsize +
2145 marksize * current_tape->tapedisks),
2147 fprintf(postscript," %%) DrawStat\n");
2148 fprintf(postscript, "(Compression Ratio: ");
2149 divzero(postscript, pct(current_tape->coutsize),current_tape->corigsize);
2150 fprintf(postscript," %%) DrawStat\n");
2151 fprintf(postscript,"(Filesystems Taped: %4d) DrawStat\n",
2152 current_tape->tapedisks);
2157 "(-) (%s) (-) ( 0) ( 32) ( 32) DrawHost\n",
2158 current_tape->label);
2160 for(dp = sortq.head; dp != NULL; dp = dp->next) {
2161 if (dp->todo == 0) {
2164 for(repdata = data(dp); repdata != NULL; repdata = repdata->next) {
2166 if(repdata->taper.tapelabel != current_tape->label) {
2170 if(repdata->dumper.result == L_SUCCESS)
2171 origsize = repdata->dumper.origsize;
2173 origsize = repdata->taper.origsize;
2175 if(repdata->taper.result == L_SUCCESS)
2176 outsize = repdata->taper.outsize;
2178 outsize = repdata->dumper.outsize;
2180 if (repdata->taper.result == L_SUCCESS) {
2181 if(origsize != 0.0) {
2182 fprintf(postscript,"(%s) (%s) (%d) (%3.0d) (%8.0f) (%8.0f) DrawHost\n",
2183 dp->host->hostname, dp->name, repdata->level,
2184 repdata->taper.filenum, origsize,
2188 fprintf(postscript,"(%s) (%s) (%d) (%3.0d) (%8s) (%8.0f) DrawHost\n",
2189 dp->host->hostname, dp->name, repdata->level,
2190 repdata->taper.filenum, "N/A",
2197 fprintf(postscript,"\nshowpage\n");