"Fossies" - the Fresh Open Source Software Archive

Member "sysstat-12.4.1/sadf_misc.c" (21 Nov 2020, 51349 Bytes) of package /linux/misc/sysstat-12.4.1.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "sadf_misc.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 12.2.3_vs_12.4.0.

    1 /*
    2  * sadf_misc.c: Funtions used by sadf to display special records
    3  * (C) 2011-2020 by Sebastien GODARD (sysstat <at> orange.fr)
    4  *
    5  ***************************************************************************
    6  * This program is free software; you can redistribute it and/or modify it *
    7  * under the terms of the GNU General Public License as published  by  the *
    8  * Free Software Foundation; either version 2 of the License, or (at  your *
    9  * option) any later version.                                              *
   10  *                                                                         *
   11  * This program is distributed in the hope that it  will  be  useful,  but *
   12  * WITHOUT ANY WARRANTY; without the implied warranty  of  MERCHANTABILITY *
   13  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
   14  * for more details.                                                       *
   15  *                                                                         *
   16  * You should have received a copy of the GNU General Public License along *
   17  * with this program; if not, write to the Free Software Foundation, Inc., *
   18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA              *
   19  ***************************************************************************
   20  */
   21 
   22 #include <stdio.h>
   23 #include <string.h>
   24 #include <time.h>
   25 
   26 #include "sadf.h"
   27 #include "pcp_def_metrics.h"
   28 
   29 #ifdef USE_NLS
   30 #include <locale.h>
   31 #include <libintl.h>
   32 #define _(string) gettext(string)
   33 #else
   34 #define _(string) (string)
   35 #endif
   36 
   37 #ifdef HAVE_PCP
   38 #include <pcp/pmapi.h>
   39 #include <pcp/import.h>
   40 #endif
   41 
   42 extern char *tzname[2];
   43 
   44 extern unsigned int flags;
   45 extern char *seps[];
   46 
   47 extern int palette;
   48 extern unsigned int svg_colors[][SVG_COL_PALETTE_SIZE];
   49 
   50 /*
   51  ***************************************************************************
   52  * Flush data to PCP archive.
   53  *
   54  * IN:
   55  * @record_hdr  Record header for current sample.
   56  * @flags   Flags for common options.
   57  ***************************************************************************
   58  */
   59 void pcp_write_data(struct record_header *record_hdr, unsigned int flags)
   60 {
   61 #ifdef HAVE_PCP
   62     int rc;
   63     struct tm lrectime;
   64     unsigned long long utc_sec = record_hdr->ust_time;
   65     static long long delta_utc = LONG_MAX;
   66 
   67     if (!PRINT_LOCAL_TIME(flags)) {
   68         if (delta_utc == LONG_MAX) {
   69             /* Convert a time_t value from local time to UTC */
   70             if (gmtime_r((const time_t *) &(record_hdr->ust_time), &lrectime)) {
   71                 utc_sec = mktime(&lrectime);
   72                 delta_utc = utc_sec - record_hdr->ust_time;
   73             }
   74         }
   75         else {
   76             /*
   77              * Once pmiWrite() has been called (after the first stats sample),
   78              * subsequent mktime() calls will not give the same result with
   79              * the same input data. So compute a time shift that will be used
   80              * for the next samples.
   81              * We should (really) be careful if pmiWrite() was to be used sooner
   82              * than for the first stats sample (e.g. if we want to save a
   83              * LINUX RESTART record heading the file).
   84              */
   85             utc_sec += delta_utc;
   86         }
   87     }
   88 
   89     /* Write data to PCP archive */
   90     if ((rc = pmiWrite(utc_sec, 0)) < 0) {
   91         fprintf(stderr, "PCP: pmiWrite: %s\n", pmiErrStr(rc));
   92         exit(4);
   93     }
   94 #endif
   95 }
   96 
   97 /*
   98  ***************************************************************************
   99  * Display restart messages (database and ppc formats).
  100  *
  101  * IN:
  102  * @cur_date    Date string of current restart message.
  103  * @cur_time    Time string of current restart message.
  104  * @utc     True if @cur_time is expressed in UTC.
  105  * @sep     Character used as separator.
  106  * @file_hdr    System activity file standard header.
  107  ***************************************************************************
  108  */
  109 void print_dbppc_restart(char *cur_date, char *cur_time, int utc, char sep,
  110              struct file_header *file_hdr)
  111 {
  112     printf("%s%c-1%c", file_hdr->sa_nodename, sep, sep);
  113     if (strlen(cur_date)) {
  114         printf("%s ", cur_date);
  115     }
  116     printf("%s", cur_time);
  117     if (strlen(cur_date) && utc) {
  118         printf(" UTC");
  119     }
  120     printf("%cLINUX-RESTART\t(%d CPU)\n",
  121            sep, file_hdr->sa_cpu_nr > 1 ? file_hdr->sa_cpu_nr - 1 : 1);
  122 }
  123 
  124 /*
  125  ***************************************************************************
  126  * Display restart messages (ppc format).
  127  *
  128  * IN:
  129  * @tab     Number of tabulations (unused here).
  130  * @action  Action expected from current function.
  131  * @cur_date    Date string of current restart message.
  132  * @cur_time    Time string of current restart message.
  133  * @utc     True if @cur_time is expressed in UTC.
  134  * @file_hdr    System activity file standard header.
  135  * @record_hdr  Current record header (unused here).
  136  ***************************************************************************
  137  */
  138 __printf_funct_t print_db_restart(int *tab, int action, char *cur_date,
  139                   char *cur_time, int utc, struct file_header *file_hdr,
  140                   struct record_header *record_hdr)
  141 {
  142     /* Actions F_BEGIN and F_END ignored */
  143     if (action == F_MAIN) {
  144         print_dbppc_restart(cur_date, cur_time, utc, ';', file_hdr);
  145     }
  146 }
  147 
  148 /*
  149  ***************************************************************************
  150  * Display restart messages (database format).
  151  *
  152  * IN:
  153  * @tab     Number of tabulations (unused here).
  154  * @action  Action expected from current function.
  155  * @cur_date    Date string of current restart message.
  156  * @cur_time    Time string of current restart message.
  157  * @utc     True if @cur_time is expressed in UTC.
  158  * @file_hdr    System activity file standard header.
  159  * @record_hdr  Current record header (unused here).
  160  ***************************************************************************
  161  */
  162 __printf_funct_t print_ppc_restart(int *tab, int action, char *cur_date,
  163                    char *cur_time, int utc, struct file_header *file_hdr,
  164                    struct record_header *record_hdr)
  165 {
  166     /* Actions F_BEGIN and F_END ignored */
  167     if (action == F_MAIN) {
  168         print_dbppc_restart(cur_date, cur_time, utc, '\t', file_hdr);
  169     }
  170 }
  171 
  172 /*
  173  ***************************************************************************
  174  * Display restart messages (XML format).
  175  *
  176  * IN:
  177  * @tab     Number of tabulations.
  178  * @action  Action expected from current function.
  179  * @cur_date    Date string of current restart message.
  180  * @cur_time    Time string of current restart message.
  181  * @utc     True if @cur_time is expressed in UTC.
  182  * @file_hdr    System activity file standard header.
  183  * @record_hdr  Current record header (unused here).
  184  *
  185  * OUT:
  186  * @tab     Number of tabulations.
  187  ***************************************************************************
  188  */
  189 __printf_funct_t print_xml_restart(int *tab, int action, char *cur_date,
  190                    char *cur_time, int utc, struct file_header *file_hdr,
  191                    struct record_header *record_hdr)
  192 {
  193     if (action & F_BEGIN) {
  194         xprintf((*tab)++, "<restarts>");
  195     }
  196     if (action & F_MAIN) {
  197         xprintf(*tab, "<boot date=\"%s\" time=\"%s\" utc=\"%d\" cpu_count=\"%d\"/>",
  198             cur_date, cur_time, utc ? 1 : 0,
  199             file_hdr->sa_cpu_nr > 1 ? file_hdr->sa_cpu_nr - 1 : 1);
  200     }
  201     if (action & F_END) {
  202         xprintf(--(*tab), "</restarts>");
  203     }
  204 }
  205 
  206 /*
  207  ***************************************************************************
  208  * Display restart messages (JSON format).
  209  *
  210  * IN:
  211  * @tab     Number of tabulations.
  212  * @action  Action expected from current function.
  213  * @cur_date    Date string of current restart message.
  214  * @cur_time    Time string of current restart message.
  215  * @utc     True if @cur_time is expressed in UTC.
  216  * @file_hdr    System activity file standard header.
  217  * @record_hdr  Current record header (unused here).
  218  *
  219  * OUT:
  220  * @tab     Number of tabulations.
  221  ***************************************************************************
  222  */
  223 __printf_funct_t print_json_restart(int *tab, int action, char *cur_date,
  224                     char *cur_time, int utc, struct file_header *file_hdr,
  225                     struct record_header *record_hdr)
  226 {
  227     static int sep = FALSE;
  228 
  229     if (action & F_BEGIN) {
  230         printf(",\n");
  231         xprintf((*tab)++, "\"restarts\": [");
  232     }
  233     if (action & F_MAIN) {
  234         if (sep) {
  235             printf(",\n");
  236         }
  237         xprintf((*tab)++, "{");
  238         xprintf(*tab, "\"boot\": {\"date\": \"%s\", \"time\": \"%s\", \"utc\": %d, \"cpu_count\": %d}",
  239             cur_date, cur_time, utc ? 1 : 0,
  240             file_hdr->sa_cpu_nr > 1 ? file_hdr->sa_cpu_nr - 1 : 1);
  241         xprintf0(--(*tab), "}");
  242         sep = TRUE;
  243     }
  244     if (action & F_END) {
  245         if (sep) {
  246             printf("\n");
  247             sep = FALSE;
  248         }
  249         xprintf0(--(*tab), "]");
  250     }
  251 }
  252 
  253 /*
  254  ***************************************************************************
  255  * Display restart messages (raw format).
  256  *
  257  * IN:
  258  * @tab     Number of tabulations (unused here).
  259  * @action  Action expected from current function.
  260  * @cur_date    Date string of current restart message.
  261  * @cur_time    Time string of current restart message.
  262  * @utc     True if @cur_time is expressed in UTC.
  263  * @file_hdr    System activity file standard header.
  264  * @record_hdr  Current record header (unused here).
  265  ***************************************************************************
  266  */
  267 __printf_funct_t print_raw_restart(int *tab, int action, char *cur_date,
  268                    char *cur_time, int utc, struct file_header *file_hdr,
  269                    struct record_header *record_hdr)
  270 {
  271     /* Actions F_BEGIN and F_END ignored */
  272     if (action == F_MAIN) {
  273         printf("%s", cur_time);
  274         if (strlen(cur_date) && utc) {
  275             printf(" UTC");
  276         }
  277         printf("; LINUX-RESTART (%d CPU)\n",
  278                file_hdr->sa_cpu_nr > 1 ? file_hdr->sa_cpu_nr - 1 : 1);
  279     }
  280 }
  281 
  282 /*
  283  ***************************************************************************
  284  * Display restart messages (PCP format).
  285  *
  286  * IN:
  287  * @tab     Number of tabulations (unused here).
  288  * @action  Action expected from current function.
  289  * @cur_date    Date string of current restart message (unused here).
  290  * @cur_time    Time string of current restart message (unused here).
  291  * @utc     True if @cur_time is expressed in UTC (unused here).
  292  * @file_hdr    System activity file standard header.
  293  * @record_hdr  Current record header.
  294  ***************************************************************************
  295  */
  296 __printf_funct_t print_pcp_restart(int *tab, int action, char *cur_date, char *cur_time,
  297                    int utc, struct file_header *file_hdr,
  298                    struct record_header *record_hdr)
  299 {
  300 #ifdef HAVE_PCP
  301     static int def_metrics = FALSE;
  302     char buf[64];
  303 
  304     if (action & F_BEGIN) {
  305         if (!def_metrics) {
  306             pmiAddMetric("system.restart.count",
  307                      PM_IN_NULL, PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_DISCRETE,
  308                      pmiUnits(0, 0, 1, 0, 0, PM_COUNT_ONE));
  309 
  310             pmiAddMetric("system.restart.ncpu",
  311                      PM_IN_NULL, PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_DISCRETE,
  312                      pmiUnits(0, 0, 1, 0, 0, PM_COUNT_ONE));
  313 
  314             def_metrics = TRUE;
  315         }
  316     }
  317     if (action & F_MAIN) {
  318         pmiPutValue("system.restart.count", NULL, "1");
  319 
  320         snprintf(buf, sizeof(buf), "%u",
  321              file_hdr->sa_cpu_nr > 1 ? file_hdr->sa_cpu_nr - 1 : 1);
  322         pmiPutValue("system.restart.ncpu", NULL, buf);
  323 
  324         /* Write data to PCP archive */
  325         pcp_write_data(record_hdr, flags);
  326     }
  327 #endif /* HAVE_PCP */
  328 }
  329 
  330 /*
  331  ***************************************************************************
  332  * Display comments (database and ppc formats).
  333  *
  334  * IN:
  335  * @cur_date    Date string of current restart message.
  336  * @cur_time    Time string of current restart message.
  337  * @utc     True if @cur_time is expressed in UTC.
  338  * @comment Comment to display.
  339  * @sep     Character used as separator.
  340  * @file_hdr    System activity file standard header.
  341  ***************************************************************************
  342  */
  343 void print_dbppc_comment(char *cur_date, char *cur_time, int utc,
  344              char *comment, char sep, struct file_header *file_hdr)
  345 {
  346     printf("%s%c-1%c", file_hdr->sa_nodename, sep, sep);
  347     if (strlen(cur_date)) {
  348         printf("%s ", cur_date);
  349     }
  350     printf("%s", cur_time);
  351     if (strlen(cur_date) && utc) {
  352         printf(" UTC");
  353     }
  354     printf("%cCOM %s\n", sep, comment);
  355 }
  356 
  357 /*
  358  ***************************************************************************
  359  * Display comments (database format).
  360  *
  361  * IN:
  362  * @tab     Number of tabulations (unused here).
  363  * @action  Action expected from current function.
  364  * @cur_date    Date string of current restart message.
  365  * @cur_time    Time string of current restart message.
  366  * @utc     True if @cur_time is expressed in UTC.
  367  * @comment Comment to display.
  368  * @file_hdr    System activity file standard header.
  369  * @record_hdr  Current record header (unused here).
  370  ***************************************************************************
  371  */
  372 __printf_funct_t print_db_comment(int *tab, int action, char *cur_date, char *cur_time,
  373                   int utc, char *comment, struct file_header *file_hdr,
  374                   struct record_header *record_hdr)
  375 {
  376     /* Actions F_BEGIN and F_END ignored */
  377     if (action & F_MAIN) {
  378         print_dbppc_comment(cur_date, cur_time, utc, comment,
  379                     ';', file_hdr);
  380     }
  381 }
  382 
  383 /*
  384  ***************************************************************************
  385  * Display comments (ppc format).
  386  *
  387  * IN:
  388  * @tab     Number of tabulations (unused here).
  389  * @action  Action expected from current function.
  390  * @cur_date    Date string of current restart message.
  391  * @cur_time    Time string of current restart message.
  392  * @utc     True if @cur_time is expressed in UTC.
  393  * @comment Comment to display.
  394  * @file_hdr    System activity file standard header.
  395  * @record_hdr  Current record header (unused here).
  396  ***************************************************************************
  397  */
  398 __printf_funct_t print_ppc_comment(int *tab, int action, char *cur_date, char *cur_time,
  399                    int utc, char *comment, struct file_header *file_hdr,
  400                    struct record_header *record_hdr)
  401 {
  402     /* Actions F_BEGIN and F_END ignored */
  403     if (action & F_MAIN) {
  404         print_dbppc_comment(cur_date, cur_time, utc, comment,
  405                     '\t', file_hdr);
  406     }
  407 }
  408 
  409 /*
  410  ***************************************************************************
  411  * Display comments (XML format).
  412  *
  413  * IN:
  414  * @tab     Number of tabulations.
  415  * @action  Action expected from current function.
  416  * @cur_date    Date string of current comment.
  417  * @cur_time    Time string of current comment.
  418  * @utc     True if @cur_time is expressed in UTC.
  419  * @comment Comment to display.
  420  * @file_hdr    System activity file standard header (unused here).
  421  * @record_hdr  Current record header (unused here).
  422  *
  423  * OUT:
  424  * @tab     Number of tabulations.
  425  ***************************************************************************
  426  */
  427 __printf_funct_t print_xml_comment(int *tab, int action, char *cur_date, char *cur_time,
  428                    int utc, char *comment, struct file_header *file_hdr,
  429                    struct record_header *record_hdr)
  430 {
  431     if (action & F_BEGIN) {
  432         xprintf((*tab)++, "<comments>");
  433     }
  434     if (action & F_MAIN) {
  435         xprintf(*tab, "<comment date=\"%s\" time=\"%s\" utc=\"%d\" com=\"%s\"/>",
  436             cur_date, cur_time, utc ? 1 : 0, comment);
  437     }
  438     if (action & F_END) {
  439         xprintf(--(*tab), "</comments>");
  440     }
  441 }
  442 
  443 /*
  444  ***************************************************************************
  445  * Display comments (JSON format).
  446  *
  447  * IN:
  448  * @tab     Number of tabulations.
  449  * @action  Action expected from current function.
  450  * @cur_date    Date string of current comment.
  451  * @cur_time    Time string of current comment.
  452  * @utc     True if @cur_time is expressed in UTC.
  453  * @comment Comment to display.
  454  * @file_hdr    System activity file standard header (unused here).
  455  * @record_hdr  Current record header (unused here).
  456  *
  457  * OUT:
  458  * @tab     Number of tabulations.
  459  ***************************************************************************
  460  */
  461 __printf_funct_t print_json_comment(int *tab, int action, char *cur_date, char *cur_time,
  462                     int utc, char *comment, struct file_header *file_hdr,
  463                     struct record_header *record_hdr)
  464 {
  465     static int sep = FALSE;
  466 
  467     if (action & F_BEGIN) {
  468         printf(",\n");
  469         xprintf((*tab)++, "\"comments\": [");
  470     }
  471     if (action & F_MAIN) {
  472         if (sep) {
  473             printf(",\n");
  474         }
  475         xprintf((*tab)++, "{");
  476         xprintf(*tab,
  477             "\"comment\": {\"date\": \"%s\", \"time\": \"%s\", "
  478             "\"utc\": %d, \"com\": \"%s\"}",
  479             cur_date, cur_time, utc ? 1 : 0, comment);
  480         xprintf0(--(*tab), "}");
  481         sep = TRUE;
  482     }
  483     if (action & F_END) {
  484         if (sep) {
  485             printf("\n");
  486             sep = FALSE;
  487         }
  488         xprintf0(--(*tab), "]");
  489     }
  490 }
  491 
  492 /*
  493  ***************************************************************************
  494  * Display comments (raw format).
  495  *
  496  * IN:
  497  * @tab     Number of tabulations (unused here).
  498  * @action  Action expected from current function.
  499  * @cur_date    Date string of current restart message.
  500  * @cur_time    Time string of current restart message.
  501  * @utc     True if @cur_time is expressed in UTC.
  502  * @comment Comment to display.
  503  * @file_hdr    System activity file standard header (unused here).
  504  * @record_hdr  Current record header (unused here).
  505  ***************************************************************************
  506  */
  507 __printf_funct_t print_raw_comment(int *tab, int action, char *cur_date, char *cur_time,
  508                    int utc, char *comment, struct file_header *file_hdr,
  509                    struct record_header *record_hdr)
  510 {
  511     /* Actions F_BEGIN and F_END ignored */
  512     if (action & F_MAIN) {
  513         printf("%s", cur_time);
  514         if (strlen(cur_date) && utc) {
  515             printf(" UTC");
  516         }
  517         printf("; COM %s\n", comment);
  518     }
  519 }
  520 
  521 /*
  522  ***************************************************************************
  523  * Display comments (PCP format).
  524  *
  525  * IN:
  526  * @tab     Number of tabulations (unused here).
  527  * @action  Action expected from current function.
  528  * @cur_date    Date string of current restart message (unused here).
  529  * @cur_time    Time string of current restart message (unused here).
  530  * @utc     True if @cur_time is expressed in UTC (unused here).
  531  * @comment Comment to display.
  532  * @file_hdr    System activity file standard header (unused here).
  533  * @record_hdr  Current record header.
  534  ***************************************************************************
  535  */
  536 __printf_funct_t print_pcp_comment(int *tab, int action, char *cur_date, char *cur_time,
  537                    int utc, char *comment, struct file_header *file_hdr,
  538                    struct record_header *record_hdr)
  539 {
  540 #ifdef HAVE_PCP
  541     static int def_metrics = FALSE;
  542 
  543     if (action & F_BEGIN) {
  544         if (!def_metrics) {
  545             pmiAddMetric("system.comment.value",
  546                      PM_IN_NULL, PM_TYPE_STRING, PM_INDOM_NULL, PM_SEM_DISCRETE,
  547                      pmiUnits(0, 0, 0, 0, 0, 0));
  548 
  549             def_metrics = TRUE;
  550         }
  551     }
  552     if (action & F_MAIN) {
  553         pmiPutValue("system.comment.value", NULL, comment);
  554 
  555         /* Write data to PCP archive */
  556         pcp_write_data(record_hdr, flags);
  557     }
  558 #endif /* HAVE_PCP */
  559 }
  560 
  561 /*
  562  ***************************************************************************
  563  * Display the "statistics" part of the report (XML format).
  564  *
  565  * IN:
  566  * @tab     Number of tabulations.
  567  * @action  Action expected from current function.
  568  * @act     Array of activities (unused here).
  569  * @id_seq  Activity sequence (unused here).
  570  *
  571  * OUT:
  572  * @tab     Number of tabulations.
  573  ***************************************************************************
  574  */
  575 __printf_funct_t print_xml_statistics(int *tab, int action, struct activity *act[],
  576                       unsigned int id_seq[])
  577 {
  578     if (action & F_BEGIN) {
  579         xprintf((*tab)++, "<statistics>");
  580     }
  581     if (action & F_END) {
  582         xprintf(--(*tab), "</statistics>");
  583     }
  584 }
  585 
  586 /*
  587  ***************************************************************************
  588  * Display the "statistics" part of the report (JSON format).
  589  *
  590  * IN:
  591  * @tab     Number of tabulations.
  592  * @action  Action expected from current function.
  593  * @act     Array of activities (unused here).
  594  * @id_seq  Activity sequence (unused here).
  595  *
  596  * OUT:
  597  * @tab     Number of tabulations.
  598  ***************************************************************************
  599  */
  600 __printf_funct_t print_json_statistics(int *tab, int action, struct activity *act[],
  601                        unsigned int id_seq[])
  602 {
  603     static int sep = FALSE;
  604 
  605     if (action & F_BEGIN) {
  606         printf(",\n");
  607         xprintf((*tab)++, "\"statistics\": [");
  608     }
  609     if (action & F_MAIN) {
  610         if (sep) {
  611             xprintf(--(*tab), "},");
  612         }
  613         xprintf((*tab)++, "{");
  614         sep = TRUE;
  615     }
  616     if (action & F_END) {
  617         if (sep) {
  618             xprintf(--(*tab), "}");
  619             sep = FALSE;
  620         }
  621         xprintf0(--(*tab), "]");
  622     }
  623 }
  624 
  625 /*
  626  ***************************************************************************
  627  * Display the "statistics" part of the report (PCP format).
  628  *
  629  * IN:
  630  * @tab     Number of tabulations (unused here).
  631  * @action  Action expected from current function.
  632  * @act     Array of activities.
  633  * @id_seq  Activity sequence.
  634  ***************************************************************************
  635  */
  636 __printf_funct_t print_pcp_statistics(int *tab, int action, struct activity *act[],
  637                       unsigned int id_seq[])
  638 {
  639 #ifdef HAVE_PCP
  640     int i, p;
  641 
  642     if (action & F_BEGIN) {
  643         for (i = 0; i < NR_ACT; i++) {
  644             if (!id_seq[i])
  645                 continue;   /* Activity not in file */
  646 
  647             p = get_activity_position(act, id_seq[i], EXIT_IF_NOT_FOUND);
  648             if (!IS_SELECTED(act[p]->options))
  649                 continue;   /* Activity not selected */
  650 
  651             switch (act[p]->id) {
  652 
  653                 case A_CPU:
  654                 case A_PWR_CPU:
  655                 case A_NET_SOFT:
  656                     pcp_def_cpu_metrics(act[p]);
  657                     break;
  658 
  659                 case A_PCSW:
  660                     pcp_def_pcsw_metrics();
  661                     break;
  662 
  663                 case A_IRQ:
  664                     pcp_def_irq_metrics(act[p]);
  665                     break;
  666 
  667                 case A_SWAP:
  668                     pcp_def_swap_metrics();
  669                     break;
  670 
  671                 case A_PAGE:
  672                     pcp_def_paging_metrics();
  673                     break;
  674 
  675                 case A_IO:
  676                     pcp_def_io_metrics();
  677                     break;
  678 
  679                 case A_MEMORY:
  680                     pcp_def_memory_metrics(act[p]);
  681                     break;
  682 
  683                 case A_KTABLES:
  684                     pcp_def_ktables_metrics();
  685                     break;
  686 
  687                 case A_QUEUE:
  688                     pcp_def_queue_metrics();
  689                     break;
  690 
  691                 case A_SERIAL:
  692                     pcp_def_serial_metrics(act[p]);
  693                     break;
  694 
  695                 case A_DISK:
  696                     pcp_def_disk_metrics(act[p]);
  697                     break;
  698 
  699                 case A_NET_DEV:
  700                 case A_NET_EDEV:
  701                     pcp_def_net_dev_metrics(act[p]);
  702                     break;
  703 
  704                 case A_NET_NFS:
  705                     pcp_def_net_nfs_metrics();
  706                     break;
  707 
  708                 case A_NET_NFSD:
  709                     pcp_def_net_nfsd_metrics();
  710                     break;
  711 
  712                 case A_NET_SOCK:
  713                     pcp_def_net_sock_metrics();
  714                     break;
  715 
  716                 case A_NET_IP:
  717                     pcp_def_net_ip_metrics();
  718                     break;
  719 
  720                 case A_NET_EIP:
  721                     pcp_def_net_eip_metrics();
  722                     break;
  723 
  724                 case A_NET_ICMP:
  725                     pcp_def_net_icmp_metrics();
  726                     break;
  727 
  728                 case A_NET_EICMP:
  729                     pcp_def_net_eicmp_metrics();
  730                     break;
  731 
  732                 case A_NET_TCP:
  733                     pcp_def_net_tcp_metrics();
  734                     break;
  735 
  736                 case A_NET_ETCP:
  737                     pcp_def_net_etcp_metrics();
  738                     break;
  739 
  740                 case A_NET_UDP:
  741                     pcp_def_net_udp_metrics();
  742                     break;
  743 
  744                 case A_NET_SOCK6:
  745                     pcp_def_net_sock6_metrics();
  746                     break;
  747 
  748                 case A_NET_IP6:
  749                     pcp_def_net_ip6_metrics();
  750                     break;
  751 
  752                 case A_NET_EIP6:
  753                     pcp_def_net_eip6_metrics();
  754                     break;
  755 
  756                 case A_NET_ICMP6:
  757                     pcp_def_net_icmp6_metrics();
  758                     break;
  759 
  760                 case A_NET_EICMP6:
  761                     pcp_def_net_eicmp6_metrics();
  762                     break;
  763 
  764                 case A_NET_UDP6:
  765                     pcp_def_net_udp6_metrics();
  766                     break;
  767 
  768                 case A_HUGE:
  769                     pcp_def_huge_metrics();
  770                     break;
  771 
  772                 case A_PWR_FAN:
  773                     pcp_def_pwr_fan_metrics(act[p]);
  774                     break;
  775 
  776                 case A_PWR_TEMP:
  777                     pcp_def_pwr_temp_metrics(act[p]);
  778                     break;
  779 
  780                 case A_PWR_IN:
  781                     pcp_def_pwr_in_metrics(act[p]);
  782                     break;
  783 
  784                 case A_PWR_USB:
  785                     pcp_def_pwr_usb_metrics(act[p]);
  786                     break;
  787 
  788                 case A_FS:
  789                     pcp_def_filesystem_metrics(act[p]);
  790                     break;
  791 
  792                 case A_NET_FC:
  793                     pcp_def_fchost_metrics(act[p]);
  794                     break;
  795 
  796                 case A_PSI_CPU:
  797                 case A_PSI_IO:
  798                 case A_PSI_MEM:
  799                     pcp_def_psi_metrics(act[p]);
  800                     break;
  801             }
  802         }
  803     }
  804 #endif /* HAVE_PCP */
  805 }
  806 
  807 /*
  808  ***************************************************************************
  809  * Display the "timestamp" part of the report (db and ppc format).
  810  *
  811  * IN:
  812  * @fmt     Output format (F_DB_OUTPUT or F_PPC_OUTPUT).
  813  * @file_hdr    System activity file standard header.
  814  * @cur_date    Date string of current record.
  815  * @cur_time    Time string of current record.
  816  * @utc     True if @cur_time is expressed in UTC.
  817  * @itv     Interval of time with preceding record.
  818  *
  819  * RETURNS:
  820  * Pointer on the "timestamp" string.
  821  ***************************************************************************
  822  */
  823 char *print_dbppc_timestamp(int fmt, struct file_header *file_hdr, char *cur_date,
  824                 char *cur_time, int utc, unsigned long long itv)
  825 {
  826     int isdb = (fmt == F_DB_OUTPUT);
  827     static char pre[512];
  828     char temp1[128], temp2[256];
  829 
  830     /* This substring appears on every output line, preformat it here */
  831     snprintf(temp1, sizeof(temp1), "%s%s%lld%s",
  832          file_hdr->sa_nodename, seps[isdb], itv, seps[isdb]);
  833     if (strlen(cur_date)) {
  834         snprintf(temp2, sizeof(temp2), "%s%s ", temp1, cur_date);
  835     }
  836     else {
  837         strcpy(temp2, temp1);
  838     }
  839     snprintf(pre, sizeof(pre), "%s%s%s", temp2, cur_time,
  840          strlen(cur_date) && utc ? " UTC" : "");
  841     pre[sizeof(pre) - 1] = '\0';
  842 
  843     if (DISPLAY_HORIZONTALLY(flags)) {
  844         printf("%s", pre);
  845     }
  846 
  847     return pre;
  848 }
  849 
  850 /*
  851  ***************************************************************************
  852  * Display the "timestamp" part of the report (ppc format).
  853  *
  854  * IN:
  855  * @parm    Pointer on specific parameters (unused here).
  856  * @action  Action expected from current function.
  857  * @cur_date    Date string of current record.
  858  * @cur_time    Time string of current record.
  859  * @itv     Interval of time with preceding record.
  860  * @record_hdr  Record header for current sample (unused here).
  861  * @file_hdr    System activity file standard header.
  862  * @flags   Flags for common options.
  863  *
  864  * RETURNS:
  865  * Pointer on the "timestamp" string.
  866  ***************************************************************************
  867  */
  868 __tm_funct_t print_ppc_timestamp(void *parm, int action, char *cur_date,
  869                  char *cur_time, unsigned long long itv,
  870                  struct record_header *record_hdr,
  871                  struct file_header *file_hdr, unsigned int flags)
  872 {
  873     int utc = !PRINT_LOCAL_TIME(flags) && !PRINT_TRUE_TIME(flags);
  874 
  875     if (action & F_BEGIN) {
  876         return print_dbppc_timestamp(F_PPC_OUTPUT, file_hdr, cur_date, cur_time, utc, itv);
  877     }
  878 
  879     return NULL;
  880 }
  881 
  882 /*
  883  ***************************************************************************
  884  * Display the "timestamp" part of the report (db format).
  885  *
  886  * IN:
  887  * @parm    Pointer on specific parameters (unused here).
  888  * @action  Action expected from current function.
  889  * @cur_date    Date string of current record.
  890  * @cur_time    Time string of current record.
  891  * @itv     Interval of time with preceding record.
  892  * @record_hdr  Record header for current sample (unused here).
  893  * @file_hdr    System activity file standard header.
  894  * @flags   Flags for common options.
  895  *
  896  * RETURNS:
  897  * Pointer on the "timestamp" string.
  898  ***************************************************************************
  899  */
  900 __tm_funct_t print_db_timestamp(void *parm, int action, char *cur_date,
  901                 char *cur_time, unsigned long long itv,
  902                 struct record_header *record_hdr,
  903                 struct file_header *file_hdr, unsigned int flags)
  904 {
  905     int utc = !PRINT_LOCAL_TIME(flags) && !PRINT_TRUE_TIME(flags);
  906 
  907     if (action & F_BEGIN) {
  908         return print_dbppc_timestamp(F_DB_OUTPUT, file_hdr, cur_date, cur_time, utc, itv);
  909     }
  910     if (action & F_END) {
  911         if (DISPLAY_HORIZONTALLY(flags)) {
  912             printf("\n");
  913         }
  914     }
  915 
  916     return NULL;
  917 }
  918 
  919 /*
  920  ***************************************************************************
  921  * Display the "timestamp" part of the report (XML format).
  922  *
  923  * IN:
  924  * @parm    Specific parameter. Here: number of tabulations.
  925  * @action  Action expected from current function.
  926  * @cur_date    Date string of current comment.
  927  * @cur_time    Time string of current comment.
  928  * @itv     Interval of time with preceding record.
  929  * @record_hdr  Record header for current sample (unused here).
  930  * @file_hdr    System activity file standard header (unused here).
  931  * @flags   Flags for common options.
  932  ***************************************************************************
  933  */
  934 __tm_funct_t print_xml_timestamp(void *parm, int action, char *cur_date,
  935                  char *cur_time, unsigned long long itv,
  936                  struct record_header *record_hdr,
  937                  struct file_header *file_hdr, unsigned int flags)
  938 {
  939     int utc = !PRINT_LOCAL_TIME(flags) && !PRINT_TRUE_TIME(flags);
  940     int *tab = (int *) parm;
  941 
  942     if (action & F_BEGIN) {
  943         xprintf((*tab)++, "<timestamp date=\"%s\" time=\"%s\" utc=\"%d\" interval=\"%llu\">",
  944             cur_date, cur_time, utc ? 1 : 0, itv);
  945     }
  946     if (action & F_END) {
  947         xprintf(--(*tab), "</timestamp>");
  948     }
  949 
  950     return NULL;
  951 }
  952 
  953 /*
  954  ***************************************************************************
  955  * Display the "timestamp" part of the report (JSON format).
  956  *
  957  * IN:
  958  * @parm    Specific parameter. Here: number of tabulations.
  959  * @action  Action expected from current function.
  960  * @cur_date    Date string of current comment.
  961  * @cur_time    Time string of current comment.
  962  * @itv     Interval of time with preceding record.
  963  * @record_hdr  Record header for current sample (unused here).
  964  * @file_hdr    System activity file standard header (unused here).
  965  * @flags   Flags for common options.
  966  ***************************************************************************
  967  */
  968 __tm_funct_t print_json_timestamp(void *parm, int action, char *cur_date,
  969                   char *cur_time, unsigned long long itv,
  970                   struct record_header *record_hdr,
  971                   struct file_header *file_hdr, unsigned int flags)
  972 {
  973     int utc = !PRINT_LOCAL_TIME(flags) && !PRINT_TRUE_TIME(flags);
  974     int *tab = (int *) parm;
  975 
  976     if (action & F_BEGIN) {
  977         xprintf0(*tab,
  978              "\"timestamp\": {\"date\": \"%s\", \"time\": \"%s\", "
  979              "\"utc\": %d, \"interval\": %llu}",
  980              cur_date, cur_time, utc ? 1 : 0, itv);
  981     }
  982     if (action & F_MAIN) {
  983         printf(",\n");
  984     }
  985     if (action & F_END) {
  986         printf("\n");
  987     }
  988 
  989     return NULL;
  990 }
  991 
  992 /*
  993  ***************************************************************************
  994  * Display the "timestamp" part of the report (raw format).
  995  *
  996  * IN:
  997  * @parm    Pointer on specific parameters (unused here).
  998  * @action  Action expected from current function.
  999  * @cur_date    Date string of current record.
 1000  * @cur_time    Time string of current record.
 1001  * @itv     Interval of time with preceding record (unused here).
 1002  * @record_hdr  Record header for current sample (unused here).
 1003  * @file_hdr    System activity file standard header (unused here).
 1004  * @flags   Flags for common options.
 1005  *
 1006  * RETURNS:
 1007  * Pointer on the "timestamp" string.
 1008  ***************************************************************************
 1009  */
 1010 __tm_funct_t print_raw_timestamp(void *parm, int action, char *cur_date,
 1011                  char *cur_time, unsigned long long itv,
 1012                  struct record_header *record_hdr,
 1013                  struct file_header *file_hdr, unsigned int flags)
 1014 {
 1015     int utc = !PRINT_LOCAL_TIME(flags) && !PRINT_TRUE_TIME(flags);
 1016     static char pre[80];
 1017 
 1018     if (action & F_BEGIN) {
 1019         snprintf(pre, 80, "%s%s", cur_time, strlen(cur_date) && utc ? " UTC" : "");
 1020         pre[79] = '\0';
 1021         return pre;
 1022     }
 1023 
 1024     return NULL;
 1025 }
 1026 
 1027 /*
 1028  ***************************************************************************
 1029  * Display the "timestamp" part of the report (PCP format).
 1030  *
 1031  * IN:
 1032  * @parm    Pointer on specific parameters (unused here).
 1033  * @action  Action expected from current function.
 1034  * @cur_date    Date string of current record (unused here).
 1035  * @cur_time    Time string of current record (unused here).
 1036  * @itv     Interval of time with preceding record (unused here).
 1037  * @record_hdr  Record header for current sample.
 1038  * @file_hdr    System activity file standard header (unused here).
 1039  * @flags   Flags for common options.
 1040  *
 1041  * RETURNS:
 1042  * Pointer on the "timestamp" string.
 1043  ***************************************************************************
 1044  */
 1045 __tm_funct_t print_pcp_timestamp(void *parm, int action, char *cur_date,
 1046                  char *cur_time, unsigned long long itv,
 1047                  struct record_header *record_hdr,
 1048                  struct file_header *file_hdr, unsigned int flags)
 1049 {
 1050     if (action & F_END) {
 1051         pcp_write_data(record_hdr, flags);
 1052     }
 1053 
 1054     return NULL;
 1055 }
 1056 
 1057 /*
 1058  ***************************************************************************
 1059  * Display the header of the report (XML format).
 1060  *
 1061  * IN:
 1062  * @parm    Specific parameter. Here: number of tabulations.
 1063  * @action  Action expected from current function.
 1064  * @dfile   Unused here (PCP archive file).
 1065  * @file_magic  System activity file magic header.
 1066  * @file_hdr    System activity file standard header.
 1067  * @act     Array of activities (unused here).
 1068  * @id_seq  Activity sequence (unused here).
 1069  * @file_actlst List of (known or unknown) activities in file (unused here).
 1070  *
 1071  * OUT:
 1072  * @parm    Number of tabulations.
 1073  ***************************************************************************
 1074  */
 1075 __printf_funct_t print_xml_header(void *parm, int action, char *dfile,
 1076                   struct file_magic *file_magic,
 1077                   struct file_header *file_hdr,
 1078                   struct activity *act[], unsigned int id_seq[],
 1079                   struct file_activity *file_actlst)
 1080 {
 1081     struct tm rectime, loc_t;
 1082     char cur_time[TIMESTAMP_LEN];
 1083     int *tab = (int *) parm;
 1084 
 1085     if (action & F_BEGIN) {
 1086         printf("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
 1087         printf("<!DOCTYPE sysstat PUBLIC \"DTD v%s sysstat //EN\"\n",
 1088                XML_DTD_VERSION);
 1089         printf("\"http://pagesperso-orange.fr/sebastien.godard/sysstat-%s.dtd\">\n",
 1090                XML_DTD_VERSION);
 1091 
 1092         xprintf(*tab, "<sysstat\n"
 1093                   "xmlns=\"http://pagesperso-orange.fr/sebastien.godard/sysstat\"\n"
 1094                   "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
 1095                   "xsi:schemaLocation=\"http://pagesperso-orange.fr/sebastien.godard sysstat.xsd\">");
 1096 
 1097         xprintf(++(*tab), "<sysdata-version>%s</sysdata-version>",
 1098             XML_DTD_VERSION);
 1099 
 1100         xprintf(*tab, "<host nodename=\"%s\">", file_hdr->sa_nodename);
 1101         xprintf(++(*tab), "<sysname>%s</sysname>", file_hdr->sa_sysname);
 1102         xprintf(*tab, "<release>%s</release>", file_hdr->sa_release);
 1103 
 1104         xprintf(*tab, "<machine>%s</machine>", file_hdr->sa_machine);
 1105         xprintf(*tab, "<number-of-cpus>%d</number-of-cpus>",
 1106             file_hdr->sa_cpu_nr > 1 ? file_hdr->sa_cpu_nr - 1 : 1);
 1107 
 1108         /* Fill file timestmap structure (rectime) */
 1109         get_file_timestamp_struct(flags, &rectime, file_hdr);
 1110         strftime(cur_time, sizeof(cur_time), "%Y-%m-%d", &rectime);
 1111         xprintf(*tab, "<file-date>%s</file-date>", cur_time);
 1112 
 1113         if (gmtime_r((const time_t *) &file_hdr->sa_ust_time, &loc_t) != NULL) {
 1114             strftime(cur_time, sizeof(cur_time), "%T", &loc_t);
 1115             xprintf(*tab, "<file-utc-time>%s</file-utc-time>", cur_time);
 1116         }
 1117 
 1118         xprintf(*tab, "<timezone>%s</timezone>", file_hdr->sa_tzname);
 1119     }
 1120     if (action & F_END) {
 1121         xprintf(--(*tab), "</host>");
 1122         xprintf(--(*tab), "</sysstat>");
 1123     }
 1124 }
 1125 
 1126 /*
 1127  ***************************************************************************
 1128  * Display the header of the report (JSON format).
 1129  *
 1130  * IN:
 1131  * @parm    Specific parameter. Here: number of tabulations.
 1132  * @action  Action expected from current function.
 1133  * @dfile   Unused here (PCP archive file).
 1134  * @file_magic  System activity file magic header.
 1135  * @file_hdr    System activity file standard header.
 1136  * @act     Array of activities (unused here).
 1137  * @id_seq  Activity sequence (unused here).
 1138  * @file_actlst List of (known or unknown) activities in file (unused here).
 1139  *
 1140  * OUT:
 1141  * @parm    Number of tabulations.
 1142  ***************************************************************************
 1143  */
 1144 __printf_funct_t print_json_header(void *parm, int action, char *dfile,
 1145                    struct file_magic *file_magic,
 1146                    struct file_header *file_hdr,
 1147                    struct activity *act[], unsigned int id_seq[],
 1148                    struct file_activity *file_actlst)
 1149 {
 1150     struct tm rectime, loc_t;
 1151     char cur_time[TIMESTAMP_LEN];
 1152     int *tab = (int *) parm;
 1153 
 1154     if (action & F_BEGIN) {
 1155         xprintf(*tab, "{\"sysstat\": {");
 1156 
 1157         xprintf(++(*tab), "\"hosts\": [");
 1158         xprintf(++(*tab), "{");
 1159         xprintf(++(*tab), "\"nodename\": \"%s\",", file_hdr->sa_nodename);
 1160         xprintf(*tab, "\"sysname\": \"%s\",", file_hdr->sa_sysname);
 1161         xprintf(*tab, "\"release\": \"%s\",", file_hdr->sa_release);
 1162 
 1163         xprintf(*tab, "\"machine\": \"%s\",", file_hdr->sa_machine);
 1164         xprintf(*tab, "\"number-of-cpus\": %d,",
 1165             file_hdr->sa_cpu_nr > 1 ? file_hdr->sa_cpu_nr - 1 : 1);
 1166 
 1167         /* Fill file timestmap structure (rectime) */
 1168         get_file_timestamp_struct(flags, &rectime, file_hdr);
 1169         strftime(cur_time, sizeof(cur_time), "%Y-%m-%d", &rectime);
 1170         xprintf(*tab, "\"file-date\": \"%s\",", cur_time);
 1171 
 1172         if (gmtime_r((const time_t *) &file_hdr->sa_ust_time, &loc_t) != NULL) {
 1173             strftime(cur_time, sizeof(cur_time), "%T", &loc_t);
 1174             xprintf(*tab, "\"file-utc-time\": \"%s\",", cur_time);
 1175         }
 1176 
 1177         xprintf0(*tab, "\"timezone\": \"%s\"", file_hdr->sa_tzname);
 1178     }
 1179     if (action & F_END) {
 1180         printf("\n");
 1181         xprintf(--(*tab), "}");
 1182         xprintf(--(*tab), "]");
 1183         xprintf(--(*tab), "}}");
 1184     }
 1185 }
 1186 
 1187 /*
 1188  ***************************************************************************
 1189  * Display data file header.
 1190  *
 1191  * IN:
 1192  * @parm    Specific parameter (unused here).
 1193  * @action  Action expected from current function.
 1194  * @dfile   Name of system activity data file (unused here).
 1195  * @file_magic  System activity file magic header.
 1196  * @file_hdr    System activity file standard header.
 1197  * @act     Array of activities.
 1198  * @id_seq  Activity sequence.
 1199  * @file_actlst List of (known or unknown) activities in file.
 1200  ***************************************************************************
 1201  */
 1202 __printf_funct_t print_hdr_header(void *parm, int action, char *dfile,
 1203                   struct file_magic *file_magic,
 1204                   struct file_header *file_hdr,
 1205                   struct activity *act[], unsigned int id_seq[],
 1206                   struct file_activity *file_actlst)
 1207 {
 1208     int i, p;
 1209     struct tm rectime, loc_t;
 1210     struct file_activity *fal;
 1211     char cur_time[TIMESTAMP_LEN];
 1212 
 1213     /* Actions F_MAIN and F_END ignored */
 1214     if (action & F_BEGIN) {
 1215         printf(_("System activity data file: %s (%#x)\n"),
 1216                dfile, file_magic->format_magic);
 1217 
 1218         display_sa_file_version(stdout, file_magic);
 1219 
 1220         if (file_magic->format_magic != FORMAT_MAGIC) {
 1221             return;
 1222         }
 1223 
 1224         printf(_("Genuine sa datafile: %s (%x)\n"),
 1225                file_magic->upgraded ? _("no") : _("yes"),
 1226                file_magic->upgraded);
 1227 
 1228         printf(_("Host: "));
 1229         print_gal_header(localtime_r((const time_t *) &(file_hdr->sa_ust_time), &rectime),
 1230                  file_hdr->sa_sysname, file_hdr->sa_release,
 1231                  file_hdr->sa_nodename, file_hdr->sa_machine,
 1232                  file_hdr->sa_cpu_nr > 1 ? file_hdr->sa_cpu_nr - 1 : 1,
 1233                  PLAIN_OUTPUT);
 1234 
 1235         /* Fill file timestamp structure (rectime) */
 1236         get_file_timestamp_struct(flags, &rectime, file_hdr);
 1237         strftime(cur_time, sizeof(cur_time), "%Y-%m-%d", &rectime);
 1238         printf(_("File date: %s\n"), cur_time);
 1239 
 1240         if (gmtime_r((const time_t *) &file_hdr->sa_ust_time, &loc_t) != NULL) {
 1241             printf(_("File time: "));
 1242             strftime(cur_time, sizeof(cur_time), "%T", &loc_t);
 1243             printf("%s UTC (%lld)\n", cur_time, file_hdr->sa_ust_time);
 1244         }
 1245 
 1246         printf(_("Timezone: %s\n"), file_hdr->sa_tzname);
 1247 
 1248         /* File composition: file_header, file_activity, record_header */
 1249         printf(_("File composition: (%d,%d,%d),(%d,%d,%d),(%d,%d,%d)\n"),
 1250                file_magic->hdr_types_nr[0], file_magic->hdr_types_nr[1], file_magic->hdr_types_nr[2],
 1251                file_hdr->act_types_nr[0], file_hdr->act_types_nr[1], file_hdr->act_types_nr[2],
 1252                file_hdr->rec_types_nr[0], file_hdr->rec_types_nr[1], file_hdr->rec_types_nr[2]);
 1253 
 1254         printf(_("Size of a long int: %d\n"), file_hdr->sa_sizeof_long);
 1255         printf("HZ = %lu\n", file_hdr->sa_hz);
 1256         printf(_("Number of activities in file: %u\n"),
 1257                file_hdr->sa_act_nr);
 1258         printf(_("Extra structures available: %c\n"),
 1259                file_hdr->extra_next ? 'Y' : 'N');
 1260 
 1261         printf(_("List of activities:\n"));
 1262         fal = file_actlst;
 1263         for (i = 0; i < file_hdr->sa_act_nr; i++, fal++) {
 1264 
 1265             p = get_activity_position(act, fal->id, RESUME_IF_NOT_FOUND);
 1266 
 1267             printf("%02d: [%02x] ", fal->id, fal->magic);
 1268             if (p >= 0) {
 1269                 printf("%-20s", act[p]->name);
 1270             }
 1271             else {
 1272                 printf("%-20s", _("Unknown activity"));
 1273             }
 1274             printf(" %c:%4d", fal->has_nr ? 'Y' : 'N', fal->nr);
 1275             if (fal->nr2 > 1) {
 1276                 printf("x%d", fal->nr2);
 1277             }
 1278             printf("\t(%d,%d,%d)", fal->types_nr[0], fal->types_nr[1], fal->types_nr[2]);
 1279             if ((p >= 0) && (act[p]->magic == ACTIVITY_MAGIC_UNKNOWN)) {
 1280                 printf(_(" \t[Unknown format]"));
 1281             }
 1282             printf("\n");
 1283         }
 1284     }
 1285 }
 1286 
 1287 /*
 1288  ***************************************************************************
 1289  * Display the header of the report (SVG format).
 1290  *
 1291  * IN:
 1292  * @parm    Specific parameters. Here: number of rows of views to display
 1293  *      or canvas height entered on the command line (@graph_nr), and
 1294  *      max number of views on a single row (@views_per_row).
 1295  * @action  Action expected from current function.
 1296  * @dfile   Name of system activity data file (unused here).
 1297  * @file_magic  System activity file magic header (unused here).
 1298  * @file_hdr    System activity file standard header.
 1299  * @act     Array of activities (unused here).
 1300  * @id_seq  Activity sequence (unused here).
 1301  * @file_actlst List of (known or unknown) activities in file (unused here).
 1302  ***************************************************************************
 1303  */
 1304 __printf_funct_t print_svg_header(void *parm, int action, char *dfile,
 1305                   struct file_magic *file_magic,
 1306                   struct file_header *file_hdr,
 1307                   struct activity *act[], unsigned int id_seq[],
 1308                   struct file_activity *file_actlst)
 1309 {
 1310     struct svg_hdr_parm *hdr_parm = (struct svg_hdr_parm *) parm;
 1311     struct tm rectime;
 1312     unsigned int height = 0, ht = 0;
 1313     int i, p;
 1314 
 1315     if (action & F_BEGIN) {
 1316         printf("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
 1317         printf("<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" ");
 1318         printf("\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n");
 1319         printf("<svg xmlns=\"http://www.w3.org/2000/svg\"");
 1320         if (DISPLAY_TOC(flags)) {
 1321             printf(" xmlns:xlink=\"http://www.w3.org/1999/xlink\"");
 1322         }
 1323         if (action & F_END) {
 1324             printf(">\n");
 1325         }
 1326     }
 1327 
 1328     if (action & F_MAIN) {
 1329         if (SET_CANVAS_HEIGHT(flags)) {
 1330             /*
 1331              * Option "-O height=..." used: @graph_nr is
 1332              * the SVG canvas height set on the command line.
 1333              */
 1334             height = hdr_parm->graph_nr;
 1335         }
 1336         else {
 1337             height = SVG_H_YSIZE +
 1338                  SVG_C_YSIZE * (DISPLAY_TOC(flags) ? hdr_parm->nr_act_dispd : 0) +
 1339                  SVG_T_YSIZE * hdr_parm->graph_nr;
 1340         }
 1341         if (height < 100) {
 1342             /* Min canvas height is 100 (at least to display "No data") */
 1343             height = 100;
 1344         }
 1345         printf(" width=\"%d\" height=\"%d\""
 1346                " fill=\"black\" stroke=\"#%06x\" stroke-width=\"1\">\n",
 1347                SVG_T_XSIZE * (hdr_parm->views_per_row), height,
 1348                svg_colors[palette][SVG_COL_DEFAULT_IDX]);
 1349         printf("<text x=\"0\" y=\"30\" text-anchor=\"start\" stroke=\"#%06x\">",
 1350                svg_colors[palette][SVG_COL_HEADER_IDX]);
 1351         print_gal_header(localtime_r((const time_t *) &(file_hdr->sa_ust_time), &rectime),
 1352                  file_hdr->sa_sysname, file_hdr->sa_release,
 1353                  file_hdr->sa_nodename, file_hdr->sa_machine,
 1354                  file_hdr->sa_cpu_nr > 1 ? file_hdr->sa_cpu_nr - 1 : 1,
 1355                  PLAIN_OUTPUT);
 1356         printf("</text>\n");
 1357         if (DISPLAY_TOC(flags)) {
 1358             for (i = 0; i < NR_ACT; i++) {
 1359                 if (!id_seq[i])
 1360                     continue;   /* Activity not in file */
 1361 
 1362                 p = get_activity_position(act, id_seq[i], EXIT_IF_NOT_FOUND);
 1363                 if (!IS_SELECTED(act[p]->options) || !act[p]->g_nr)
 1364                     continue;   /* Activity not selected or no graph available */
 1365 
 1366                 printf("<a xlink:href=\"#g%d-0\" xlink:title=\"%s\">\n",
 1367                        act[p]->id, act[p]->name);
 1368                 printf("<text x=\"10\" y=\"%d\">%s</text></a>\n",
 1369                        SVG_H_YSIZE + ht, act[p]->desc);
 1370                 ht += SVG_C_YSIZE;
 1371             }
 1372         }
 1373     }
 1374 
 1375     if (action & F_END) {
 1376         if (!(action & F_BEGIN)) {
 1377             if (!hdr_parm->graph_nr) {
 1378                 /* No views displayed */
 1379                 printf("<text x= \"0\" y=\"%d\" text-anchor=\"start\" stroke=\"#%06x\">",
 1380                        SVG_H_YSIZE +
 1381                        SVG_C_YSIZE * (DISPLAY_TOC(flags) ? hdr_parm->nr_act_dispd : 0),
 1382                        svg_colors[palette][SVG_COL_ERROR_IDX]);
 1383                 printf("No data!</text>\n");
 1384             }
 1385             /* Give actual SVG height */
 1386             printf("<!-- Actual canvas height: %d -->\n",
 1387                    SVG_H_YSIZE +
 1388                    SVG_C_YSIZE * (DISPLAY_TOC(flags) ? hdr_parm->nr_act_dispd : 0) +
 1389                    SVG_T_YSIZE * hdr_parm->graph_nr);
 1390         }
 1391         printf("</svg>\n");
 1392     }
 1393 }
 1394 
 1395 /*
 1396  ***************************************************************************
 1397  * PCP header function.
 1398  *
 1399  * IN:
 1400  * @parm    Specific parameter (unused here).
 1401  * @action  Action expected from current function.
 1402  * @dfile   Name of PCP archive file.
 1403  * @file_magic  System activity file magic header (unused here).
 1404  * @file_hdr    System activity file standard header (unused here).
 1405  * @act     Array of activities (unused here).
 1406  * @id_seq  Activity sequence (unused here).
 1407  * @file_actlst List of (known or unknown) activities in file (unused here).
 1408  ***************************************************************************
 1409  */
 1410 __printf_funct_t print_pcp_header(void *parm, int action, char *dfile,
 1411                   struct file_magic *file_magic,
 1412                   struct file_header *file_hdr,
 1413                   struct activity *act[], unsigned int id_seq[],
 1414                   struct file_activity *file_actlst)
 1415 {
 1416 #ifdef HAVE_PCP
 1417     char buf[64];
 1418     struct tm lrectime;
 1419     unsigned long long utc_sec = file_hdr->sa_ust_time;
 1420 
 1421     if (action & F_BEGIN) {
 1422         /* Create new PCP context */
 1423         pmiStart(dfile, FALSE);
 1424 
 1425         if (PRINT_LOCAL_TIME(flags)) {
 1426             pmiSetTimezone(file_hdr->sa_tzname);
 1427         }
 1428         else {
 1429             pmiSetTimezone("UTC");
 1430         }
 1431 
 1432         /* Save hostname */
 1433         pmiSetHostname(file_hdr->sa_nodename);
 1434 
 1435         /* Save number of CPU in PCP archive */
 1436         pmiAddMetric("hinv.ncpu",
 1437                  PM_IN_NULL, PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_DISCRETE,
 1438                  pmiUnits(0, 0, 1, 0, 0, PM_COUNT_ONE));
 1439         snprintf(buf, sizeof(buf), "%u",
 1440              file_hdr->sa_cpu_nr > 1 ? file_hdr->sa_cpu_nr - 1 : 1);
 1441         pmiPutValue("hinv.ncpu", NULL, buf);
 1442     }
 1443 
 1444     if (action & F_END) {
 1445         if (action & F_BEGIN) {
 1446             /* Only the header data will be written to PCP archive */
 1447             if (!PRINT_LOCAL_TIME(flags)) {
 1448                 /* Convert a time_t value from local time to UTC */
 1449                 if (gmtime_r((const time_t *) &(file_hdr->sa_ust_time), &lrectime)) {
 1450                     utc_sec = mktime(&lrectime);
 1451                 }
 1452             }
 1453             pmiWrite(utc_sec, 0);
 1454         }
 1455         pmiEnd();
 1456     }
 1457 #endif
 1458 }
 1459 
 1460 /*
 1461  ***************************************************************************
 1462  * Count the number of new network interfaces in current sample. If a new
 1463  * interface is found then add it to the linked list starting at
 1464  * @a->item_list.
 1465  *
 1466  * IN:
 1467  * @a       Activity structure with statistics.
 1468  * @curr    Index in array for current sample statistics.
 1469  *
 1470  * RETURNS:
 1471  * Number of new interfaces identified in current sample that were not
 1472  * previously in the list.
 1473  ***************************************************************************
 1474  */
 1475 __nr_t count_new_net_dev(struct activity *a, int curr)
 1476 {
 1477     int i, nr = 0;
 1478     struct stats_net_dev *sndc;
 1479 
 1480     for (i = 0; i < a->nr[curr]; i++) {
 1481         sndc = (struct stats_net_dev *) ((char *) a->buf[curr] + i * a->msize);
 1482 
 1483         nr += add_list_item(&(a->item_list), sndc->interface, MAX_IFACE_LEN);
 1484     }
 1485 
 1486     return nr;
 1487 }
 1488 
 1489 /*
 1490  ***************************************************************************
 1491  * Count the number of new network interfaces in current sample. If a new
 1492  * interface is found then add it to the linked list starting at
 1493  * @a->item_list.
 1494  *
 1495  * IN:
 1496  * @a       Activity structure with statistics.
 1497  * @curr    Index in array for current sample statistics.
 1498  *
 1499  * RETURNS:
 1500  * Number of new interfaces identified in current sample that were not
 1501  * previously in the list.
 1502  ***************************************************************************
 1503  */
 1504 __nr_t count_new_net_edev(struct activity *a, int curr)
 1505 {
 1506     int i, nr = 0;
 1507     struct stats_net_edev *snedc;
 1508 
 1509     for (i = 0; i < a->nr[curr]; i++) {
 1510         snedc = (struct stats_net_edev *) ((char *) a->buf[curr] + i * a->msize);
 1511 
 1512         nr += add_list_item(&(a->item_list), snedc->interface, MAX_IFACE_LEN);
 1513     }
 1514 
 1515     return nr;
 1516 }
 1517 
 1518 /*
 1519  ***************************************************************************
 1520  * Count the number of new filesystems in current sample. If a new
 1521  * filesystem is found then add it to the linked list starting at
 1522  * @a->item_list.
 1523  *
 1524  * IN:
 1525  * @a       Activity structure with statistics.
 1526  * @curr    Index in array for current sample statistics.
 1527  *
 1528  * RETURNS:
 1529  * Number of new filesystems identified in current sample that were not
 1530  * previously in the list.
 1531  ***************************************************************************
 1532  */
 1533 __nr_t count_new_filesystem(struct activity *a, int curr)
 1534 {
 1535     int i, nr = 0;
 1536     struct stats_filesystem *sfc;
 1537 
 1538     for (i = 0; i < a->nr[curr]; i++) {
 1539         sfc = (struct stats_filesystem *) ((char *) a->buf[curr] + i * a->msize);
 1540 
 1541         nr += add_list_item(&(a->item_list),
 1542                     DISPLAY_MOUNT(a->opt_flags) ? sfc->mountp : sfc->fs_name,
 1543                     MAX_FS_LEN);
 1544     }
 1545 
 1546     return nr;
 1547 }
 1548 
 1549 /*
 1550  ***************************************************************************
 1551  * Count the number of new fchosts in current sample. If a new
 1552  * fchost is found then add it to the linked list starting at
 1553  * @a->item_list.
 1554  *
 1555  * IN:
 1556  * @a       Activity structure with statistics.
 1557  * @curr    Index in array for current sample statistics.
 1558  *
 1559  * RETURNS:
 1560  * Number of new fchosts identified in current sample that were not
 1561  * previously in the list.
 1562  ***************************************************************************
 1563  */
 1564 __nr_t count_new_fchost(struct activity *a, int curr)
 1565 {
 1566     int i, nr = 0;
 1567     struct stats_fchost *sfcc;
 1568 
 1569     for (i = 0; i < a->nr[curr]; i++) {
 1570         sfcc = (struct stats_fchost *) ((char *) a->buf[curr] + i * a->msize);
 1571 
 1572         nr += add_list_item(&(a->item_list), sfcc->fchost_name, MAX_FCH_LEN);
 1573     }
 1574 
 1575     return nr;
 1576 }
 1577 
 1578 /*
 1579  ***************************************************************************
 1580  * Count the number of new block devices in current sample. If a new
 1581  * block device is found then add it to the linked list starting at
 1582  * @a->item_list.
 1583  *
 1584  * IN:
 1585  * @a       Activity structure with statistics.
 1586  * @curr    Index in array for current sample statistics.
 1587  *
 1588  * RETURNS:
 1589  * Number of new block devices identified in current sample that were not
 1590  * previously in the list.
 1591  ***************************************************************************
 1592  */
 1593 __nr_t count_new_disk(struct activity *a, int curr)
 1594 {
 1595     int i, nr = 0;
 1596     struct stats_disk *sdc;
 1597 
 1598     for (i = 0; i < a->nr[curr]; i++) {
 1599         sdc = (struct stats_disk *) ((char *) a->buf[curr] + i * a->msize);
 1600 
 1601         nr += add_list_item(&(a->item_list),
 1602                     get_device_name(sdc->major, sdc->minor, sdc->wwn, sdc->part_nr,
 1603                             DISPLAY_PRETTY(flags), DISPLAY_PERSIST_NAME_S(flags),
 1604                             USE_STABLE_ID(flags), NULL),
 1605                     MAX_DEV_LEN);
 1606     }
 1607 
 1608     return nr;
 1609 }
 1610 
 1611 /*
 1612  ***************************************************************************
 1613  * Init custom color palette used to draw graphs (sadf -g).
 1614  ***************************************************************************
 1615  */
 1616 void init_custom_color_palette()
 1617 {
 1618     char *e, *p;
 1619     int len;
 1620     unsigned int val;
 1621 
 1622     /* Read S_COLORS_PALETTE environment variable */
 1623     if ((e = __getenv(ENV_COLORS_PALETTE)) == NULL)
 1624         /* Environment variable not set */
 1625         return;
 1626 
 1627     for (p = strtok(e, ":"); p; p =strtok(NULL, ":")) {
 1628 
 1629         len = strlen(p);
 1630         if ((len > 8) || (len < 3) || (*(p + 1) != '=') ||
 1631             (strspn(p + 2, "0123456789ABCDEFabcdef") != (len - 2)))
 1632             /* Ignore malformed codes */
 1633             continue;
 1634 
 1635         sscanf(p + 2, "%x", &val);
 1636 
 1637         if ((*p >= '0') && (*p <= '9')) {
 1638             svg_colors[SVG_CUSTOM_COL_PALETTE][*p & 0xf] = val;
 1639             continue;
 1640         }
 1641         else if (((*p >= 'A') && (*p <= 'F')) ||
 1642              ((*p >= 'a') && (*p <= 'f'))) {
 1643             svg_colors[SVG_CUSTOM_COL_PALETTE][9 + (*p & 0xf)] = val;
 1644             continue;
 1645         }
 1646 
 1647         switch (*p) {
 1648             case 'G':
 1649                 svg_colors[SVG_CUSTOM_COL_PALETTE][SVG_COL_GRID_IDX] = val;
 1650                 break;
 1651             case 'H':
 1652                 svg_colors[SVG_CUSTOM_COL_PALETTE][SVG_COL_HEADER_IDX] = val;
 1653                 break;
 1654             case 'I':
 1655                 svg_colors[SVG_CUSTOM_COL_PALETTE][SVG_COL_INFO_IDX] = val;
 1656                 break;
 1657             case 'K':
 1658                 svg_colors[SVG_CUSTOM_COL_PALETTE][SVG_COL_BCKGRD_IDX] = val;
 1659                 break;
 1660             case 'L':
 1661                 svg_colors[SVG_CUSTOM_COL_PALETTE][SVG_COL_DEFAULT_IDX] = val;
 1662                 break;
 1663             case 'T':
 1664                 svg_colors[SVG_CUSTOM_COL_PALETTE][SVG_COL_TITLE_IDX] = val;
 1665                 break;
 1666             case 'W':
 1667                 svg_colors[SVG_CUSTOM_COL_PALETTE][SVG_COL_ERROR_IDX] = val;
 1668                 break;
 1669             case 'X':
 1670                 svg_colors[SVG_CUSTOM_COL_PALETTE][SVG_COL_AXIS_IDX] = val;
 1671                 break;
 1672         }
 1673     }
 1674 }