/* *************************************************************************** * Read next sample statistics. If it's a special record (RESTART or COMMENT) * then display it if requested. Also fill timestamps structures. * * IN: * @ifd File descriptor * @action Flags indicating if special records should be displayed or not. * * @curr Index in array for current sample statistics. * @file System activity data file name (name of file being read). * @rtype Record type (RESTART, COMMENT, etc.) * @tab Number of tabulations to print. * @file_actlst List of (known or unknown) activities in file. * @file_magic System activity file magic header. * @rectime Structure where timestamp (expressed in local time or in UTC * depending on whether options -T/-t have been used or not) can * be saved for current record. * @loctime Structure where timestamp (expressed in local time) can be * saved for current record. * * OUT: * @rectime Structure where timestamp (expressed in local time or in UTC * depending on whether options -T/-t have been used or not) has * been saved for current record. * @loctime Structure where timestamp (expressed in local time) has been * saved for current record. * * RETURNS: * TRUE if end of file has been reached. *************************************************************************** */ int read_next_sample(int ifd, int action, int curr, char *file, int *rtype, int tab, struct file_magic *file_magic, struct file_activity *file_actlst, struct tm *rectime, struct tm *loctime) { int eosaf; /* Read current record */ eosaf = sa_fread(ifd, &record_hdr[curr], RECORD_HEADER_SIZE, SOFT_SIZE); *rtype = record_hdr[curr].record_type; if (!eosaf) { if (*rtype == R_COMMENT) { if (action & IGNORE_COMMENT) { /* Ignore COMMENT record */ if (lseek(ifd, MAX_COMMENT_LEN, SEEK_CUR) < MAX_COMMENT_LEN) { perror("lseek"); } } else { /* Display COMMENT record */ print_special_record(curr, tm_start.use, tm_end.use, *rtype, ifd, rectime, loctime, file, tab, file_magic); } } else if (*rtype == R_RESTART) { if (action & IGNORE_RESTART) { /* * Ignore RESTART record (don't display it) * but anyway we have to reallocate volatile * activities structures (unless we don't want to * do it now). */ if (!(action & DONT_READ_VOLATILE)) { read_vol_act_structures(ifd, act, file, file_magic, file_hdr.sa_vol_act_nr); } } else { /* Display RESTART record */ print_special_record(curr, tm_start.use, tm_end.use, *rtype, ifd, rectime, loctime, file, tab, file_magic); } } else { /* * OK: Previous record was not a special one. * So read now the extra fields. */ read_file_stat_bunch(act, curr, ifd, file_hdr.sa_act_nr, file_actlst); sa_get_record_timestamp_struct(flags, &record_hdr[curr], rectime, loctime); } } return eosaf; }
/* *************************************************************************** * Display file contents in selected format (logic #2). * Logic #2: Grouped by activity. Sorted by timestamp. Stop on RESTART * records. * Formats: ppc, CSV * * IN: * @ifd File descriptor of input file. * @file_actlst List of (known or unknown) activities in file. * @cpu_nr Number of processors for current activity data file. * @rectime Structure where timestamp (expressed in local time or in UTC * depending on whether options -T/-t have been used or not) can * be saved for current record. * @loctime Structure where timestamp (expressed in local time) can be * saved for current record. * @file Name of file being read. * @file_magic file_magic structure filled with file magic header data. *************************************************************************** */ void logic2_display_loop(int ifd, struct file_activity *file_actlst, __nr_t cpu_nr, struct tm *rectime, struct tm *loctime, char *file, struct file_magic *file_magic) { int i, p; int curr = 1, rtype; int eosaf = TRUE, reset = FALSE; long cnt = 1; off_t fpos; /* 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 (read_next_sample(ifd, IGNORE_NOTHING, 0, file, &rtype, 0, file_magic, file_actlst, rectime, loctime)) /* End of sa data file */ return; } while ((rtype == R_RESTART) || (rtype == R_COMMENT) || (tm_start.use && (datecmp(loctime, &tm_start) < 0)) || (tm_end.use && (datecmp(loctime, &tm_end) >= 0))); /* Save the first stats collected. Used for example in next_slice() function */ copy_structures(act, id_seq, record_hdr, 2, 0); /* Set flag to reset last_uptime variable. Should be done after a LINUX RESTART record */ reset = TRUE; /* 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 */ if (DISPLAY_HORIZONTALLY(flags)) { /* * If stats are displayed horizontally, then all activities * are printed on the same line. */ rw_curr_act_stats(ifd, fpos, &curr, &cnt, &eosaf, ALL_ACTIVITIES, &reset, file_actlst, cpu_nr, rectime, loctime, file, file_magic); } else { /* For each requested activity... */ for (i = 0; i < NR_ACT; i++) { if (!id_seq[i]) continue; p = get_activity_position(act, id_seq[i], EXIT_IF_NOT_FOUND); if (!IS_SELECTED(act[p]->options)) continue; if (!HAS_MULTIPLE_OUTPUTS(act[p]->options)) { rw_curr_act_stats(ifd, fpos, &curr, &cnt, &eosaf, act[p]->id, &reset, file_actlst, cpu_nr, rectime, loctime, file, file_magic); } else { unsigned int optf, msk; optf = act[p]->opt_flags; for (msk = 1; msk < 0x100; msk <<= 1) { if ((act[p]->opt_flags & 0xff) & msk) { act[p]->opt_flags &= (0xffffff00 + msk); rw_curr_act_stats(ifd, fpos, &curr, &cnt, &eosaf, act[p]->id, &reset, file_actlst, cpu_nr, rectime, loctime, file, file_magic); act[p]->opt_flags = optf; } } } } } if (!cnt) { /* Go to next Linux restart, if possible */ do { eosaf = read_next_sample(ifd, IGNORE_RESTART | DONT_READ_VOLATILE, curr, file, &rtype, 0, file_magic, file_actlst, rectime, loctime); } while (!eosaf && (rtype != R_RESTART)); } /* * The last record we read was a RESTART one: Print it. * NB: Unlike COMMENTS records (which are displayed for each * activity), RESTART ones are only displayed once. */ if (!eosaf && (record_hdr[curr].record_type == R_RESTART)) { print_special_record(&record_hdr[curr], flags, &tm_start, &tm_end, R_RESTART, ifd, rectime, loctime, file, 0, file_magic, &file_hdr, act, fmt[f_position]); } } while (!eosaf); }