struct report_format pcp_fmt = {
.id = F_PCP_OUTPUT,
.options = FO_HEADER_ONLY + FO_LOCAL_TIME + FO_NO_TRUE_TIME +
- FO_ITEM_LIST,
+ FO_ITEM_LIST + FO_FULL_ORDER,
.f_header = print_pcp_header,
.f_statistics = print_pcp_statistics,
.f_timestamp = print_pcp_timestamp,
- .f_restart = NULL,
+ .f_restart = print_pcp_restart,
.f_comment = NULL,
.f_display = logic1_display_loop
};
/*
* This function displays the restart messages.
*/
- __printf_funct_t (*f_restart) (int *, int, char *, char *, int, struct file_header *);
+ __printf_funct_t (*f_restart) (int *, int, char *, char *, int,
+ struct file_header *, struct record_header *);
/*
* This function displays the comments.
*/
struct tm *, struct tm *, void *);
};
+
/* Possible actions for functions used to display reports */
#define F_BEGIN 0x01
#define F_MAIN 0x02
void print_sar_comment
(int *, int, char *, char *, int, char *, struct file_header *);
__printf_funct_t print_sar_restart
- (int *, int, char *, char *, int, struct file_header *);
+ (int *, int, char *, char *, int, struct file_header *, struct record_header *);
int print_special_record
(struct record_header *, unsigned int, struct tstamp *, struct tstamp *,
int, int, struct tm *, struct tm *, char *, int, struct file_magic *,
if (*ofmt->f_restart) {
(*ofmt->f_restart)(&tab, F_MAIN, cur_date, cur_time,
!PRINT_LOCAL_TIME(l_flags) &&
- !PRINT_TRUE_TIME(l_flags), file_hdr);
+ !PRINT_TRUE_TIME(l_flags), file_hdr, record_hdr);
}
}
else if (rtype == R_COMMENT) {
{
int curr, rtype, tab = 0;
int eosaf, next, reset = FALSE;
+ int ign_flag = IGNORE_COMMENT + IGNORE_RESTART;
long cnt = 1;
char *pcparchive = (char *) dparm;
/* No record to display */
return;
}
-
/* Save current file position */
seek_file_position(ifd, DO_SAVE);
&file_hdr, act, id_seq, file_actlst);
}
+ if (ORDER_ALL_RECORDS(fmt[f_position]->options)) {
+ ign_flag = IGNORE_NOTHING;
+
+ /* RESTART and COMMENTS records will be immediately processed */
+ if (*fmt[f_position]->f_restart) {
+ (*fmt[f_position]->f_restart)(&tab, F_BEGIN, NULL, NULL, FALSE,
+ &file_hdr, NULL);
+ }
+ if (DISPLAY_COMMENT(flags) && (*fmt[f_position]->f_comment)) {
+ (*fmt[f_position]->f_comment)(&tab, F_BEGIN, NULL, NULL, 0, NULL,
+ &file_hdr);
+ }
+ }
+
/* Process activities */
if (*fmt[f_position]->f_statistics) {
(*fmt[f_position]->f_statistics)(&tab, F_BEGIN, act, id_seq);
do {
/*
* If this record is a special (RESTART or COMMENT) one,
- * skip it and try to read the next record in file.
+ * process it then try to read the next record in file.
*/
do {
- eosaf = read_next_sample(ifd, IGNORE_COMMENT | IGNORE_RESTART, 0,
- file, &rtype, tab, file_magic, file_actlst,
+ eosaf = read_next_sample(ifd, ign_flag, 0, file,
+ &rtype, tab, file_magic, file_actlst,
rectime, loctime, UEOF_STOP);
}
while (!eosaf && ((rtype == R_RESTART) || (rtype == R_COMMENT) ||
if (!eosaf) {
do {
- eosaf = read_next_sample(ifd, IGNORE_COMMENT | IGNORE_RESTART, curr,
- file, &rtype, tab, file_magic, file_actlst,
+ eosaf = read_next_sample(ifd, ign_flag, curr, file,
+ &rtype, tab, file_magic, file_actlst,
rectime, loctime, UEOF_CONT);
if (!eosaf && (rtype != R_COMMENT) && (rtype != R_RESTART)) {
if (!cnt) {
/* Go to next Linux restart, if possible */
do {
- eosaf = read_next_sample(ifd, IGNORE_COMMENT | IGNORE_RESTART, curr,
- file, &rtype, tab, file_magic, file_actlst,
+ eosaf = read_next_sample(ifd, ign_flag, curr, file,
+ &rtype, tab, file_magic, file_actlst,
rectime, loctime, UEOF_CONT);
}
while (!eosaf && (rtype != R_RESTART));
(*fmt[f_position]->f_statistics)(&tab, F_END, act, id_seq);
}
+ if (ign_flag == IGNORE_NOTHING) {
+ /*
+ * RESTART and COMMENT records have already been processed.
+ * Display possible trailing data then terminate.
+ */
+ if (*fmt[f_position]->f_restart) {
+ (*fmt[f_position]->f_restart)(&tab, F_END, NULL, NULL,
+ FALSE, &file_hdr, NULL);
+ }
+ if (DISPLAY_COMMENT(flags) && (*fmt[f_position]->f_comment)) {
+ (*fmt[f_position]->f_comment)(&tab, F_END, NULL, NULL, 0, NULL,
+ &file_hdr);
+ }
+ goto terminate;
+ }
+
/* Rewind file */
seek_file_position(ifd, DO_RESTORE);
/* Process now RESTART entries to display restart messages */
if (*fmt[f_position]->f_restart) {
(*fmt[f_position]->f_restart)(&tab, F_BEGIN, NULL, NULL, FALSE,
- &file_hdr);
+ &file_hdr, NULL);
}
do {
while (!eosaf);
if (*fmt[f_position]->f_restart) {
- (*fmt[f_position]->f_restart)(&tab, F_END, NULL, NULL, FALSE, &file_hdr);
+ (*fmt[f_position]->f_restart)(&tab, F_END, NULL, NULL, FALSE, &file_hdr, NULL);
}
/* Rewind file */
}
}
+terminate:
/* Print header trailer */
if (*fmt[f_position]->f_header) {
(*fmt[f_position]->f_header)(&tab, F_END, pcparchive, file_magic,
*/
#define FO_ITEM_LIST 0x200
+/*
+ * Indicate that all the records, including RESTART and COMMENT ones,
+ * should be displayed in order of time.
+ */
+#define FO_FULL_ORDER 0x400
+
#define SET_LC_NUMERIC_C(m) (((m) & FO_LC_NUMERIC_C) == FO_LC_NUMERIC_C)
#define ACCEPT_HEADER_ONLY(m) (((m) & FO_HEADER_ONLY) == FO_HEADER_ONLY)
#define ACCEPT_BAD_FILE_FORMAT(m) (((m) & FO_BAD_FILE_FORMAT) == FO_BAD_FILE_FORMAT)
#define TEST_MARKUP(m) (((m) & FO_TEST_MARKUP) == FO_TEST_MARKUP)
#define REJECT_TRUE_TIME(m) (((m) & FO_NO_TRUE_TIME) == FO_NO_TRUE_TIME)
#define CREATE_ITEM_LIST(m) (((m) & FO_ITEM_LIST) == FO_ITEM_LIST)
+#define ORDER_ALL_RECORDS(m) (((m) & FO_FULL_ORDER) == FO_FULL_ORDER)
/*
* Prototypes used to display restart messages
*/
__printf_funct_t print_db_restart
- (int *, int, char *, char *, int, struct file_header *);
+ (int *, int, char *, char *, int, struct file_header *, struct record_header *);
__printf_funct_t print_ppc_restart
- (int *, int, char *, char *, int, struct file_header *);
+ (int *, int, char *, char *, int, struct file_header *, struct record_header *);
__printf_funct_t print_xml_restart
- (int *, int, char *, char *, int, struct file_header *);
+ (int *, int, char *, char *, int, struct file_header *, struct record_header *);
__printf_funct_t print_json_restart
- (int *, int, char *, char *, int, struct file_header *);
+ (int *, int, char *, char *, int, struct file_header *, struct record_header *);
__printf_funct_t print_raw_restart
- (int *, int, char *, char *, int, struct file_header *);
+ (int *, int, char *, char *, int, struct file_header *, struct record_header *);
+__printf_funct_t print_pcp_restart
+ (int *, int, char *, char *, int, struct file_header *, struct record_header *);
/*
* Prototypes used to display comments
extern int palette;
extern unsigned int svg_colors[][SVG_COL_PALETTE_SIZE];
+/*
+ ***************************************************************************
+ * Flush data to PCP archive.
+ *
+ * IN:
+ * @record_hdr Record header for current sample.
+ * @flags Flags for common options.
+ ***************************************************************************
+ */
+void pcp_write_data(struct record_header *record_hdr, unsigned int flags)
+{
+#ifdef HAVE_PCP
+ int rc;
+ struct tm lrectime;
+ unsigned long long utc_sec = record_hdr->ust_time;
+ static long long delta_utc = LONG_MAX;
+
+ if (!PRINT_LOCAL_TIME(flags)) {
+ if (delta_utc == LONG_MAX) {
+ /* Convert a time_t value from local time to UTC */
+ if (gmtime_r((const time_t *) &(record_hdr->ust_time), &lrectime)) {
+ utc_sec = mktime(&lrectime);
+ delta_utc = utc_sec - record_hdr->ust_time;
+ }
+ }
+ else {
+ /*
+ * Once pmiWrite() has been called (after the first stats sample),
+ * subsequent mktime() calls will not give the same result with
+ * the same input data. So compute a time shift that will be used
+ * for the next samples.
+ * We should (really) be careful if pmiWrite() was to be used sooner
+ * than for the first stats sample (e.g. if we want to save a
+ * LINUX RESTART record heading the file).
+ */
+ utc_sec += delta_utc;
+ }
+ }
+
+ /* Write data to PCP archive */
+ if ((rc = pmiWrite(utc_sec, 0)) < 0) {
+ fprintf(stderr, "PCP: pmiWrite: %s\n", pmiErrStr(rc));
+ exit(4);
+ }
+#endif
+}
+
/*
***************************************************************************
* Display restart messages (database and ppc formats).
* @cur_time Time string of current restart message.
* @utc True if @cur_time is expressed in UTC.
* @file_hdr System activity file standard header.
+ * @record_hdr Current record header (unused here).
***************************************************************************
*/
__printf_funct_t print_db_restart(int *tab, int action, char *cur_date,
- char *cur_time, int utc, struct file_header *file_hdr)
+ char *cur_time, int utc, struct file_header *file_hdr,
+ struct record_header *record_hdr)
{
/* Actions F_BEGIN and F_END ignored */
if (action == F_MAIN) {
* @cur_time Time string of current restart message.
* @utc True if @cur_time is expressed in UTC.
* @file_hdr System activity file standard header.
+ * @record_hdr Current record header (unused here).
***************************************************************************
*/
__printf_funct_t print_ppc_restart(int *tab, int action, char *cur_date,
- char *cur_time, int utc, struct file_header *file_hdr)
+ char *cur_time, int utc, struct file_header *file_hdr,
+ struct record_header *record_hdr)
{
/* Actions F_BEGIN and F_END ignored */
if (action == F_MAIN) {
* @cur_time Time string of current restart message.
* @utc True if @cur_time is expressed in UTC.
* @file_hdr System activity file standard header.
+ * @record_hdr Current record header (unused here).
*
* OUT:
* @tab Number of tabulations.
***************************************************************************
*/
__printf_funct_t print_xml_restart(int *tab, int action, char *cur_date,
- char *cur_time, int utc, struct file_header *file_hdr)
+ char *cur_time, int utc, struct file_header *file_hdr,
+ struct record_header *record_hdr)
{
if (action & F_BEGIN) {
xprintf((*tab)++, "<restarts>");
* @cur_time Time string of current restart message.
* @utc True if @cur_time is expressed in UTC.
* @file_hdr System activity file standard header.
+ * @record_hdr Current record header (unused here).
*
* OUT:
* @tab Number of tabulations.
***************************************************************************
*/
__printf_funct_t print_json_restart(int *tab, int action, char *cur_date,
- char *cur_time, int utc, struct file_header *file_hdr)
+ char *cur_time, int utc, struct file_header *file_hdr,
+ struct record_header *record_hdr)
{
static int sep = FALSE;
* @cur_time Time string of current restart message.
* @utc True if @cur_time is expressed in UTC.
* @file_hdr System activity file standard header.
+ * @record_hdr Current record header (unused here).
***************************************************************************
*/
__printf_funct_t print_raw_restart(int *tab, int action, char *cur_date,
- char *cur_time, int utc, struct file_header *file_hdr)
+ char *cur_time, int utc, struct file_header *file_hdr,
+ struct record_header *record_hdr)
{
/* Actions F_BEGIN and F_END ignored */
if (action == F_MAIN) {
}
}
+/*
+ ***************************************************************************
+ * Display restart messages (PCP format).
+ *
+ * IN:
+ * @tab Number of tabulations (unused here).
+ * @action Action expected from current function.
+ * @cur_date Date string of current restart message (unused here).
+ * @cur_time Time string of current restart message (unused here).
+ * @utc True if @cur_time is expressed in UTC (unused here).
+ * @file_hdr System activity file standard header.
+ * @record_hdr Current record header.
+ ***************************************************************************
+ */
+__printf_funct_t print_pcp_restart(int *tab, int action, char *cur_date, char *cur_time,
+ int utc, struct file_header *file_hdr,
+ struct record_header *record_hdr)
+{
+#ifdef HAVE_PCP
+ static int def_metrics = FALSE;
+ int rc;
+ char buf[64];
+
+ if (action & F_BEGIN) {
+ if (!def_metrics) {
+ pmiAddMetric("system.restart.count",
+ PM_IN_NULL, PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_DISCRETE,
+ pmiUnits(0, 0, 1, 0, 0, PM_COUNT_ONE));
+
+ pmiAddMetric("system.restart.ncpu",
+ PM_IN_NULL, PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_DISCRETE,
+ pmiUnits(0, 0, 1, 0, 0, PM_COUNT_ONE));
+
+ def_metrics = TRUE;
+ }
+ }
+ if (action & F_MAIN) {
+ if ((rc = pmiPutValue("system.restart.count", NULL, "1")) < 0) {
+ fprintf(stderr, "PCP: pmiPutValue 1: %s\n", pmiErrStr(rc));
+ }
+
+ snprintf(buf, sizeof(buf), "%u",
+ file_hdr->sa_cpu_nr > 1 ? file_hdr->sa_cpu_nr - 1 : 1);
+ if ((rc = pmiPutValue("system.restart.ncpu", NULL, buf)) < 0) {
+ fprintf(stderr, "PCP: pmiPutValue 2: %s\n", pmiErrStr(rc));
+ }
+
+ /* Write data to PCP archive */
+ pcp_write_data(record_hdr, flags);
+ }
+#endif /* HAVE_PCP */
+}
+
/*
***************************************************************************
* Display comments (database and ppc formats).
* @itv Interval of time with preceding record (unused here).
* @record_hdr Record header for current sample.
* @file_hdr System activity file standard header (unused here).
- * @flags Flags for common options (unused here).
+ * @flags Flags for common options.
*
* RETURNS:
* Pointer on the "timestamp" string.
struct record_header *record_hdr,
struct file_header *file_hdr, unsigned int flags)
{
-#ifdef HAVE_PCP
- int rc;
- struct tm lrectime;
- unsigned long long utc_sec = record_hdr->ust_time;
- static long long delta_utc = LONG_MAX;
-
if (action & F_END) {
- if (!PRINT_LOCAL_TIME(flags)) {
- if (delta_utc == LONG_MAX) {
- /* Convert a time_t value from local time to UTC */
- if (gmtime_r((const time_t *) &(record_hdr->ust_time), &lrectime)) {
- utc_sec = mktime(&lrectime);
- delta_utc = utc_sec - record_hdr->ust_time;
- }
- }
- else {
- /*
- * Once pmiWrite() has been called (after the first stats sample),
- * subsequent mktime() calls will not give the same result with
- * the same input data. So compute a time shift that will be used
- * for the next samples.
- * We should (really) be careful if pmiWrite() was to be used sooner
- * than for the first stats sample (e.g. if we want to save a
- * LINUX RESTART record heading the file).
- */
- utc_sec += delta_utc;
- }
- }
-
- /* Write data to PCP archive */
- if ((rc = pmiWrite(utc_sec, 0)) < 0) {
- fprintf(stderr, "PCP: pmiWrite: %s\n", pmiErrStr(rc));
- exit(4);
- }
+ pcp_write_data(record_hdr, flags);
}
-#endif
+
return NULL;
}
* @cur_time Time string of current restart message.
* @utc True if @cur_time is expressed in UTC (unused here).
* @file_hdr System activity file standard header.
+ * @record_hdr Current record header (unused here).
***************************************************************************
*/
__printf_funct_t print_sar_restart(int *tab, int action, char *cur_date, char *cur_time,
- int utc, struct file_header *file_hdr)
+ int utc, struct file_header *file_hdr,
+ struct record_header *record_hdr)
{
char restart[64];