📄 reporter.c
字号:
/* * Amanda, The Advanced Maryland Automatic Network Disk Archiver * Copyright (c) 1991-1998, 2000 University of Maryland at College Park * All Rights Reserved. * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of U.M. not be used in advertising or * publicity pertaining to distribution of the software without specific, * written prior permission. U.M. makes no representations about the * suitability of this software for any purpose. It is provided "as is" * without express or implied warranty. * * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M. * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Author: James da Silva, Systems Design and Analysis Group * Computer Science Department * University of Maryland at College Park *//* * $Id: reporter.c,v 1.132 2006/08/28 17:02:48 martinea Exp $ * * nightly Amanda Report generator *//* * report format * tape label message * error messages * strange messages * summary stats * details for errors * details for strange * notes * success summary */#include "amanda.h"#include "conffile.h"#include "columnar.h"#include "tapefile.h"#include "diskfile.h"#include "infofile.h"#include "logfile.h"#include "version.h"#include "util.h"#include "timestamp.h"#include "holding.h"/* don't have (or need) a skipped type except internally to reporter */#define L_SKIPPED L_MARKER#define STATUS_STRANGE 2#define STATUS_FAILED 4#define STATUS_MISSING 8#define STATUS_TAPE 16typedef struct line_s { struct line_s *next; char *str;} line_t;typedef struct timedata_s { logtype_t result; double origsize, outsize; char *datestamp; double sec, kps; int filenum; char *tapelabel; int totpart;} timedata_t;typedef struct repdata_s { disk_t *disk; char *datestamp; double est_nsize, est_csize; timedata_t taper; timedata_t dumper; timedata_t chunker; int level; struct repdata_s *next;} repdata_t;#define data(dp) ((repdata_t *)(dp)->up)static struct cumulative_stats { int dumpdisks, tapedisks, tapechunks; double taper_time, dumper_time; double outsize, origsize, tapesize; double coutsize, corigsize; /* compressed dump only */} stats[3];static int dumpdisks[10], tapedisks[10], tapechunks[10]; /* by-level breakdown of disk count */typedef struct taper_s { char *label; double taper_time; double coutsize, corigsize; int tapedisks, tapechunks; struct taper_s *next;} taper_t;static taper_t *stats_by_tape = NULL;static taper_t *current_tape = NULL;typedef struct X_summary_s { char *hostname; char *diskname; int level; char *str; struct X_summary_s *next;} X_summary_t;static X_summary_t *first_strange=NULL, *last_strange=NULL;static X_summary_t *first_failed=NULL, *last_failed=NULL;static double total_time, startup_time, planner_time;/* count files to tape */static int tapefcount = 0;static int exit_status = 0;static char *run_datestamp;static char *tape_labels = NULL;static int last_run_tapes = 0;static int degraded_mode = 0; /* defined in driverio too */static int normal_run = 0;static int amflush_run = 0;static int got_finish = 0;static int cmdlogfname = 0;static char *ghostname = NULL;static char *tapestart_error = NULL;static FILE *logfile, *mailf;static FILE *postscript;static char *printer;static disklist_t diskq;static disklist_t sortq;static line_t *errsum = NULL;static line_t *errdet = NULL;static line_t *strangedet = NULL;static line_t *notes = NULL;static char MaxWidthsRequested = 0; /* determined via config data */static char *displayunit;static long int unitdivisor;/* local functions */int main(int argc, char **argv);static char * nicedate(const char * datestamp);static char * prefix(char *host, char *disk, int level);static char * prefixstrange(char *host, char *disk, int level, size_t len_host, size_t len_disk);static char * Rule(int From, int To);static char * sDivZero(double a, double b, int cn);static char * TextRule(int From, int To, char *s);static int ColWidth(int From, int To);static int contline_next(void);static int sort_by_name(disk_t *a, disk_t *b);static repdata_t *find_repdata(disk_t *dp, char *datestamp, int level);static repdata_t *handle_chunk(logtype_t logtype);static repdata_t *handle_success(logtype_t logtype);static void addline(line_t **lp, char *str);static void addtoX_summary(X_summary_t **first, X_summary_t **last, char *host, char *disk, int level, char *str);static void bogus_line(const char *);static void CalcMaxWidth(void);static void CheckFloatMax(ColumnInfo *cd, double d);static void CheckIntMax(ColumnInfo *cd, int n);static void CheckStringMax(ColumnInfo *cd, char *s);static void copy_template_file(char *lbl_templ);static void do_postscript_output(void);static void generate_missing(void);static void generate_bad_estimate(void);static void handle_disk(void);static void handle_error(void);static void handle_failed(void);static void handle_finish(void);static void handle_note(void);static void handle_partial(void);static void handle_start(void);static void handle_stats(void);static void handle_strange(void);static void handle_summary(void);static void output_lines(line_t *lp, FILE *f);static void output_stats(void);static void output_X_summary(X_summary_t *first);static void output_summary(void);static void output_tapeinfo(void);static void sort_disks(void);static void usage(void);static intColWidth( int From, int To){ int i, Width= 0; for (i=From; i<=To && ColumnData[i].Name != NULL; i++) { Width+= ColumnData[i].PrefixSpace + ColumnData[i].Width; } return Width;}static char *Rule( int From, int To){ int i, ThisLeng; int Leng= ColWidth(0, ColumnDataCount()); char *RuleSpace= alloc((size_t)(Leng+1)); ThisLeng= ColWidth(From, To); for (i=0;i<ColumnData[From].PrefixSpace; i++) RuleSpace[i]= ' '; for (; i<ThisLeng; i++) RuleSpace[i]= '-'; RuleSpace[ThisLeng]= '\0'; return RuleSpace;}static char *TextRule( int From, int To, char * s){ ColumnInfo *cd= &ColumnData[From]; int leng; int nbrules, i, txtlength; int RuleSpaceSize= ColWidth(0, ColumnDataCount()); char *RuleSpace= alloc((size_t)RuleSpaceSize), *tmp; leng = (int)strlen(s); if(leng >= (RuleSpaceSize - cd->PrefixSpace)) leng = RuleSpaceSize - cd->PrefixSpace - 1; g_snprintf(RuleSpace, (size_t)RuleSpaceSize, "%*s%*.*s ", cd->PrefixSpace, "", leng, leng, s); txtlength = cd->PrefixSpace + leng + 1; nbrules = ColWidth(From,To) - txtlength; for(tmp=RuleSpace + txtlength, i=nbrules ; i>0; tmp++,i--) *tmp='-'; *tmp = '\0'; return RuleSpace;}static char *sDivZero( double a, double b, int cn){ ColumnInfo *cd= &ColumnData[cn]; static char PrtBuf[256]; if (!isnormal(b)) g_snprintf(PrtBuf, SIZEOF(PrtBuf), "%*s", cd->Width, "-- "); else g_snprintf(PrtBuf, SIZEOF(PrtBuf), cd->Format, cd->Width, cd->Precision, a/b); return PrtBuf;}static intcontline_next(void){ int ch; if ((ch = getc(logfile)) != EOF) { if (ungetc(ch, logfile) == EOF) { if (ferror(logfile)) { error(_("ungetc failed: %s\n"), strerror(errno)); /*NOTREACHED*/ } error(_("ungetc failed: EOF\n")); /*NOTREACHED*/ } } return ch == ' ';}static voidaddline( line_t ** lp, char * str){ line_t *new, *p; /* allocate new line node */ new = (line_t *) alloc(SIZEOF(line_t)); new->next = NULL; new->str = stralloc(str); /* add to end of list */ p = *lp; if (p == NULL) { *lp = new; } else { while (p->next != NULL) p = p->next; p->next = new; }}static voidusage(void){ error(_("Usage: amreport conf [-i] [-M address] [-f output-file] [-l logfile] [-p postscript-file] [-o configoption]*")); /*NOTREACHED*/}intmain( int argc, char ** argv){ char *conf_diskfile; char *conf_tapelist; char *conf_infofile; char *logfname, *psfname, *outfname, *subj_str = NULL; tapetype_t *tp; int opt; char *mail_cmd = NULL, *printer_cmd = NULL; extern int optind; char * cwd = NULL; char *ColumnSpec = ""; char *errstr = NULL; int cn; int mailout = 1; char *mailto = NULL; char *lbl_templ = NULL; config_overwrites_t *cfg_ovr = NULL; char *cfg_opt = NULL; /* * Configure program for internationalization: * 1) Only set the message locale for now. * 2) Set textdomain for all amanda related programs to "amanda" * We don't want to be forced to support dozens of message catalogs. */ setlocale(LC_MESSAGES, "C"); textdomain("amanda"); safe_fd(-1, 0); set_pname("amreport"); dbopen(DBG_SUBDIR_SERVER); /* Don't die when child closes pipe */ signal(SIGPIPE, SIG_IGN); /* Process options */ erroutput_type = ERR_INTERACTIVE; outfname = NULL; psfname = NULL; logfname = NULL; cmdlogfname = 0; cwd = g_get_current_dir(); if (cwd == NULL) { error(_("Cannot determine current working directory: %s"), strerror(errno)); /*NOTREACHED*/ } if (argc >= 2) { if (argv[1][0] == '-') { usage(); return 1; } /* get the config name and move past it */ cfg_opt = argv[1]; --argc; ++argv; cfg_ovr = new_config_overwrites(argc/2); while((opt = getopt(argc, argv, "o:M:f:l:p:i")) != EOF) { switch(opt) { case 'i': mailout = 0; break; case 'M': if (mailto != NULL) { error(_("you may specify at most one -M")); /*NOTREACHED*/ } mailto = stralloc(optarg); if(!validate_mailto(mailto)) { error(_("mail address has invalid characters")); /*NOTREACHED*/ } break; case 'f': if (outfname != NULL) { error(_("you may specify at most one -f")); /*NOTREACHED*/ } if (*optarg == '/') { outfname = stralloc(optarg); } else { outfname = vstralloc(cwd, "/", optarg, NULL); } break; case 'l': cmdlogfname = 1; if (logfname != NULL) { error(_("you may specify at most one -l")); /*NOTREACHED*/ } if (*optarg == '/') { logfname = stralloc(optarg); } else { logfname = vstralloc(cwd, "/", optarg, NULL); } break; case 'p': if (psfname != NULL) { error(_("you may specify at most one -p")); /*NOTREACHED*/ } if (*optarg == '/') { psfname = stralloc(optarg); } else { psfname = vstralloc(cwd, "/", optarg, NULL); } break; case 'o': add_config_overwrite_opt(cfg_ovr, optarg); break; case '?': usage(); return 1; default: break; } } argc -= optind; argv += optind; } if( !mailout && mailto ){ g_printf(_("You cannot specify both -i & -M at the same time\n")); exit(1); } amfree(cwd);#if !defined MAILER if(!outfname) { g_printf(_("You must run amreport with '-f <output file>' because configure\n")); g_printf(_("didn't find a mailer.\n")); exit (1); }#endif /* read configuration files */ /* ignore any errors reading the config file (amreport can run without a config) */ config_init(CONFIG_INIT_EXPLICIT_NAME | CONFIG_INIT_USE_CWD, cfg_opt); if (cfg_ovr) apply_config_overwrites(cfg_ovr); check_running_as(RUNNING_AS_DUMPUSER); dbrename(config_name, DBG_SUBDIR_SERVER); safe_cd(); /* must be called *after* config_init() */ conf_diskfile = config_dir_relative(getconf_str(CNF_DISKFILE)); /* Ignore error from read_diskfile */ read_diskfile(conf_diskfile, &diskq); amfree(conf_diskfile); if(mailout && !mailto && getconf_seen(CNF_MAILTO) && strlen(getconf_str(CNF_MAILTO)) > 0) { mailto = getconf_str(CNF_MAILTO); if(!validate_mailto(mailto)){ mailto = NULL; } } conf_tapelist = config_dir_relative(getconf_str(CNF_TAPELIST)); /* Ignore error from read_tapelist */ read_tapelist(conf_tapelist); amfree(conf_tapelist); conf_infofile = config_dir_relative(getconf_str(CNF_INFOFILE)); if(open_infofile(conf_infofile)) { error(_("could not open info db \"%s\""), conf_infofile); /*NOTREACHED*/ } amfree(conf_infofile); displayunit = getconf_str(CNF_DISPLAYUNIT); unitdivisor = getconf_unit_divisor(); ColumnSpec = getconf_str(CNF_COLUMNSPEC); if(SetColumnDataFromString(ColumnData, ColumnSpec, &errstr) < 0) { curlog = L_ERROR; curprog = P_REPORTER; curstr = errstr; handle_error(); amfree(errstr); curstr = NULL; ColumnSpec = ""; /* use the default */ if(SetColumnDataFromString(ColumnData, ColumnSpec, &errstr) < 0) { curlog = L_ERROR; curprog = P_REPORTER; curstr = errstr; handle_error(); amfree(errstr); curstr = NULL; } } for (cn = 0; ColumnData[cn].Name != NULL; cn++) { if (ColumnData[cn].MaxWidth) { MaxWidthsRequested = 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -