]> granicus.if.org Git - sysstat/commitdiff
sadf: PCP: Save RESTART records in PCP archive
authorSebastien GODARD <sysstat@users.noreply.github.com>
Sat, 13 Apr 2019 09:28:35 +0000 (11:28 +0200)
committerSebastien GODARD <sysstat@users.noreply.github.com>
Sat, 13 Apr 2019 09:28:35 +0000 (11:28 +0200)
Signed-off-by: Sebastien GODARD <sysstat@users.noreply.github.com>
format.c
sa.h
sa_common.c
sadf.c
sadf.h
sadf_misc.c
sar.c

index 64c578a585882e308699beda0949c1eebd140c75..37dce19b0c8aec43f81409d34b2c1dce1ba70f72 100644 (file)
--- a/format.c
+++ b/format.c
@@ -156,11 +156,11 @@ struct report_format raw_fmt = {
 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
 };
diff --git a/sa.h b/sa.h
index 9d6f1b84c39b8e383f9ae300bb2a88c974382b29..52ad70b262466a645d0d15afa41467ef1148980d 100644 (file)
--- a/sa.h
+++ b/sa.h
@@ -1033,7 +1033,8 @@ struct report_format {
        /*
         * 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.
         */
@@ -1045,6 +1046,7 @@ struct report_format {
                           struct tm *, struct tm *, void *);
 };
 
+
 /* Possible actions for functions used to display reports */
 #define F_BEGIN        0x01
 #define F_MAIN 0x02
@@ -1390,7 +1392,7 @@ void print_report_hdr
 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 *,
index 08f097afcdf40b9d32255711391b255d402cd7fa..7941efa0a871c5a2bdea95305bf134405c9a424e 100644 (file)
@@ -2908,7 +2908,7 @@ int print_special_record(struct record_header *record_hdr, unsigned int l_flags,
                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) {
diff --git a/sadf.c b/sadf.c
index e19cb85f8d84179c9f3462a2b5dc9992e4a0f061..fe3062c9d20e409dbe6f6bcd751d7d606785c187 100644 (file)
--- a/sadf.c
+++ b/sadf.c
@@ -1022,6 +1022,7 @@ void logic1_display_loop(int ifd, char *file, struct file_activity *file_actlst,
 {
        int curr, rtype, tab = 0;
        int eosaf, next, reset = FALSE;
+       int ign_flag = IGNORE_COMMENT + IGNORE_RESTART;
        long cnt = 1;
        char *pcparchive = (char *) dparm;
 
@@ -1031,7 +1032,6 @@ void logic1_display_loop(int ifd, char *file, struct file_activity *file_actlst,
                        /* No record to display */
                        return;
        }
-
        /* Save current file position */
        seek_file_position(ifd, DO_SAVE);
 
@@ -1041,6 +1041,20 @@ void logic1_display_loop(int ifd, char *file, struct file_activity *file_actlst,
                                             &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);
@@ -1049,11 +1063,11 @@ void logic1_display_loop(int ifd, char *file, struct file_activity *file_actlst,
        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) ||
@@ -1069,8 +1083,8 @@ void logic1_display_loop(int ifd, char *file, struct file_activity *file_actlst,
 
                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)) {
@@ -1097,8 +1111,8 @@ void logic1_display_loop(int ifd, char *file, struct file_activity *file_actlst,
                        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));
@@ -1112,13 +1126,29 @@ void logic1_display_loop(int ifd, char *file, struct file_activity *file_actlst,
                (*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 {
@@ -1129,7 +1159,7 @@ void logic1_display_loop(int ifd, char *file, struct file_activity *file_actlst,
        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 */
@@ -1154,6 +1184,7 @@ void logic1_display_loop(int ifd, char *file, struct file_activity *file_actlst,
                }
        }
 
+terminate:
        /* Print header trailer */
        if (*fmt[f_position]->f_header) {
                (*fmt[f_position]->f_header)(&tab, F_END, pcparchive, file_magic,
diff --git a/sadf.h b/sadf.h
index 7e96abdd1d852c6f72678ddfe602c73c74cec70a..6736792070523747782be53baf09eaf5b0eed57a 100644 (file)
--- a/sadf.h
+++ b/sadf.h
  */
 #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)
 
 
 /*
@@ -127,15 +134,17 @@ void convert_file
  * 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
index 8d07038bc640e7c20b2ee7df044bd4e1b7922833..10e575dd17c5871877e02114cd9746b7b853e6f2 100644 (file)
@@ -47,6 +47,53 @@ extern char *seps[];
 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).
@@ -85,10 +132,12 @@ void print_dbppc_restart(char *cur_date, char *cur_time, int utc, char sep,
  * @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) {
@@ -107,10 +156,12 @@ __printf_funct_t print_db_restart(int *tab, int action, char *cur_date,
  * @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) {
@@ -129,13 +180,15 @@ __printf_funct_t print_ppc_restart(int *tab, int action, char *cur_date,
  * @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>");
@@ -161,13 +214,15 @@ __printf_funct_t print_xml_restart(int *tab, int action, char *cur_date,
  * @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;
 
@@ -206,10 +261,12 @@ __printf_funct_t print_json_restart(int *tab, int action, char *cur_date,
  * @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) {
@@ -222,6 +279,59 @@ __printf_funct_t print_raw_restart(int *tab, int action, char *cur_date,
        }
 }
 
+/*
+ ***************************************************************************
+ * 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).
@@ -853,7 +963,7 @@ __tm_funct_t print_raw_timestamp(void *parm, int action, char *cur_date,
  * @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.
@@ -864,42 +974,10 @@ __tm_funct_t print_pcp_timestamp(void *parm, int action, char *cur_date,
                                 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;
 }
 
diff --git a/sar.c b/sar.c
index e19b115ae8cf1b5cb66728d0b595e31f93beacfa..b7315ae1a0e154dfdff4659436e5fbc1a13f4195 100644 (file)
--- a/sar.c
+++ b/sar.c
@@ -602,10 +602,12 @@ int sa_read(void *buffer, size_t size)
  * @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];