/* *************************************************************************** * Check system activity datafile contents before displaying stats. * Display file header if option -H has been entered, else call function * corresponding to selected output format. * * IN: * @dfile System activity data file name. *************************************************************************** */ void read_stats_from_file(char dfile[]) { struct file_magic file_magic; struct file_activity *file_actlst = NULL; struct tm rectime, loctime; int ifd, ignore, tab = 0; __nr_t cpu_nr; /* Prepare file for reading and read its headers */ ignore = ACCEPT_BAD_FILE_FORMAT(fmt[f_position]->options); check_file_actlst(&ifd, dfile, act, &file_magic, &file_hdr, &file_actlst, id_seq, ignore); /* Now pick up number of proc for this file */ cpu_nr = act[get_activity_position(act, A_CPU, EXIT_IF_NOT_FOUND)]->nr; if (DISPLAY_HDR_ONLY(flags)) { if (*fmt[f_position]->f_header) { /* Display only data file header then exit */ (*fmt[f_position]->f_header)(&tab, F_BEGIN + F_END, dfile, &file_magic, &file_hdr, cpu_nr, act, id_seq); } exit(0); } /* Perform required allocations */ allocate_structures(act); /* Call function corresponding to selected output format */ if (format == F_SVG_OUTPUT) { logic3_display_loop(ifd, file_actlst, cpu_nr, &rectime, &loctime, dfile, &file_magic); } else if (DISPLAY_GROUPED_STATS(fmt[f_position]->options)) { logic2_display_loop(ifd, file_actlst, cpu_nr, &rectime, &loctime, dfile, &file_magic); } else { logic1_display_loop(ifd, file_actlst, dfile, &file_magic, cpu_nr, &rectime, &loctime); } close(ifd); free(file_actlst); free_structures(act); }
/* *************************************************************************** * Read statistics from a system activity data file. * * IN: * @from_file Input file name. *************************************************************************** */ void read_stats_from_file(char from_file[]) { struct file_magic file_magic; struct file_activity *file_actlst = NULL; int curr = 1, i, p; int ifd, rtype; int rows, eosaf = TRUE, reset = FALSE; long cnt = 1; off_t fpos; /* Get window size */ rows = get_win_height(); /* Read file headers and activity list */ check_file_actlst(&ifd, from_file, act, &file_magic, &file_hdr, &file_actlst, id_seq, FALSE); /* Perform required allocations */ allocate_structures(act); /* Print report header */ print_report_hdr(flags, &rectime, &file_hdr, act[get_activity_position(act, A_CPU)]->nr); /* Read system statistics from file */ do { /* * If this record is a special (RESTART or COMMENT) one, print it and * (try to) get another one. */ do { if (sa_fread(ifd, &record_hdr[0], RECORD_HEADER_SIZE, SOFT_SIZE)) /* End of sa data file */ return; rtype = record_hdr[0].record_type; if ((rtype == R_RESTART) || (rtype == R_COMMENT)) { sar_print_special(0, tm_start.use, tm_end.use, rtype, ifd, from_file, &file_magic); } else { /* * OK: Previous record was not a special one. * So read now the extra fields. */ read_file_stat_bunch(act, 0, ifd, file_hdr.sa_act_nr, file_actlst); if (sar_get_record_timestamp_struct(0)) /* * An error was detected. * The timestamp hasn't been updated. */ continue; } } while ((rtype == R_RESTART) || (rtype == R_COMMENT) || (tm_start.use && (datecmp(&rectime, &tm_start) < 0)) || (tm_end.use && (datecmp(&rectime, &tm_end) >=0))); /* Save the first stats collected. Will be used to compute the average */ copy_structures(act, id_seq, record_hdr, 2, 0); reset = TRUE; /* Set flag to reset last_uptime variable */ /* Save current file position */ if ((fpos = lseek(ifd, 0, SEEK_CUR)) < 0) { perror("lseek"); exit(2); } /* * Read and write stats located between two possible Linux restarts. * Activities that should be displayed are saved in id_seq[] array. */ for (i = 0; i < NR_ACT; i++) { if (!id_seq[i]) continue; if ((p = get_activity_position(act, id_seq[i])) < 0) { /* Should never happen */ PANIC(1); } if (!IS_SELECTED(act[p]->options)) continue; if (!HAS_MULTIPLE_OUTPUTS(act[p]->options)) { handle_curr_act_stats(ifd, fpos, &curr, &cnt, &eosaf, rows, act[p]->id, &reset, file_actlst, from_file, &file_magic); } else { unsigned int optf, msk; optf = act[p]->opt_flags; for (msk = 1; msk < 0x10; msk <<= 1) { if (act[p]->opt_flags & msk) { act[p]->opt_flags &= msk; handle_curr_act_stats(ifd, fpos, &curr, &cnt, &eosaf, rows, act[p]->id, &reset, file_actlst, from_file, &file_magic); act[p]->opt_flags = optf; } } } } if (!cnt) { /* Go to next Linux restart, if possible */ do { eosaf = sa_fread(ifd, &record_hdr[curr], RECORD_HEADER_SIZE, SOFT_SIZE); rtype = record_hdr[curr].record_type; if (!eosaf && (rtype != R_RESTART) && (rtype != R_COMMENT)) { read_file_stat_bunch(act, curr, ifd, file_hdr.sa_act_nr, file_actlst); } else if (!eosaf && (rtype == R_COMMENT)) { /* This was a COMMENT record: print it */ sar_print_special(curr, tm_start.use, tm_end.use, R_COMMENT, ifd, from_file, &file_magic); } } while (!eosaf && (rtype != R_RESTART)); } /* The last record we read was a RESTART one: Print it */ if (!eosaf && (record_hdr[curr].record_type == R_RESTART)) { sar_print_special(curr, tm_start.use, tm_end.use, R_RESTART, ifd, from_file, &file_magic); } } while (!eosaf); close(ifd); free(file_actlst); }